mirror of
https://github.com/php/php-src.git
synced 2026-04-27 01:48:26 +02:00
Merge branch 'master' into Closure_apply
Conflicts: Zend/zend_closures.c Zend/zend_closures.h Zend/zend_execute_API.c Zend/zend_vm_def.h
This commit is contained in:
@@ -48,110 +48,80 @@ define print_cvs
|
||||
end
|
||||
|
||||
define dump_bt
|
||||
set $t = $arg0
|
||||
while $t
|
||||
printf "[%p] ", $t
|
||||
set $fst = $t->function_state
|
||||
if $fst.function->common.function_name
|
||||
if $fst.arguments
|
||||
set $count = (int)*($fst.arguments)
|
||||
|
||||
if $t->object
|
||||
if $fst.function.common.scope
|
||||
printf "%s->", $fst.function.common.scope->name
|
||||
else
|
||||
if !$eg
|
||||
____executor_globals
|
||||
end
|
||||
|
||||
set $known_class = 0
|
||||
if $eg
|
||||
set $handle = $t->object.value.obj.handle
|
||||
set $handlers = $t->object.value.obj.handlers
|
||||
set $zobj = (zend_object *)$eg.objects_store.object_buckets[$handle].bucket.obj.object
|
||||
|
||||
if $handlers->get_class_entry == &zend_std_object_get_class
|
||||
set $known_class = 1
|
||||
|
||||
if $handlers.get_class_name
|
||||
if $handlers.get_class_name != &zend_std_object_get_class_name
|
||||
set $known_class = 0
|
||||
end
|
||||
end
|
||||
|
||||
if $known_class
|
||||
printf "%s->", $zobj->ce.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if !$known_class
|
||||
printf "(Unknown)->"
|
||||
end
|
||||
end
|
||||
set $ex = $arg0->prev_execute_data
|
||||
while $ex
|
||||
printf "[%p] ", $ex
|
||||
set $func = $ex->func
|
||||
if $func
|
||||
if $ex->object
|
||||
if $func->common.scope
|
||||
printf "%s->", $func->common.scope->name->val
|
||||
else
|
||||
if $fst.function.common.scope
|
||||
printf "%s::", $fst.function.common.scope->name
|
||||
end
|
||||
printf "%s->", $ex->object->ce.name->val
|
||||
end
|
||||
else
|
||||
if $func->common.scope
|
||||
printf "%s::", $func->common.scope->name->val
|
||||
end
|
||||
end
|
||||
|
||||
printf "%s(", $func->common.function_name->val
|
||||
|
||||
set $callFrameSize = (sizeof(zend_execute_data) + sizeof(zval) - 1) / sizeof(zval)
|
||||
|
||||
set $count = $ex->num_args
|
||||
set $arg = 0
|
||||
while $arg < $count
|
||||
if $arg > 0
|
||||
printf ", "
|
||||
end
|
||||
|
||||
printf "%s(", $fst.function->common.function_name
|
||||
while $count > 0
|
||||
set $zvalue = *(zval **)($fst.arguments - $count)
|
||||
set $type = $zvalue->type
|
||||
if $type == 0
|
||||
printf "NULL"
|
||||
end
|
||||
if $type == 1
|
||||
printf "%ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 2
|
||||
printf "%f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 3
|
||||
if $zvalue->value.lval
|
||||
printf "true"
|
||||
else
|
||||
printf "false"
|
||||
end
|
||||
end
|
||||
if $type == 4
|
||||
printf "array(%d)[%p]", $zvalue->value.ht->nNumOfElements, $zvalue
|
||||
end
|
||||
if $type == 5
|
||||
printf "object[%p]", $zvalue
|
||||
end
|
||||
if $type == 6
|
||||
____print_str $zvalue->value.str.val $zvalue->value.str.len
|
||||
end
|
||||
if $type == 7
|
||||
printf "resource(#%d)", $zvalue->value.lval
|
||||
end
|
||||
if $type == 8
|
||||
printf "constant"
|
||||
end
|
||||
if $type == 9
|
||||
printf "const_array"
|
||||
end
|
||||
if $type > 9
|
||||
printf "unknown type %d", $type
|
||||
end
|
||||
set $count = $count -1
|
||||
if $count > 0
|
||||
printf ", "
|
||||
end
|
||||
set $zvalue = (zval *) $ex + $callFrameSize + $arg
|
||||
set $type = $zvalue->u1.v.type
|
||||
if $type == 1
|
||||
printf "NULL"
|
||||
end
|
||||
printf ") "
|
||||
else
|
||||
printf "%s() ", $fst.function->common.function_name
|
||||
if $type == 2
|
||||
printf "false"
|
||||
end
|
||||
if $type == 3
|
||||
printf "true"
|
||||
end
|
||||
if $type == 4
|
||||
printf "%ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 5
|
||||
printf "%f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 6
|
||||
____print_str $zvalue->value.str->val $zvalue->value.str->len
|
||||
end
|
||||
if $type == 7
|
||||
printf "array(%d)[%p]", $zvalue->value.arr->ht->nNumOfElements, $zvalue
|
||||
end
|
||||
if $type == 8
|
||||
printf "object[%p]", $zvalue
|
||||
end
|
||||
if $type == 9
|
||||
printf "resource(#%d)", $zvalue->value.lval
|
||||
end
|
||||
if $type == 10
|
||||
printf "reference"
|
||||
end
|
||||
if $type > 10
|
||||
printf "unknown type %d", $type
|
||||
end
|
||||
set $arg = $arg + 1
|
||||
end
|
||||
|
||||
printf ") "
|
||||
else
|
||||
printf "??? "
|
||||
end
|
||||
if $t->op_array != 0
|
||||
printf "%s:%d ", $t->op_array->filename, $t->opline->lineno
|
||||
if $func != 0
|
||||
printf "%s:%d ", $func->op_array.filename->val, $ex->opline->lineno
|
||||
end
|
||||
set $t = $t->prev_execute_data
|
||||
set $ex = $ex->prev_execute_data
|
||||
printf "\n"
|
||||
end
|
||||
end
|
||||
@@ -171,34 +141,37 @@ end
|
||||
|
||||
define ____printzv_contents
|
||||
set $zvalue = $arg0
|
||||
set $type = $zvalue->type
|
||||
set $type = $zvalue->u1.v.type
|
||||
|
||||
printf "(refcount=%d", $zvalue->refcount__gc
|
||||
if $zvalue->is_ref__gc
|
||||
printf ",is_ref"
|
||||
# 15 == IS_INDIRECT
|
||||
if $type >= 5 && $type != 15
|
||||
printf "(refcount=%d) ", $zvalue->value.counted->refcount
|
||||
end
|
||||
printf ") "
|
||||
|
||||
if $type == 0
|
||||
printf "NULL"
|
||||
printf "UNDEF"
|
||||
end
|
||||
if $type == 1
|
||||
printf "long: %ld", $zvalue->value.lval
|
||||
printf "NULL"
|
||||
end
|
||||
if $type == 2
|
||||
printf "double: %f", $zvalue->value.dval
|
||||
printf "bool: false"
|
||||
end
|
||||
if $type == 3
|
||||
printf "bool: "
|
||||
if $zvalue->value.lval
|
||||
printf "true"
|
||||
else
|
||||
printf "false"
|
||||
end
|
||||
printf "bool: true"
|
||||
end
|
||||
if $type == 4
|
||||
printf "array(%d): ", $zvalue->value.ht->nNumOfElements
|
||||
if $type == 4
|
||||
printf "long: %ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 5
|
||||
printf "double: %f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 6
|
||||
printf "string: %s", $zvalue->value.str->val
|
||||
end
|
||||
if $type == 7
|
||||
printf "array: "
|
||||
if ! $arg1
|
||||
printf "{\n"
|
||||
set $ind = $ind + 1
|
||||
____print_ht $zvalue->value.ht 1
|
||||
set $ind = $ind - 1
|
||||
@@ -207,32 +180,21 @@ define ____printzv_contents
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
printf "}"
|
||||
end
|
||||
set $type = 0
|
||||
end
|
||||
if $type == 5
|
||||
if $type == 8
|
||||
printf "object"
|
||||
____executor_globals
|
||||
set $handle = $zvalue->value.obj.handle
|
||||
set $handlers = $zvalue->value.obj.handlers
|
||||
if basic_functions_module.zts
|
||||
set $zobj = zend_objects_get_address($zvalue, $tsrm_ls)
|
||||
else
|
||||
set $zobj = zend_objects_get_address($zvalue)
|
||||
end
|
||||
if $handlers->get_class_entry == &zend_std_object_get_class
|
||||
set $cname = $zobj->ce.name
|
||||
else
|
||||
set $cname = "Unknown"
|
||||
end
|
||||
set $zobj = $zvalue->value.obj
|
||||
set $cname = $zobj->ce->name->val
|
||||
printf "(%s) #%d", $cname, $handle
|
||||
if ! $arg1
|
||||
if $handlers->get_properties == &zend_std_get_properties
|
||||
set $ht = $zobj->properties
|
||||
if $ht
|
||||
printf "(%d): ", $ht->nNumOfElements
|
||||
printf "{\n"
|
||||
set $ind = $ind + 1
|
||||
____print_ht $ht 1
|
||||
set $ind = $ind - 1
|
||||
@@ -241,7 +203,6 @@ define ____printzv_contents
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
printf "}"
|
||||
else
|
||||
echo "no properties found"
|
||||
end
|
||||
@@ -249,20 +210,36 @@ define ____printzv_contents
|
||||
end
|
||||
set $type = 0
|
||||
end
|
||||
if $type == 6
|
||||
printf "string(%d): ", $zvalue->value.str.len
|
||||
____print_str $zvalue->value.str.val $zvalue->value.str.len
|
||||
end
|
||||
if $type == 7
|
||||
printf "resource: #%d", $zvalue->value.lval
|
||||
end
|
||||
if $type == 8
|
||||
printf "constant"
|
||||
end
|
||||
if $type == 9
|
||||
printf "const_array"
|
||||
printf "resource: #%d", $zvalue->value.res->handle
|
||||
end
|
||||
if $type > 9
|
||||
if $type == 10
|
||||
printf "reference: "
|
||||
____printzv &$zvalue->value.ref->val $arg1
|
||||
end
|
||||
if $type == 11
|
||||
printf "const: %s", $zvalue->value.str->val
|
||||
end
|
||||
if $type == 12
|
||||
printf "const_ast"
|
||||
end
|
||||
if $type == 13
|
||||
printf "_IS_BOOL"
|
||||
end
|
||||
if $type == 14
|
||||
printf "IS_CALLABLE"
|
||||
end
|
||||
if $type == 15
|
||||
printf "indirect: "
|
||||
____printzv $zvalue->value.zv $arg1
|
||||
end
|
||||
if $type == 16
|
||||
printf "string_offset"
|
||||
end
|
||||
if $type == 17
|
||||
printf "pointer: %p", $zvalue->value.ptr
|
||||
end
|
||||
if $type > 17
|
||||
printf "unknown type %d", $type
|
||||
end
|
||||
printf "\n"
|
||||
@@ -274,10 +251,6 @@ define ____printzv
|
||||
|
||||
printf "[%p] ", $zvalue
|
||||
|
||||
if $zvalue == $eg.uninitialized_zval_ptr
|
||||
printf "*uninitialized* "
|
||||
end
|
||||
|
||||
set $zcontents = (zval*) $zvalue
|
||||
if $arg1
|
||||
____printzv_contents $zcontents $arg1
|
||||
@@ -320,42 +293,60 @@ end
|
||||
|
||||
define ____print_ht
|
||||
set $ht = (HashTable*)$arg0
|
||||
set $p = $ht->pListHead
|
||||
|
||||
while $p != 0
|
||||
set $i = $ind
|
||||
while $i > 0
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
|
||||
if $p->nKeyLength > 0
|
||||
____print_str $p->arKey $p->nKeyLength
|
||||
printf " => "
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
|
||||
if $arg1 == 0
|
||||
printf "%p\n", (void*)$p->pData
|
||||
end
|
||||
if $arg1 == 1
|
||||
set $zval = *(zval **)$p->pData
|
||||
____printzv $zval 1
|
||||
end
|
||||
if $arg1 == 2
|
||||
printf "%s\n", (char*)$p->pData
|
||||
end
|
||||
|
||||
set $p = $p->pListNext
|
||||
set $n = $ind
|
||||
while $n > 0
|
||||
printf " "
|
||||
set $n = $n - 1
|
||||
end
|
||||
|
||||
if $ht->u.v.flags & 4
|
||||
printf "Packed"
|
||||
else
|
||||
printf "Hash"
|
||||
end
|
||||
printf "(%d)[%p]: {\n", $ht->nNumOfElements, $ht
|
||||
|
||||
set $num = $ht->nNumUsed
|
||||
set $i = 0
|
||||
set $ind = $ind + 1
|
||||
while $i < $num
|
||||
set $p = (Bucket*)($ht->arData + $i)
|
||||
set $n = $ind
|
||||
if $p->val.u1.v.type > 0
|
||||
while $n > 0
|
||||
printf " "
|
||||
set $n = $n - 1
|
||||
end
|
||||
printf "[%d] ", $i
|
||||
if $p->key
|
||||
printf "%s => ", $p->key->val
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
if $arg1 == 0
|
||||
printf "%p\n", (zval *)&$p->val
|
||||
end
|
||||
if $arg1 == 1
|
||||
set $zval = (zval *)&$p->val
|
||||
____printzv $zval 1
|
||||
end
|
||||
if $arg1 == 2
|
||||
printf "%s\n", (char*)$p->val.value.ptr
|
||||
end
|
||||
if $arg1 == 3
|
||||
set $func = (zend_function*)$p->val.value.ptr
|
||||
printf "\"%s\"\n", $func->common.function_name->val
|
||||
end
|
||||
end
|
||||
set $i = $i + 1
|
||||
end
|
||||
set $ind = $ind - 1
|
||||
printf "}\n"
|
||||
end
|
||||
|
||||
define print_ht
|
||||
set $ind = 1
|
||||
printf "[%p] {\n", $arg0
|
||||
set $ind = 0
|
||||
____print_ht $arg0 1
|
||||
printf "}\n"
|
||||
end
|
||||
|
||||
document print_ht
|
||||
@@ -363,10 +354,8 @@ document print_ht
|
||||
end
|
||||
|
||||
define print_htptr
|
||||
set $ind = 1
|
||||
printf "[%p] {\n", $arg0
|
||||
set $ind = 0
|
||||
____print_ht $arg0 0
|
||||
printf "}\n"
|
||||
end
|
||||
|
||||
document print_htptr
|
||||
@@ -374,46 +363,17 @@ document print_htptr
|
||||
end
|
||||
|
||||
define print_htstr
|
||||
set $ind = 1
|
||||
printf "[%p] {\n", $arg0
|
||||
set $ind = 0
|
||||
____print_ht $arg0 2
|
||||
printf "}\n"
|
||||
end
|
||||
|
||||
document print_htstr
|
||||
dumps elements of HashTable made of strings
|
||||
end
|
||||
|
||||
define ____print_ft
|
||||
set $ht = $arg0
|
||||
set $p = $ht->pListHead
|
||||
|
||||
while $p != 0
|
||||
set $func = (zend_function*)$p->pData
|
||||
|
||||
set $i = $ind
|
||||
while $i > 0
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
|
||||
if $p->nKeyLength > 0
|
||||
____print_str $p->arKey $p->nKeyLength
|
||||
printf " => "
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
|
||||
printf "\"%s\"\n", $func->common.function_name
|
||||
set $p = $p->pListNext
|
||||
end
|
||||
end
|
||||
|
||||
define print_ft
|
||||
set $ind = 1
|
||||
printf "[%p] {\n", $arg0
|
||||
____print_ft $arg0
|
||||
printf "}\n"
|
||||
set $ind = 0
|
||||
____print_ht $arg0 3
|
||||
end
|
||||
|
||||
document print_ft
|
||||
@@ -429,15 +389,15 @@ define ____print_inh_class
|
||||
printf "final "
|
||||
end
|
||||
end
|
||||
printf "class %s", $ce->name
|
||||
printf "class %s", $ce->name->val
|
||||
if $ce->parent != 0
|
||||
printf " extends %s", $ce->parent->name
|
||||
printf " extends %s", $ce->parent->name->val
|
||||
end
|
||||
if $ce->num_interfaces != 0
|
||||
printf " implements"
|
||||
set $tmp = 0
|
||||
while $tmp < $ce->num_interfaces
|
||||
printf " %s", $ce->interfaces[$tmp]->name
|
||||
printf " %s", $ce->interfaces[$tmp]->name->val
|
||||
set $tmp = $tmp + 1
|
||||
if $tmp < $ce->num_interfaces
|
||||
printf ","
|
||||
@@ -449,10 +409,10 @@ end
|
||||
|
||||
define ____print_inh_iface
|
||||
set $ce = $arg0
|
||||
printf "interface %s", $ce->name
|
||||
printf "interface %s", $ce->name->val
|
||||
if $ce->num_interfaces != 0
|
||||
set $ce = $ce->interfaces[0]
|
||||
printf " extends %s", $ce->name
|
||||
printf " extends %s", $ce->name->val
|
||||
else
|
||||
set $ce = 0
|
||||
end
|
||||
@@ -516,7 +476,7 @@ define ____print_str
|
||||
set $tmp = 0
|
||||
set $str = $arg0
|
||||
printf "\""
|
||||
while $tmp < $arg1
|
||||
while $tmp < $arg1 && $tmp < 256
|
||||
if $str[$tmp] > 32 && $str[$tmp] < 127
|
||||
printf "%c", $str[$tmp]
|
||||
else
|
||||
@@ -524,6 +484,9 @@ define ____print_str
|
||||
end
|
||||
set $tmp = $tmp + 1
|
||||
end
|
||||
if $tmp != $arg1
|
||||
printf "..."
|
||||
end
|
||||
printf "\""
|
||||
end
|
||||
|
||||
@@ -618,9 +581,9 @@ define zmemcheck
|
||||
if $p->magic == 0xfb8277dc
|
||||
set $stat = "CACHED"
|
||||
end
|
||||
set $filename = strrchr($p->filename, '/')
|
||||
set $filename = strrchr($p->filename->val, '/')
|
||||
if !$filename
|
||||
set $filename = $p->filename
|
||||
set $filename = $p->filename->val
|
||||
else
|
||||
set $filename = $filename + 1
|
||||
end
|
||||
|
||||
@@ -4,6 +4,10 @@ php:
|
||||
# We only specify one version so we only get one worker
|
||||
- 5.4
|
||||
|
||||
branches:
|
||||
except:
|
||||
- phpng
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_failure: change
|
||||
|
||||
@@ -16,6 +16,8 @@ PHP NEWS
|
||||
- Standard:
|
||||
. Removed call_user_method() and call_user_method_array() functions. (Kalle)
|
||||
. Fix user session handlers (See rfc:session.user.return-value). (Sara)
|
||||
. Added intdiv() function. (Andrea)
|
||||
. Improved precision of log() function for base 2 and 10. (Marc Bennewitz)
|
||||
|
||||
- XSL:
|
||||
. Fixed bug #64776 (The XSLT extension is not thread safe). (Mike)
|
||||
|
||||
+2
-4
@@ -51,9 +51,7 @@ Currently we have the following branches in use::
|
||||
PHP-5.4 Is used to release the PHP 5.4.x series. This is a current
|
||||
stable version and is open for bugfixes only.
|
||||
|
||||
PHP-5.3 Is used to release the PHP 5.3.x series. This is currently
|
||||
in extended support and open forsecurity fixes only. Triaged
|
||||
via security@php.net
|
||||
PHP-5.3 This branch is closed.
|
||||
|
||||
PHP-5.2 This branch is closed.
|
||||
|
||||
@@ -63,7 +61,7 @@ Currently we have the following branches in use::
|
||||
|
||||
The next few rules are more of a technical nature::
|
||||
|
||||
1. All changes should first go to the lowest branch (i.e. 5.3) and then
|
||||
1. All changes should first go to the lowest branch (i.e. 5.4) and then
|
||||
get merged up to all other branches. If a change is not needed for
|
||||
later branches (i.e. fixes for features which where dropped from later
|
||||
branches) an empty merge should be done.
|
||||
|
||||
+18
-17
@@ -17,7 +17,7 @@ Online Forums
|
||||
-------------
|
||||
There are several IRC channels where PHP developers are often
|
||||
available to discuss questions. They include #php.pecl and #php.doc
|
||||
on the EFNet network and #php-dev-win on FreeNode.
|
||||
on the EFNet network and #winphp-dev on FreeNode.
|
||||
|
||||
|
||||
PHP Patches
|
||||
@@ -33,16 +33,27 @@ and discuss it on the development mail list internals@lists.php.net.
|
||||
RFC Wiki accounts can be requested on
|
||||
http://wiki.php.net/start?do=register. PHP extension maintainers can
|
||||
be found in the EXTENSIONS file in the PHP source. Mail list
|
||||
subscription is explained on http://www.php.net/mailing-lists.php.
|
||||
subscription is explained on http://php.net/mailing-lists.php.
|
||||
|
||||
Information on PHP internal C functions is at
|
||||
http://www.php.net/internals, though this is considered incomplete.
|
||||
Various external resources can be found on the web. A standard
|
||||
http://php.net/internals, though this is considered incomplete.
|
||||
Various external resources can be found on the web. See
|
||||
https://wiki.php.net/internals for some references. A standard
|
||||
printed reference is the book "Extending and Embedding PHP" by Sara
|
||||
Golemon.
|
||||
|
||||
Attach the patch to the PHP bug and consider sending a notification
|
||||
email about the change to internals@lists.php.net. Also CC the
|
||||
The preferred way to propose PHP patch is sending pull request from
|
||||
GitHub: https://github.com/php/php-src
|
||||
|
||||
Fork the official PHP repository and send a pull request. A
|
||||
notification will be sent to the pull request mailing list. Sending a
|
||||
note to PHP Internals list (internals@lists.php.net) may help getting
|
||||
more feedback and quicker turnaround. You can also add pull requests
|
||||
to bug reports at http://bugs.php.net/.
|
||||
|
||||
If you are not using GitHub, attach your patch to a PHP bug and
|
||||
consider sending a notification email about the change to
|
||||
internals@lists.php.net. If the bug is for an extension, also CC the
|
||||
extension maintainer. Explain what has been changed by your patch.
|
||||
Test scripts should be included.
|
||||
|
||||
@@ -50,16 +61,6 @@ Please make the mail subject prefix "[PATCH]". If attaching a patch,
|
||||
ensure it has a file extension of ".txt". This is because only MIME
|
||||
attachments of type 'text/*' are accepted.
|
||||
|
||||
The preferred way to propose PHP patch is sending pull request from
|
||||
github.
|
||||
|
||||
https://github.com/php/php-src
|
||||
|
||||
Fork the official PHP repository and send a pull request. A
|
||||
notification will be sent to the pull request mailing list. Sending a
|
||||
note to PHP Internals list (internals@lists.php.net) may help getting
|
||||
more feedback and quicker turnaround. You can also add pull requests
|
||||
to bug reports at http://bugs.php.net/.
|
||||
|
||||
|
||||
PHP Documentation Patches
|
||||
@@ -71,7 +72,7 @@ the PHP mail archives.
|
||||
|
||||
If your change is large, then first discuss it with the mail list
|
||||
phpdoc@lists.php.net. Subscription is explained on
|
||||
http://www.php.net/mailing-lists.php.
|
||||
http://php.net/mailing-lists.php.
|
||||
|
||||
Information on contributing to PHP documentation is at
|
||||
http://php.net/dochowto and http://wiki.php.net/doc/howto
|
||||
|
||||
@@ -28,6 +28,8 @@ PHP X.Y UPGRADE NOTES
|
||||
2. New Features
|
||||
========================================
|
||||
|
||||
- Standard
|
||||
. intdiv() function for integer division added.
|
||||
|
||||
========================================
|
||||
3. Changes in SAPI modules
|
||||
@@ -69,7 +71,7 @@ PHP X.Y UPGRADE NOTES
|
||||
========================================
|
||||
|
||||
- Core
|
||||
, PHP_INT_MIN added.
|
||||
. PHP_INT_MIN added.
|
||||
|
||||
========================================
|
||||
11. Changes to INI File Handling
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ int(0)
|
||||
int(2)
|
||||
int(0)
|
||||
|
||||
Warning: Missing argument 2 for test3() in %s on line %d
|
||||
Warning: Missing argument 2 for test3()%s
|
||||
int(1)
|
||||
int(2)
|
||||
int(1)
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ bool(false)
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Missing argument 2 for test3() in %s on line %d
|
||||
Warning: Missing argument 2 for test3()%s
|
||||
int(1)
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ array(2) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Missing argument 2 for test3() in %s on line %d
|
||||
Warning: Missing argument 2 for test3()%s
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Identical comparison of array with references
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$foo = 42;
|
||||
$array1 = [&$foo];
|
||||
$array2 = [$foo];
|
||||
var_dump($array1 === $array2);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
@@ -6,4 +6,4 @@ Bug #24773 (unset() of integers treated as arrays causes a crash)
|
||||
unset($array["lvl1"]["lvl2"]["b"]);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot unset string offsets in %s on line %d
|
||||
Fatal error: Cannot use string offset as an array in %s on line %d
|
||||
|
||||
@@ -42,7 +42,6 @@ $page["name"] = A::A_ftk();
|
||||
Non-static method A::A_ftk() should not be called statically
|
||||
1 %sbug38047.php:13 get_error_context()
|
||||
2 %sbug38047.php:36 kalus_error_handler()
|
||||
3 %sbug38047.php:36 A_ftk()
|
||||
|
||||
Missing argument 1 for A::A_ftk(), called in %sbug38047.php on line 36 and defined
|
||||
1 %sbug38047.php:13 get_error_context()
|
||||
|
||||
@@ -25,7 +25,7 @@ try {
|
||||
--EXPECTF--
|
||||
1. exception 'Exception' with message 'aaa' in %sbug52361.php:5
|
||||
Stack trace:
|
||||
#0 %sbug52361.php(16): aaa->__destruct()
|
||||
#0 %sbug52361.php(13): aaa->__destruct()
|
||||
#1 %sbug52361.php(16): bbb()
|
||||
#2 {main}
|
||||
2. exception 'Exception' with message 'bbb' in %sbug52361.php:13
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Bug #54013 (ReflectionParam for duplicate parameter contains garbage)
|
||||
Bug #54013 (ReflectionParam for duplicate parameter contains garbage) (PHP7)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
@@ -21,11 +21,4 @@ var_dump($params[0], $params[1]);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(ReflectionParameter)#%d (1) {
|
||||
["name"]=>
|
||||
string(8) "aaaaaaaa"
|
||||
}
|
||||
object(ReflectionParameter)#%d (1) {
|
||||
["name"]=>
|
||||
string(8) "aaaaaaaa"
|
||||
}
|
||||
Fatal error: Redefinition of parameter aaaaaaaa in %sbug54013.php on line 5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Bug #64515 (Memoryleak when using the same variablename 2times in function declaration)
|
||||
Bug #64515 (Memoryleak when using the same variablename 2times in function declaration) (PHP7)
|
||||
--FILE--
|
||||
<?php
|
||||
function foo($unused = null, $unused = null, $arg = array()) {
|
||||
@@ -8,5 +8,5 @@ function foo($unused = null, $unused = null, $arg = array()) {
|
||||
foo();
|
||||
echo "okey";
|
||||
?>
|
||||
--EXPECT--
|
||||
okey
|
||||
--EXPECTF--
|
||||
Fatal error: Redefinition of parameter unused in %sbug64515.php on line 2
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
--TEST--
|
||||
Bug #64896 (Segfault with gc_collect_cycles using unserialize on certain objects)
|
||||
--XFAIL--
|
||||
We can not fix this bug without a significant (performace slow down) change to gc
|
||||
--FILE--
|
||||
<?php
|
||||
$bar = NULL;
|
||||
@@ -38,7 +36,7 @@ object(bad)#4 (1) {
|
||||
*/
|
||||
?>
|
||||
--EXPECTF--
|
||||
bject(bad)#%d (1) {
|
||||
object(bad)#%d (1) {
|
||||
["_private":"bad":private]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
|
||||
@@ -11,7 +11,8 @@ class Test
|
||||
protected static $array = [
|
||||
self::FIRST => 'first',
|
||||
'second',
|
||||
'third'
|
||||
'third',
|
||||
4,
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
@@ -22,9 +23,13 @@ class Test
|
||||
|
||||
$test = new Test();
|
||||
?>
|
||||
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
array (
|
||||
1 => 'first',
|
||||
2 => 'second',
|
||||
3 => 'third',
|
||||
4 => 4,
|
||||
)
|
||||
===DONE===
|
||||
|
||||
@@ -13,6 +13,6 @@ call_user_func(array('foo', 'teste'));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method foo::teste() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method foo::teste() should not be called statically in %s on line %d
|
||||
|
||||
Fatal error: Using $this when not in object context in %s on line %d
|
||||
|
||||
@@ -18,7 +18,7 @@ var_dump(call_user_func(array('foo', 'teste')));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method foo::teste() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method foo::teste() should not be called statically in %s on line %d
|
||||
%string|unicode%(1) "x"
|
||||
array(1) {
|
||||
[0]=>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Conversion of a class constant to a reference after it has been cached
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Test {
|
||||
const TEST = 'TEST';
|
||||
|
||||
private $prop;
|
||||
|
||||
public function readConst() {
|
||||
$this->prop = self::TEST;
|
||||
}
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
$obj = new Test;
|
||||
$obj->readConst();
|
||||
unset($obj);
|
||||
var_dump(Test::TEST);
|
||||
}
|
||||
|
||||
doTest();
|
||||
eval('class Test2 extends Test {}');
|
||||
doTest();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(4) "TEST"
|
||||
string(4) "TEST"
|
||||
@@ -6,9 +6,7 @@ errmsg: arrays are not allowed in class constants
|
||||
class test {
|
||||
const TEST = array(1,2,3);
|
||||
}
|
||||
|
||||
var_dump(test::TEST);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
||||
@@ -105,7 +105,7 @@ Hello, you
|
||||
Notice: Undefined variable: this in %s on line %d
|
||||
NULL
|
||||
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method Hello::world() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method Hello::world() should not be called statically in %s on line %d
|
||||
Hello, you
|
||||
|
||||
Notice: Undefined variable: this in %s on line %d
|
||||
|
||||
@@ -16,5 +16,5 @@ var_dump(gc_collect_cycles());
|
||||
echo "ok\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
int(10002)
|
||||
int(2)
|
||||
ok
|
||||
|
||||
@@ -33,5 +33,5 @@ unset($foo);
|
||||
unset($bar);
|
||||
var_dump(gc_collect_cycles());
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
--EXPECTREGEX--
|
||||
int\([23]\)
|
||||
|
||||
@@ -28,6 +28,7 @@ Stack trace:
|
||||
|
||||
Next exception 'Exception' with message 'foobar' in %sgc_030.php:%d
|
||||
Stack trace:
|
||||
#0 %sgc_030.php(%d): foo->__destruct()
|
||||
#1 {main}
|
||||
#0 [internal function]: foo->__destruct()
|
||||
#1 %sgc_030.php(%d): gc_collect_cycles()
|
||||
#2 {main}
|
||||
thrown in %sgc_030.php on line %d
|
||||
|
||||
@@ -11,26 +11,26 @@ $b =& $a;
|
||||
$a[0][0] = $a;
|
||||
debug_zval_dump($a);
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) refcount(1){
|
||||
--EXPECTF--
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
*RECURSION*
|
||||
}
|
||||
}
|
||||
}
|
||||
array(1) refcount(1){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(1){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(1){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
*RECURSION*
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ foreach ($gen as &$value) { }
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): unknown()
|
||||
#1 {main}
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ Stack trace:
|
||||
|
||||
exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): unknown()
|
||||
#1 {main}
|
||||
#0 {main}
|
||||
|
||||
in generator
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
--FILE--
|
||||
<?php
|
||||
const C = array();
|
||||
|
||||
var_dump(C);
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(0) {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Inc/dec of reference object properties
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$obj = new stdClass;
|
||||
$obj->cursor = 0;
|
||||
$ref =& $obj->cursor;
|
||||
|
||||
$obj->cursor++;
|
||||
var_dump($obj->cursor);
|
||||
|
||||
$obj->cursor--;
|
||||
var_dump($obj->cursor);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(0)
|
||||
@@ -35,7 +35,7 @@ object(foo)#%d (0) {
|
||||
object(foo)#%d (0) {
|
||||
}
|
||||
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method foo::test() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method foo::test() should not be called statically in %s on line %d
|
||||
|
||||
Strict Standards: Non-static method bar::show() should not be called statically in %s on line %d
|
||||
object(foo)#%d (0) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Use power operator on reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$a = 2;
|
||||
$b = 3;
|
||||
|
||||
$ref =& $b;
|
||||
|
||||
$a **= $b;
|
||||
|
||||
var_dump($a);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(8)
|
||||
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Throw reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$e = new Exception;
|
||||
$ref =& $e;
|
||||
throw $e;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'Exception' in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
+267
-276
@@ -55,6 +55,7 @@ ZEND_API void (*zend_unblock_interruptions)(void);
|
||||
ZEND_API void (*zend_ticks_function)(int ticks TSRMLS_DC);
|
||||
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
|
||||
int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
|
||||
zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
|
||||
ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
|
||||
ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
|
||||
|
||||
@@ -123,8 +124,6 @@ static HashTable *global_persistent_list = NULL;
|
||||
|
||||
ZEND_API zend_utility_values zend_uv;
|
||||
|
||||
ZEND_API zval zval_used_for_init; /* True global variable */
|
||||
|
||||
/* version information */
|
||||
static char *zend_version_info;
|
||||
static uint zend_version_info_length;
|
||||
@@ -133,11 +132,9 @@ static uint zend_version_info_length;
|
||||
|
||||
static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent, zend_bool is_object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **tmp;
|
||||
char *string_key;
|
||||
HashPosition iterator;
|
||||
zval *tmp;
|
||||
zend_string *string_key;
|
||||
ulong num_key;
|
||||
uint str_len;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < indent; i++) {
|
||||
@@ -145,46 +142,45 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
|
||||
}
|
||||
ZEND_PUTS_EX("(\n");
|
||||
indent += PRINT_ZVAL_INDENT;
|
||||
zend_hash_internal_pointer_reset_ex(ht, &iterator);
|
||||
while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
|
||||
ZEND_HASH_FOREACH_KEY_VAL(ht, num_key, string_key, tmp) {
|
||||
if (Z_TYPE_P(tmp) == IS_INDIRECT) {
|
||||
tmp = Z_INDIRECT_P(tmp);
|
||||
if (Z_TYPE_P(tmp) == IS_UNDEF) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < indent; i++) {
|
||||
ZEND_PUTS_EX(" ");
|
||||
}
|
||||
ZEND_PUTS_EX("[");
|
||||
switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
|
||||
case HASH_KEY_IS_STRING:
|
||||
if (is_object) {
|
||||
const char *prop_name, *class_name;
|
||||
int prop_len;
|
||||
int mangled = zend_unmangle_property_name_ex(string_key, str_len - 1, &class_name, &prop_name, &prop_len);
|
||||
if (string_key) {
|
||||
if (is_object) {
|
||||
const char *prop_name, *class_name;
|
||||
int prop_len;
|
||||
int mangled = zend_unmangle_property_name_ex(string_key->val, string_key->len, &class_name, &prop_name, &prop_len);
|
||||
|
||||
ZEND_WRITE_EX(prop_name, prop_len);
|
||||
if (class_name && mangled == SUCCESS) {
|
||||
if (class_name[0]=='*') {
|
||||
ZEND_PUTS_EX(":protected");
|
||||
} else {
|
||||
ZEND_PUTS_EX(":");
|
||||
ZEND_PUTS_EX(class_name);
|
||||
ZEND_PUTS_EX(":private");
|
||||
}
|
||||
ZEND_WRITE_EX(prop_name, prop_len);
|
||||
if (class_name && mangled == SUCCESS) {
|
||||
if (class_name[0]=='*') {
|
||||
ZEND_PUTS_EX(":protected");
|
||||
} else {
|
||||
ZEND_PUTS_EX(":");
|
||||
ZEND_PUTS_EX(class_name);
|
||||
ZEND_PUTS_EX(":private");
|
||||
}
|
||||
} else {
|
||||
ZEND_WRITE_EX(string_key, str_len-1);
|
||||
}
|
||||
break;
|
||||
case HASH_KEY_IS_LONG:
|
||||
{
|
||||
char key[25];
|
||||
snprintf(key, sizeof(key), "%ld", num_key);
|
||||
ZEND_PUTS_EX(key);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
ZEND_WRITE_EX(string_key->val, string_key->len);
|
||||
}
|
||||
} else {
|
||||
char key[25];
|
||||
snprintf(key, sizeof(key), "%ld", num_key);
|
||||
ZEND_PUTS_EX(key);
|
||||
}
|
||||
ZEND_PUTS_EX("] => ");
|
||||
zend_print_zval_r_ex(write_func, *tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC);
|
||||
zend_print_zval_r_ex(write_func, tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC);
|
||||
ZEND_PUTS_EX("\n");
|
||||
zend_hash_move_forward_ex(ht, &iterator);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
indent -= PRINT_ZVAL_INDENT;
|
||||
for (i = 0; i < indent; i++) {
|
||||
ZEND_PUTS_EX(" ");
|
||||
@@ -195,145 +191,124 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
|
||||
|
||||
static void print_flat_hash(HashTable *ht TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **tmp;
|
||||
char *string_key;
|
||||
HashPosition iterator;
|
||||
zval *tmp;
|
||||
zend_string *string_key;
|
||||
ulong num_key;
|
||||
uint str_len;
|
||||
int i = 0;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(ht, &iterator);
|
||||
while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
|
||||
ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) {
|
||||
if (i++ > 0) {
|
||||
ZEND_PUTS(",");
|
||||
}
|
||||
ZEND_PUTS("[");
|
||||
switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
|
||||
case HASH_KEY_IS_STRING:
|
||||
ZEND_PUTS(string_key);
|
||||
break;
|
||||
case HASH_KEY_IS_LONG:
|
||||
zend_printf("%ld", num_key);
|
||||
break;
|
||||
if (string_key) {
|
||||
ZEND_WRITE(string_key->val, string_key->len);
|
||||
} else {
|
||||
zend_printf("%ld", num_key);
|
||||
}
|
||||
ZEND_PUTS("] => ");
|
||||
zend_print_flat_zval_r(*tmp TSRMLS_CC);
|
||||
zend_hash_move_forward_ex(ht, &iterator);
|
||||
}
|
||||
zend_print_flat_zval_r(tmp TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) /* {{{ */
|
||||
ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (Z_TYPE_P(expr)==IS_STRING) {
|
||||
*use_copy = 0;
|
||||
return;
|
||||
if (Z_TYPE_P(expr) == IS_STRING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
again:
|
||||
switch (Z_TYPE_P(expr)) {
|
||||
case IS_NULL:
|
||||
Z_STRLEN_P(expr_copy) = 0;
|
||||
Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC();
|
||||
break;
|
||||
case IS_BOOL:
|
||||
if (Z_LVAL_P(expr)) {
|
||||
Z_STRLEN_P(expr_copy) = 1;
|
||||
Z_STRVAL_P(expr_copy) = estrndup("1", 1);
|
||||
case IS_FALSE:
|
||||
ZVAL_EMPTY_STRING(expr_copy);
|
||||
break;
|
||||
case IS_TRUE:
|
||||
if (CG(one_char_string)['1']) {
|
||||
ZVAL_INT_STR(expr_copy, CG(one_char_string)['1']);
|
||||
} else {
|
||||
Z_STRLEN_P(expr_copy) = 0;
|
||||
Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC();
|
||||
ZVAL_NEW_STR(expr_copy, STR_INIT("1", 1, 0));
|
||||
}
|
||||
break;
|
||||
case IS_RESOURCE: {
|
||||
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "Resource id #%ld", Z_RES_HANDLE_P(expr));
|
||||
ZVAL_NEW_STR(expr_copy, STR_INIT(buf, len, 0));
|
||||
}
|
||||
break;
|
||||
case IS_RESOURCE:
|
||||
Z_STRVAL_P(expr_copy) = (char *) emalloc(sizeof("Resource id #") - 1 + MAX_LENGTH_OF_LONG);
|
||||
Z_STRLEN_P(expr_copy) = snprintf(Z_STRVAL_P(expr_copy), sizeof("Resource id #") - 1 + MAX_LENGTH_OF_LONG, "Resource id #%ld", Z_LVAL_P(expr));
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
zend_error(E_NOTICE, "Array to string conversion");
|
||||
Z_STRLEN_P(expr_copy) = sizeof("Array") - 1;
|
||||
Z_STRVAL_P(expr_copy) = estrndup("Array", Z_STRLEN_P(expr_copy));
|
||||
// TODO: use interned string ???
|
||||
ZVAL_NEW_STR(expr_copy, STR_INIT("Array", sizeof("Array") - 1, 0));
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)) {
|
||||
Z_ADDREF_P(expr);
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
|
||||
zval_ptr_dtor(expr);
|
||||
break;
|
||||
}
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)) {
|
||||
zval *val;
|
||||
|
||||
ALLOC_ZVAL(val);
|
||||
INIT_PZVAL_COPY(val, expr);
|
||||
zval_copy_ctor(val);
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)(val, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
|
||||
zval_ptr_dtor(&val);
|
||||
break;
|
||||
}
|
||||
zval_ptr_dtor(&val);
|
||||
}
|
||||
if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) {
|
||||
zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
|
||||
|
||||
Z_ADDREF_P(z);
|
||||
if (Z_TYPE_P(z) != IS_OBJECT) {
|
||||
zend_make_printable_zval(z, expr_copy, use_copy);
|
||||
if (*use_copy) {
|
||||
zval_ptr_dtor(&z);
|
||||
} else {
|
||||
ZVAL_ZVAL(expr_copy, z, 0, 1);
|
||||
*use_copy = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
zval_ptr_dtor(&z);
|
||||
}
|
||||
zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name);
|
||||
Z_STRLEN_P(expr_copy) = 0;
|
||||
Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC();
|
||||
zval_ptr_dtor(expr);
|
||||
}
|
||||
if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) {
|
||||
zval rv;
|
||||
zval *z = Z_OBJ_HANDLER_P(expr, get)(expr, &rv TSRMLS_CC);
|
||||
|
||||
Z_ADDREF_P(z);
|
||||
if (Z_TYPE_P(z) != IS_OBJECT) {
|
||||
if (zend_make_printable_zval(z, expr_copy TSRMLS_CC)) {
|
||||
zval_ptr_dtor(z);
|
||||
} else {
|
||||
ZVAL_ZVAL(expr_copy, z, 0, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
zval_ptr_dtor(z);
|
||||
}
|
||||
zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name->val);
|
||||
ZVAL_EMPTY_STRING(expr_copy);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
*expr_copy = *expr;
|
||||
zval_copy_ctor(expr_copy);
|
||||
ZVAL_DUP(expr_copy, expr);
|
||||
zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC);
|
||||
break;
|
||||
case IS_REFERENCE:
|
||||
expr = Z_REFVAL_P(expr);
|
||||
if (Z_TYPE_P(expr) == IS_STRING) {
|
||||
ZVAL_STR(expr_copy, STR_COPY(Z_STR_P(expr)));
|
||||
return 1;
|
||||
}
|
||||
goto again;
|
||||
break;
|
||||
default:
|
||||
*expr_copy = *expr;
|
||||
zval_copy_ctor(expr_copy);
|
||||
ZVAL_DUP(expr_copy, expr);
|
||||
convert_to_string(expr_copy);
|
||||
break;
|
||||
}
|
||||
Z_TYPE_P(expr_copy) = IS_STRING;
|
||||
*use_copy = 1;
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_print_zval(zval *expr, int indent) /* {{{ */
|
||||
ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return zend_print_zval_ex(zend_write, expr, indent);
|
||||
return zend_print_zval_ex(zend_write, expr, indent TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent) /* {{{ */
|
||||
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval expr_copy;
|
||||
int use_copy;
|
||||
zend_string *str = zval_get_string(expr);
|
||||
int len = str->len;
|
||||
|
||||
zend_make_printable_zval(expr, &expr_copy, &use_copy);
|
||||
if (use_copy) {
|
||||
expr = &expr_copy;
|
||||
if (len != 0) {
|
||||
write_func(str->val, len);
|
||||
}
|
||||
if (Z_STRLEN_P(expr) == 0) { /* optimize away empty strings */
|
||||
if (use_copy) {
|
||||
zval_dtor(expr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
write_func(Z_STRVAL_P(expr), Z_STRLEN_P(expr));
|
||||
if (use_copy) {
|
||||
zval_dtor(expr);
|
||||
}
|
||||
return Z_STRLEN_P(expr);
|
||||
|
||||
STR_RELEASE(str);
|
||||
return len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -342,49 +317,51 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */
|
||||
switch (Z_TYPE_P(expr)) {
|
||||
case IS_ARRAY:
|
||||
ZEND_PUTS("Array (");
|
||||
if (++Z_ARRVAL_P(expr)->nApplyCount>1) {
|
||||
if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) &&
|
||||
++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) {
|
||||
ZEND_PUTS(" *RECURSION*");
|
||||
Z_ARRVAL_P(expr)->nApplyCount--;
|
||||
Z_ARRVAL_P(expr)->u.v.nApplyCount--;
|
||||
return;
|
||||
}
|
||||
print_flat_hash(Z_ARRVAL_P(expr) TSRMLS_CC);
|
||||
ZEND_PUTS(")");
|
||||
Z_ARRVAL_P(expr)->nApplyCount--;
|
||||
if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) {
|
||||
Z_ARRVAL_P(expr)->u.v.nApplyCount--;
|
||||
}
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
{
|
||||
HashTable *properties = NULL;
|
||||
const char *class_name = NULL;
|
||||
zend_uint clen;
|
||||
zend_string *class_name = NULL;
|
||||
|
||||
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
|
||||
Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
|
||||
class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr), 0 TSRMLS_CC);
|
||||
}
|
||||
if (class_name) {
|
||||
zend_printf("%s Object (", class_name);
|
||||
zend_printf("%s Object (", class_name->val);
|
||||
} else {
|
||||
zend_printf("%s Object (", "Unknown Class");
|
||||
}
|
||||
if (class_name) {
|
||||
efree((char*)class_name);
|
||||
STR_RELEASE(class_name);
|
||||
}
|
||||
if (Z_OBJ_HANDLER_P(expr, get_properties)) {
|
||||
properties = Z_OBJPROP_P(expr);
|
||||
}
|
||||
if (properties) {
|
||||
if (++properties->nApplyCount>1) {
|
||||
if (++properties->u.v.nApplyCount>1) {
|
||||
ZEND_PUTS(" *RECURSION*");
|
||||
properties->nApplyCount--;
|
||||
properties->u.v.nApplyCount--;
|
||||
return;
|
||||
}
|
||||
print_flat_hash(properties TSRMLS_CC);
|
||||
properties->nApplyCount--;
|
||||
properties->u.v.nApplyCount--;
|
||||
}
|
||||
ZEND_PUTS(")");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zend_print_variable(expr);
|
||||
zend_print_variable(expr TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -398,54 +375,57 @@ ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC) /* {{{ */
|
||||
|
||||
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZVAL_DEREF(expr);
|
||||
switch (Z_TYPE_P(expr)) {
|
||||
case IS_ARRAY:
|
||||
ZEND_PUTS_EX("Array\n");
|
||||
if (++Z_ARRVAL_P(expr)->nApplyCount>1) {
|
||||
if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) &&
|
||||
++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) {
|
||||
ZEND_PUTS_EX(" *RECURSION*");
|
||||
Z_ARRVAL_P(expr)->nApplyCount--;
|
||||
Z_ARRVAL_P(expr)->u.v.nApplyCount--;
|
||||
return;
|
||||
}
|
||||
print_hash(write_func, Z_ARRVAL_P(expr), indent, 0 TSRMLS_CC);
|
||||
Z_ARRVAL_P(expr)->nApplyCount--;
|
||||
if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) {
|
||||
Z_ARRVAL_P(expr)->u.v.nApplyCount--;
|
||||
}
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
{
|
||||
HashTable *properties;
|
||||
const char *class_name = NULL;
|
||||
zend_uint clen;
|
||||
zend_string *class_name = NULL;
|
||||
int is_temp;
|
||||
|
||||
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
|
||||
Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
|
||||
class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr), 0 TSRMLS_CC);
|
||||
}
|
||||
if (class_name) {
|
||||
ZEND_PUTS_EX(class_name);
|
||||
ZEND_PUTS_EX(class_name->val);
|
||||
} else {
|
||||
ZEND_PUTS_EX("Unknown Class");
|
||||
}
|
||||
ZEND_PUTS_EX(" Object\n");
|
||||
if (class_name) {
|
||||
efree((char*)class_name);
|
||||
STR_RELEASE(class_name);
|
||||
}
|
||||
if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
|
||||
break;
|
||||
}
|
||||
if (++properties->nApplyCount>1) {
|
||||
if (++properties->u.v.nApplyCount>1) {
|
||||
ZEND_PUTS_EX(" *RECURSION*");
|
||||
properties->nApplyCount--;
|
||||
properties->u.v.nApplyCount--;
|
||||
return;
|
||||
}
|
||||
print_hash(write_func, properties, indent, 1 TSRMLS_CC);
|
||||
properties->nApplyCount--;
|
||||
properties->u.v.nApplyCount--;
|
||||
if (is_temp) {
|
||||
zend_hash_destroy(properties);
|
||||
efree(properties);
|
||||
FREE_HASHTABLE(properties);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zend_print_zval_ex(write_func, expr, indent);
|
||||
zend_print_zval_ex(write_func, expr, indent TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -501,20 +481,25 @@ static void zend_init_exception_op(TSRMLS_D) /* {{{ */
|
||||
/* }}} */
|
||||
|
||||
#ifdef ZTS
|
||||
static void function_copy_ctor(zval *zv)
|
||||
{
|
||||
zend_function *old_func = Z_FUNC_P(zv);
|
||||
Z_FUNC_P(zv) = pemalloc(sizeof(zend_internal_function), 1);
|
||||
memcpy(Z_FUNC_P(zv), old_func, sizeof(zend_internal_function));
|
||||
function_add_ref(Z_FUNC_P(zv));
|
||||
}
|
||||
|
||||
static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function tmp_func;
|
||||
zend_class_entry *tmp_class;
|
||||
|
||||
compiler_globals->compiled_filename = NULL;
|
||||
|
||||
compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
|
||||
zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||||
zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function));
|
||||
zend_hash_init_ex(compiler_globals->function_table, 1024, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||||
zend_hash_copy(compiler_globals->function_table, global_function_table, function_copy_ctor);
|
||||
|
||||
compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
|
||||
zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
|
||||
zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *));
|
||||
zend_hash_init_ex(compiler_globals->class_table, 64, NULL, ZEND_CLASS_DTOR, 1, 0);
|
||||
zend_hash_copy(compiler_globals->class_table, global_class_table, zend_class_add_ref);
|
||||
|
||||
zend_set_default_compile_time_values(TSRMLS_C);
|
||||
|
||||
@@ -522,7 +507,7 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS
|
||||
|
||||
compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
|
||||
zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0);
|
||||
zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL, NULL, sizeof(zend_auto_global) /* empty element */);
|
||||
zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL /* empty element */);
|
||||
|
||||
compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table);
|
||||
if (compiler_globals->last_static_member) {
|
||||
@@ -552,7 +537,7 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS
|
||||
free(compiler_globals->static_members_table);
|
||||
}
|
||||
if (compiler_globals->script_encoding_list) {
|
||||
pefree(compiler_globals->script_encoding_list, 1);
|
||||
pefree((char*)compiler_globals->script_encoding_list, 1);
|
||||
}
|
||||
compiler_globals->last_static_member = 0;
|
||||
}
|
||||
@@ -565,9 +550,8 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS
|
||||
zend_init_rsrc_plist(TSRMLS_C);
|
||||
zend_init_exception_op(TSRMLS_C);
|
||||
EG(lambda_count) = 0;
|
||||
EG(user_error_handler) = NULL;
|
||||
EG(user_exception_handler) = NULL;
|
||||
EG(in_execution) = 0;
|
||||
ZVAL_UNDEF(&EG(user_error_handler));
|
||||
ZVAL_UNDEF(&EG(user_exception_handler));
|
||||
EG(in_autoload) = NULL;
|
||||
EG(current_execute_data) = NULL;
|
||||
EG(current_module) = NULL;
|
||||
@@ -621,16 +605,28 @@ static void php_scanner_globals_ctor(zend_php_scanner_globals *scanner_globals_p
|
||||
|
||||
void zend_init_opcodes_handlers(void);
|
||||
|
||||
static zend_bool php_auto_globals_create_globals(const char *name, uint name_len TSRMLS_DC) /* {{{ */
|
||||
static void module_destructor_zval(zval *zv) /* {{{ */
|
||||
{
|
||||
zval *globals;
|
||||
zend_module_entry *module = (zend_module_entry*)Z_PTR_P(zv);
|
||||
|
||||
ALLOC_ZVAL(globals);
|
||||
Z_SET_REFCOUNT_P(globals, 1);
|
||||
Z_SET_ISREF_P(globals);
|
||||
Z_TYPE_P(globals) = IS_ARRAY;
|
||||
Z_ARRVAL_P(globals) = &EG(symbol_table);
|
||||
zend_hash_update(&EG(symbol_table), name, name_len + 1, &globals, sizeof(zval *), NULL);
|
||||
module_destructor(module);
|
||||
free(module);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void auto_global_dtor(zval *zv) /* {{{ */
|
||||
{
|
||||
free(Z_PTR_P(zv));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool php_auto_globals_create_globals(zend_string *name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval globals;
|
||||
|
||||
ZVAL_ARR(&globals, &EG(symbol_table));
|
||||
ZVAL_NEW_REF(&globals, &globals);
|
||||
zend_hash_update(&EG(symbol_table).ht, name, &globals);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -677,6 +673,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
|
||||
zend_ticks_function = utility_functions->ticks_function;
|
||||
zend_on_timeout = utility_functions->on_timeout;
|
||||
zend_vspprintf = utility_functions->vspprintf_function;
|
||||
zend_vstrpprintf = utility_functions->vstrpprintf_function;
|
||||
zend_getenv = utility_functions->getenv_function;
|
||||
zend_resolve_path = utility_functions->resolve_path_function;
|
||||
|
||||
@@ -704,19 +701,14 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
|
||||
GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
|
||||
GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));
|
||||
|
||||
zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 1024, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_CLASS_TABLE, 64, NULL, ZEND_CLASS_DTOR, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, auto_global_dtor, 1, 0);
|
||||
zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 128, NULL, ZEND_CONSTANT_DTOR, 1, 0);
|
||||
|
||||
zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
|
||||
zend_hash_init_ex(&module_registry, 32, NULL, module_destructor_zval, 1, 0);
|
||||
zend_init_rsrc_list_dtors();
|
||||
|
||||
/* This zval can be used to initialize allocate zval's to an uninit'ed value */
|
||||
Z_UNSET_ISREF(zval_used_for_init);
|
||||
Z_SET_REFCOUNT(zval_used_for_init, 1);
|
||||
Z_TYPE(zval_used_for_init) = IS_NULL;
|
||||
|
||||
#ifdef ZTS
|
||||
ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
|
||||
ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
|
||||
@@ -740,14 +732,14 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
|
||||
ini_scanner_globals_ctor(&ini_scanner_globals TSRMLS_CC);
|
||||
php_scanner_globals_ctor(&language_scanner_globals TSRMLS_CC);
|
||||
zend_set_default_compile_time_values(TSRMLS_C);
|
||||
EG(user_error_handler) = NULL;
|
||||
EG(user_exception_handler) = NULL;
|
||||
ZVAL_UNDEF(&EG(user_error_handler));
|
||||
ZVAL_UNDEF(&EG(user_exception_handler));
|
||||
#endif
|
||||
|
||||
zend_interned_strings_init(TSRMLS_C);
|
||||
zend_startup_builtin_functions(TSRMLS_C);
|
||||
zend_register_standard_constants(TSRMLS_C);
|
||||
zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, 1, php_auto_globals_create_globals TSRMLS_CC);
|
||||
zend_register_auto_global(STR_INIT("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals TSRMLS_CC);
|
||||
|
||||
#ifndef ZTS
|
||||
zend_init_rsrc_plist(TSRMLS_C);
|
||||
@@ -880,7 +872,7 @@ ZEND_API void _zend_bailout(char *filename, uint lineno) /* {{{ */
|
||||
}
|
||||
CG(unclean_shutdown) = 1;
|
||||
CG(active_class_entry) = NULL;
|
||||
CG(in_compilation) = EG(in_execution) = 0;
|
||||
CG(in_compilation) = 0;
|
||||
EG(current_execute_data) = NULL;
|
||||
LONGJMP(*EG(bailout), FAILURE);
|
||||
}
|
||||
@@ -938,8 +930,7 @@ void zend_call_destructors(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_deactivate(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
/* we're no longer executing anything */
|
||||
EG(opline_ptr) = NULL;
|
||||
EG(active_symbol_table) = NULL;
|
||||
EG(current_execute_data) = NULL;
|
||||
|
||||
zend_try {
|
||||
shutdown_scanner(TSRMLS_C);
|
||||
@@ -1019,14 +1010,15 @@ ZEND_API int zend_get_configuration_directive(const char *name, uint name_length
|
||||
|
||||
ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
{
|
||||
char *str;
|
||||
int len;
|
||||
va_list args;
|
||||
va_list usr_copy;
|
||||
zval ***params;
|
||||
zval *retval;
|
||||
zval *z_error_type, *z_error_message, *z_error_filename, *z_error_lineno, *z_context;
|
||||
zval params[5];
|
||||
zval retval;
|
||||
const char *error_filename;
|
||||
uint error_lineno;
|
||||
zval *orig_user_error_handler;
|
||||
uint error_lineno = 0;
|
||||
zval orig_user_error_handler;
|
||||
zend_bool in_compilation;
|
||||
zend_class_entry *saved_class_entry;
|
||||
zend_stack bp_stack;
|
||||
@@ -1037,10 +1029,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
zend_stack declare_stack;
|
||||
zend_stack list_stack;
|
||||
zend_stack context_stack;
|
||||
zend_array *symbol_table;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
/* Report about uncaught exception in case of fatal errors */
|
||||
if (EG(exception)) {
|
||||
zend_execute_data *ex;
|
||||
zend_op *opline;
|
||||
|
||||
switch (type) {
|
||||
case E_CORE_ERROR:
|
||||
case E_ERROR:
|
||||
@@ -1048,13 +1044,19 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
case E_PARSE:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_USER_ERROR:
|
||||
if (zend_is_executing(TSRMLS_C)) {
|
||||
error_lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
ex = EG(current_execute_data);
|
||||
opline = NULL;
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
|
||||
EG(opline_before_exception)) {
|
||||
opline = EG(opline_before_exception);
|
||||
}
|
||||
zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
|
||||
EG(exception) = NULL;
|
||||
if (zend_is_executing(TSRMLS_C) && EG(opline_ptr)) {
|
||||
active_opline->lineno = error_lineno;
|
||||
if (opline) {
|
||||
ex->opline = opline;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1083,11 +1085,16 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
case E_USER_DEPRECATED:
|
||||
case E_RECOVERABLE_ERROR:
|
||||
if (zend_is_compiling(TSRMLS_C)) {
|
||||
error_filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
error_filename = zend_get_compiled_filename(TSRMLS_C)->val;
|
||||
error_lineno = zend_get_compiled_lineno(TSRMLS_C);
|
||||
} else if (zend_is_executing(TSRMLS_C)) {
|
||||
error_filename = zend_get_executed_filename(TSRMLS_C);
|
||||
error_lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
if (error_filename[0] == '[') { /* [no active file] */
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
} else {
|
||||
error_lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
}
|
||||
} else {
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
@@ -1116,7 +1123,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
va_start(args, format);
|
||||
|
||||
/* if we don't have a user defined error handler */
|
||||
if (!EG(user_error_handler)
|
||||
if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
|
||||
|| !(EG(user_error_handler_error_reporting) & type)
|
||||
|| EG(error_handling) != EH_NORMAL) {
|
||||
zend_error_cb(type, error_filename, error_lineno, format, args);
|
||||
@@ -1132,12 +1139,6 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
break;
|
||||
default:
|
||||
/* Handle the error in user space */
|
||||
ALLOC_INIT_ZVAL(z_error_message);
|
||||
ALLOC_INIT_ZVAL(z_error_type);
|
||||
ALLOC_INIT_ZVAL(z_error_filename);
|
||||
ALLOC_INIT_ZVAL(z_error_lineno);
|
||||
ALLOC_INIT_ZVAL(z_context);
|
||||
|
||||
/* va_copy() is __va_copy() in old gcc versions.
|
||||
* According to the autoconf manual, using
|
||||
* memcpy(&dst, &src, sizeof(va_list))
|
||||
@@ -1150,44 +1151,35 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
# endif
|
||||
#endif
|
||||
va_copy(usr_copy, args);
|
||||
Z_STRLEN_P(z_error_message) = zend_vspprintf(&Z_STRVAL_P(z_error_message), 0, format, usr_copy);
|
||||
len = zend_vspprintf(&str, 0, format, usr_copy);
|
||||
ZVAL_NEW_STR(¶ms[1], STR_INIT(str, len, 0));
|
||||
efree(str);
|
||||
#ifdef va_copy
|
||||
va_end(usr_copy);
|
||||
#endif
|
||||
Z_TYPE_P(z_error_message) = IS_STRING;
|
||||
|
||||
Z_LVAL_P(z_error_type) = type;
|
||||
Z_TYPE_P(z_error_type) = IS_LONG;
|
||||
ZVAL_LONG(¶ms[0], type);
|
||||
|
||||
if (error_filename) {
|
||||
ZVAL_STRING(z_error_filename, error_filename, 1);
|
||||
ZVAL_STRING(¶ms[2], error_filename);
|
||||
} else {
|
||||
ZVAL_NULL(¶ms[2]);
|
||||
}
|
||||
|
||||
Z_LVAL_P(z_error_lineno) = error_lineno;
|
||||
Z_TYPE_P(z_error_lineno) = IS_LONG;
|
||||
ZVAL_LONG(¶ms[3], error_lineno);
|
||||
|
||||
if (!EG(active_symbol_table)) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
}
|
||||
symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
|
||||
/* during shutdown the symbol table table can be still null */
|
||||
if (!EG(active_symbol_table)) {
|
||||
Z_TYPE_P(z_context) = IS_NULL;
|
||||
if (!symbol_table) {
|
||||
ZVAL_NULL(¶ms[4]);
|
||||
} else {
|
||||
Z_ARRVAL_P(z_context) = EG(active_symbol_table);
|
||||
Z_TYPE_P(z_context) = IS_ARRAY;
|
||||
zval_copy_ctor(z_context);
|
||||
ZVAL_NEW_ARR(¶ms[4]);
|
||||
zend_array_dup(Z_ARRVAL(params[4]), &symbol_table->ht);
|
||||
}
|
||||
|
||||
params = (zval ***) emalloc(sizeof(zval **)*5);
|
||||
params[0] = &z_error_type;
|
||||
params[1] = &z_error_message;
|
||||
params[2] = &z_error_filename;
|
||||
params[3] = &z_error_lineno;
|
||||
params[4] = &z_context;
|
||||
|
||||
orig_user_error_handler = EG(user_error_handler);
|
||||
EG(user_error_handler) = NULL;
|
||||
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
|
||||
ZVAL_UNDEF(&EG(user_error_handler));
|
||||
|
||||
/* User error handler may include() additinal PHP files.
|
||||
* If an error was generated during comilation PHP will compile
|
||||
@@ -1209,9 +1201,10 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
CG(in_compilation) = 0;
|
||||
}
|
||||
|
||||
if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC) == SUCCESS) {
|
||||
if (retval) {
|
||||
if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) {
|
||||
ZVAL_UNDEF(&retval);
|
||||
if (call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC) == SUCCESS) {
|
||||
if (Z_TYPE(retval) != IS_UNDEF) {
|
||||
if (Z_TYPE(retval) == IS_FALSE) {
|
||||
zend_error_cb(type, error_filename, error_lineno, format, args);
|
||||
}
|
||||
zval_ptr_dtor(&retval);
|
||||
@@ -1234,19 +1227,17 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
CG(in_compilation) = 1;
|
||||
}
|
||||
|
||||
if (!EG(user_error_handler)) {
|
||||
EG(user_error_handler) = orig_user_error_handler;
|
||||
}
|
||||
else {
|
||||
zval_ptr_dtor(¶ms[4]);
|
||||
zval_ptr_dtor(¶ms[3]);
|
||||
zval_ptr_dtor(¶ms[2]);
|
||||
zval_ptr_dtor(¶ms[1]);
|
||||
zval_ptr_dtor(¶ms[0]);
|
||||
|
||||
if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF) {
|
||||
ZVAL_COPY_VALUE(&EG(user_error_handler), &orig_user_error_handler);
|
||||
} else {
|
||||
zval_ptr_dtor(&orig_user_error_handler);
|
||||
}
|
||||
|
||||
efree(params);
|
||||
zval_ptr_dtor(&z_error_message);
|
||||
zval_ptr_dtor(&z_error_type);
|
||||
zval_ptr_dtor(&z_error_filename);
|
||||
zval_ptr_dtor(&z_error_lineno);
|
||||
zval_ptr_dtor(&z_context);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1255,7 +1246,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
if (type == E_PARSE) {
|
||||
/* eval() errors do not affect exit_status */
|
||||
if (!(EG(current_execute_data) &&
|
||||
EG(current_execute_data)->opline &&
|
||||
EG(current_execute_data)->func &&
|
||||
ZEND_USER_CODE(EG(current_execute_data)->func->type) &&
|
||||
EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
|
||||
EG(current_execute_data)->opline->extended_value == ZEND_EVAL)) {
|
||||
EG(exit_status) = 255;
|
||||
@@ -1295,13 +1287,12 @@ ZEND_API void zend_output_debug_string(zend_bool trigger_break, const char *form
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) /* {{{ */
|
||||
ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_count, ...) /* {{{ */
|
||||
{
|
||||
va_list files;
|
||||
int i;
|
||||
zend_file_handle *file_handle;
|
||||
zend_op_array *orig_op_array = EG(active_op_array);
|
||||
zval **orig_retval_ptr_ptr = EG(return_value_ptr_ptr);
|
||||
zend_op_array *op_array;
|
||||
long orig_interactive = CG(interactive);
|
||||
|
||||
va_start(files, file_count);
|
||||
@@ -1319,33 +1310,31 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
|
||||
}
|
||||
}
|
||||
|
||||
EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC);
|
||||
op_array = zend_compile_file(file_handle, type TSRMLS_CC);
|
||||
if (file_handle->opened_path) {
|
||||
int dummy = 1;
|
||||
zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path) + 1, (void *)&dummy, sizeof(int), NULL);
|
||||
zend_hash_str_add_empty_element(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path));
|
||||
}
|
||||
zend_destroy_file_handle(file_handle TSRMLS_CC);
|
||||
if (EG(active_op_array)) {
|
||||
EG(return_value_ptr_ptr) = retval ? retval : NULL;
|
||||
zend_execute(EG(active_op_array) TSRMLS_CC);
|
||||
if (op_array) {
|
||||
zend_execute(op_array, retval TSRMLS_CC);
|
||||
zend_exception_restore(TSRMLS_C);
|
||||
if (EG(exception)) {
|
||||
if (EG(user_exception_handler)) {
|
||||
zval *orig_user_exception_handler;
|
||||
zval **params[1], *retval2, *old_exception;
|
||||
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
|
||||
zval orig_user_exception_handler;
|
||||
zval params[1], retval2;
|
||||
zend_object *old_exception;
|
||||
old_exception = EG(exception);
|
||||
EG(exception) = NULL;
|
||||
params[0] = &old_exception;
|
||||
orig_user_exception_handler = EG(user_exception_handler);
|
||||
if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
|
||||
if (retval2 != NULL) {
|
||||
zval_ptr_dtor(&retval2);
|
||||
}
|
||||
ZVAL_OBJ(¶ms[0], old_exception);
|
||||
ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
|
||||
ZVAL_UNDEF(&retval2);
|
||||
if (call_user_function_ex(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
|
||||
zval_ptr_dtor(&retval2);
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(&EG(exception));
|
||||
OBJ_RELEASE(EG(exception));
|
||||
EG(exception) = NULL;
|
||||
}
|
||||
zval_ptr_dtor(&old_exception);
|
||||
OBJ_RELEASE(old_exception);
|
||||
} else {
|
||||
EG(exception) = old_exception;
|
||||
zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
|
||||
@@ -1354,19 +1343,15 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
|
||||
zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
destroy_op_array(EG(active_op_array) TSRMLS_CC);
|
||||
efree(EG(active_op_array));
|
||||
destroy_op_array(op_array TSRMLS_CC);
|
||||
efree(op_array);
|
||||
} else if (type==ZEND_REQUIRE) {
|
||||
va_end(files);
|
||||
EG(active_op_array) = orig_op_array;
|
||||
EG(return_value_ptr_ptr) = orig_retval_ptr_ptr;
|
||||
CG(interactive) = orig_interactive;
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
va_end(files);
|
||||
EG(active_op_array) = orig_op_array;
|
||||
EG(return_value_ptr_ptr) = orig_retval_ptr_ptr;
|
||||
CG(interactive) = orig_interactive;
|
||||
|
||||
return SUCCESS;
|
||||
@@ -1382,7 +1367,7 @@ ZEND_API char *zend_make_compiled_string_description(const char *name TSRMLS_DC)
|
||||
char *compiled_string_description;
|
||||
|
||||
if (zend_is_compiling(TSRMLS_C)) {
|
||||
cur_filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
cur_filename = zend_get_compiled_filename(TSRMLS_C)->val;
|
||||
cur_lineno = zend_get_compiled_lineno(TSRMLS_C);
|
||||
} else if (zend_is_executing(TSRMLS_C)) {
|
||||
cur_filename = zend_get_executed_filename(TSRMLS_C);
|
||||
@@ -1401,6 +1386,12 @@ void free_estring(char **str_p) /* {{{ */
|
||||
{
|
||||
efree(*str_p);
|
||||
}
|
||||
|
||||
void free_string_zval(zval *zv) /* {{{ */
|
||||
{
|
||||
zend_string *str = Z_PTR_P(zv);
|
||||
STR_RELEASE(str);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
|
||||
+223
-245
@@ -22,7 +22,7 @@
|
||||
#ifndef ZEND_H
|
||||
#define ZEND_H
|
||||
|
||||
#define ZEND_VERSION "2.7.0-dev"
|
||||
#define ZEND_VERSION "2.8.0-dev"
|
||||
|
||||
#define ZEND_ENGINE_2
|
||||
|
||||
@@ -52,20 +52,20 @@
|
||||
# define ZEND_PATHS_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
#ifdef ZEND_WIN32
|
||||
/* Only use this macro if you know for sure that all of the switches values
|
||||
are covered by its case statements */
|
||||
#define EMPTY_SWITCH_DEFAULT_CASE() \
|
||||
default: \
|
||||
__assume(0); \
|
||||
break;
|
||||
#if ZEND_DEBUG
|
||||
# define EMPTY_SWITCH_DEFAULT_CASE() default: ZEND_ASSERT(0); break;
|
||||
#elif defined(ZEND_WIN32)
|
||||
# define EMPTY_SWITCH_DEFAULT_CASE() default: __assume(0); break;
|
||||
#else
|
||||
#define EMPTY_SWITCH_DEFAULT_CASE()
|
||||
# define EMPTY_SWITCH_DEFAULT_CASE()
|
||||
#endif
|
||||
|
||||
/* all HAVE_XXX test have to be after the include of zend_config above */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_UNIX_H
|
||||
# include <unix.h>
|
||||
@@ -179,6 +179,14 @@ char *alloca ();
|
||||
# define ZEND_ATTRIBUTE_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 4003
|
||||
# define ZEND_ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
# define ZEND_ATTRIBUTE_UNUSED_LABEL __attribute__((cold, unused));
|
||||
#else
|
||||
# define ZEND_ATTRIBUTE_UNUSED
|
||||
# define ZEND_ATTRIBUTE_UNUSED_LABEL
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
|
||||
# define ZEND_FASTCALL __attribute__((fastcall))
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
@@ -252,7 +260,6 @@ char *alloca ();
|
||||
#include "zend_alloc.h"
|
||||
|
||||
#include "zend_types.h"
|
||||
#include "zend_string.h"
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
@@ -284,11 +291,16 @@ typedef enum {
|
||||
} ZEND_RESULT_CODE;
|
||||
|
||||
#include "zend_hash.h"
|
||||
#include "zend_ts_hash.h"
|
||||
#include "zend_llist.h"
|
||||
|
||||
#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC
|
||||
#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC
|
||||
#define INTERNAL_FUNCTION_PARAMETERS zend_uint param_count, zval *return_value TSRMLS_DC
|
||||
#define INTERNAL_FUNCTION_PARAM_PASSTHRU param_count, return_value TSRMLS_CC
|
||||
|
||||
#define USED_RET() \
|
||||
(!EG(current_execute_data) || \
|
||||
!EG(current_execute_data)->prev_execute_data || \
|
||||
!ZEND_USER_CODE(EG(current_execute_data)->prev_execute_data->func->common.type) || \
|
||||
!(EG(current_execute_data)->prev_execute_data->opline->result_type & EXT_TYPE_UNUSED))
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)
|
||||
void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn));
|
||||
@@ -296,75 +308,38 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
|
||||
# define zend_error_noreturn zend_error
|
||||
#endif
|
||||
|
||||
/*
|
||||
* zval
|
||||
*/
|
||||
typedef struct _zend_class_entry zend_class_entry;
|
||||
|
||||
typedef struct _zend_guard {
|
||||
zend_bool in_get;
|
||||
zend_bool in_set;
|
||||
zend_bool in_unset;
|
||||
zend_bool in_isset;
|
||||
zend_bool dummy; /* sizeof(zend_guard) must not be equal to sizeof(void*) */
|
||||
} zend_guard;
|
||||
|
||||
typedef struct _zend_object {
|
||||
zend_class_entry *ce;
|
||||
HashTable *properties;
|
||||
zval **properties_table;
|
||||
HashTable *guards; /* protects from __get/__set ... recursion */
|
||||
} zend_object;
|
||||
|
||||
#include "zend_object_handlers.h"
|
||||
#include "zend_ast.h"
|
||||
|
||||
typedef union _zvalue_value {
|
||||
long lval; /* long value */
|
||||
double dval; /* double value */
|
||||
struct {
|
||||
char *val;
|
||||
int len;
|
||||
} str;
|
||||
HashTable *ht; /* hash table value */
|
||||
zend_object_value obj;
|
||||
zend_ast *ast;
|
||||
} zvalue_value;
|
||||
/* overloaded elements data types */
|
||||
#define OE_IS_ARRAY (1<<0)
|
||||
#define OE_IS_OBJECT (1<<1)
|
||||
#define OE_IS_METHOD (1<<2)
|
||||
|
||||
struct _zval_struct {
|
||||
/* Variable information */
|
||||
zvalue_value value; /* value */
|
||||
zend_uint refcount__gc;
|
||||
zend_uchar type; /* active type */
|
||||
zend_uchar is_ref__gc;
|
||||
};
|
||||
|
||||
#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
|
||||
#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc)
|
||||
#define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz))
|
||||
#define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz))
|
||||
#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz))
|
||||
#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz))
|
||||
#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz))
|
||||
#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref)
|
||||
|
||||
#define Z_REFCOUNT_P(pz) zval_refcount_p(pz)
|
||||
#define Z_REFCOUNT_P(pz) zval_refcount_p(pz)
|
||||
#define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc)
|
||||
#define Z_ADDREF_P(pz) zval_addref_p(pz)
|
||||
#define Z_DELREF_P(pz) zval_delref_p(pz)
|
||||
#define Z_ISREF_P(pz) zval_isref_p(pz)
|
||||
#define Z_SET_ISREF_P(pz) zval_set_isref_p(pz)
|
||||
#define Z_UNSET_ISREF_P(pz) zval_unset_isref_p(pz)
|
||||
#define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref)
|
||||
#define Z_ADDREF_P(pz) zval_addref_p(pz)
|
||||
#define Z_DELREF_P(pz) zval_delref_p(pz)
|
||||
|
||||
#define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z))
|
||||
#define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z))
|
||||
#define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc)
|
||||
#define Z_ADDREF(z) Z_ADDREF_P(&(z))
|
||||
#define Z_DELREF(z) Z_DELREF_P(&(z))
|
||||
#define Z_ISREF(z) Z_ISREF_P(&(z))
|
||||
#define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z))
|
||||
#define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z))
|
||||
#define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref)
|
||||
#define Z_ADDREF(z) Z_ADDREF_P(&(z))
|
||||
#define Z_DELREF(z) Z_DELREF_P(&(z))
|
||||
|
||||
#define Z_TRY_ADDREF_P(pz) do { \
|
||||
if (Z_REFCOUNTED_P((pz))) { \
|
||||
Z_ADDREF_P((pz)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define Z_TRY_DELREF_P(pz) do { \
|
||||
if (Z_REFCOUNTED_P((pz))) { \
|
||||
Z_DELREF_P((pz)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z))
|
||||
#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))
|
||||
|
||||
#if ZEND_DEBUG
|
||||
#define zend_always_inline inline
|
||||
@@ -388,43 +363,63 @@ struct _zval_struct {
|
||||
#endif /* ZEND_DEBUG */
|
||||
|
||||
#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
|
||||
# define EXPECTED(condition) __builtin_expect(condition, 1)
|
||||
# define UNEXPECTED(condition) __builtin_expect(condition, 0)
|
||||
# define EXPECTED(condition) __builtin_expect(!(!(condition)), 1)
|
||||
# define UNEXPECTED(condition) __builtin_expect(!(!(condition)), 0)
|
||||
#else
|
||||
# define EXPECTED(condition) (condition)
|
||||
# define UNEXPECTED(condition) (condition)
|
||||
#endif
|
||||
|
||||
#ifndef XtOffsetOf
|
||||
# if defined(CRAY) || (defined(__ARMCC_VERSION) && !defined(LINUX))
|
||||
# ifdef __STDC__
|
||||
# define XtOffset(p_type, field) _Offsetof(p_type, field)
|
||||
# else
|
||||
# ifdef CRAY2
|
||||
# define XtOffset(p_type, field) \
|
||||
(sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))
|
||||
|
||||
# else /* !CRAY2 */
|
||||
|
||||
# define XtOffset(p_type, field) ((unsigned int)&(((p_type)NULL)->field))
|
||||
|
||||
# endif /* !CRAY2 */
|
||||
# endif /* __STDC__ */
|
||||
# else /* ! (CRAY || __arm) */
|
||||
|
||||
# define XtOffset(p_type, field) \
|
||||
((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
|
||||
|
||||
# endif /* !CRAY */
|
||||
|
||||
# ifdef offsetof
|
||||
# define XtOffsetOf(s_type, field) offsetof(s_type, field)
|
||||
# else
|
||||
# define XtOffsetOf(s_type, field) XtOffset(s_type*, field)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "zend_string.h"
|
||||
|
||||
static zend_always_inline zend_uint zval_refcount_p(zval* pz) {
|
||||
return pz->refcount__gc;
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz));
|
||||
return GC_REFCOUNT(Z_COUNTED_P(pz));
|
||||
}
|
||||
|
||||
static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) {
|
||||
return pz->refcount__gc = rc;
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
|
||||
return GC_REFCOUNT(Z_COUNTED_P(pz)) = rc;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_uint zval_addref_p(zval* pz) {
|
||||
return ++pz->refcount__gc;
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
|
||||
return ++GC_REFCOUNT(Z_COUNTED_P(pz));
|
||||
}
|
||||
|
||||
static zend_always_inline zend_uint zval_delref_p(zval* pz) {
|
||||
return --pz->refcount__gc;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_bool zval_isref_p(zval* pz) {
|
||||
return pz->is_ref__gc;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_bool zval_set_isref_p(zval* pz) {
|
||||
return pz->is_ref__gc = 1;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_bool zval_unset_isref_p(zval* pz) {
|
||||
return pz->is_ref__gc = 0;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref) {
|
||||
return pz->is_ref__gc = isref;
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
|
||||
return --GC_REFCOUNT(Z_COUNTED_P(pz));
|
||||
}
|
||||
|
||||
/* excpt.h on Digital Unix 4.0 defines function_table */
|
||||
@@ -442,20 +437,18 @@ typedef struct _zend_serialize_data zend_serialize_data;
|
||||
typedef struct _zend_unserialize_data zend_unserialize_data;
|
||||
|
||||
struct _zend_trait_method_reference {
|
||||
const char* method_name;
|
||||
unsigned int mname_len;
|
||||
|
||||
zend_string *method_name;
|
||||
zend_class_entry *ce;
|
||||
|
||||
const char* class_name;
|
||||
unsigned int cname_len;
|
||||
zend_string *class_name;
|
||||
};
|
||||
typedef struct _zend_trait_method_reference zend_trait_method_reference;
|
||||
|
||||
struct _zend_trait_precedence {
|
||||
zend_trait_method_reference *trait_method;
|
||||
|
||||
zend_class_entry** exclude_from_classes;
|
||||
zend_trait_method_reference *trait_method;
|
||||
union {
|
||||
zend_class_entry *ce;
|
||||
zend_string *class_name;
|
||||
} *exclude_from_classes;
|
||||
};
|
||||
typedef struct _zend_trait_precedence zend_trait_precedence;
|
||||
|
||||
@@ -465,8 +458,7 @@ struct _zend_trait_alias {
|
||||
/**
|
||||
* name for method to be added
|
||||
*/
|
||||
const char* alias;
|
||||
unsigned int alias_len;
|
||||
zend_string *alias;
|
||||
|
||||
/**
|
||||
* modifiers to be set on trait method
|
||||
@@ -477,17 +469,16 @@ typedef struct _zend_trait_alias zend_trait_alias;
|
||||
|
||||
struct _zend_class_entry {
|
||||
char type;
|
||||
const char *name;
|
||||
zend_uint name_length;
|
||||
zend_string *name;
|
||||
struct _zend_class_entry *parent;
|
||||
int refcount;
|
||||
zend_uint ce_flags;
|
||||
|
||||
HashTable function_table;
|
||||
HashTable properties_info;
|
||||
zval **default_properties_table;
|
||||
zval **default_static_members_table;
|
||||
zval **static_members_table;
|
||||
zval *default_properties_table;
|
||||
zval *default_static_members_table;
|
||||
zval *static_members_table;
|
||||
HashTable constants_table;
|
||||
int default_properties_count;
|
||||
int default_static_members_count;
|
||||
@@ -509,14 +500,14 @@ struct _zend_class_entry {
|
||||
zend_class_iterator_funcs iterator_funcs;
|
||||
|
||||
/* handlers */
|
||||
zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
|
||||
zend_object* (*create_object)(zend_class_entry *class_type TSRMLS_DC);
|
||||
zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
|
||||
int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); /* a class implements this interface */
|
||||
union _zend_function *(*get_static_method)(zend_class_entry *ce, char* method, int method_len TSRMLS_DC);
|
||||
union _zend_function *(*get_static_method)(zend_class_entry *ce, zend_string* method TSRMLS_DC);
|
||||
|
||||
/* serializer callbacks */
|
||||
int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
|
||||
int (*unserialize)(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
|
||||
int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
|
||||
|
||||
zend_class_entry **interfaces;
|
||||
zend_uint num_interfaces;
|
||||
@@ -528,11 +519,10 @@ struct _zend_class_entry {
|
||||
|
||||
union {
|
||||
struct {
|
||||
const char *filename;
|
||||
zend_string *filename;
|
||||
zend_uint line_start;
|
||||
zend_uint line_end;
|
||||
const char *doc_comment;
|
||||
zend_uint doc_comment_len;
|
||||
zend_string *doc_comment;
|
||||
} user;
|
||||
struct {
|
||||
const struct _zend_function_entry *builtin_functions;
|
||||
@@ -555,6 +545,7 @@ typedef struct _zend_utility_functions {
|
||||
void (*on_timeout)(int seconds TSRMLS_DC);
|
||||
int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
|
||||
int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
|
||||
zend_string *(*vstrpprintf_function)(size_t max_len, const char *format, va_list ap);
|
||||
char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC);
|
||||
char *(*resolve_path_function)(const char *filename, int filename_len TSRMLS_DC);
|
||||
} zend_utility_functions;
|
||||
@@ -578,33 +569,6 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
#define ZEND_TRUTH(x) ((x) ? 1 : 0)
|
||||
#define ZEND_LOG_XOR(a, b) (ZEND_TRUTH(a) ^ ZEND_TRUTH(b))
|
||||
|
||||
/* data types */
|
||||
/* All data types <= IS_BOOL have their constructor/destructors skipped */
|
||||
#define IS_NULL 0
|
||||
#define IS_LONG 1
|
||||
#define IS_DOUBLE 2
|
||||
#define IS_BOOL 3
|
||||
#define IS_ARRAY 4
|
||||
#define IS_OBJECT 5
|
||||
#define IS_STRING 6
|
||||
#define IS_RESOURCE 7
|
||||
#define IS_CONSTANT 8
|
||||
#define IS_CONSTANT_AST 9
|
||||
#define IS_CALLABLE 10
|
||||
|
||||
#define IS_CONSTANT_TYPE_MASK 0x00f
|
||||
#define IS_CONSTANT_UNQUALIFIED 0x010
|
||||
#define IS_LEXICAL_VAR 0x020
|
||||
#define IS_LEXICAL_REF 0x040
|
||||
#define IS_CONSTANT_IN_NAMESPACE 0x100
|
||||
|
||||
#define IS_CONSTANT_TYPE(type) (((type) & IS_CONSTANT_TYPE_MASK) >= IS_CONSTANT && ((type) & IS_CONSTANT_TYPE_MASK) <= IS_CONSTANT_AST)
|
||||
|
||||
/* overloaded elements data types */
|
||||
#define OE_IS_ARRAY (1<<0)
|
||||
#define OE_IS_OBJECT (1<<1)
|
||||
#define OE_IS_METHOD (1<<2)
|
||||
|
||||
int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC);
|
||||
void zend_shutdown(TSRMLS_D);
|
||||
void zend_register_standard_ini_entries(TSRMLS_D);
|
||||
@@ -645,9 +609,9 @@ END_EXTERN_C()
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API char *get_zend_version(void);
|
||||
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy);
|
||||
ZEND_API int zend_print_zval(zval *expr, int indent);
|
||||
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent);
|
||||
ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC);
|
||||
ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC);
|
||||
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC);
|
||||
ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC);
|
||||
ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC);
|
||||
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC);
|
||||
@@ -671,22 +635,9 @@ END_EXTERN_C()
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API void free_estring(char **str_p);
|
||||
ZEND_API void free_string_zval(zval *zv);
|
||||
END_EXTERN_C()
|
||||
|
||||
/* FIXME: Check if we can save if (ptr) too */
|
||||
|
||||
#define STR_FREE(ptr) if (ptr) { str_efree(ptr); }
|
||||
#define STR_FREE_REL(ptr) if (ptr) { str_efree_rel(ptr); }
|
||||
|
||||
#ifndef ZTS
|
||||
#define STR_EMPTY_ALLOC() CG(interned_empty_string)? CG(interned_empty_string) : estrndup("", sizeof("")-1)
|
||||
#else
|
||||
#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1)
|
||||
#endif
|
||||
|
||||
#define STR_REALLOC(ptr, size) \
|
||||
ptr = (char *) erealloc(ptr, size);
|
||||
|
||||
/* output support */
|
||||
#define ZEND_WRITE(str, str_len) zend_write((str), (str_len))
|
||||
#define ZEND_WRITE_EX(str, str_len) write_func((str), (str_len))
|
||||
@@ -705,6 +656,7 @@ extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, cons
|
||||
extern ZEND_API void (*zend_on_timeout)(int seconds TSRMLS_DC);
|
||||
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
|
||||
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
|
||||
extern zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
|
||||
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
|
||||
extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
|
||||
|
||||
@@ -747,101 +699,127 @@ END_EXTERN_C()
|
||||
#define ZMSG_LOG_SCRIPT_NAME 6L
|
||||
#define ZMSG_MEMORY_LEAKS_GRAND_TOTAL 7L
|
||||
|
||||
#define INIT_PZVAL(z) \
|
||||
(z)->refcount__gc = 1; \
|
||||
(z)->is_ref__gc = 0;
|
||||
|
||||
#define INIT_ZVAL(z) z = zval_used_for_init;
|
||||
|
||||
#define ALLOC_INIT_ZVAL(zp) \
|
||||
ALLOC_ZVAL(zp); \
|
||||
INIT_ZVAL(*zp);
|
||||
|
||||
#define MAKE_STD_ZVAL(zv) \
|
||||
ALLOC_ZVAL(zv); \
|
||||
INIT_PZVAL(zv);
|
||||
|
||||
#define PZVAL_IS_REF(z) Z_ISREF_P(z)
|
||||
|
||||
#define ZVAL_COPY_VALUE(z, v) \
|
||||
do { \
|
||||
(z)->value = (v)->value; \
|
||||
Z_TYPE_P(z) = Z_TYPE_P(v); \
|
||||
#define ZVAL_COPY_VALUE(z, v) \
|
||||
do { \
|
||||
zval *_z1 = (z); \
|
||||
zval *_z2 = (v); \
|
||||
(_z1)->value = (_z2)->value; \
|
||||
Z_TYPE_INFO_P(_z1) = Z_TYPE_INFO_P(_z2); \
|
||||
} while (0)
|
||||
|
||||
#define INIT_PZVAL_COPY(z, v) \
|
||||
do { \
|
||||
ZVAL_COPY_VALUE(z, v); \
|
||||
Z_SET_REFCOUNT_P(z, 1); \
|
||||
Z_UNSET_ISREF_P(z); \
|
||||
#define ZVAL_COPY(z, v) \
|
||||
do { \
|
||||
zval *__z1 = (z); \
|
||||
zval *__z2 = (v); \
|
||||
ZVAL_COPY_VALUE(__z1, __z2); \
|
||||
if (Z_OPT_REFCOUNTED_P(__z1)) { \
|
||||
Z_ADDREF_P(__z1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL(ppzv) \
|
||||
do { \
|
||||
if (Z_REFCOUNT_PP((ppzv)) > 1) { \
|
||||
zval *new_zv; \
|
||||
Z_DELREF_PP(ppzv); \
|
||||
ALLOC_ZVAL(new_zv); \
|
||||
INIT_PZVAL_COPY(new_zv, *(ppzv)); \
|
||||
*(ppzv) = new_zv; \
|
||||
zval_copy_ctor(new_zv); \
|
||||
} \
|
||||
#define ZVAL_DUP(z, v) \
|
||||
do { \
|
||||
zval *__z1 = (z); \
|
||||
zval *__z2 = (v); \
|
||||
ZVAL_COPY_VALUE(__z1, __z2); \
|
||||
zval_opt_copy_ctor(__z1); \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_IF_NOT_REF(ppzv) \
|
||||
if (!PZVAL_IS_REF(*ppzv)) { \
|
||||
SEPARATE_ZVAL(ppzv); \
|
||||
}
|
||||
#define ZVAL_DEREF(z) do { \
|
||||
if (UNEXPECTED(Z_ISREF_P(z))) { \
|
||||
(z) = Z_REFVAL_P(z); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_TO_MAKE_IS_REF(ppzv) \
|
||||
if (!PZVAL_IS_REF(*ppzv)) { \
|
||||
SEPARATE_ZVAL(ppzv); \
|
||||
Z_SET_ISREF_PP((ppzv)); \
|
||||
}
|
||||
#define ZVAL_MAKE_REF(zv) do { \
|
||||
zval *__zv = (zv); \
|
||||
if (!Z_ISREF_P(__zv)) { \
|
||||
ZVAL_NEW_REF(__zv, __zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define COPY_PZVAL_TO_ZVAL(zv, pzv) \
|
||||
(zv) = *(pzv); \
|
||||
if (Z_REFCOUNT_P(pzv)>1) { \
|
||||
zval_copy_ctor(&(zv)); \
|
||||
Z_DELREF_P((pzv)); \
|
||||
} else { \
|
||||
FREE_ZVAL(pzv); \
|
||||
} \
|
||||
INIT_PZVAL(&(zv));
|
||||
|
||||
#define MAKE_COPY_ZVAL(ppzv, pzv) \
|
||||
INIT_PZVAL_COPY(pzv, *(ppzv)); \
|
||||
zval_copy_ctor((pzv));
|
||||
#define ZVAL_UNREF(z) do { \
|
||||
zval *_z = (z); \
|
||||
zend_reference *ref; \
|
||||
ZEND_ASSERT(Z_ISREF_P(_z)); \
|
||||
ref = Z_REF_P(_z); \
|
||||
ZVAL_COPY_VALUE(_z, &ref->val); \
|
||||
efree(ref); \
|
||||
} while (0)
|
||||
|
||||
#define REPLACE_ZVAL_VALUE(ppzv_dest, pzv_src, copy) { \
|
||||
int is_ref, refcount; \
|
||||
\
|
||||
SEPARATE_ZVAL_IF_NOT_REF(ppzv_dest); \
|
||||
is_ref = Z_ISREF_PP(ppzv_dest); \
|
||||
refcount = Z_REFCOUNT_PP(ppzv_dest); \
|
||||
zval_dtor(*ppzv_dest); \
|
||||
ZVAL_COPY_VALUE(*ppzv_dest, pzv_src); \
|
||||
if (copy) { \
|
||||
zval_copy_ctor(*ppzv_dest); \
|
||||
} \
|
||||
Z_SET_ISREF_TO_PP(ppzv_dest, is_ref); \
|
||||
Z_SET_REFCOUNT_PP(ppzv_dest, refcount); \
|
||||
}
|
||||
#define SEPARATE_STRING(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_REFCOUNTED_P(_zv) && \
|
||||
Z_REFCOUNT_P(_zv) > 1) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ARG_IF_REF(varptr) \
|
||||
if (PZVAL_IS_REF(varptr)) { \
|
||||
zval *original_var = varptr; \
|
||||
ALLOC_ZVAL(varptr); \
|
||||
INIT_PZVAL_COPY(varptr, original_var); \
|
||||
zval_copy_ctor(varptr); \
|
||||
} else { \
|
||||
Z_ADDREF_P(varptr); \
|
||||
}
|
||||
#define SEPARATE_ARRAY(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_NOREF(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_REFCOUNTED_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} else if (Z_ISREF_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
ZVAL_DUP(_zv, Z_REFVAL_P(_zv)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ARG_IF_REF(varptr) do { \
|
||||
ZVAL_DEREF(varptr); \
|
||||
if (Z_REFCOUNTED_P(varptr)) { \
|
||||
Z_ADDREF_P(varptr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define READY_TO_DESTROY(zv) \
|
||||
(Z_REFCOUNT_P(zv) == 1 && \
|
||||
(Z_TYPE_P(zv) != IS_OBJECT || \
|
||||
zend_objects_store_get_refcount(zv TSRMLS_CC) == 1))
|
||||
(Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
|
||||
|
||||
#define ZEND_MAX_RESERVED_RESOURCES 4
|
||||
|
||||
@@ -858,7 +836,7 @@ typedef enum {
|
||||
typedef struct {
|
||||
zend_error_handling_t handling;
|
||||
zend_class_entry *exception;
|
||||
zval *user_handler;
|
||||
zval user_handler;
|
||||
} zend_error_handling;
|
||||
|
||||
ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC);
|
||||
|
||||
+1275
-1189
File diff suppressed because it is too large
Load Diff
+771
-227
File diff suppressed because it is too large
Load Diff
+15
-4
@@ -1758,11 +1758,22 @@ static void zend_mm_safe_error(zend_mm_heap *heap,
|
||||
uint error_lineno;
|
||||
TSRMLS_FETCH();
|
||||
if (zend_is_compiling(TSRMLS_C)) {
|
||||
error_filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
zend_string *str = zend_get_compiled_filename(TSRMLS_C);
|
||||
error_filename = str ? str->val : NULL;
|
||||
error_lineno = zend_get_compiled_lineno(TSRMLS_C);
|
||||
} else if (EG(in_execution)) {
|
||||
error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
|
||||
error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
|
||||
} else if (EG(current_execute_data)) {
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex) {
|
||||
error_filename = ex->func->op_array.filename->val;
|
||||
error_lineno = ex->opline->lineno;
|
||||
} else {
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
}
|
||||
} else {
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
|
||||
@@ -136,9 +136,6 @@ inline static void * __zend_realloc(void *p, size_t len)
|
||||
#define perealloc_recoverable_rel(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc_recoverable_rel((ptr), (size)))
|
||||
#define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s))
|
||||
|
||||
#define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):STR_EMPTY_ALLOC())
|
||||
#define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):STR_EMPTY_ALLOC())
|
||||
|
||||
ZEND_API int zend_set_memory_limit(size_t memory_limit TSRMLS_DC);
|
||||
|
||||
ZEND_API void start_memory_manager(TSRMLS_D);
|
||||
@@ -161,19 +158,6 @@ ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
/* fast cache for zval's */
|
||||
#define ALLOC_ZVAL(z) \
|
||||
(z) = (zval *) emalloc(sizeof(zval))
|
||||
|
||||
#define FREE_ZVAL(z) \
|
||||
efree_rel(z)
|
||||
|
||||
#define ALLOC_ZVAL_REL(z) \
|
||||
(z) = (zval *) emalloc_rel(sizeof(zval))
|
||||
|
||||
#define FREE_ZVAL_REL(z) \
|
||||
efree_rel(z)
|
||||
|
||||
/* fast cache for HashTables */
|
||||
#define ALLOC_HASHTABLE(ht) \
|
||||
(ht) = (HashTable *) emalloc(sizeof(HashTable))
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2014 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 |
|
||||
| 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 |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id:$ */
|
||||
|
||||
#ifndef _ZEND_ARENA_H_
|
||||
#define _ZEND_ARENA_H_
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
typedef struct _zend_arena zend_arena;
|
||||
|
||||
struct _zend_arena {
|
||||
char *ptr;
|
||||
char *end;
|
||||
zend_arena *prev;
|
||||
};
|
||||
|
||||
static zend_always_inline zend_arena* zend_arena_create(size_t size)
|
||||
{
|
||||
zend_arena *arena = (zend_arena*)emalloc(size);
|
||||
|
||||
arena->ptr = (char*) arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
|
||||
arena->end = (char*) arena + size;
|
||||
arena->prev = NULL;
|
||||
return arena;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_arena_destroy(zend_arena *arena)
|
||||
{
|
||||
do {
|
||||
zend_arena *prev = arena->prev;
|
||||
efree(arena);
|
||||
arena = prev;
|
||||
} while (arena);
|
||||
}
|
||||
|
||||
#define ZEND_ARENA_ALIGNMENT 8U
|
||||
|
||||
static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t size)
|
||||
{
|
||||
zend_arena *arena = *arena_ptr;
|
||||
char *ptr = arena->ptr;
|
||||
|
||||
size = ZEND_MM_ALIGNED_SIZE(size);
|
||||
|
||||
if (EXPECTED(size <= (size_t)(arena->end - ptr))) {
|
||||
arena->ptr = ptr + size;
|
||||
} else {
|
||||
size_t arena_size =
|
||||
UNEXPECTED((size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) > (size_t)(arena->end - (char*) arena)) ?
|
||||
(size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) :
|
||||
(arena->end - (char*) arena);
|
||||
zend_arena *new_arena = (zend_arena*)emalloc(arena_size);
|
||||
|
||||
ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
|
||||
new_arena->ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena)) + size;
|
||||
new_arena->end = (char*) new_arena + arena_size;
|
||||
new_arena->prev = arena;
|
||||
*arena_ptr = new_arena;
|
||||
}
|
||||
|
||||
return (void*) ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t count, size_t unit_size)
|
||||
{
|
||||
size_t size = unit_size * count;
|
||||
void *ret;
|
||||
|
||||
ZEND_ASSERT(size >= unit_size && size >= count);
|
||||
ret = zend_arena_alloc(arena_ptr, size);
|
||||
memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline void* zend_arena_checkpoint(zend_arena *arena)
|
||||
{
|
||||
return arena->ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_arena_release(zend_arena **arena_ptr, void *checkpoint)
|
||||
{
|
||||
zend_arena *arena = *arena_ptr;
|
||||
|
||||
while (UNEXPECTED((char*)checkpoint > arena->end) ||
|
||||
UNEXPECTED((char*)checkpoint < (char*)arena)) {
|
||||
zend_arena *prev = arena->prev;
|
||||
efree(arena);
|
||||
*arena_ptr = arena = prev;
|
||||
}
|
||||
arena->ptr = (char*)checkpoint;
|
||||
}
|
||||
|
||||
#endif /* _ZEND_ARENA_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
+48
-22
@@ -28,8 +28,7 @@ ZEND_API zend_ast *zend_ast_create_constant(zval *zv)
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zval));
|
||||
ast->kind = ZEND_CONST;
|
||||
ast->children = 0;
|
||||
ast->u.val = (zval*)(ast + 1);
|
||||
INIT_PZVAL_COPY(ast->u.val, zv);
|
||||
ZVAL_COPY_VALUE(&ast->u.val, zv);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
|
||||
int i;
|
||||
|
||||
if (ast->kind == ZEND_CONST) {
|
||||
return !IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val));
|
||||
return !Z_CONSTANT(ast->u.val);
|
||||
} else {
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
if ((&ast->u.child)[i]) {
|
||||
@@ -102,6 +101,37 @@ ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TSRMLS_DC)
|
||||
{
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_UNDEF:
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(result), expr);
|
||||
break;
|
||||
case IS_STRING:
|
||||
zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
|
||||
zval_dtor(offset);
|
||||
break;
|
||||
case IS_NULL:
|
||||
zend_symtable_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), expr);
|
||||
break;
|
||||
case IS_LONG:
|
||||
zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), expr);
|
||||
break;
|
||||
case IS_FALSE:
|
||||
zend_hash_index_update(Z_ARRVAL_P(result), 0, expr);
|
||||
break;
|
||||
case IS_TRUE:
|
||||
zend_hash_index_update(Z_ARRVAL_P(result), 1, expr);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
|
||||
break;
|
||||
default:
|
||||
zend_error(E_ERROR, "Illegal offset type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC)
|
||||
{
|
||||
zval op1, op2;
|
||||
@@ -253,16 +283,14 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
|
||||
case ZEND_CONST:
|
||||
/* class constants may be updated in-place */
|
||||
if (scope) {
|
||||
if (IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val))) {
|
||||
if (Z_OPT_CONSTANT(ast->u.val)) {
|
||||
zval_update_constant_ex(&ast->u.val, 1, scope TSRMLS_CC);
|
||||
}
|
||||
*result = *ast->u.val;
|
||||
zval_copy_ctor(result);
|
||||
ZVAL_DUP(result, &ast->u.val);
|
||||
} else {
|
||||
*result = *ast->u.val;
|
||||
zval_copy_ctor(result);
|
||||
if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
|
||||
zval_update_constant_ex(&result, 1, scope TSRMLS_CC);
|
||||
ZVAL_DUP(result, &ast->u.val);
|
||||
if (Z_OPT_CONSTANT_P(result)) {
|
||||
zval_update_constant_ex(result, 1, scope TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -315,19 +343,17 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_INIT_ARRAY:
|
||||
INIT_PZVAL(result);
|
||||
array_init(result);
|
||||
{
|
||||
int i;
|
||||
zend_bool has_key;
|
||||
for (i = 0; i < ast->children; i+=2) {
|
||||
zval *expr;
|
||||
MAKE_STD_ZVAL(expr);
|
||||
if ((has_key = !!(&ast->u.child)[i])) {
|
||||
if ((&ast->u.child)[i]) {
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC);
|
||||
} else {
|
||||
ZVAL_UNDEF(&op1);
|
||||
}
|
||||
zend_ast_evaluate(expr, (&ast->u.child)[i+1], scope TSRMLS_CC);
|
||||
zend_do_add_static_array_element(result, has_key?&op1:NULL, expr);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[i+1], scope TSRMLS_CC);
|
||||
zend_ast_add_array_element(result, &op1, &op2 TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -335,9 +361,9 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
{
|
||||
zval *tmp;
|
||||
zval tmp;
|
||||
zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
|
||||
ZVAL_ZVAL(result, tmp, 1, 1);
|
||||
ZVAL_ZVAL(result, &tmp, 1, 1);
|
||||
}
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
@@ -352,8 +378,8 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
|
||||
if (ast == NULL) {
|
||||
return NULL;
|
||||
} else if (ast->kind == ZEND_CONST) {
|
||||
zend_ast *copy = zend_ast_create_constant(ast->u.val);
|
||||
zval_copy_ctor(copy->u.val);
|
||||
zend_ast *copy = zend_ast_create_constant(&ast->u.val);
|
||||
zval_copy_ctor(©->u.val);
|
||||
return copy;
|
||||
} else if (ast->children) {
|
||||
zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
|
||||
@@ -373,7 +399,7 @@ ZEND_API void zend_ast_destroy(zend_ast *ast)
|
||||
int i;
|
||||
|
||||
if (ast->kind == ZEND_CONST) {
|
||||
zval_dtor(ast->u.val);
|
||||
zval_dtor(&ast->u.val);
|
||||
} else {
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
if ((&ast->u.child)[i]) {
|
||||
|
||||
+1
-3
@@ -22,8 +22,6 @@
|
||||
#ifndef ZEND_AST_H
|
||||
#define ZEND_AST_H
|
||||
|
||||
typedef struct _zend_ast zend_ast;
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
typedef enum _zend_ast_kind {
|
||||
@@ -40,7 +38,7 @@ struct _zend_ast {
|
||||
unsigned short kind;
|
||||
unsigned short children;
|
||||
union {
|
||||
zval *val;
|
||||
zval val;
|
||||
zend_ast *child;
|
||||
} u;
|
||||
};
|
||||
|
||||
+706
-612
File diff suppressed because it is too large
Load Diff
+110
-135
@@ -37,7 +37,7 @@
|
||||
typedef struct _zend_closure {
|
||||
zend_object std;
|
||||
zend_function func;
|
||||
zval *this_ptr;
|
||||
zval this_ptr;
|
||||
HashTable *debug_info;
|
||||
} zend_closure;
|
||||
|
||||
@@ -47,25 +47,21 @@ static zend_object_handlers closure_handlers;
|
||||
|
||||
ZEND_METHOD(Closure, __invoke) /* {{{ */
|
||||
{
|
||||
zend_function *func = EG(current_execute_data)->function_state.function;
|
||||
zval ***arguments;
|
||||
zval *closure_result_ptr = NULL;
|
||||
zend_function *func = EG(current_execute_data)->func;
|
||||
zval *arguments;
|
||||
|
||||
arguments = emalloc(sizeof(zval**) * ZEND_NUM_ARGS());
|
||||
arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
|
||||
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
|
||||
efree(arguments);
|
||||
zend_error(E_RECOVERABLE_ERROR, "Cannot get arguments for calling closure");
|
||||
RETVAL_FALSE;
|
||||
} else if (call_user_function_ex(CG(function_table), NULL, this_ptr, &closure_result_ptr, ZEND_NUM_ARGS(), arguments, 1, NULL TSRMLS_CC) == FAILURE) {
|
||||
} else if (call_user_function_ex(CG(function_table), NULL, getThis(), return_value, ZEND_NUM_ARGS(), arguments, 1, NULL TSRMLS_CC) == FAILURE) {
|
||||
RETVAL_FALSE;
|
||||
} else if (closure_result_ptr) {
|
||||
zval_ptr_dtor(&return_value);
|
||||
*return_value_ptr = closure_result_ptr;
|
||||
}
|
||||
efree(arguments);
|
||||
|
||||
/* destruct the function also, then - we have allocated it in get_method */
|
||||
efree((char*)func->internal_function.function_name);
|
||||
STR_RELEASE(func->internal_function.function_name);
|
||||
efree(func);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -74,7 +70,7 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */
|
||||
Call closure, binding to a given object */
|
||||
ZEND_METHOD(Closure, call) /* {{{ */
|
||||
{
|
||||
zval *zclosure, *newthis, *closure_result_ptr = NULL;
|
||||
zval *zclosure, *newthis, closure_result;
|
||||
zend_closure *closure;
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fci_cache;
|
||||
@@ -83,7 +79,7 @@ ZEND_METHOD(Closure, call) /* {{{ */
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC);
|
||||
closure = (zend_closure *)Z_OBJ_P(zclosure);
|
||||
|
||||
if (closure->func.common.fn_flags & ZEND_ACC_STATIC) {
|
||||
zend_error(E_WARNING, "Cannot bind an instance to a static closure");
|
||||
@@ -101,22 +97,22 @@ ZEND_METHOD(Closure, call) /* {{{ */
|
||||
|
||||
fci.size = sizeof(fci);
|
||||
fci.function_table = CG(function_table);
|
||||
fci.object_ptr = newthis;
|
||||
fci.function_name = zclosure;
|
||||
fci.retval_ptr_ptr = &closure_result_ptr;
|
||||
fci.object = Z_OBJ_P(newthis);
|
||||
fci.function_name = *zclosure;
|
||||
fci.retval = &closure_result;
|
||||
fci.no_separation = 1;
|
||||
fci.symbol_table = NULL;
|
||||
|
||||
fci_cache.initialized = 1;
|
||||
fci_cache.function_handler = &closure->func;
|
||||
fci_cache.object_ptr = newthis;
|
||||
fci_cache.object = Z_OBJ_P(newthis);
|
||||
fci_cache.calling_scope = fci_cache.called_scope = Z_OBJCE_P(newthis);
|
||||
|
||||
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == FAILURE) {
|
||||
RETVAL_FALSE;
|
||||
} else if (closure_result_ptr) {
|
||||
} else {
|
||||
zval_ptr_dtor(&return_value);
|
||||
*return_value_ptr = closure_result_ptr;
|
||||
*return_value = closure_result;
|
||||
}
|
||||
|
||||
if (fci.param_count) {
|
||||
@@ -131,14 +127,14 @@ ZEND_METHOD(Closure, bind)
|
||||
{
|
||||
zval *newthis, *zclosure, *scope_arg = NULL;
|
||||
zend_closure *closure;
|
||||
zend_class_entry *ce, **ce_p;
|
||||
zend_class_entry *ce;
|
||||
zend_bool unbound_scoped = false;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|zb", &zclosure, zend_ce_closure, &newthis, &scope_arg, &unbound_scoped) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC);
|
||||
closure = (zend_closure *)Z_OBJ_P(zclosure);
|
||||
|
||||
if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
zend_error(E_WARNING, "Cannot bind an instance to a static closure");
|
||||
@@ -150,34 +146,16 @@ ZEND_METHOD(Closure, bind)
|
||||
} else if (Z_TYPE_P(scope_arg) == IS_NULL) {
|
||||
ce = NULL;
|
||||
} else {
|
||||
char *class_name;
|
||||
int class_name_len;
|
||||
zval tmp_zval;
|
||||
INIT_ZVAL(tmp_zval);
|
||||
|
||||
if (Z_TYPE_P(scope_arg) == IS_STRING) {
|
||||
class_name = Z_STRVAL_P(scope_arg);
|
||||
class_name_len = Z_STRLEN_P(scope_arg);
|
||||
} else {
|
||||
tmp_zval = *scope_arg;
|
||||
zval_copy_ctor(&tmp_zval);
|
||||
convert_to_string(&tmp_zval);
|
||||
class_name = Z_STRVAL(tmp_zval);
|
||||
class_name_len = Z_STRLEN(tmp_zval);
|
||||
}
|
||||
|
||||
if ((class_name_len == sizeof("static") - 1) &&
|
||||
(memcmp("static", class_name, sizeof("static") - 1) == 0)) {
|
||||
zend_string *class_name = zval_get_string(scope_arg);
|
||||
if ((class_name->len == sizeof("static") - 1) &&
|
||||
(memcmp("static", class_name->val, sizeof("static") - 1) == 0)) {
|
||||
ce = closure->func.common.scope;
|
||||
}
|
||||
else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) {
|
||||
zend_error(E_WARNING, "Class '%s' not found", class_name);
|
||||
zval_dtor(&tmp_zval);
|
||||
} else if ((ce = zend_lookup_class_ex(class_name, NULL, 1 TSRMLS_CC)) == NULL) {
|
||||
zend_error(E_WARNING, "Class '%s' not found", class_name->val);
|
||||
STR_RELEASE(class_name);
|
||||
RETURN_NULL();
|
||||
} else {
|
||||
ce = *ce_p;
|
||||
}
|
||||
zval_dtor(&tmp_zval);
|
||||
STR_RELEASE(class_name);
|
||||
}
|
||||
} else { /* scope argument not given; do not change the scope by default */
|
||||
ce = closure->func.common.scope;
|
||||
@@ -187,7 +165,7 @@ ZEND_METHOD(Closure, bind)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_function *zend_closure_get_constructor(zval *object TSRMLS_DC) /* {{{ */
|
||||
static zend_function *zend_closure_get_constructor(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed");
|
||||
return NULL;
|
||||
@@ -196,13 +174,13 @@ static zend_function *zend_closure_get_constructor(zval *object TSRMLS_DC) /* {{
|
||||
|
||||
static int zend_closure_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return (Z_OBJ_HANDLE_P(o1) != Z_OBJ_HANDLE_P(o2));
|
||||
return (Z_OBJ_P(o1) != Z_OBJ_P(o2));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
||||
zend_closure *closure = (zend_closure *)object;
|
||||
zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
|
||||
|
||||
invoke->common = closure->func.common;
|
||||
@@ -211,65 +189,63 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC) /* {
|
||||
invoke->internal_function.handler = ZEND_MN(Closure___invoke);
|
||||
invoke->internal_function.module = 0;
|
||||
invoke->internal_function.scope = zend_ce_closure;
|
||||
invoke->internal_function.function_name = estrndup(ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1);
|
||||
invoke->internal_function.function_name = STR_INIT(ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1, 0);
|
||||
return invoke;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
||||
zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
|
||||
return &closure->func;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
||||
return closure->this_ptr;
|
||||
zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
|
||||
return &closure->this_ptr;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
static zend_function *zend_closure_get_method(zend_object **object, zend_string *method, const zval *key TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *lc_name;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
zend_string *lc_name;
|
||||
|
||||
lc_name = do_alloca(method_len + 1, use_heap);
|
||||
zend_str_tolower_copy(lc_name, method_name, method_len);
|
||||
if ((method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) &&
|
||||
memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
|
||||
lc_name = STR_ALLOC(method->len, 0);
|
||||
zend_str_tolower_copy(lc_name->val, method->val, method->len);
|
||||
if ((method->len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) &&
|
||||
memcmp(lc_name->val, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
|
||||
) {
|
||||
free_alloca(lc_name, use_heap);
|
||||
return zend_get_closure_invoke_method(*object_ptr TSRMLS_CC);
|
||||
STR_FREE(lc_name);
|
||||
return zend_get_closure_invoke_method(*object TSRMLS_CC);
|
||||
}
|
||||
free_alloca(lc_name, use_heap);
|
||||
return std_object_handlers.get_method(object_ptr, method_name, method_len, key TSRMLS_CC);
|
||||
STR_FREE(lc_name);
|
||||
return std_object_handlers.get_method(object, method, key TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *zend_closure_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
static zval *zend_closure_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
Z_ADDREF(EG(uninitialized_zval));
|
||||
return &EG(uninitialized_zval);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_closure_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
static void zend_closure_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval **zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
static zval *zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (has_set_exists != 2) {
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
@@ -278,13 +254,13 @@ static int zend_closure_has_property(zval *object, zval *member, int has_set_exi
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_closure_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
static void zend_closure_unset_property(zval *object, zval *member, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
|
||||
static void zend_closure_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)object;
|
||||
|
||||
@@ -293,7 +269,7 @@ static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
|
||||
if (closure->func.type == ZEND_USER_FUNCTION) {
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
while (ex) {
|
||||
if (ex->op_array == &closure->func.op_array) {
|
||||
if (ex->func == &closure->func) {
|
||||
zend_error(E_ERROR, "Cannot destroy active lambda function");
|
||||
}
|
||||
ex = ex->prev_execute_data;
|
||||
@@ -306,42 +282,37 @@ static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
|
||||
efree(closure->debug_info);
|
||||
}
|
||||
|
||||
if (closure->this_ptr) {
|
||||
if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
|
||||
zval_ptr_dtor(&closure->this_ptr);
|
||||
}
|
||||
|
||||
efree(closure);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value zend_closure_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
static zend_object *zend_closure_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure;
|
||||
zend_object_value object;
|
||||
|
||||
closure = emalloc(sizeof(zend_closure));
|
||||
memset(closure, 0, sizeof(zend_closure));
|
||||
|
||||
zend_object_std_init(&closure->std, class_type TSRMLS_CC);
|
||||
closure->std.handlers = &closure_handlers;
|
||||
|
||||
object.handle = zend_objects_store_put(closure, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_closure_free_storage, NULL TSRMLS_CC);
|
||||
object.handlers = &closure_handlers;
|
||||
|
||||
return object;
|
||||
return (zend_object*)closure;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value zend_closure_clone(zval *zobject TSRMLS_DC) /* {{{ */
|
||||
static zend_object *zend_closure_clone(zval *zobject TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(zobject TSRMLS_CC);
|
||||
zend_closure *closure = (zend_closure *)Z_OBJ_P(zobject);
|
||||
zval result;
|
||||
|
||||
zend_create_closure(&result, &closure->func, closure->func.common.scope, closure->this_ptr TSRMLS_CC);
|
||||
return Z_OBJVAL(result);
|
||||
zend_create_closure(&result, &closure->func, closure->func.common.scope, &closure->this_ptr TSRMLS_CC);
|
||||
return Z_OBJ(result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */
|
||||
int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure;
|
||||
|
||||
@@ -349,17 +320,17 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
||||
closure = (zend_closure *)Z_OBJ_P(obj);
|
||||
*fptr_ptr = &closure->func;
|
||||
|
||||
if (closure->this_ptr) {
|
||||
if (zobj_ptr) {
|
||||
*zobj_ptr = closure->this_ptr;
|
||||
if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
|
||||
if (obj_ptr) {
|
||||
*obj_ptr = Z_OBJ(closure->this_ptr);
|
||||
}
|
||||
*ce_ptr = Z_OBJCE_P(closure->this_ptr);
|
||||
*ce_ptr = Z_OBJCE(closure->this_ptr);
|
||||
} else {
|
||||
if (zobj_ptr) {
|
||||
*zobj_ptr = NULL;
|
||||
if (obj_ptr) {
|
||||
*obj_ptr = NULL;
|
||||
}
|
||||
*ce_ptr = closure->func.common.scope;
|
||||
}
|
||||
@@ -369,55 +340,52 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function
|
||||
|
||||
static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(object TSRMLS_CC);
|
||||
zval *val;
|
||||
zend_closure *closure = (zend_closure *)Z_OBJ_P(object);
|
||||
zval val;
|
||||
struct _zend_arg_info *arg_info = closure->func.common.arg_info;
|
||||
|
||||
*is_temp = 0;
|
||||
|
||||
if (closure->debug_info == NULL) {
|
||||
ALLOC_HASHTABLE(closure->debug_info);
|
||||
zend_hash_init(closure->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_init(closure->debug_info, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
}
|
||||
if (closure->debug_info->nApplyCount == 0) {
|
||||
if (closure->debug_info->u.v.nApplyCount == 0) {
|
||||
if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
|
||||
HashTable *static_variables = closure->func.op_array.static_variables;
|
||||
MAKE_STD_ZVAL(val);
|
||||
array_init(val);
|
||||
zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*));
|
||||
zend_hash_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL);
|
||||
ZVAL_NEW_ARR(&val);
|
||||
zend_array_dup(Z_ARRVAL(val), static_variables);
|
||||
zend_hash_str_update(closure->debug_info, "static", sizeof("static")-1, &val);
|
||||
}
|
||||
|
||||
if (closure->this_ptr) {
|
||||
Z_ADDREF_P(closure->this_ptr);
|
||||
zend_symtable_update(closure->debug_info, "this", sizeof("this"), (void *) &closure->this_ptr, sizeof(zval *), NULL);
|
||||
if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
|
||||
Z_ADDREF(closure->this_ptr);
|
||||
zend_hash_str_update(closure->debug_info, "this", sizeof("this")-1, &closure->this_ptr);
|
||||
}
|
||||
|
||||
if (arg_info) {
|
||||
zend_uint i, required = closure->func.common.required_num_args;
|
||||
|
||||
MAKE_STD_ZVAL(val);
|
||||
array_init(val);
|
||||
array_init(&val);
|
||||
|
||||
for (i = 0; i < closure->func.common.num_args; i++) {
|
||||
char *name, *info;
|
||||
int name_len, info_len;
|
||||
zend_string *name;
|
||||
zval info;
|
||||
if (arg_info->name) {
|
||||
name_len = zend_spprintf(&name, 0, "%s$%s",
|
||||
arg_info->pass_by_reference ? "&" : "",
|
||||
arg_info->name);
|
||||
name = zend_strpprintf(0, "%s$%s",
|
||||
arg_info->pass_by_reference ? "&" : "",
|
||||
arg_info->name);
|
||||
} else {
|
||||
name_len = zend_spprintf(&name, 0, "%s$param%d",
|
||||
arg_info->pass_by_reference ? "&" : "",
|
||||
i + 1);
|
||||
name = zend_strpprintf(0, "%s$param%d",
|
||||
arg_info->pass_by_reference ? "&" : "",
|
||||
i + 1);
|
||||
}
|
||||
info_len = zend_spprintf(&info, 0, "%s",
|
||||
i >= required ? "<optional>" : "<required>");
|
||||
add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0);
|
||||
efree(name);
|
||||
ZVAL_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>"));
|
||||
zend_hash_update(Z_ARRVAL(val), name, &info);
|
||||
STR_RELEASE(name);
|
||||
arg_info++;
|
||||
}
|
||||
zend_hash_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL);
|
||||
zend_hash_str_update(closure->debug_info, "parameter", sizeof("parameter")-1, &val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,12 +393,18 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static HashTable *zend_closure_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
|
||||
static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
||||
zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
|
||||
|
||||
*table = closure->this_ptr ? &closure->this_ptr : NULL;
|
||||
*n = closure->this_ptr ? 1 : 0;
|
||||
if (closure->debug_info != NULL) {
|
||||
zend_hash_destroy(closure->debug_info);
|
||||
efree(closure->debug_info);
|
||||
closure->debug_info = NULL;
|
||||
}
|
||||
|
||||
*table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL;
|
||||
*n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0;
|
||||
return (closure->func.type == ZEND_USER_FUNCTION) ?
|
||||
closure->func.op_array.static_variables : NULL;
|
||||
}
|
||||
@@ -482,6 +456,8 @@ void zend_register_closure_ce(TSRMLS_D) /* {{{ */
|
||||
zend_ce_closure->unserialize = zend_class_unserialize_deny;
|
||||
|
||||
memcpy(&closure_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
||||
closure_handlers.free_obj = zend_closure_free_storage;
|
||||
closure_handlers.clone_obj = NULL;
|
||||
closure_handlers.get_constructor = zend_closure_get_constructor;
|
||||
closure_handlers.get_method = zend_closure_get_method;
|
||||
closure_handlers.write_property = zend_closure_write_property;
|
||||
@@ -508,12 +484,12 @@ ZEND_API void zend_create_closure_ex(zval *res, zend_function *func, zend_class_
|
||||
|
||||
object_init_ex(res, zend_ce_closure);
|
||||
|
||||
closure = (zend_closure *)zend_object_store_get_object(res TSRMLS_CC);
|
||||
closure = (zend_closure *)Z_OBJ_P(res);
|
||||
|
||||
closure->func = *func;
|
||||
closure->func.common.prototype = NULL;
|
||||
|
||||
if ((scope == NULL) && (this_ptr != NULL)) {
|
||||
if ((scope == NULL) && this_ptr && (Z_TYPE_P(this_ptr) != IS_UNDEF)) {
|
||||
/* use dummy scope if we're binding an object without specifying a scope */
|
||||
/* maybe it would be better to create one for this purpose */
|
||||
scope = zend_ce_closure;
|
||||
@@ -525,7 +501,7 @@ ZEND_API void zend_create_closure_ex(zval *res, zend_function *func, zend_class_
|
||||
|
||||
ALLOC_HASHTABLE(closure->func.op_array.static_variables);
|
||||
zend_hash_init(closure->func.op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_apply_with_arguments(static_variables TSRMLS_CC, (apply_func_args_t)zval_copy_static_var, 1, closure->func.op_array.static_variables);
|
||||
zend_hash_apply_with_arguments(static_variables TSRMLS_CC, zval_copy_static_var, 1, closure->func.op_array.static_variables);
|
||||
}
|
||||
closure->func.op_array.run_time_cache = NULL;
|
||||
(*closure->func.op_array.refcount)++;
|
||||
@@ -533,12 +509,12 @@ ZEND_API void zend_create_closure_ex(zval *res, zend_function *func, zend_class_
|
||||
/* verify that we aren't binding internal function to a wrong scope */
|
||||
if(func->common.scope != NULL) {
|
||||
if(scope && !instanceof_function(scope, func->common.scope TSRMLS_CC)) {
|
||||
zend_error(E_WARNING, "Cannot bind function %s::%s to scope class %s", func->common.scope->name, func->common.function_name, scope->name);
|
||||
zend_error(E_WARNING, "Cannot bind function %s::%s to scope class %s", func->common.scope->name->val, func->common.function_name->val, scope->name->val);
|
||||
scope = NULL;
|
||||
}
|
||||
if(scope && this_ptr && (func->common.fn_flags & ZEND_ACC_STATIC) == 0 &&
|
||||
!instanceof_function(Z_OBJCE_P(this_ptr), closure->func.common.scope TSRMLS_CC)) {
|
||||
zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", func->common.scope->name, func->common.function_name, Z_OBJCE_P(this_ptr)->name);
|
||||
zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", func->common.scope->name->val, func->common.function_name->val, Z_OBJCE_P(this_ptr)->name->val);
|
||||
scope = NULL;
|
||||
this_ptr = NULL;
|
||||
}
|
||||
@@ -549,19 +525,18 @@ ZEND_API void zend_create_closure_ex(zval *res, zend_function *func, zend_class_
|
||||
}
|
||||
}
|
||||
|
||||
closure->this_ptr = NULL;
|
||||
ZVAL_UNDEF(&closure->this_ptr);
|
||||
/* Invariants:
|
||||
* If the closure is unscoped, it is unbound.
|
||||
* If the closure is scoped, it may be static, bound or unbound */
|
||||
closure->func.common.scope = scope;
|
||||
if (scope) {
|
||||
closure->func.common.fn_flags |= ZEND_ACC_PUBLIC;
|
||||
if (this_ptr && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) {
|
||||
closure->this_ptr = this_ptr;
|
||||
Z_ADDREF_P(this_ptr);
|
||||
/* We assume that a static scoped closure is desired if given NULL to bind to
|
||||
If an unbound scoped closure is desired, the parameter must be set to 1*/
|
||||
} else if (!unbound_scoped) {
|
||||
if (this_ptr && Z_TYPE_P(this_ptr) == IS_OBJECT && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) {
|
||||
ZVAL_COPY(&closure->this_ptr, this_ptr);
|
||||
/* We assume that a static scoped closure is desired if given NULL to bind to
|
||||
If an unbound scoped closure is desired, the parameter must be set to 1*/
|
||||
} else if (!unbound_scoped) {
|
||||
closure->func.common.fn_flags |= ZEND_ACC_STATIC;
|
||||
/* Unbound but scoped was explicitly specified and we wish to avoid E_ERROR when calling without object
|
||||
We don't do this if it has implict allowed static (i.e. is a method, should E_STRICT)
|
||||
|
||||
@@ -30,7 +30,7 @@ extern ZEND_API zend_class_entry *zend_ce_closure;
|
||||
|
||||
ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zval *this_ptr TSRMLS_DC);
|
||||
ZEND_API void zend_create_closure_ex(zval *res, zend_function *op_array, zend_class_entry *scope, zval *this_ptr, zend_bool unbound_scoped TSRMLS_DC);
|
||||
ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC);
|
||||
ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *obj TSRMLS_DC);
|
||||
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC);
|
||||
ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC);
|
||||
|
||||
|
||||
+1671
-1194
File diff suppressed because it is too large
Load Diff
+140
-160
@@ -45,10 +45,9 @@
|
||||
#define RESET_DOC_COMMENT() \
|
||||
{ \
|
||||
if (CG(doc_comment)) { \
|
||||
efree(CG(doc_comment)); \
|
||||
STR_RELEASE(CG(doc_comment)); \
|
||||
CG(doc_comment) = NULL; \
|
||||
} \
|
||||
CG(doc_comment_len) = 0; \
|
||||
}
|
||||
|
||||
typedef struct _zend_op_array zend_op_array;
|
||||
@@ -60,21 +59,10 @@ typedef struct _zend_compiler_context {
|
||||
int literals_size;
|
||||
int current_brk_cont;
|
||||
int backpatch_count;
|
||||
int nested_calls;
|
||||
int used_stack;
|
||||
int in_finally;
|
||||
HashTable *labels;
|
||||
} zend_compiler_context;
|
||||
|
||||
typedef struct _zend_literal {
|
||||
zval constant;
|
||||
zend_ulong hash_value;
|
||||
zend_uint cache_slot;
|
||||
} zend_literal;
|
||||
|
||||
#define Z_HASH_P(zv) \
|
||||
(((zend_literal*)(zv))->hash_value)
|
||||
|
||||
typedef union _znode_op {
|
||||
zend_uint constant;
|
||||
zend_uint var;
|
||||
@@ -83,7 +71,6 @@ typedef union _znode_op {
|
||||
zend_uint opline_num; /* Needs to be signed */
|
||||
zend_op *jmp_addr;
|
||||
zval *zv;
|
||||
zend_literal *literal;
|
||||
void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */
|
||||
} znode_op;
|
||||
|
||||
@@ -142,9 +129,9 @@ typedef struct _zend_try_catch_element {
|
||||
} zend_try_catch_element;
|
||||
|
||||
#if SIZEOF_LONG == 8
|
||||
#define THIS_HASHVAL 210728972157UL
|
||||
#define THIS_HASHVAL 6385726429UL
|
||||
#else
|
||||
#define THIS_HASHVAL 275574653UL
|
||||
#define THIS_HASHVAL 2090759133UL
|
||||
#endif
|
||||
|
||||
/* method flags (types) */
|
||||
@@ -225,20 +212,17 @@ char *zend_visibility_string(zend_uint fn_flags);
|
||||
|
||||
typedef struct _zend_property_info {
|
||||
zend_uint flags;
|
||||
const char *name;
|
||||
int name_length;
|
||||
zend_string *name;
|
||||
ulong h;
|
||||
int offset;
|
||||
const char *doc_comment;
|
||||
int doc_comment_len;
|
||||
zend_string *doc_comment;
|
||||
zend_class_entry *ce;
|
||||
} zend_property_info;
|
||||
|
||||
|
||||
typedef struct _zend_arg_info {
|
||||
const char *name;
|
||||
const char *name; // TODO: convert into zend_string ???
|
||||
zend_uint name_len;
|
||||
const char *class_name;
|
||||
const char *class_name; // TODO: convert into zend_string ???
|
||||
zend_uint class_name_len;
|
||||
zend_uchar type_hint;
|
||||
zend_uchar pass_by_reference;
|
||||
@@ -261,19 +245,13 @@ typedef struct _zend_internal_function_info {
|
||||
zend_bool _is_variadic;
|
||||
} zend_internal_function_info;
|
||||
|
||||
typedef struct _zend_compiled_variable {
|
||||
const char *name;
|
||||
int name_len;
|
||||
ulong hash_value;
|
||||
} zend_compiled_variable;
|
||||
|
||||
struct _zend_op_array {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
const char *function_name;
|
||||
zend_string *function_name;
|
||||
zend_class_entry *scope;
|
||||
zend_uint fn_flags;
|
||||
union _zend_function *prototype;
|
||||
zend_function *prototype;
|
||||
zend_uint num_args;
|
||||
zend_uint required_num_args;
|
||||
zend_arg_info *arg_info;
|
||||
@@ -284,14 +262,11 @@ struct _zend_op_array {
|
||||
zend_op *opcodes;
|
||||
zend_uint last;
|
||||
|
||||
zend_compiled_variable *vars;
|
||||
zend_string **vars;
|
||||
int last_var;
|
||||
|
||||
zend_uint T;
|
||||
|
||||
zend_uint nested_calls;
|
||||
zend_uint used_stack;
|
||||
|
||||
zend_brk_cont_element *brk_cont_array;
|
||||
int last_brk_cont;
|
||||
|
||||
@@ -304,14 +279,13 @@ struct _zend_op_array {
|
||||
|
||||
zend_uint this_var;
|
||||
|
||||
const char *filename;
|
||||
zend_string *filename;
|
||||
zend_uint line_start;
|
||||
zend_uint line_end;
|
||||
const char *doc_comment;
|
||||
zend_uint doc_comment_len;
|
||||
zend_string *doc_comment;
|
||||
zend_uint early_binding; /* the linked list of delayed declarations */
|
||||
|
||||
zend_literal *literals;
|
||||
zval *literals;
|
||||
int last_literal;
|
||||
|
||||
void **run_time_cache;
|
||||
@@ -327,10 +301,10 @@ struct _zend_op_array {
|
||||
typedef struct _zend_internal_function {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
const char * function_name;
|
||||
zend_string* function_name;
|
||||
zend_class_entry *scope;
|
||||
zend_uint fn_flags;
|
||||
union _zend_function *prototype;
|
||||
zend_function *prototype;
|
||||
zend_uint num_args;
|
||||
zend_uint required_num_args;
|
||||
zend_arg_info *arg_info;
|
||||
@@ -340,14 +314,14 @@ typedef struct _zend_internal_function {
|
||||
struct _zend_module_entry *module;
|
||||
} zend_internal_function;
|
||||
|
||||
#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "")
|
||||
#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name->val : "")
|
||||
|
||||
typedef union _zend_function {
|
||||
union _zend_function {
|
||||
zend_uchar type; /* MUST be the first element of this struct! */
|
||||
|
||||
struct {
|
||||
zend_uchar type; /* never used */
|
||||
const char *function_name;
|
||||
zend_string *function_name;
|
||||
zend_class_entry *scope;
|
||||
zend_uint fn_flags;
|
||||
union _zend_function *prototype;
|
||||
@@ -358,16 +332,11 @@ typedef union _zend_function {
|
||||
|
||||
zend_op_array op_array;
|
||||
zend_internal_function internal_function;
|
||||
} zend_function;
|
||||
|
||||
|
||||
typedef struct _zend_function_state {
|
||||
zend_function *function;
|
||||
void **arguments;
|
||||
} zend_function_state;
|
||||
};
|
||||
|
||||
typedef struct _zend_function_call_entry {
|
||||
zend_function *fbc;
|
||||
zend_uint op_number;
|
||||
zend_uint arg_num;
|
||||
zend_bool uses_argument_unpacking;
|
||||
} zend_function_call_entry;
|
||||
@@ -385,43 +354,51 @@ typedef struct _list_llist_element {
|
||||
znode value;
|
||||
} list_llist_element;
|
||||
|
||||
union _temp_variable;
|
||||
|
||||
typedef struct _call_slot {
|
||||
zend_function *fbc;
|
||||
zval *object;
|
||||
zend_class_entry *called_scope;
|
||||
zend_uint num_additional_args;
|
||||
zend_bool is_ctor_call;
|
||||
zend_bool is_ctor_result_used;
|
||||
} call_slot;
|
||||
typedef enum _vm_frame_kind {
|
||||
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
|
||||
VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
|
||||
VM_FRAME_TOP_FUNCTION, /* direct VM call to function from external C code */
|
||||
VM_FRAME_TOP_CODE /* direct VM call to "main" code from external C code */
|
||||
} vm_frame_kind;
|
||||
|
||||
struct _zend_execute_data {
|
||||
struct _zend_op *opline;
|
||||
zend_function_state function_state;
|
||||
zend_op_array *op_array;
|
||||
zval *object;
|
||||
HashTable *symbol_table;
|
||||
struct _zend_execute_data *prev_execute_data;
|
||||
zval *old_error_reporting;
|
||||
zend_bool nested;
|
||||
zval **original_return_value;
|
||||
zend_class_entry *current_scope;
|
||||
zend_class_entry *current_called_scope;
|
||||
zval *current_this;
|
||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||
zval *delayed_exception;
|
||||
call_slot *call_slots;
|
||||
call_slot *call;
|
||||
struct _zend_op *opline; /* executed opline */
|
||||
zend_execute_data *call; /* current call */
|
||||
void **run_time_cache;
|
||||
zend_function *func; /* executed op_array */
|
||||
zend_uint num_args;
|
||||
zend_uchar flags;
|
||||
zend_uchar frame_kind;
|
||||
zend_class_entry *called_scope;
|
||||
zend_object *object;
|
||||
zend_execute_data *prev_nested_call;
|
||||
zend_execute_data *prev_execute_data;
|
||||
zval *return_value;
|
||||
zend_class_entry *scope; /* function scope (self) */
|
||||
zend_array *symbol_table;
|
||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||
zend_object *delayed_exception;
|
||||
zval old_error_reporting;
|
||||
};
|
||||
|
||||
#define ZEND_CALL_CTOR (1 << 0)
|
||||
#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1)
|
||||
|
||||
#define ZEND_CALL_FRAME_SLOT \
|
||||
((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
|
||||
|
||||
#define ZEND_CALL_ARG(call, n) \
|
||||
(((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1)))
|
||||
|
||||
#define EX(element) execute_data.element
|
||||
|
||||
#define EX_TMP_VAR(ex, n) ((temp_variable*)(((char*)(ex)) + ((int)(n))))
|
||||
#define EX_TMP_VAR_NUM(ex, n) (EX_TMP_VAR(ex, 0) - (1 + (n)))
|
||||
#define EX_VAR_2(ex, n) ((zval*)(((char*)(ex)) + ((int)(n))))
|
||||
#define EX_VAR_NUM_2(ex, n) (((zval*)(ex)) + (ZEND_CALL_FRAME_SLOT + ((int)(n))))
|
||||
|
||||
#define EX_CV_NUM(ex, n) (((zval***)(((char*)(ex))+ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))))+(n))
|
||||
#define EX_VAR(n) EX_VAR_2(execute_data, n)
|
||||
#define EX_VAR_NUM(n) EX_VAR_NUM_2(execute_data, n)
|
||||
|
||||
#define EX_VAR_TO_NUM(n) (EX_VAR_2(NULL, n) - EX_VAR_NUM_2(NULL, 0))
|
||||
|
||||
#define IS_CONST (1<<0)
|
||||
#define IS_TMP_VAR (1<<1)
|
||||
@@ -447,9 +424,9 @@ ZEND_API int lex_scan(zval *zendlval TSRMLS_DC);
|
||||
void startup_scanner(TSRMLS_D);
|
||||
void shutdown_scanner(TSRMLS_D);
|
||||
|
||||
ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC);
|
||||
ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC);
|
||||
ZEND_API char *zend_get_compiled_filename(TSRMLS_D);
|
||||
ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename TSRMLS_DC);
|
||||
ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename TSRMLS_DC);
|
||||
ZEND_API zend_string *zend_get_compiled_filename(TSRMLS_D);
|
||||
ZEND_API int zend_get_compiled_lineno(TSRMLS_D);
|
||||
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
|
||||
|
||||
@@ -457,7 +434,7 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace
|
||||
void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
|
||||
void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
|
||||
void zend_resolve_class_name(znode *class_name TSRMLS_DC);
|
||||
ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len);
|
||||
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var);
|
||||
|
||||
#ifdef ZTS
|
||||
const char *zend_get_zendtext(TSRMLS_D);
|
||||
@@ -466,44 +443,44 @@ int zend_get_zendleng(TSRMLS_D);
|
||||
|
||||
|
||||
/* parser-driven code generators */
|
||||
void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC);
|
||||
void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC);
|
||||
void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC);
|
||||
void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
|
||||
void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC);
|
||||
void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
|
||||
void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC);
|
||||
void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC);
|
||||
void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC);
|
||||
void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC);
|
||||
void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC);
|
||||
void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC);
|
||||
void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC);
|
||||
void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC);
|
||||
void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC);
|
||||
|
||||
void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC);
|
||||
void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC);
|
||||
void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC);
|
||||
void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
|
||||
void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC);
|
||||
void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC);
|
||||
void zend_do_print(znode *result, const znode *arg TSRMLS_DC);
|
||||
void zend_do_echo(const znode *arg TSRMLS_DC);
|
||||
void zend_do_print(znode *result, znode *arg TSRMLS_DC);
|
||||
void zend_do_echo(znode *arg TSRMLS_DC);
|
||||
typedef int (*unary_op_type)(zval *, zval * TSRMLS_DC);
|
||||
typedef int (*binary_op_type)(zval *, zval *, zval * TSRMLS_DC);
|
||||
ZEND_API unary_op_type get_unary_op(int opcode);
|
||||
ZEND_API binary_op_type get_binary_op(int opcode);
|
||||
|
||||
void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC);
|
||||
void zend_do_while_cond(znode *expr, znode *close_bracket_token TSRMLS_DC);
|
||||
void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC);
|
||||
void zend_do_do_while_begin(TSRMLS_D);
|
||||
void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC);
|
||||
void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, znode *expr TSRMLS_DC);
|
||||
|
||||
|
||||
void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC);
|
||||
void zend_do_if_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC);
|
||||
void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC);
|
||||
void zend_do_if_end(TSRMLS_D);
|
||||
|
||||
void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC);
|
||||
void zend_do_for_cond(znode *expr, znode *second_semicolon_token TSRMLS_DC);
|
||||
void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC);
|
||||
void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC);
|
||||
|
||||
void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC);
|
||||
void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC);
|
||||
void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
|
||||
void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
|
||||
|
||||
void zend_do_begin_variable_parse(TSRMLS_D);
|
||||
void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC);
|
||||
@@ -512,23 +489,23 @@ void zend_check_writable_variable(const znode *variable);
|
||||
|
||||
void zend_do_free(znode *op1 TSRMLS_DC);
|
||||
|
||||
void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC);
|
||||
void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC);
|
||||
void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC);
|
||||
void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
|
||||
|
||||
int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier);
|
||||
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
|
||||
void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC);
|
||||
void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initialization, znode *class_type, zend_bool pass_by_reference, zend_bool is_variadic TSRMLS_DC);
|
||||
void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization, znode *class_type, zend_bool pass_by_reference, zend_bool is_variadic TSRMLS_DC);
|
||||
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC);
|
||||
void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
|
||||
void zend_do_clone(znode *result, const znode *expr TSRMLS_DC);
|
||||
void zend_do_clone(znode *result, znode *expr TSRMLS_DC);
|
||||
void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC);
|
||||
void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC);
|
||||
void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC);
|
||||
int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
|
||||
void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC);
|
||||
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_yield(znode *result, znode *value, znode *key, zend_bool is_variable TSRMLS_DC);
|
||||
void zend_do_handle_exception(TSRMLS_D);
|
||||
|
||||
void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC);
|
||||
@@ -540,9 +517,9 @@ void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC);
|
||||
void zend_do_end_catch(znode *catch_token TSRMLS_DC);
|
||||
void zend_do_finally(znode *finally_token TSRMLS_DC);
|
||||
void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC);
|
||||
void zend_do_throw(const znode *expr TSRMLS_DC);
|
||||
void zend_do_throw(znode *expr TSRMLS_DC);
|
||||
|
||||
ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time);
|
||||
ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *do_bind_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC);
|
||||
ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC);
|
||||
@@ -567,24 +544,24 @@ void zend_do_unpack_params(znode *params TSRMLS_DC);
|
||||
|
||||
|
||||
void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC);
|
||||
void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC);
|
||||
void zend_do_boolean_or_end(znode *result, znode *expr1, znode *expr2, const znode *op_token TSRMLS_DC);
|
||||
void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC);
|
||||
void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC);
|
||||
void zend_do_boolean_and_end(znode *result, znode *expr1, znode *expr2, const znode *op_token TSRMLS_DC);
|
||||
|
||||
void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC);
|
||||
void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC);
|
||||
|
||||
void zend_do_switch_cond(const znode *cond TSRMLS_DC);
|
||||
void zend_do_switch_end(const znode *case_list TSRMLS_DC);
|
||||
void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC);
|
||||
void zend_do_case_before_statement(const znode *case_list, znode *case_token, znode *case_expr TSRMLS_DC);
|
||||
void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC);
|
||||
void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC);
|
||||
|
||||
void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC);
|
||||
void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC);
|
||||
void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC);
|
||||
void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC);
|
||||
void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC);
|
||||
void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC);
|
||||
|
||||
void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC);
|
||||
void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC);
|
||||
|
||||
void zend_do_halt_compiler_register(TSRMLS_D);
|
||||
|
||||
@@ -597,11 +574,11 @@ void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC);
|
||||
|
||||
void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC);
|
||||
|
||||
void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC);
|
||||
void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC);
|
||||
|
||||
void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC);
|
||||
void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC);
|
||||
void zend_do_add_static_array_element(zval *result, zval *offset, const zval *expr);
|
||||
void zend_do_init_array(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC);
|
||||
void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC);
|
||||
void zend_do_end_array(znode *result, const znode *array_node TSRMLS_DC);
|
||||
void zend_do_list_init(TSRMLS_D);
|
||||
void zend_do_list_end(znode *result, znode *expr TSRMLS_DC);
|
||||
void zend_do_add_list_element(const znode *element TSRMLS_DC);
|
||||
@@ -613,13 +590,13 @@ void zend_init_list(void *result, void *item TSRMLS_DC);
|
||||
void zend_add_to_list(void *result, void *item TSRMLS_DC);
|
||||
|
||||
|
||||
void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC);
|
||||
void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC);
|
||||
void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC);
|
||||
void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC);
|
||||
|
||||
void zend_do_unset(const znode *variable TSRMLS_DC);
|
||||
void zend_do_unset(znode *variable TSRMLS_DC);
|
||||
void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC);
|
||||
|
||||
void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC);
|
||||
void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC);
|
||||
|
||||
void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC);
|
||||
void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC);
|
||||
@@ -629,17 +606,17 @@ void zend_do_declare_begin(TSRMLS_D);
|
||||
void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC);
|
||||
void zend_do_declare_end(const znode *declare_token TSRMLS_DC);
|
||||
|
||||
void zend_do_exit(znode *result, const znode *message TSRMLS_DC);
|
||||
void zend_do_exit(znode *result, znode *message TSRMLS_DC);
|
||||
|
||||
void zend_do_begin_silence(znode *strudel_token TSRMLS_DC);
|
||||
void zend_do_end_silence(const znode *strudel_token TSRMLS_DC);
|
||||
void zend_do_end_silence(znode *strudel_token TSRMLS_DC);
|
||||
|
||||
void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC);
|
||||
void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *jmp_token, const znode *colon_token TSRMLS_DC);
|
||||
void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC);
|
||||
void zend_do_jmp_set_else(znode *result, znode *false_value, const znode *jmp_token, znode *colon_token TSRMLS_DC);
|
||||
|
||||
void zend_do_begin_qm_op(const znode *cond, znode *qm_token TSRMLS_DC);
|
||||
void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC);
|
||||
void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_token, const znode *colon_token TSRMLS_DC);
|
||||
void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC);
|
||||
void zend_do_qm_true(znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC);
|
||||
void zend_do_qm_false(znode *result, znode *false_value, znode *qm_token, const znode *colon_token TSRMLS_DC);
|
||||
|
||||
void zend_do_extended_info(TSRMLS_D);
|
||||
void zend_do_extended_fcall_begin(TSRMLS_D);
|
||||
@@ -651,7 +628,7 @@ void zend_do_abstract_method(const znode *function_name, znode *modifiers, const
|
||||
|
||||
void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC);
|
||||
void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC);
|
||||
void zend_do_begin_namespace(const znode *name, zend_bool with_brackets TSRMLS_DC);
|
||||
void zend_do_begin_namespace(znode *name, zend_bool with_brackets TSRMLS_DC);
|
||||
void zend_do_end_namespace(TSRMLS_D);
|
||||
void zend_verify_namespace(TSRMLS_D);
|
||||
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
|
||||
@@ -664,7 +641,7 @@ void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
|
||||
void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
|
||||
|
||||
void zend_do_label(znode *label TSRMLS_DC);
|
||||
void zend_do_goto(const znode *label TSRMLS_DC);
|
||||
void zend_do_goto(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(int temporary TSRMLS_DC);
|
||||
|
||||
@@ -678,30 +655,28 @@ ZEND_API void function_add_ref(zend_function *function);
|
||||
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 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 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);
|
||||
ZEND_API void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size TSRMLS_DC);
|
||||
ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC);
|
||||
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC);
|
||||
ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC);
|
||||
ZEND_API int zend_cleanup_user_class_data(zend_class_entry **pce TSRMLS_DC);
|
||||
ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC);
|
||||
ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC);
|
||||
ZEND_API void zend_cleanup_internal_classes(TSRMLS_D);
|
||||
ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC);
|
||||
ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC);
|
||||
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array);
|
||||
|
||||
ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC);
|
||||
ZEND_API void zend_function_dtor(zend_function *function);
|
||||
ZEND_API void destroy_zend_class(zend_class_entry **pce);
|
||||
void zend_class_add_ref(zend_class_entry **ce);
|
||||
ZEND_API void zend_function_dtor(zval *zv);
|
||||
ZEND_API void destroy_zend_class(zval *zv);
|
||||
void zend_class_add_ref(zval *zv);
|
||||
|
||||
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal);
|
||||
ZEND_API zend_string *zend_mangle_property_name(const char *src1, int src1_length, const char *src2, int src2_length, int internal);
|
||||
#define zend_unmangle_property_name(mangled_property, mangled_property_len, class_name, prop_name) \
|
||||
zend_unmangle_property_name_ex(mangled_property, mangled_property_len, class_name, prop_name, NULL)
|
||||
ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int mangled_property_len, const char **class_name, const char **prop_name, int *prop_len);
|
||||
|
||||
#define ZEND_FUNCTION_DTOR (void (*)(void *)) zend_function_dtor
|
||||
#define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class
|
||||
#define ZEND_FUNCTION_DTOR zend_function_dtor
|
||||
#define ZEND_CLASS_DTOR destroy_zend_class
|
||||
|
||||
zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC);
|
||||
void init_op(zend_op *op TSRMLS_DC);
|
||||
@@ -718,24 +693,22 @@ ZEND_API char *zend_make_compiled_string_description(const char *name TSRMLS_DC)
|
||||
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC);
|
||||
int zend_get_class_fetch_type(const char *class_name, uint class_name_len);
|
||||
|
||||
typedef zend_bool (*zend_auto_global_callback)(const char *name, uint name_len TSRMLS_DC);
|
||||
typedef zend_bool (*zend_auto_global_callback)(zend_string *name TSRMLS_DC);
|
||||
typedef struct _zend_auto_global {
|
||||
const char *name;
|
||||
uint name_len;
|
||||
zend_string *name;
|
||||
zend_auto_global_callback auto_global_callback;
|
||||
zend_bool jit;
|
||||
zend_bool armed;
|
||||
} zend_auto_global;
|
||||
|
||||
ZEND_API int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC);
|
||||
ZEND_API int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC);
|
||||
ZEND_API void zend_activate_auto_globals(TSRMLS_D);
|
||||
ZEND_API zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hashval TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_is_auto_global(zend_string *name TSRMLS_DC);
|
||||
ZEND_API size_t zend_dirname(char *path, size_t len);
|
||||
|
||||
int zendlex(znode *zendlval TSRMLS_DC);
|
||||
|
||||
int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
|
||||
|
||||
/* BEGIN: OPCODES */
|
||||
|
||||
@@ -749,12 +722,10 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_FETCH_CLASS_DEFAULT 0
|
||||
#define ZEND_FETCH_CLASS_SELF 1
|
||||
#define ZEND_FETCH_CLASS_PARENT 2
|
||||
#define ZEND_FETCH_CLASS_MAIN 3 /* unused */
|
||||
#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused */
|
||||
#define ZEND_FETCH_CLASS_AUTO 5
|
||||
#define ZEND_FETCH_CLASS_INTERFACE 6
|
||||
#define ZEND_FETCH_CLASS_STATIC 7
|
||||
#define ZEND_FETCH_CLASS_TRAIT 14
|
||||
#define ZEND_FETCH_CLASS_STATIC 3
|
||||
#define ZEND_FETCH_CLASS_AUTO 4
|
||||
#define ZEND_FETCH_CLASS_INTERFACE 5
|
||||
#define ZEND_FETCH_CLASS_TRAIT 6
|
||||
#define ZEND_FETCH_CLASS_MASK 0x0f
|
||||
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
|
||||
#define ZEND_FETCH_CLASS_SILENT 0x0100
|
||||
@@ -769,7 +740,6 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_PARSED_NEW (1<<6)
|
||||
#define ZEND_PARSED_LIST_EXPR (1<<7)
|
||||
|
||||
|
||||
/* unset types */
|
||||
#define ZEND_UNSET_REG 0
|
||||
|
||||
@@ -789,6 +759,9 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_EVAL_CODE 4
|
||||
#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
|
||||
|
||||
/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */
|
||||
#define ZEND_USER_CODE(type) ((type & 1) == 0)
|
||||
|
||||
#define ZEND_INTERNAL_CLASS 1
|
||||
#define ZEND_USER_CLASS 2
|
||||
|
||||
@@ -841,11 +814,11 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_SEND_PREFER_REF 2
|
||||
|
||||
#define CHECK_ARG_SEND_TYPE(zf, arg_num, m) \
|
||||
((zf)->common.arg_info && \
|
||||
(arg_num <= (zf)->common.num_args \
|
||||
(EXPECTED((zf)->common.arg_info != NULL) && \
|
||||
(EXPECTED(arg_num <= (zf)->common.num_args) \
|
||||
? ((zf)->common.arg_info[arg_num-1].pass_by_reference & (m)) \
|
||||
: ((zf)->common.fn_flags & ZEND_ACC_VARIADIC) \
|
||||
? ((zf)->common.arg_info[(zf)->common.num_args-1].pass_by_reference & (m)) : 0))
|
||||
: (UNEXPECTED((zf)->common.fn_flags & ZEND_ACC_VARIADIC) != 0) && \
|
||||
((zf)->common.arg_info[(zf)->common.num_args-1].pass_by_reference & (m))))
|
||||
|
||||
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF)
|
||||
@@ -870,6 +843,10 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_FAST_CALL_FROM_CATCH 1
|
||||
#define ZEND_FAST_CALL_FROM_FINALLY 2
|
||||
|
||||
#define ZEND_ARRAY_ELEMENT_REF (1<<0)
|
||||
#define ZEND_ARRAY_NOT_PACKED (1<<1)
|
||||
#define ZEND_ARRAY_SIZE_SHIFT 2
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_CLONE_FUNC_NAME "__clone"
|
||||
@@ -895,7 +872,7 @@ END_EXTERN_C()
|
||||
/* call op_array handler of extendions */
|
||||
#define ZEND_COMPILE_HANDLE_OP_ARRAY (1<<1)
|
||||
|
||||
/* generate ZEND_DO_FCALL_BY_NAME for internal functions instead of ZEND_DO_FCALL */
|
||||
/* generate ZEND_INIT_FCALL_BY_NAME for internal functions instead of ZEND_INIT_FCALL */
|
||||
#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
|
||||
|
||||
/* don't perform early binding for classes inherited form internal ones;
|
||||
@@ -909,6 +886,9 @@ END_EXTERN_C()
|
||||
/* disable constant substitution at compile-time */
|
||||
#define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<5)
|
||||
|
||||
/* disable usage of builtin instruction for strlen() */
|
||||
#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<6)
|
||||
|
||||
/* The default value for CG(compiler_options) */
|
||||
#define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY
|
||||
|
||||
|
||||
+186
-167
@@ -27,47 +27,67 @@
|
||||
#include "zend_globals.h"
|
||||
#include "zend_API.h"
|
||||
|
||||
void free_zend_constant(zend_constant *c)
|
||||
void free_zend_constant(zval *zv)
|
||||
{
|
||||
zend_constant *c = Z_PTR_P(zv);
|
||||
|
||||
if (!(c->flags & CONST_PERSISTENT)) {
|
||||
zval_dtor(&c->value);
|
||||
} else {
|
||||
zval_internal_dtor(&c->value);
|
||||
}
|
||||
str_free(c->name);
|
||||
if (c->name) {
|
||||
STR_RELEASE(c->name);
|
||||
}
|
||||
pefree(c, c->flags & CONST_PERSISTENT);
|
||||
}
|
||||
|
||||
|
||||
void copy_zend_constant(zend_constant *c)
|
||||
static void copy_zend_constant(zval *zv)
|
||||
{
|
||||
c->name = str_strndup(c->name, c->name_len - 1);
|
||||
zend_constant *c = Z_PTR_P(zv);
|
||||
|
||||
Z_PTR_P(zv) = pemalloc(sizeof(zend_constant), c->flags & CONST_PERSISTENT);
|
||||
memcpy(Z_PTR_P(zv), c, sizeof(zend_constant));
|
||||
|
||||
c = Z_PTR_P(zv);
|
||||
c->name = STR_COPY(c->name);
|
||||
if (!(c->flags & CONST_PERSISTENT)) {
|
||||
zval_copy_ctor(&c->value);
|
||||
} else {
|
||||
if (Z_TYPE(c->value) == IS_STRING) {
|
||||
Z_STR(c->value) = STR_DUP(Z_STR(c->value), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void zend_copy_constants(HashTable *target, HashTable *source)
|
||||
{
|
||||
zend_constant tmp_constant;
|
||||
|
||||
zend_hash_copy(target, source, (copy_ctor_func_t) copy_zend_constant, &tmp_constant, sizeof(zend_constant));
|
||||
zend_hash_copy(target, source, copy_zend_constant);
|
||||
}
|
||||
|
||||
|
||||
static int clean_non_persistent_constant(const zend_constant *c TSRMLS_DC)
|
||||
static int clean_non_persistent_constant(zval *zv TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c = Z_PTR_P(zv);
|
||||
return (c->flags & CONST_PERSISTENT) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
|
||||
}
|
||||
|
||||
|
||||
static int clean_non_persistent_constant_full(const zend_constant *c TSRMLS_DC)
|
||||
static int clean_non_persistent_constant_full(zval *zv TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c = Z_PTR_P(zv);
|
||||
return (c->flags & CONST_PERSISTENT) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
static int clean_module_constant(const zend_constant *c, int *module_number TSRMLS_DC)
|
||||
static int clean_module_constant(zval *el, void *arg TSRMLS_DC)
|
||||
{
|
||||
if (c->module_number == *module_number) {
|
||||
zend_constant *c = (zend_constant *)Z_PTR_P(el);
|
||||
int module_number = *(int *)arg;
|
||||
|
||||
if (c->module_number == module_number) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -77,7 +97,7 @@ static int clean_module_constant(const zend_constant *c, int *module_number TSRM
|
||||
|
||||
void clean_module_constants(int module_number TSRMLS_DC)
|
||||
{
|
||||
zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) clean_module_constant, (void *) &module_number TSRMLS_CC);
|
||||
zend_hash_apply_with_argument(EG(zend_constants), clean_module_constant, (void *) &module_number TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +105,7 @@ int zend_startup_constants(TSRMLS_D)
|
||||
{
|
||||
EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
|
||||
|
||||
if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
zend_hash_init(EG(zend_constants), 128, NULL, ZEND_CONSTANT_DTOR, 1);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -137,9 +155,9 @@ int zend_shutdown_constants(TSRMLS_D)
|
||||
void clean_non_persistent_constants(TSRMLS_D)
|
||||
{
|
||||
if (EG(full_tables_cleanup)) {
|
||||
zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
|
||||
zend_hash_apply(EG(zend_constants), clean_non_persistent_constant_full TSRMLS_CC);
|
||||
} else {
|
||||
zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
|
||||
zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,8 +167,7 @@ ZEND_API void zend_register_null_constant(const char *name, uint name_len, int f
|
||||
|
||||
ZVAL_NULL(&c.value);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
@@ -161,8 +178,7 @@ ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_
|
||||
|
||||
ZVAL_BOOL(&c.value, bval);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
@@ -173,8 +189,7 @@ ZEND_API void zend_register_long_constant(const char *name, uint name_len, long
|
||||
|
||||
ZVAL_LONG(&c.value, lval);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
@@ -186,8 +201,7 @@ ZEND_API void zend_register_double_constant(const char *name, uint name_len, dou
|
||||
|
||||
ZVAL_DOUBLE(&c.value, dval);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
@@ -197,10 +211,9 @@ ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, ch
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
ZVAL_STRINGL(&c.value, strval, strlen, 0);
|
||||
ZVAL_NEW_STR(&c.value, STR_INIT(strval, strlen, flags & CONST_PERSISTENT));
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
@@ -211,121 +224,135 @@ ZEND_API void zend_register_string_constant(const char *name, uint name_len, cha
|
||||
zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
|
||||
}
|
||||
|
||||
static int zend_get_special_constant(const char *name, uint name_len, zend_constant **c TSRMLS_DC)
|
||||
static zend_constant *zend_get_special_constant(const char *name, uint name_len TSRMLS_DC)
|
||||
{
|
||||
int ret;
|
||||
zend_constant *c;
|
||||
static char haltoff[] = "__COMPILER_HALT_OFFSET__";
|
||||
|
||||
if (!EG(in_execution)) {
|
||||
return 0;
|
||||
if (!EG(current_execute_data)) {
|
||||
return NULL;
|
||||
} else if (name_len == sizeof("__CLASS__")-1 &&
|
||||
!memcmp(name, "__CLASS__", sizeof("__CLASS__")-1)) {
|
||||
zend_constant tmp;
|
||||
|
||||
/* Returned constants may be cached, so they have to be stored */
|
||||
if (EG(scope) && EG(scope)->name) {
|
||||
int const_name_len;
|
||||
char *const_name;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
zend_string *const_name;
|
||||
|
||||
const_name_len = sizeof("\0__CLASS__") + EG(scope)->name_length;
|
||||
const_name = do_alloca(const_name_len, use_heap);
|
||||
memcpy(const_name, "\0__CLASS__", sizeof("\0__CLASS__")-1);
|
||||
zend_str_tolower_copy(const_name + sizeof("\0__CLASS__")-1, EG(scope)->name, EG(scope)->name_length);
|
||||
if (zend_hash_find(EG(zend_constants), const_name, const_name_len, (void**)c) == FAILURE) {
|
||||
zend_hash_add(EG(zend_constants), const_name, const_name_len, (void*)&tmp, sizeof(zend_constant), (void**)c);
|
||||
memset(*c, 0, sizeof(zend_constant));
|
||||
Z_STRVAL((**c).value) = estrndup(EG(scope)->name, EG(scope)->name_length);
|
||||
Z_STRLEN((**c).value) = EG(scope)->name_length;
|
||||
Z_TYPE((**c).value) = IS_STRING;
|
||||
const_name_len = sizeof("\0__CLASS__") + EG(scope)->name->len;
|
||||
const_name = STR_ALLOC(const_name_len, 0);
|
||||
memcpy(const_name->val, "\0__CLASS__", sizeof("\0__CLASS__")-1);
|
||||
zend_str_tolower_copy(const_name->val + sizeof("\0__CLASS__")-1, EG(scope)->name->val, EG(scope)->name->len);
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), const_name)) == NULL) {
|
||||
c = emalloc(sizeof(zend_constant));
|
||||
memset(c, 0, sizeof(zend_constant));
|
||||
ZVAL_STR(&c->value, STR_COPY(EG(scope)->name));
|
||||
zend_hash_add_ptr(EG(zend_constants), const_name, c);
|
||||
}
|
||||
free_alloca(const_name, use_heap);
|
||||
STR_RELEASE(const_name);
|
||||
} else {
|
||||
if (zend_hash_find(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void**)c) == FAILURE) {
|
||||
zend_hash_add(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void*)&tmp, sizeof(zend_constant), (void**)c);
|
||||
memset(*c, 0, sizeof(zend_constant));
|
||||
Z_STRVAL((**c).value) = estrndup("", 0);
|
||||
Z_STRLEN((**c).value) = 0;
|
||||
Z_TYPE((**c).value) = IS_STRING;
|
||||
zend_string *const_name = STR_INIT("\0__CLASS__", sizeof("\0__CLASS__")-1, 0);
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), const_name)) == NULL) {
|
||||
c = emalloc(sizeof(zend_constant));
|
||||
memset(c, 0, sizeof(zend_constant));
|
||||
ZVAL_EMPTY_STRING(&c->value);
|
||||
zend_hash_add_ptr(EG(zend_constants), const_name, c);
|
||||
}
|
||||
STR_RELEASE(const_name);
|
||||
}
|
||||
return 1;
|
||||
return c;
|
||||
} else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
|
||||
!memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
|
||||
const char *cfilename;
|
||||
char *haltname;
|
||||
int len, clen;
|
||||
zend_string *haltname;
|
||||
int clen;
|
||||
|
||||
cfilename = zend_get_executed_filename(TSRMLS_C);
|
||||
clen = strlen(cfilename);
|
||||
/* check for __COMPILER_HALT_OFFSET__ */
|
||||
zend_mangle_property_name(&haltname, &len, haltoff,
|
||||
haltname = zend_mangle_property_name(haltoff,
|
||||
sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
|
||||
ret = zend_hash_find(EG(zend_constants), haltname, len+1, (void **) c);
|
||||
efree(haltname);
|
||||
return (ret == SUCCESS);
|
||||
c = zend_hash_find_ptr(EG(zend_constants), haltname);
|
||||
STR_FREE(haltname);
|
||||
return c;
|
||||
} else {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC)
|
||||
ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c;
|
||||
int retval = 1;
|
||||
char *lookup_name;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
|
||||
lookup_name = zend_str_tolower_dup(name, name_len);
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
|
||||
if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) {
|
||||
char *lcname = do_alloca(name_len + 1, use_heap);
|
||||
zend_str_tolower_copy(lcname, name, name_len);
|
||||
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) {
|
||||
if (c->flags & CONST_CS) {
|
||||
retval=0;
|
||||
c = NULL;
|
||||
}
|
||||
} else {
|
||||
retval = zend_get_special_constant(name, name_len, &c TSRMLS_CC);
|
||||
c = zend_get_special_constant(name, name_len TSRMLS_CC);
|
||||
}
|
||||
efree(lookup_name);
|
||||
free_alloca(lcname, use_heap);
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
*result = c->value;
|
||||
zval_copy_ctor(result);
|
||||
Z_SET_REFCOUNT_P(result, 1);
|
||||
Z_UNSET_ISREF_P(result);
|
||||
}
|
||||
|
||||
return retval;
|
||||
return c ? &c->value : NULL;
|
||||
}
|
||||
|
||||
ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
|
||||
ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) {
|
||||
char *lcname = do_alloca(name->len + 1, use_heap);
|
||||
zend_str_tolower_copy(lcname, name->val, name->len);
|
||||
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name->len)) != NULL) {
|
||||
if (c->flags & CONST_CS) {
|
||||
c = NULL;
|
||||
}
|
||||
} else {
|
||||
c = zend_get_special_constant(name->val, name->len TSRMLS_CC);
|
||||
}
|
||||
free_alloca(lcname, use_heap);
|
||||
}
|
||||
|
||||
return c ? &c->value : NULL;
|
||||
}
|
||||
|
||||
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, ulong flags TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c;
|
||||
int retval = 1;
|
||||
const char *colon;
|
||||
zend_class_entry *ce = NULL;
|
||||
char *class_name;
|
||||
zval **ret_constant;
|
||||
zend_string *class_name;
|
||||
const char *name = cname->val;
|
||||
uint name_len = cname->len;
|
||||
|
||||
/* Skip leading \\ */
|
||||
if (name[0] == '\\') {
|
||||
name += 1;
|
||||
name_len -= 1;
|
||||
cname = NULL;
|
||||
}
|
||||
|
||||
|
||||
if ((colon = zend_memrchr(name, ':', name_len)) &&
|
||||
colon > name && (*(colon - 1) == ':')) {
|
||||
int class_name_len = colon - name - 1;
|
||||
int const_name_len = name_len - class_name_len - 2;
|
||||
const char *constant_name = colon + 1;
|
||||
zend_string *constant_name = STR_INIT(colon + 1, const_name_len, 0);
|
||||
char *lcname;
|
||||
zval *ret_constant = NULL;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
class_name = estrndup(name, class_name_len);
|
||||
lcname = zend_str_tolower_dup(class_name, class_name_len);
|
||||
class_name = STR_INIT(name, class_name_len, 0);
|
||||
lcname = do_alloca(class_name_len + 1, use_heap);
|
||||
zend_str_tolower_copy(lcname, name, class_name_len);
|
||||
if (!scope) {
|
||||
if (EG(in_execution)) {
|
||||
if (EG(current_execute_data)) {
|
||||
scope = EG(scope);
|
||||
} else {
|
||||
scope = CG(active_class_entry);
|
||||
@@ -338,9 +365,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
ce = scope;
|
||||
} else {
|
||||
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
|
||||
retval = 0;
|
||||
}
|
||||
efree(lcname);
|
||||
} else if (class_name_len == sizeof("parent")-1 &&
|
||||
!memcmp(lcname, "parent", sizeof("parent")-1)) {
|
||||
if (!scope) {
|
||||
@@ -350,31 +375,33 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
} else {
|
||||
ce = scope->parent;
|
||||
}
|
||||
efree(lcname);
|
||||
} else if (class_name_len == sizeof("static")-1 &&
|
||||
!memcmp(lcname, "static", sizeof("static")-1)) {
|
||||
if (EG(called_scope)) {
|
||||
ce = EG(called_scope);
|
||||
if (EG(current_execute_data) && EG(current_execute_data)->called_scope) {
|
||||
ce = EG(current_execute_data)->called_scope;
|
||||
} else {
|
||||
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
|
||||
}
|
||||
efree(lcname);
|
||||
} else {
|
||||
efree(lcname);
|
||||
ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
|
||||
ce = zend_fetch_class(class_name, flags TSRMLS_CC);
|
||||
}
|
||||
if (retval && ce) {
|
||||
if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
|
||||
retval = 0;
|
||||
free_alloca(lcname, use_heap);
|
||||
if (ce) {
|
||||
ret_constant = zend_hash_find(&ce->constants_table, constant_name);
|
||||
if (ret_constant == NULL) {
|
||||
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name, constant_name);
|
||||
zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val);
|
||||
}
|
||||
} else if (Z_ISREF_P(ret_constant)) {
|
||||
ret_constant = Z_REFVAL_P(ret_constant);
|
||||
}
|
||||
} else if (!ce) {
|
||||
retval = 0;
|
||||
}
|
||||
efree(class_name);
|
||||
goto finish;
|
||||
STR_RELEASE(class_name);
|
||||
STR_FREE(constant_name);
|
||||
if (ret_constant && Z_CONSTANT_P(ret_constant)) {
|
||||
zval_update_constant_ex(ret_constant, 1, ce TSRMLS_CC);
|
||||
}
|
||||
return ret_constant;
|
||||
}
|
||||
|
||||
/* non-class constant */
|
||||
@@ -384,138 +411,130 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
int const_name_len = name_len - prefix_len - 1;
|
||||
const char *constant_name = colon + 1;
|
||||
char *lcname;
|
||||
int found_const = 0;
|
||||
int lcname_len;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
lcname = zend_str_tolower_dup(name, prefix_len);
|
||||
lcname_len = prefix_len + 1 + const_name_len;
|
||||
lcname = do_alloca(lcname_len + 1, use_heap);
|
||||
zend_str_tolower_copy(lcname, name, prefix_len);
|
||||
/* Check for namespace constant */
|
||||
|
||||
/* Concatenate lowercase namespace name and constant name */
|
||||
lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
|
||||
lcname[prefix_len] = '\\';
|
||||
memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
|
||||
found_const = 1;
|
||||
} else {
|
||||
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) {
|
||||
/* try lowercase */
|
||||
zend_str_tolower(lcname + prefix_len + 1, const_name_len);
|
||||
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
|
||||
if ((c->flags & CONST_CS) == 0) {
|
||||
found_const = 1;
|
||||
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) {
|
||||
if ((c->flags & CONST_CS) != 0) {
|
||||
c = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
efree(lcname);
|
||||
if(found_const) {
|
||||
*result = c->value;
|
||||
zval_update_constant_ex(&result, 1, NULL TSRMLS_CC);
|
||||
zval_copy_ctor(result);
|
||||
Z_SET_REFCOUNT_P(result, 1);
|
||||
Z_UNSET_ISREF_P(result);
|
||||
return 1;
|
||||
free_alloca(lcname, use_heap);
|
||||
if (c) {
|
||||
return &c->value;
|
||||
}
|
||||
/* name requires runtime resolution, need to check non-namespaced name */
|
||||
if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
|
||||
name = constant_name;
|
||||
name_len = const_name_len;
|
||||
return zend_get_constant(name, name_len, result TSRMLS_CC);
|
||||
return zend_get_constant_str(constant_name, const_name_len TSRMLS_CC);
|
||||
}
|
||||
retval = 0;
|
||||
finish:
|
||||
if (retval) {
|
||||
zval_update_constant_ex(ret_constant, 1, ce TSRMLS_CC);
|
||||
*result = **ret_constant;
|
||||
zval_copy_ctor(result);
|
||||
INIT_PZVAL(result);
|
||||
}
|
||||
|
||||
return retval;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zend_get_constant(name, name_len, result TSRMLS_CC);
|
||||
if (cname) {
|
||||
return zend_get_constant(cname TSRMLS_CC);
|
||||
} else {
|
||||
return zend_get_constant_str(name, name_len TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRMLS_DC)
|
||||
zend_constant *zend_quick_get_constant(const zval *key, ulong flags TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c;
|
||||
|
||||
if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) {
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), Z_STR_P(key))) == NULL) {
|
||||
key++;
|
||||
if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE ||
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), Z_STR_P(key))) == NULL ||
|
||||
(c->flags & CONST_CS) != 0) {
|
||||
if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
|
||||
key++;
|
||||
if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) {
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), Z_STR_P(key))) == NULL) {
|
||||
key++;
|
||||
if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE ||
|
||||
if ((c = zend_hash_find_ptr(EG(zend_constants), Z_STR_P(key))) == NULL ||
|
||||
(c->flags & CONST_CS) != 0) {
|
||||
|
||||
key--;
|
||||
if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) {
|
||||
return NULL;
|
||||
}
|
||||
c = zend_get_special_constant(Z_STRVAL_P(key), Z_STRLEN_P(key) TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
key--;
|
||||
if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) {
|
||||
return NULL;
|
||||
}
|
||||
c = zend_get_special_constant(Z_STRVAL_P(key), Z_STRLEN_P(key) TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c)
|
||||
{
|
||||
void *ret;
|
||||
zend_constant *copy = pemalloc(sizeof(zend_constant), c->flags & CONST_PERSISTENT);
|
||||
|
||||
memcpy(copy, c, sizeof(zend_constant));
|
||||
ret = zend_hash_add_ptr(ht, key, copy);
|
||||
if (!ret) {
|
||||
pefree(copy, c->flags & CONST_PERSISTENT);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
|
||||
{
|
||||
char *lowercase_name = NULL;
|
||||
char *name;
|
||||
zend_string *lowercase_name = NULL;
|
||||
zend_string *name;
|
||||
int ret = SUCCESS;
|
||||
ulong chash;
|
||||
|
||||
#if 0
|
||||
printf("Registering constant for module %d\n", c->module_number);
|
||||
#endif
|
||||
|
||||
if (!(c->flags & CONST_CS)) {
|
||||
/* keep in mind that c->name_len already contains the '\0' */
|
||||
lowercase_name = estrndup(c->name, c->name_len-1);
|
||||
zend_str_tolower(lowercase_name, c->name_len-1);
|
||||
lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
|
||||
lowercase_name = STR_ALLOC(c->name->len, c->flags & CONST_PERSISTENT);
|
||||
zend_str_tolower_copy(lowercase_name->val, c->name->val, c->name->len);
|
||||
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
|
||||
name = lowercase_name;
|
||||
} else {
|
||||
char *slash = strrchr(c->name, '\\');
|
||||
char *slash = strrchr(c->name->val, '\\');
|
||||
if (slash) {
|
||||
lowercase_name = estrndup(c->name, c->name_len-1);
|
||||
zend_str_tolower(lowercase_name, slash-c->name);
|
||||
lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
|
||||
lowercase_name = STR_INIT(c->name->val, c->name->len, c->flags & CONST_PERSISTENT);
|
||||
zend_str_tolower(lowercase_name->val, slash - c->name->val);
|
||||
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
|
||||
name = lowercase_name;
|
||||
} else {
|
||||
name = c->name;
|
||||
}
|
||||
}
|
||||
chash = str_hash(name, c->name_len-1);
|
||||
|
||||
/* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
|
||||
if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
|
||||
&& !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
|
||||
|| zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
|
||||
if ((c->name->len == sizeof("__COMPILER_HALT_OFFSET__")-1
|
||||
&& !memcmp(name->val, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
|
||||
|| zend_hash_add_constant(EG(zend_constants), name, c) == NULL) {
|
||||
|
||||
/* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
|
||||
if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
|
||||
&& memcmp(name, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
|
||||
name++;
|
||||
if (c->name->val[0] == '\0' && c->name->len > sizeof("\0__COMPILER_HALT_OFFSET__")-1
|
||||
&& memcmp(name->val, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
|
||||
}
|
||||
zend_error(E_NOTICE,"Constant %s already defined", name);
|
||||
str_free(c->name);
|
||||
zend_error(E_NOTICE,"Constant %s already defined", name->val);
|
||||
STR_RELEASE(c->name);
|
||||
if (!(c->flags & CONST_PERSISTENT)) {
|
||||
zval_dtor(&c->value);
|
||||
}
|
||||
ret = FAILURE;
|
||||
}
|
||||
if (lowercase_name) {
|
||||
str_efree(lowercase_name);
|
||||
STR_RELEASE(lowercase_name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
+19
-20
@@ -33,17 +33,16 @@
|
||||
typedef struct _zend_constant {
|
||||
zval value;
|
||||
int flags;
|
||||
char *name;
|
||||
uint name_len;
|
||||
zend_string *name;
|
||||
int module_number;
|
||||
} zend_constant;
|
||||
|
||||
#define REGISTER_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name), (bval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name), (lval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_DOUBLE_CONSTANT(name, dval, flags) zend_register_double_constant((name), sizeof(name), (dval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_STRING_CONSTANT(name, str, flags) zend_register_string_constant((name), sizeof(name), (str), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_STRINGL_CONSTANT(name, str, len, flags) zend_register_stringl_constant((name), sizeof(name), (str), (len), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name)-1, (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name)-1, (bval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name)-1, (lval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_DOUBLE_CONSTANT(name, dval, flags) zend_register_double_constant((name), sizeof(name)-1, (dval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_STRING_CONSTANT(name, str, flags) zend_register_string_constant((name), sizeof(name)-1, (str), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_STRINGL_CONSTANT(name, str, len, flags) zend_register_stringl_constant((name), sizeof(name)-1, (str), (len), (flags), module_number TSRMLS_CC)
|
||||
|
||||
#define REGISTER_NS_NULL_CONSTANT(ns, name, flags) zend_register_null_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_BOOL_CONSTANT(ns, name, bval, flags) zend_register_bool_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (bval), (flags), module_number TSRMLS_CC)
|
||||
@@ -52,22 +51,23 @@ typedef struct _zend_constant {
|
||||
#define REGISTER_NS_STRING_CONSTANT(ns, name, str, flags) zend_register_string_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (str), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_STRINGL_CONSTANT(ns, name, str, len, flags) zend_register_stringl_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (str), (len), (flags), module_number TSRMLS_CC)
|
||||
|
||||
#define REGISTER_MAIN_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name), (bval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name), (lval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_DOUBLE_CONSTANT(name, dval, flags) zend_register_double_constant((name), sizeof(name), (dval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_STRING_CONSTANT(name, str, flags) zend_register_string_constant((name), sizeof(name), (str), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_STRINGL_CONSTANT(name, str, len, flags) zend_register_stringl_constant((name), sizeof(name), (str), (len), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name)-1, (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name)-1, (bval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name)-1, (lval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_DOUBLE_CONSTANT(name, dval, flags) zend_register_double_constant((name), sizeof(name)-1, (dval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_STRING_CONSTANT(name, str, flags) zend_register_string_constant((name), sizeof(name)-1, (str), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_STRINGL_CONSTANT(name, str, len, flags) zend_register_stringl_constant((name), sizeof(name)-1, (str), (len), (flags), 0 TSRMLS_CC)
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
void clean_module_constants(int module_number TSRMLS_DC);
|
||||
void free_zend_constant(zend_constant *c);
|
||||
void free_zend_constant(zval *zv);
|
||||
int zend_startup_constants(TSRMLS_D);
|
||||
int zend_shutdown_constants(TSRMLS_D);
|
||||
void zend_register_standard_constants(TSRMLS_D);
|
||||
void clean_non_persistent_constants(TSRMLS_D);
|
||||
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC);
|
||||
ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC);
|
||||
ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC);
|
||||
ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC);
|
||||
ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, ulong flags TSRMLS_DC);
|
||||
ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);
|
||||
@@ -76,11 +76,10 @@ ZEND_API void zend_register_string_constant(const char *name, uint name_len, cha
|
||||
ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC);
|
||||
void zend_copy_constants(HashTable *target, HashTable *sourc);
|
||||
void copy_zend_constant(zend_constant *c);
|
||||
zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRMLS_DC);
|
||||
zend_constant *zend_quick_get_constant(const zval *key, ulong flags TSRMLS_DC);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_CONSTANT_DTOR (void (*)(void *)) free_zend_constant
|
||||
#define ZEND_CONSTANT_DTOR free_zend_constant
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+9
-4
@@ -26,8 +26,13 @@
|
||||
/* PHP DTrace probes {{{ */
|
||||
static inline const char *dtrace_get_executed_filename(TSRMLS_D)
|
||||
{
|
||||
if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
|
||||
return EG(current_execute_data)->op_array->filename;
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex) {
|
||||
return ex->func->op_array.filename->val;
|
||||
} else {
|
||||
return zend_get_executed_filename(TSRMLS_C);
|
||||
}
|
||||
@@ -81,7 +86,7 @@ ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC)
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC)
|
||||
{
|
||||
int lineno;
|
||||
const char *filename;
|
||||
@@ -94,7 +99,7 @@ ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_
|
||||
DTRACE_EXECUTE_ENTRY((char *)filename, lineno);
|
||||
}
|
||||
|
||||
execute_internal(execute_data_ptr, fci, return_value_used TSRMLS_CC);
|
||||
execute_internal(execute_data, return_value TSRMLS_CC);
|
||||
|
||||
if (DTRACE_EXECUTE_RETURN_ENABLED()) {
|
||||
DTRACE_EXECUTE_RETURN((char *)filename, lineno);
|
||||
|
||||
+2
-2
@@ -32,11 +32,11 @@ extern "C" {
|
||||
#ifdef HAVE_DTRACE
|
||||
ZEND_API zend_op_array *(*zend_dtrace_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
|
||||
ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC);
|
||||
ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
|
||||
ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
|
||||
ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
|
||||
ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
#include <zend_dtrace_gen.h>
|
||||
|
||||
#endif /* HAVE_DTRACE */
|
||||
|
||||
+226
-205
@@ -34,26 +34,29 @@ static zend_class_entry *error_exception_ce;
|
||||
static zend_object_handlers default_exception_handlers;
|
||||
ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
|
||||
|
||||
void zend_exception_set_previous(zval *exception, zval *add_previous TSRMLS_DC)
|
||||
void zend_exception_set_previous(zend_object *exception, zend_object *add_previous TSRMLS_DC)
|
||||
{
|
||||
zval *previous;
|
||||
zval tmp, *previous, zv, *pzv;
|
||||
|
||||
if (exception == add_previous || !add_previous || !exception) {
|
||||
return;
|
||||
}
|
||||
if (Z_TYPE_P(add_previous) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) {
|
||||
ZVAL_OBJ(&tmp, add_previous);
|
||||
if (!instanceof_function(Z_OBJCE(tmp), default_exception_ce TSRMLS_CC)) {
|
||||
zend_error(E_ERROR, "Cannot set non exception as previous exception");
|
||||
return;
|
||||
}
|
||||
while (exception && exception != add_previous && Z_OBJ_HANDLE_P(exception) != Z_OBJ_HANDLE_P(add_previous)) {
|
||||
previous = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
|
||||
ZVAL_OBJ(&zv, exception);
|
||||
pzv = &zv;
|
||||
do {
|
||||
previous = zend_read_property(default_exception_ce, pzv, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
|
||||
if (Z_TYPE_P(previous) == IS_NULL) {
|
||||
zend_update_property(default_exception_ce, exception, "previous", sizeof("previous")-1, add_previous TSRMLS_CC);
|
||||
Z_DELREF_P(add_previous);
|
||||
zend_update_property(default_exception_ce, pzv, "previous", sizeof("previous")-1, &tmp TSRMLS_CC);
|
||||
GC_REFCOUNT(add_previous)--;
|
||||
return;
|
||||
}
|
||||
exception = previous;
|
||||
}
|
||||
pzv = previous;
|
||||
} while (pzv && Z_OBJ_P(pzv) != add_previous);
|
||||
}
|
||||
|
||||
void zend_exception_save(TSRMLS_D) /* {{{ */
|
||||
@@ -85,12 +88,11 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
#ifdef HAVE_DTRACE
|
||||
if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
|
||||
const char *classname;
|
||||
zend_uint name_len;
|
||||
zend_string *classname;
|
||||
|
||||
if (exception != NULL) {
|
||||
zend_get_object_classname(exception, &classname, &name_len TSRMLS_CC);
|
||||
DTRACE_EXCEPTION_THROWN((char *)classname);
|
||||
classname = zend_get_object_classname(Z_OBJ_P(exception) TSRMLS_CC);
|
||||
DTRACE_EXCEPTION_THROWN(classname->val);
|
||||
} else {
|
||||
DTRACE_EXCEPTION_THROWN(NULL);
|
||||
}
|
||||
@@ -98,9 +100,9 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
|
||||
#endif /* HAVE_DTRACE */
|
||||
|
||||
if (exception != NULL) {
|
||||
zval *previous = EG(exception);
|
||||
zend_exception_set_previous(exception, EG(exception) TSRMLS_CC);
|
||||
EG(exception) = exception;
|
||||
zend_object *previous = EG(exception);
|
||||
zend_exception_set_previous(Z_OBJ_P(exception), EG(exception) TSRMLS_CC);
|
||||
EG(exception) = Z_OBJ_P(exception);
|
||||
if (previous) {
|
||||
return;
|
||||
}
|
||||
@@ -116,7 +118,8 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
|
||||
zend_throw_exception_hook(exception TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (EG(current_execute_data)->opline == NULL ||
|
||||
if (!EG(current_execute_data)->func ||
|
||||
!ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
|
||||
(EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
/* no need to rethrow the exception */
|
||||
return;
|
||||
@@ -129,13 +132,14 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
|
||||
ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if (EG(prev_exception)) {
|
||||
zval_ptr_dtor(&EG(prev_exception));
|
||||
|
||||
OBJ_RELEASE(EG(prev_exception));
|
||||
EG(prev_exception) = NULL;
|
||||
}
|
||||
if (!EG(exception)) {
|
||||
return;
|
||||
}
|
||||
zval_ptr_dtor(&EG(exception));
|
||||
OBJ_RELEASE(EG(exception));
|
||||
EG(exception) = NULL;
|
||||
EG(current_execute_data)->opline = EG(opline_before_exception);
|
||||
#if ZEND_DEBUG
|
||||
@@ -144,37 +148,35 @@ ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */
|
||||
static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval obj;
|
||||
zend_object *object;
|
||||
zval *trace;
|
||||
zval trace;
|
||||
|
||||
Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC);
|
||||
Z_OBJ(obj) = object = zend_objects_new(class_type TSRMLS_CC);
|
||||
Z_OBJ_HT(obj) = &default_exception_handlers;
|
||||
|
||||
object_properties_init(object, class_type);
|
||||
|
||||
ALLOC_ZVAL(trace);
|
||||
Z_UNSET_ISREF_P(trace);
|
||||
Z_SET_REFCOUNT_P(trace, 0);
|
||||
zend_fetch_debug_backtrace(trace, skip_top_traces, 0, 0 TSRMLS_CC);
|
||||
zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0 TSRMLS_CC);
|
||||
Z_SET_REFCOUNT(trace, 0);
|
||||
|
||||
zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC);
|
||||
zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
|
||||
zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, trace TSRMLS_CC);
|
||||
zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, &trace TSRMLS_CC);
|
||||
|
||||
return Z_OBJVAL(obj);
|
||||
return object;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
static zend_object *zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return zend_default_exception_new_ex(class_type, 0 TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value zend_error_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
static zend_object *zend_error_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return zend_default_exception_new_ex(class_type, 2 TSRMLS_CC);
|
||||
}
|
||||
@@ -193,19 +195,19 @@ ZEND_METHOD(exception, __clone)
|
||||
Exception constructor */
|
||||
ZEND_METHOD(exception, __construct)
|
||||
{
|
||||
char *message = NULL;
|
||||
zend_string *message = NULL;
|
||||
long code = 0;
|
||||
zval *object, *previous = NULL;
|
||||
int argc = ZEND_NUM_ARGS(), message_len;
|
||||
int argc = ZEND_NUM_ARGS();
|
||||
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|slO!", &message, &message_len, &code, &previous, default_exception_ce) == FAILURE) {
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|SlO!", &message, &code, &previous, default_exception_ce) == FAILURE) {
|
||||
zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]])");
|
||||
}
|
||||
|
||||
object = getThis();
|
||||
|
||||
if (message) {
|
||||
zend_update_property_stringl(default_exception_ce, object, "message", sizeof("message")-1, message, message_len TSRMLS_CC);
|
||||
zend_update_property_str(default_exception_ce, object, "message", sizeof("message")-1, message TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (code) {
|
||||
@@ -267,10 +269,7 @@ static void _default_exception_get_entry(zval *object, char *name, int name_len,
|
||||
zval *value;
|
||||
|
||||
value = zend_read_property(default_exception_ce, object, name, name_len, 0 TSRMLS_CC);
|
||||
|
||||
*return_value = *value;
|
||||
zval_copy_ctor(return_value);
|
||||
INIT_PZVAL(return_value);
|
||||
ZVAL_COPY(return_value, value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -335,45 +334,43 @@ ZEND_METHOD(error_exception, getSeverity)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ gettraceasstring() macros */
|
||||
#define TRACE_APPEND_CHR(chr) \
|
||||
*str = (char*)erealloc(*str, *len + 1 + 1); \
|
||||
(*str)[(*len)++] = chr
|
||||
#define TRACE_APPEND_CHR(chr) \
|
||||
str = STR_REALLOC(str, str->len + 1, 0); \
|
||||
str->val[str->len - 1] = chr
|
||||
|
||||
#define TRACE_APPEND_STRL(val, vallen) \
|
||||
{ \
|
||||
int l = vallen; \
|
||||
*str = (char*)erealloc(*str, *len + l + 1); \
|
||||
memcpy((*str) + *len, val, l); \
|
||||
*len += l; \
|
||||
#define TRACE_APPEND_STRL(v, l) \
|
||||
{ \
|
||||
str = STR_REALLOC(str, str->len + (l), 0); \
|
||||
memcpy(str->val + str->len - (l), (v), (l)); \
|
||||
}
|
||||
|
||||
#define TRACE_APPEND_STR(val) \
|
||||
TRACE_APPEND_STRL(val, sizeof(val)-1)
|
||||
#define TRACE_APPEND_STR(v) \
|
||||
TRACE_APPEND_STRL((v), sizeof((v))-1)
|
||||
|
||||
#define TRACE_APPEND_KEY(key) \
|
||||
if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
|
||||
if (Z_TYPE_PP(tmp) != IS_STRING) { \
|
||||
zend_error(E_WARNING, "Value for %s is no string", key); \
|
||||
TRACE_APPEND_STR("[unknown]"); \
|
||||
} else { \
|
||||
TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
|
||||
} \
|
||||
}
|
||||
#define TRACE_APPEND_KEY(key) do { \
|
||||
tmp = zend_hash_str_find(ht, key, sizeof(key)-1); \
|
||||
if (tmp) { \
|
||||
if (Z_TYPE_P(tmp) != IS_STRING) { \
|
||||
zend_error(E_WARNING, "Value for %s is no string", key); \
|
||||
TRACE_APPEND_STR("[unknown]"); \
|
||||
} else { \
|
||||
TRACE_APPEND_STRL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define TRACE_ARG_APPEND(vallen) \
|
||||
*str = (char*)erealloc(*str, *len + 1 + vallen); \
|
||||
memmove((*str) + *len - l_added + 1 + vallen, (*str) + *len - l_added + 1, l_added);
|
||||
#define TRACE_ARG_APPEND(vallen) do { \
|
||||
int len = str->len; \
|
||||
str = STR_REALLOC(str, len + vallen, 0); \
|
||||
memmove(str->val + len - l_added + 1 + vallen, str->val + len - l_added + 1, l_added); \
|
||||
} while (0)
|
||||
|
||||
/* }}} */
|
||||
|
||||
static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||
static void _build_trace_args(zval *arg, zend_string **str_ptr TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char **str;
|
||||
int *len;
|
||||
|
||||
str = va_arg(args, char**);
|
||||
len = va_arg(args, int*);
|
||||
zend_string *str = *str_ptr;
|
||||
|
||||
/* the trivial way would be to do:
|
||||
* convert_to_string_ex(arg);
|
||||
@@ -381,48 +378,49 @@ static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, z
|
||||
* but that could cause some E_NOTICE and also damn long lines.
|
||||
*/
|
||||
|
||||
switch (Z_TYPE_PP(arg)) {
|
||||
ZVAL_DEREF(arg);
|
||||
switch (Z_TYPE_P(arg)) {
|
||||
case IS_NULL:
|
||||
TRACE_APPEND_STR("NULL, ");
|
||||
break;
|
||||
case IS_STRING: {
|
||||
int l_added;
|
||||
TRACE_APPEND_CHR('\'');
|
||||
if (Z_STRLEN_PP(arg) > 15) {
|
||||
TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
|
||||
if (Z_STRLEN_P(arg) > 15) {
|
||||
TRACE_APPEND_STRL(Z_STRVAL_P(arg), 15);
|
||||
TRACE_APPEND_STR("...', ");
|
||||
l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
|
||||
} else {
|
||||
l_added = Z_STRLEN_PP(arg);
|
||||
TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
|
||||
l_added = Z_STRLEN_P(arg);
|
||||
TRACE_APPEND_STRL(Z_STRVAL_P(arg), l_added);
|
||||
TRACE_APPEND_STR("', ");
|
||||
l_added += 3 + 1;
|
||||
}
|
||||
while (--l_added) {
|
||||
unsigned char chr = (*str)[*len - l_added];
|
||||
unsigned char chr = str->val[str->len - l_added];
|
||||
if (chr < 32 || chr == '\\' || chr > 126) {
|
||||
(*str)[*len - l_added] = '\\';
|
||||
str->val[str->len - l_added] = '\\';
|
||||
|
||||
switch (chr) {
|
||||
case '\n':
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = 'n';
|
||||
str->val[str->len - l_added] = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = 'r';
|
||||
str->val[str->len - l_added] = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = 't';
|
||||
str->val[str->len - l_added] = 't';
|
||||
break;
|
||||
case '\f':
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = 'f';
|
||||
str->val[str->len - l_added] = 'f';
|
||||
break;
|
||||
case '\v':
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = 'v';
|
||||
str->val[str->len - l_added] = 'v';
|
||||
break;
|
||||
#ifndef PHP_WIN32
|
||||
case '\e':
|
||||
@@ -430,43 +428,47 @@ static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, z
|
||||
case VK_ESCAPE:
|
||||
#endif
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = 'e';
|
||||
str->val[str->len - l_added] = 'e';
|
||||
break;
|
||||
case '\\':
|
||||
TRACE_ARG_APPEND(1);
|
||||
(*str)[++(*len) - l_added] = '\\';
|
||||
str->val[str->len - l_added] = '\\';
|
||||
break;
|
||||
default:
|
||||
TRACE_ARG_APPEND(3);
|
||||
(*str)[*len - l_added + 1] = 'x';
|
||||
str->val[str->len - l_added - 2] = 'x';
|
||||
if ((chr >> 4) < 10) {
|
||||
(*str)[*len - l_added + 2] = (chr >> 4) + '0';
|
||||
str->val[str->len - l_added - 1] = (chr >> 4) + '0';
|
||||
} else {
|
||||
(*str)[*len - l_added + 2] = (chr >> 4) + 'A' - 10;
|
||||
str->val[str->len - l_added - 1] = (chr >> 4) + 'A' - 10;
|
||||
}
|
||||
if (chr % 16 < 10) {
|
||||
(*str)[*len - l_added + 3] = chr % 16 + '0';
|
||||
str->val[str->len - l_added] = chr % 16 + '0';
|
||||
} else {
|
||||
(*str)[*len - l_added + 3] = chr % 16 + 'A' - 10;
|
||||
str->val[str->len - l_added] = chr % 16 + 'A' - 10;
|
||||
}
|
||||
*len += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IS_BOOL:
|
||||
if (Z_LVAL_PP(arg)) {
|
||||
TRACE_APPEND_STR("true, ");
|
||||
} else {
|
||||
TRACE_APPEND_STR("false, ");
|
||||
}
|
||||
case IS_FALSE:
|
||||
TRACE_APPEND_STR("false, ");
|
||||
break;
|
||||
case IS_RESOURCE:
|
||||
case IS_TRUE:
|
||||
TRACE_APPEND_STR("true, ");
|
||||
break;
|
||||
case IS_RESOURCE: {
|
||||
long lval = Z_RES_HANDLE_P(arg);
|
||||
char s_tmp[MAX_LENGTH_OF_LONG + 1];
|
||||
int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
|
||||
TRACE_APPEND_STR("Resource id #");
|
||||
/* break; */
|
||||
TRACE_APPEND_STRL(s_tmp, l_tmp);
|
||||
TRACE_APPEND_STR(", ");
|
||||
break;
|
||||
}
|
||||
case IS_LONG: {
|
||||
long lval = Z_LVAL_PP(arg);
|
||||
long lval = Z_LVAL_P(arg);
|
||||
char s_tmp[MAX_LENGTH_OF_LONG + 1];
|
||||
int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
|
||||
TRACE_APPEND_STRL(s_tmp, l_tmp);
|
||||
@@ -474,7 +476,7 @@ static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, z
|
||||
break;
|
||||
}
|
||||
case IS_DOUBLE: {
|
||||
double dval = Z_DVAL_PP(arg);
|
||||
double dval = Z_DVAL_P(arg);
|
||||
char *s_tmp;
|
||||
int l_tmp;
|
||||
|
||||
@@ -490,58 +492,52 @@ static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, z
|
||||
TRACE_APPEND_STR("Array, ");
|
||||
break;
|
||||
case IS_OBJECT: {
|
||||
const char *class_name;
|
||||
zend_uint class_name_len;
|
||||
int dup;
|
||||
zend_string *class_name;
|
||||
|
||||
TRACE_APPEND_STR("Object(");
|
||||
|
||||
dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
|
||||
|
||||
TRACE_APPEND_STRL(class_name, class_name_len);
|
||||
if(!dup) {
|
||||
efree((char*)class_name);
|
||||
}
|
||||
class_name = zend_get_object_classname(Z_OBJ_P(arg) TSRMLS_CC);
|
||||
|
||||
TRACE_APPEND_STRL(class_name->val, class_name->len);
|
||||
TRACE_APPEND_STR("), ");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
*str_ptr = str;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||
static void _build_trace_string(zval *frame, ulong index, zend_string **str_ptr, int *num TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *s_tmp, **str;
|
||||
int *len, *num;
|
||||
char *s_tmp;
|
||||
int len;
|
||||
long line;
|
||||
HashTable *ht = Z_ARRVAL_PP(frame);
|
||||
zval **file, **tmp;
|
||||
HashTable *ht;
|
||||
zval *file, *tmp;
|
||||
zend_string *str = *str_ptr;
|
||||
|
||||
if (Z_TYPE_PP(frame) != IS_ARRAY) {
|
||||
zend_error(E_WARNING, "Expected array for frame %lu", hash_key->h);
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
if (Z_TYPE_P(frame) != IS_ARRAY) {
|
||||
zend_error(E_WARNING, "Expected array for frame %lu", index);
|
||||
return;
|
||||
}
|
||||
|
||||
str = va_arg(args, char**);
|
||||
len = va_arg(args, int*);
|
||||
num = va_arg(args, int*);
|
||||
|
||||
ht = Z_ARRVAL_P(frame);
|
||||
s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
|
||||
sprintf(s_tmp, "#%d ", (*num)++);
|
||||
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
|
||||
len = sprintf(s_tmp, "#%d ", (*num)++);
|
||||
TRACE_APPEND_STRL(s_tmp, len);
|
||||
efree(s_tmp);
|
||||
if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
|
||||
if (Z_TYPE_PP(file) != IS_STRING) {
|
||||
file = zend_hash_str_find(ht, "file", sizeof("file")-1);
|
||||
if (file) {
|
||||
if (Z_TYPE_P(file) != IS_STRING) {
|
||||
zend_error(E_WARNING, "Function name is no string");
|
||||
TRACE_APPEND_STR("[unknown function]");
|
||||
} else{
|
||||
if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
|
||||
if (Z_TYPE_PP(tmp) == IS_LONG) {
|
||||
line = Z_LVAL_PP(tmp);
|
||||
tmp = zend_hash_str_find(ht, "line", sizeof("line")-1);
|
||||
if (tmp) {
|
||||
if (Z_TYPE_P(tmp) == IS_LONG) {
|
||||
line = Z_LVAL_P(tmp);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Line is no long");
|
||||
line = 0;
|
||||
@@ -549,9 +545,9 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg
|
||||
} else {
|
||||
line = 0;
|
||||
}
|
||||
s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
|
||||
sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
|
||||
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
|
||||
s_tmp = emalloc(Z_STRLEN_P(file) + MAX_LENGTH_OF_LONG + 4 + 1);
|
||||
len = sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_P(file), line);
|
||||
TRACE_APPEND_STRL(s_tmp, len);
|
||||
efree(s_tmp);
|
||||
}
|
||||
} else {
|
||||
@@ -561,19 +557,25 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg
|
||||
TRACE_APPEND_KEY("type");
|
||||
TRACE_APPEND_KEY("function");
|
||||
TRACE_APPEND_CHR('(');
|
||||
if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
|
||||
if (Z_TYPE_PP(tmp) == IS_ARRAY) {
|
||||
int last_len = *len;
|
||||
zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)_build_trace_args, 2, str, len);
|
||||
if (last_len != *len) {
|
||||
*len -= 2; /* remove last ', ' */
|
||||
tmp = zend_hash_str_find(ht, "args", sizeof("args")-1);
|
||||
if (tmp) {
|
||||
if (Z_TYPE_P(tmp) == IS_ARRAY) {
|
||||
int last_len = str->len;
|
||||
zval *arg;
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) {
|
||||
_build_trace_args(arg, &str TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (last_len != str->len) {
|
||||
str->len -= 2; /* remove last ', ' */
|
||||
}
|
||||
} else {
|
||||
zend_error(E_WARNING, "args element is no array");
|
||||
}
|
||||
}
|
||||
TRACE_APPEND_STR(")\n");
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
*str_ptr = str;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -581,25 +583,27 @@ static int _build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list arg
|
||||
Obtain the backtrace for the exception as a string (instead of an array) */
|
||||
ZEND_METHOD(exception, getTraceAsString)
|
||||
{
|
||||
zval *trace;
|
||||
char *res, **str, *s_tmp;
|
||||
int res_len = 0, *len = &res_len, num = 0;
|
||||
zval *trace, *frame;
|
||||
ulong index;
|
||||
zend_string *str, *key;
|
||||
int num = 0, len;
|
||||
char s_tmp[MAX_LENGTH_OF_LONG + 7 + 1 + 1];
|
||||
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
res = estrdup("");
|
||||
str = &res;
|
||||
str = STR_ALLOC(0, 0);
|
||||
|
||||
trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC);
|
||||
zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)_build_trace_string, 3, str, len, &num);
|
||||
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(trace), index, key, frame) {
|
||||
_build_trace_string(frame, index, &str, &num TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
|
||||
sprintf(s_tmp, "#%d {main}", num);
|
||||
TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
|
||||
efree(s_tmp);
|
||||
len = sprintf(s_tmp, "#%d {main}", num);
|
||||
TRACE_APPEND_STRL(s_tmp, len);
|
||||
|
||||
res[res_len] = '\0';
|
||||
RETURN_STRINGL(res, res_len, 0);
|
||||
str->val[str->len] = '\0';
|
||||
|
||||
RETURN_NEW_STR(str);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -613,7 +617,7 @@ ZEND_METHOD(exception, getPrevious)
|
||||
|
||||
previous = zend_read_property(default_exception_ce, getThis(), "previous", sizeof("previous")-1, 1 TSRMLS_CC);
|
||||
RETURN_ZVAL(previous, 1, 0);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ */
|
||||
{
|
||||
@@ -627,22 +631,33 @@ int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ *
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
zend_string *zend_strpprintf(int max_len, const char *format, ...) /* {{{ */
|
||||
{
|
||||
va_list arg;
|
||||
zend_string *str;
|
||||
|
||||
va_start(arg, format);
|
||||
str = zend_vstrpprintf(max_len, format, arg);
|
||||
va_end(arg);
|
||||
return str;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string Exception::__toString()
|
||||
Obtain the string representation of the Exception object */
|
||||
ZEND_METHOD(exception, __toString)
|
||||
{
|
||||
zval message, file, line, *trace, *exception;
|
||||
char *str, *prev_str;
|
||||
int len = 0;
|
||||
zval message, file, line, trace, *exception;
|
||||
zend_string *str, *prev_str;
|
||||
zend_fcall_info fci;
|
||||
zval fname;
|
||||
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
str = estrndup("", 0);
|
||||
str = STR_EMPTY_ALLOC();
|
||||
|
||||
exception = getThis();
|
||||
ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 1);
|
||||
ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1);
|
||||
|
||||
while (exception && Z_TYPE_P(exception) == IS_OBJECT) {
|
||||
prev_str = str;
|
||||
@@ -656,51 +671,49 @@ ZEND_METHOD(exception, __toString)
|
||||
|
||||
fci.size = sizeof(fci);
|
||||
fci.function_table = &Z_OBJCE_P(exception)->function_table;
|
||||
fci.function_name = &fname;
|
||||
ZVAL_COPY_VALUE(&fci.function_name, &fname);
|
||||
fci.symbol_table = NULL;
|
||||
fci.object_ptr = exception;
|
||||
fci.retval_ptr_ptr = &trace;
|
||||
fci.object = Z_OBJ_P(exception);
|
||||
fci.retval = &trace;
|
||||
fci.param_count = 0;
|
||||
fci.params = NULL;
|
||||
fci.no_separation = 1;
|
||||
|
||||
zend_call_function(&fci, NULL TSRMLS_CC);
|
||||
|
||||
if (Z_TYPE_P(trace) != IS_STRING) {
|
||||
if (Z_TYPE(trace) != IS_STRING) {
|
||||
zval_ptr_dtor(&trace);
|
||||
trace = NULL;
|
||||
ZVAL_UNDEF(&trace);
|
||||
}
|
||||
|
||||
if (Z_STRLEN(message) > 0) {
|
||||
len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s",
|
||||
Z_OBJCE_P(exception)->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
|
||||
(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n",
|
||||
len ? "\n\nNext " : "", prev_str);
|
||||
str = zend_strpprintf(0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s",
|
||||
Z_OBJCE_P(exception)->name->val, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
|
||||
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
|
||||
prev_str->len ? "\n\nNext " : "", prev_str->val);
|
||||
} else {
|
||||
len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s",
|
||||
Z_OBJCE_P(exception)->name, Z_STRVAL(file), Z_LVAL(line),
|
||||
(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n",
|
||||
len ? "\n\nNext " : "", prev_str);
|
||||
str = zend_strpprintf(0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s",
|
||||
Z_OBJCE_P(exception)->name->val, Z_STRVAL(file), Z_LVAL(line),
|
||||
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
|
||||
prev_str->len ? "\n\nNext " : "", prev_str->val);
|
||||
}
|
||||
efree(prev_str);
|
||||
STR_RELEASE(prev_str);
|
||||
zval_dtor(&message);
|
||||
zval_dtor(&file);
|
||||
zval_dtor(&line);
|
||||
|
||||
exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 0 TSRMLS_CC);
|
||||
|
||||
if (trace) {
|
||||
zval_ptr_dtor(&trace);
|
||||
}
|
||||
zval_ptr_dtor(&trace);
|
||||
|
||||
}
|
||||
zval_dtor(&fname);
|
||||
|
||||
/* We store the result in the private property string so we can access
|
||||
* the result in uncaught exception handlers without memleaks. */
|
||||
zend_update_property_string(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
|
||||
zend_update_property_str(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
|
||||
|
||||
RETURN_STRINGL(str, len, 0);
|
||||
RETURN_STR(str);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -769,7 +782,7 @@ void zend_register_default_exception(TSRMLS_D) /* {{{ */
|
||||
zend_declare_property_null(default_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
|
||||
error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce, NULL TSRMLS_CC);
|
||||
error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce TSRMLS_CC);
|
||||
error_exception_ce->create_object = zend_error_exception_new;
|
||||
zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||||
}
|
||||
@@ -787,11 +800,10 @@ ZEND_API zend_class_entry *zend_get_error_exception(TSRMLS_D) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *ex;
|
||||
zval ex;
|
||||
|
||||
MAKE_STD_ZVAL(ex);
|
||||
if (exception_ce) {
|
||||
if (!instanceof_function(exception_ce, default_exception_ce TSRMLS_CC)) {
|
||||
zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class");
|
||||
@@ -800,41 +812,43 @@ ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, const char
|
||||
} else {
|
||||
exception_ce = default_exception_ce;
|
||||
}
|
||||
object_init_ex(ex, exception_ce);
|
||||
object_init_ex(&ex, exception_ce);
|
||||
|
||||
|
||||
if (message) {
|
||||
zend_update_property_string(default_exception_ce, ex, "message", sizeof("message")-1, message TSRMLS_CC);
|
||||
zend_update_property_string(default_exception_ce, &ex, "message", sizeof("message")-1, message TSRMLS_CC);
|
||||
}
|
||||
if (code) {
|
||||
zend_update_property_long(default_exception_ce, ex, "code", sizeof("code")-1, code TSRMLS_CC);
|
||||
zend_update_property_long(default_exception_ce, &ex, "code", sizeof("code")-1, code TSRMLS_CC);
|
||||
}
|
||||
|
||||
zend_throw_exception_internal(ex TSRMLS_CC);
|
||||
return ex;
|
||||
zend_throw_exception_internal(&ex TSRMLS_CC);
|
||||
return Z_OBJ(ex);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...) /* {{{ */
|
||||
ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...) /* {{{ */
|
||||
{
|
||||
va_list arg;
|
||||
char *message;
|
||||
zval *zexception;
|
||||
zend_object *obj;
|
||||
|
||||
va_start(arg, format);
|
||||
zend_vspprintf(&message, 0, format, arg);
|
||||
va_end(arg);
|
||||
zexception = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
|
||||
obj = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
|
||||
efree(message);
|
||||
return zexception;
|
||||
return obj;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *ex = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
|
||||
zend_update_property_long(default_exception_ce, ex, "severity", sizeof("severity")-1, severity TSRMLS_CC);
|
||||
return ex;
|
||||
zval ex;
|
||||
zend_object *obj = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
|
||||
ZVAL_OBJ(&ex, obj);
|
||||
zend_update_property_long(default_exception_ce, &ex, "severity", sizeof("severity")-1, severity TSRMLS_CC);
|
||||
return obj;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -849,29 +863,36 @@ static void zend_error_va(int type, const char *file, uint lineno, const char *f
|
||||
/* }}} */
|
||||
|
||||
/* This function doesn't return if it uses E_ERROR */
|
||||
ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC) /* {{{ */
|
||||
ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce_exception = Z_OBJCE_P(exception);
|
||||
zval exception;
|
||||
zend_class_entry *ce_exception;
|
||||
|
||||
ZVAL_OBJ(&exception, ex);
|
||||
ce_exception = Z_OBJCE(exception);
|
||||
if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) {
|
||||
zval *str, *file, *line;
|
||||
zval tmp, *str, *file, *line;
|
||||
|
||||
EG(exception) = NULL;
|
||||
|
||||
zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &str);
|
||||
zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &tmp);
|
||||
if (!EG(exception)) {
|
||||
if (Z_TYPE_P(str) != IS_STRING) {
|
||||
zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name);
|
||||
if (Z_TYPE(tmp) != IS_STRING) {
|
||||
zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name->val);
|
||||
} else {
|
||||
zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name : Z_STRVAL_P(str) TSRMLS_CC);
|
||||
zend_update_property_string(default_exception_ce, &exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name->val : Z_STRVAL(tmp) TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
zval_ptr_dtor(&str);
|
||||
zval_ptr_dtor(&tmp);
|
||||
|
||||
if (EG(exception)) {
|
||||
zval zv;
|
||||
|
||||
ZVAL_OBJ(&zv, EG(exception));
|
||||
/* do the best we can to inform about the inner exception */
|
||||
if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) {
|
||||
file = zend_read_property(default_exception_ce, EG(exception), "file", sizeof("file")-1, 1 TSRMLS_CC);
|
||||
line = zend_read_property(default_exception_ce, EG(exception), "line", sizeof("line")-1, 1 TSRMLS_CC);
|
||||
file = zend_read_property(default_exception_ce, &zv, "file", sizeof("file")-1, 1 TSRMLS_CC);
|
||||
line = zend_read_property(default_exception_ce, &zv, "line", sizeof("line")-1, 1 TSRMLS_CC);
|
||||
|
||||
convert_to_string(file);
|
||||
file = (Z_STRLEN_P(file) > 0) ? file : NULL;
|
||||
@@ -880,12 +901,12 @@ ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC) /* {
|
||||
file = NULL;
|
||||
line = NULL;
|
||||
}
|
||||
zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE_P(EG(exception))->name, ce_exception->name);
|
||||
zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE(zv)->name->val, ce_exception->name->val);
|
||||
}
|
||||
|
||||
str = zend_read_property(default_exception_ce, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
|
||||
file = zend_read_property(default_exception_ce, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
|
||||
line = zend_read_property(default_exception_ce, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
|
||||
str = zend_read_property(default_exception_ce, &exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
|
||||
file = zend_read_property(default_exception_ce, &exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
|
||||
line = zend_read_property(default_exception_ce, &exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
|
||||
|
||||
convert_to_string(str);
|
||||
convert_to_string(file);
|
||||
@@ -893,7 +914,7 @@ ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC) /* {
|
||||
|
||||
zend_error_va(severity, (Z_STRLEN_P(file) > 0) ? Z_STRVAL_P(file) : NULL, Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str));
|
||||
} else {
|
||||
zend_error(severity, "Uncaught exception '%s'", ce_exception->name);
|
||||
zend_error(severity, "Uncaught exception '%s'", ce_exception->name->val);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
ZEND_API void zend_exception_set_previous(zval *exception, zval *add_previous TSRMLS_DC);
|
||||
ZEND_API void zend_exception_set_previous(zend_object *exception, zend_object *add_previous TSRMLS_DC);
|
||||
ZEND_API void zend_exception_save(TSRMLS_D);
|
||||
ZEND_API void zend_exception_restore(TSRMLS_D);
|
||||
|
||||
@@ -40,20 +40,21 @@ ZEND_API void zend_register_default_classes(TSRMLS_D);
|
||||
|
||||
/* exception_ce NULL or zend_exception_get_default() or a derived class
|
||||
* message NULL or the message of the exception */
|
||||
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC);
|
||||
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...);
|
||||
ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC);
|
||||
ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...);
|
||||
ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC);
|
||||
ZEND_API void zend_clear_exception(TSRMLS_D);
|
||||
|
||||
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC);
|
||||
ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC);
|
||||
|
||||
extern ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
|
||||
|
||||
/* show an exception using zend_error(severity,...), severity should be E_ERROR */
|
||||
ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC);
|
||||
ZEND_API void zend_exception_error(zend_object *exception, int severity TSRMLS_DC);
|
||||
|
||||
/* do not export, in php it's available thru spprintf directly */
|
||||
int zend_spprintf(char **message, int max_len, const char *format, ...);
|
||||
zend_string *zend_strpprintf(int max_len, const char *format, ...);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
||||
+1223
-1164
File diff suppressed because it is too large
Load Diff
+142
-207
@@ -27,76 +27,48 @@
|
||||
#include "zend_operators.h"
|
||||
#include "zend_variables.h"
|
||||
|
||||
typedef union _temp_variable {
|
||||
zval tmp_var;
|
||||
struct {
|
||||
zval **ptr_ptr;
|
||||
zval *ptr;
|
||||
zend_bool fcall_returned_reference;
|
||||
} var;
|
||||
struct {
|
||||
zval **ptr_ptr; /* shared with var.ptr_ptr */
|
||||
zval *str;
|
||||
zend_uint offset;
|
||||
} str_offset;
|
||||
struct {
|
||||
zval **ptr_ptr; /* shared with var.ptr_ptr */
|
||||
zval *ptr; /* shared with var.ptr */
|
||||
HashPointer fe_pos;
|
||||
} fe;
|
||||
zend_class_entry *class_entry;
|
||||
} temp_variable;
|
||||
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
struct _zend_fcall_info;
|
||||
ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);
|
||||
ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
|
||||
void init_executor(TSRMLS_D);
|
||||
void shutdown_executor(TSRMLS_D);
|
||||
void shutdown_destructors(TSRMLS_D);
|
||||
ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC);
|
||||
ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC);
|
||||
ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
|
||||
ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
ZEND_API int zend_is_true(zval *op TSRMLS_DC);
|
||||
ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
|
||||
ZEND_API int zend_lookup_class_ex(const char *name, int name_length, const zend_literal *key, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload TSRMLS_DC);
|
||||
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
|
||||
ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC);
|
||||
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
|
||||
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
|
||||
|
||||
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC);
|
||||
ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
|
||||
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
|
||||
ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
|
||||
|
||||
static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
|
||||
{
|
||||
if (!Z_DELREF_P(zval_ptr)) {
|
||||
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
|
||||
GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
|
||||
zval_dtor(zval_ptr);
|
||||
efree_rel(zval_ptr);
|
||||
} else {
|
||||
if (Z_REFCOUNT_P(zval_ptr) == 1) {
|
||||
Z_UNSET_ISREF_P(zval_ptr);
|
||||
if (Z_REFCOUNTED_P(zval_ptr)) {
|
||||
if (!Z_DELREF_P(zval_ptr)) {
|
||||
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
|
||||
_zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
|
||||
} else {
|
||||
GC_ZVAL_CHECK_POSSIBLE_ROOT(zval_ptr);
|
||||
}
|
||||
|
||||
GC_ZVAL_CHECK_POSSIBLE_ROOT(zval_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void i_zval_ptr_dtor_nogc(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
|
||||
{
|
||||
if (!Z_DELREF_P(zval_ptr)) {
|
||||
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
|
||||
GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
|
||||
zval_dtor(zval_ptr);
|
||||
efree_rel(zval_ptr);
|
||||
} else {
|
||||
if (Z_REFCOUNT_P(zval_ptr) == 1) {
|
||||
Z_UNSET_ISREF_P(zval_ptr);
|
||||
if (Z_REFCOUNTED_P(zval_ptr)) {
|
||||
if (!Z_DELREF_P(zval_ptr)) {
|
||||
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
|
||||
_zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,15 +77,22 @@ static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC)
|
||||
{
|
||||
int result;
|
||||
|
||||
again:
|
||||
switch (Z_TYPE_P(op)) {
|
||||
case IS_UNDEF:
|
||||
case IS_NULL:
|
||||
case IS_FALSE:
|
||||
result = 0;
|
||||
break;
|
||||
case IS_TRUE:
|
||||
result = 1;
|
||||
break;
|
||||
case IS_LONG:
|
||||
case IS_BOOL:
|
||||
case IS_RESOURCE:
|
||||
result = (Z_LVAL_P(op)?1:0);
|
||||
break;
|
||||
case IS_RESOURCE:
|
||||
result = (Z_RES_HANDLE_P(op)?1:0);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
result = (Z_DVAL_P(op) ? 1 : 0);
|
||||
break;
|
||||
@@ -129,26 +108,32 @@ static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC)
|
||||
result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
if(IS_ZEND_STD_OBJECT(*op)) {
|
||||
if (IS_ZEND_STD_OBJECT(*op)) {
|
||||
if (Z_OBJ_HT_P(op)->cast_object) {
|
||||
zval tmp;
|
||||
if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) {
|
||||
result = Z_LVAL(tmp);
|
||||
if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) {
|
||||
result = Z_TYPE(tmp) == IS_TRUE;
|
||||
break;
|
||||
}
|
||||
zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val);
|
||||
} else if (Z_OBJ_HT_P(op)->get) {
|
||||
zval *tmp = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);
|
||||
if(Z_TYPE_P(tmp) != IS_OBJECT) {
|
||||
zval rv;
|
||||
zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC);
|
||||
if (Z_TYPE_P(tmp) != IS_OBJECT) {
|
||||
/* for safety - avoid loop */
|
||||
convert_to_boolean(tmp);
|
||||
result = Z_LVAL_P(tmp);
|
||||
zval_ptr_dtor(&tmp);
|
||||
result = Z_TYPE_P(tmp) == IS_TRUE;
|
||||
zval_ptr_dtor(tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = 1;
|
||||
break;
|
||||
case IS_REFERENCE:
|
||||
op = Z_REFVAL_P(op);
|
||||
goto again;
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
break;
|
||||
@@ -156,36 +141,40 @@ static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC)
|
||||
return result;
|
||||
}
|
||||
|
||||
ZEND_API int zval_update_constant(zval **pp, zend_bool inline_change TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_no_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_ex(zval **pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_inline_change(zval *pp, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
|
||||
|
||||
/* dedicated Zend executor functions - do not use! */
|
||||
#define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
|
||||
#define ZEND_VM_STACK_PAGE_SIZE (16 * 1024) /* should be a power of 2 */
|
||||
|
||||
struct _zend_vm_stack {
|
||||
void **top;
|
||||
void **end;
|
||||
zval *top;
|
||||
zval *end;
|
||||
zend_vm_stack prev;
|
||||
};
|
||||
|
||||
#define ZEND_VM_STACK_ELEMETS(stack) \
|
||||
((void**)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
|
||||
#define ZEND_VM_STACK_HEADER_SLOT \
|
||||
((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
|
||||
|
||||
#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
|
||||
do { \
|
||||
if (UNEXPECTED((count) > \
|
||||
EG(argument_stack)->end - EG(argument_stack)->top)) { \
|
||||
zend_vm_stack_extend((count) TSRMLS_CC); \
|
||||
} \
|
||||
#define ZEND_VM_STACK_ELEMETS(stack) \
|
||||
(((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOT)
|
||||
|
||||
#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
|
||||
do { \
|
||||
if (UNEXPECTED(((count) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) > \
|
||||
(size_t)(((char*)EG(argument_stack)->end) - \
|
||||
((char*)EG(argument_stack)->top)))) { \
|
||||
zend_vm_stack_extend((count) TSRMLS_CC); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
|
||||
zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(void*) * count);
|
||||
zend_vm_stack page = (zend_vm_stack)emalloc(count * ZEND_MM_ALIGNED_SIZE(sizeof(zval)));
|
||||
|
||||
page->top = ZEND_VM_STACK_ELEMETS(page);
|
||||
page->end = page->top + count;
|
||||
page->end = (zval*)page + count;
|
||||
page->prev = NULL;
|
||||
return page;
|
||||
}
|
||||
@@ -193,6 +182,7 @@ static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
|
||||
static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
|
||||
{
|
||||
EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
|
||||
EG(argument_stack)->top++;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
|
||||
@@ -208,141 +198,77 @@ static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
|
||||
|
||||
static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
|
||||
{
|
||||
zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
|
||||
int size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval));
|
||||
zend_vm_stack p = zend_vm_stack_new_page(
|
||||
(size >= (ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) ?
|
||||
(size + ((ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) &
|
||||
~((ZEND_VM_STACK_PAGE_SIZE * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) :
|
||||
ZEND_VM_STACK_PAGE_SIZE);
|
||||
p->prev = EG(argument_stack);
|
||||
EG(argument_stack) = p;
|
||||
}
|
||||
|
||||
static zend_always_inline void **zend_vm_stack_top(TSRMLS_D)
|
||||
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
|
||||
{
|
||||
return EG(argument_stack)->top;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
|
||||
{
|
||||
*(EG(argument_stack)->top++) = ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline void *zend_vm_stack_pop(TSRMLS_D)
|
||||
{
|
||||
void *el = *(--EG(argument_stack)->top);
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
size = (size + (sizeof(void*) - 1)) / sizeof(void*);
|
||||
|
||||
/* the following comparison must be optimized out at compile time */
|
||||
if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
|
||||
int extra = (ZEND_MM_ALIGNMENT - ((zend_uintptr_t)EG(argument_stack)->top & (ZEND_MM_ALIGNMENT - 1))) / sizeof(void*);
|
||||
|
||||
if (UNEXPECTED(size + extra + ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*) >
|
||||
(zend_uintptr_t)(EG(argument_stack)->end - EG(argument_stack)->top))) {
|
||||
zend_vm_stack_extend(size TSRMLS_CC);
|
||||
} else {
|
||||
void **old_top = EG(argument_stack)->top;
|
||||
|
||||
EG(argument_stack)->top += extra;
|
||||
/* store old top on the stack */
|
||||
*EG(argument_stack)->top = (void*)old_top;
|
||||
EG(argument_stack)->top += ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*);
|
||||
}
|
||||
} else {
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED((int)size);
|
||||
int used_stack = ZEND_CALL_FRAME_SLOT + num_args;
|
||||
zend_execute_data *call;
|
||||
|
||||
if (ZEND_USER_CODE(func->type)) {
|
||||
used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
|
||||
}
|
||||
ret = (void*)EG(argument_stack)->top;
|
||||
EG(argument_stack)->top += size;
|
||||
return ret;
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(used_stack);
|
||||
call = (zend_execute_data*)EG(argument_stack)->top;
|
||||
EG(argument_stack)->top += used_stack;
|
||||
call->func = func;
|
||||
call->num_args = 0;
|
||||
call->flags = flags;
|
||||
call->called_scope = called_scope;
|
||||
call->object = object;
|
||||
call->prev_nested_call = prev;
|
||||
return call;
|
||||
}
|
||||
|
||||
static zend_always_inline void** zend_vm_stack_frame_base(zend_execute_data *ex)
|
||||
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
|
||||
{
|
||||
return (void**)((char*)ex->call_slots +
|
||||
ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls);
|
||||
zend_uint first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
|
||||
|
||||
if (UNEXPECTED(call->num_args > first_extra_arg)) {
|
||||
zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
|
||||
zval *p = end + (call->num_args - first_extra_arg);
|
||||
do {
|
||||
p--;
|
||||
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||
} while (p != end);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
|
||||
static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call TSRMLS_DC)
|
||||
{
|
||||
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
|
||||
zend_uint num_args = call->num_args;
|
||||
|
||||
if (num_args > 0) {
|
||||
zval *end = ZEND_CALL_ARG(call, 1);
|
||||
zval *p = end + num_args;
|
||||
|
||||
do {
|
||||
p--;
|
||||
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||
} while (p != end);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC)
|
||||
{
|
||||
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (zval*)call)) {
|
||||
zend_vm_stack p = EG(argument_stack);
|
||||
|
||||
EG(argument_stack) = p->prev;
|
||||
efree(p);
|
||||
} else {
|
||||
EG(argument_stack)->top = (void**)ptr;
|
||||
EG(argument_stack)->top = (zval*)call;
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
|
||||
{
|
||||
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
|
||||
zend_vm_stack p = EG(argument_stack);
|
||||
|
||||
EG(argument_stack) = p->prev;
|
||||
efree(p);
|
||||
} else {
|
||||
/* the following comparison must be optimized out at compile time */
|
||||
if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
|
||||
ptr = (void*)(((char*)ptr) - ZEND_MM_ALIGNED_SIZE(sizeof(void*)));
|
||||
EG(argument_stack)->top = *(void***)ptr;
|
||||
} else {
|
||||
EG(argument_stack)->top = (void**)ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
|
||||
{
|
||||
void **p = EG(argument_stack)->top - 1;
|
||||
void **end = p - (int)(zend_uintptr_t)*p;
|
||||
|
||||
while (p != end) {
|
||||
zval *q = (zval *) *(--p);
|
||||
*p = NULL;
|
||||
i_zval_ptr_dtor(q ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||
}
|
||||
if (nested) {
|
||||
EG(argument_stack)->top = p;
|
||||
} else {
|
||||
zend_vm_stack_free_int(p TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
|
||||
{
|
||||
if (ex) {
|
||||
void **p = ex->function_state.arguments;
|
||||
return (int)(zend_uintptr_t) *p;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zval** zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
|
||||
{
|
||||
void **p = ex->function_state.arguments;
|
||||
int arg_count = (int)(zend_uintptr_t) *p;
|
||||
|
||||
if (UNEXPECTED(requested_arg > arg_count)) {
|
||||
return NULL;
|
||||
}
|
||||
return (zval**)p - arg_count + requested_arg - 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
|
||||
{
|
||||
return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data);
|
||||
}
|
||||
|
||||
static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
|
||||
{
|
||||
return zend_vm_stack_get_arg_ex(EG(current_execute_data)->prev_execute_data, requested_arg);
|
||||
}
|
||||
|
||||
void execute_new_code(TSRMLS_D);
|
||||
|
||||
|
||||
@@ -356,11 +282,11 @@ ZEND_API zend_bool zend_is_executing(TSRMLS_D);
|
||||
ZEND_API void zend_set_timeout(long seconds, int reset_signals);
|
||||
ZEND_API void zend_unset_timeout(TSRMLS_D);
|
||||
ZEND_API void zend_timeout(int dummy);
|
||||
ZEND_API zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type TSRMLS_DC);
|
||||
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_fetch_dimension_by_zval(zval **result, zval *container, zval *dim TSRMLS_DC);
|
||||
ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC);
|
||||
|
||||
#ifdef ZEND_WIN32
|
||||
void zend_init_timeout_thread(void);
|
||||
@@ -369,17 +295,12 @@ void zend_shutdown_timeout_thread(void);
|
||||
#define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2)
|
||||
#endif
|
||||
|
||||
#define zendi_zval_copy_ctor(p) zval_copy_ctor(&(p))
|
||||
#define zendi_zval_dtor(p) zval_dtor(&(p))
|
||||
|
||||
#define active_opline (*EG(opline_ptr))
|
||||
|
||||
/* The following tries to resolve the classname of a zval of type object.
|
||||
* Since it is slow it should be only used in error messages.
|
||||
*/
|
||||
#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && Z_TYPE_P(zval) == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "")
|
||||
#define Z_OBJ_CLASS_NAME_P(obj) (((obj) && (obj)->handlers->get_class_entry != NULL && (obj)->handlers->get_class_entry) ? (obj)->handlers->get_class_entry(obj TSRMLS_CC)->name->val : "")
|
||||
|
||||
ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var);
|
||||
ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var);
|
||||
|
||||
#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
|
||||
#define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */
|
||||
@@ -394,33 +315,47 @@ ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode);
|
||||
|
||||
/* former zend_execute_locks.h */
|
||||
typedef struct _zend_free_op {
|
||||
zval* var;
|
||||
zval *var;
|
||||
/* int is_var; */
|
||||
} zend_free_op;
|
||||
|
||||
ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC);
|
||||
ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC);
|
||||
|
||||
ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
|
||||
|
||||
void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC);
|
||||
void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC);
|
||||
void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC);
|
||||
|
||||
#define CACHED_PTR(num) \
|
||||
EG(active_op_array)->run_time_cache[(num)]
|
||||
EX(run_time_cache)[(num)]
|
||||
|
||||
#define CACHE_PTR(num, ptr) do { \
|
||||
EG(active_op_array)->run_time_cache[(num)] = (ptr); \
|
||||
EX(run_time_cache)[(num)] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
#define CACHED_POLYMORPHIC_PTR(num, ce) \
|
||||
((EG(active_op_array)->run_time_cache[(num)] == (ce)) ? \
|
||||
EG(active_op_array)->run_time_cache[(num) + 1] : \
|
||||
((EX(run_time_cache)[(num)] == (ce)) ? \
|
||||
EX(run_time_cache)[(num) + 1] : \
|
||||
NULL)
|
||||
|
||||
#define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
|
||||
EG(active_op_array)->run_time_cache[(num)] = (ce); \
|
||||
EG(active_op_array)->run_time_cache[(num) + 1] = (ptr); \
|
||||
EX(run_time_cache)[(num)] = (ce); \
|
||||
EX(run_time_cache)[(num) + 1] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
#define CACHED_PTR_EX(slot) \
|
||||
(slot)[0]
|
||||
|
||||
#define CACHE_PTR_EX(slot, ptr) do { \
|
||||
(slot)[0] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
#define CACHED_POLYMORPHIC_PTR_EX(slot, ce) \
|
||||
(((slot)[0] == (ce)) ? (slot)[1] : NULL)
|
||||
|
||||
#define CACHE_POLYMORPHIC_PTR_EX(slot, ce, ptr) do { \
|
||||
(slot)[0] = (ce); \
|
||||
(slot)[1] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
+594
-530
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@
|
||||
/* The first number is the engine version and the rest is the date.
|
||||
* This way engine 2/3 API no. is always greater than engine 1 API no..
|
||||
*/
|
||||
#define ZEND_EXTENSION_API_NO 220131227
|
||||
#define ZEND_EXTENSION_API_NO 220140815
|
||||
|
||||
typedef struct _zend_extension_version_info {
|
||||
int zend_extension_api_no;
|
||||
|
||||
+531
-561
File diff suppressed because it is too large
Load Diff
+34
-123
@@ -40,62 +40,46 @@
|
||||
# define GC_BENCH_PEAK(peak, counter)
|
||||
#endif
|
||||
|
||||
#define GC_COLOR 0x03
|
||||
#define GC_COLOR 0xc000
|
||||
|
||||
#define GC_BLACK 0x00
|
||||
#define GC_WHITE 0x01
|
||||
#define GC_GREY 0x02
|
||||
#define GC_PURPLE 0x03
|
||||
#define GC_BLACK 0x0000
|
||||
#define GC_WHITE 0x8000
|
||||
#define GC_GREY 0x4000
|
||||
#define GC_PURPLE 0xc000
|
||||
|
||||
#define GC_ADDRESS(v) \
|
||||
((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))
|
||||
((v) & ~GC_COLOR)
|
||||
#define GC_SET_ADDRESS(v, a) \
|
||||
(v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & GC_COLOR) | ((zend_uintptr_t)(a))))
|
||||
do {(v) = ((v) & GC_COLOR) | (a);} while (0)
|
||||
#define GC_GET_COLOR(v) \
|
||||
(((zend_uintptr_t)(v)) & GC_COLOR)
|
||||
#define GC_SET_COLOR(v, c) \
|
||||
(v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & ~GC_COLOR) | (c)))
|
||||
do {(v) = ((v) & ~GC_COLOR) | (c);} while (0)
|
||||
#define GC_SET_BLACK(v) \
|
||||
(v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))
|
||||
do {(v) = (v) & ~GC_COLOR;} while (0)
|
||||
#define GC_SET_PURPLE(v) \
|
||||
(v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) | GC_PURPLE))
|
||||
do {(v) = (v) | GC_COLOR;} while (0)
|
||||
|
||||
#define GC_ZVAL_INIT(z) \
|
||||
((zval_gc_info*)(z))->u.buffered = NULL
|
||||
#define GC_ZVAL_ADDRESS(v) \
|
||||
GC_ADDRESS(((zval_gc_info*)(v))->u.buffered)
|
||||
GC_ADDRESS(Z_GC_INFO_P(v))
|
||||
#define GC_ZVAL_SET_ADDRESS(v, a) \
|
||||
GC_SET_ADDRESS(((zval_gc_info*)(v))->u.buffered, (a))
|
||||
GC_SET_ADDRESS(Z_GC_INFO_P(v), (a))
|
||||
#define GC_ZVAL_GET_COLOR(v) \
|
||||
GC_GET_COLOR(((zval_gc_info*)(v))->u.buffered)
|
||||
GC_GET_COLOR(Z_GC_INFO_P(v))
|
||||
#define GC_ZVAL_SET_COLOR(v, c) \
|
||||
GC_SET_COLOR(((zval_gc_info*)(v))->u.buffered, (c))
|
||||
GC_SET_COLOR(Z_GC_INFO_P(v), (c))
|
||||
#define GC_ZVAL_SET_BLACK(v) \
|
||||
GC_SET_BLACK(((zval_gc_info*)(v))->u.buffered)
|
||||
GC_SET_BLACK(Z_GC_INFO_P(v))
|
||||
#define GC_ZVAL_SET_PURPLE(v) \
|
||||
GC_SET_PURPLE(((zval_gc_info*)(v))->u.buffered)
|
||||
|
||||
#define GC_OBJ_INIT(z) \
|
||||
(z)->buffered = NULL
|
||||
GC_SET_PURPLE(Z_GC_INFO_P(v))
|
||||
|
||||
typedef struct _gc_root_buffer {
|
||||
struct _gc_root_buffer *prev; /* double-linked list */
|
||||
struct _gc_root_buffer *next;
|
||||
zend_object_handle handle; /* must be 0 for zval */
|
||||
union {
|
||||
zval *pz;
|
||||
const zend_object_handlers *handlers;
|
||||
} u;
|
||||
zend_refcounted *ref;
|
||||
struct _gc_root_buffer *next; /* double-linked list */
|
||||
struct _gc_root_buffer *prev;
|
||||
zend_uint refcount;
|
||||
} gc_root_buffer;
|
||||
|
||||
typedef struct _zval_gc_info {
|
||||
zval z;
|
||||
union {
|
||||
gc_root_buffer *buffered;
|
||||
struct _zval_gc_info *next;
|
||||
} u;
|
||||
} zval_gc_info;
|
||||
|
||||
typedef struct _zend_gc_globals {
|
||||
zend_bool gc_enabled;
|
||||
zend_bool gc_active;
|
||||
@@ -106,9 +90,8 @@ typedef struct _zend_gc_globals {
|
||||
gc_root_buffer *first_unused; /* pointer to first unused buffer */
|
||||
gc_root_buffer *last_unused; /* pointer to last unused buffer */
|
||||
|
||||
zval_gc_info *zval_to_free; /* temporary list of zvals to free */
|
||||
zval_gc_info *free_list;
|
||||
zval_gc_info *next_to_free;
|
||||
gc_root_buffer to_free; /* list to free */
|
||||
gc_root_buffer *next_to_free;
|
||||
|
||||
zend_uint gc_runs;
|
||||
zend_uint collected;
|
||||
@@ -117,13 +100,9 @@ typedef struct _zend_gc_globals {
|
||||
zend_uint root_buf_length;
|
||||
zend_uint root_buf_peak;
|
||||
zend_uint zval_possible_root;
|
||||
zend_uint zobj_possible_root;
|
||||
zend_uint zval_buffered;
|
||||
zend_uint zobj_buffered;
|
||||
zend_uint zval_remove_from_buffer;
|
||||
zend_uint zobj_remove_from_buffer;
|
||||
zend_uint zval_marked_grey;
|
||||
zend_uint zobj_marked_grey;
|
||||
#endif
|
||||
|
||||
} zend_gc_globals;
|
||||
@@ -140,9 +119,8 @@ extern ZEND_API zend_gc_globals gc_globals;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API int gc_collect_cycles(TSRMLS_D);
|
||||
ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC);
|
||||
ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC);
|
||||
ZEND_API void gc_remove_zval_from_buffer(zval *zv TSRMLS_DC);
|
||||
ZEND_API void gc_possible_root(zend_refcounted *ref TSRMLS_DC);
|
||||
ZEND_API void gc_remove_from_buffer(zend_refcounted *ref TSRMLS_DC);
|
||||
ZEND_API void gc_globals_ctor(TSRMLS_D);
|
||||
ZEND_API void gc_globals_dtor(TSRMLS_D);
|
||||
ZEND_API void gc_init(TSRMLS_D);
|
||||
@@ -150,90 +128,23 @@ ZEND_API void gc_reset(TSRMLS_D);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define GC_ZVAL_CHECK_POSSIBLE_ROOT(z) \
|
||||
gc_zval_check_possible_root((z) TSRMLS_CC)
|
||||
gc_check_possible_root((z) TSRMLS_CC)
|
||||
|
||||
#define GC_REMOVE_FROM_BUFFER(current) \
|
||||
gc_remove_from_buffer((current) TSRMLS_CC)
|
||||
|
||||
#define GC_REMOVE_ZVAL_FROM_BUFFER(z) \
|
||||
if (GC_ADDRESS(((zval_gc_info*)z)->u.buffered)) { \
|
||||
gc_remove_zval_from_buffer(z TSRMLS_CC); \
|
||||
}
|
||||
|
||||
#define GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject) \
|
||||
do { \
|
||||
if (EXPECTED(EG(objects_store).object_buckets != NULL) && \
|
||||
EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zobject)].valid) { \
|
||||
gc_zobj_possible_root(zobject TSRMLS_CC); \
|
||||
} \
|
||||
#define GC_REMOVE_FROM_BUFFER(p) do { \
|
||||
zend_refcounted *_p = (zend_refcounted*)(p); \
|
||||
if (GC_ADDRESS(GC_INFO(_p))) { \
|
||||
gc_remove_from_buffer(_p TSRMLS_CC); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define GC_REMOVE_ZOBJ_FROM_BUFFER(obj) \
|
||||
do { \
|
||||
if (GC_ADDRESS((obj)->buffered) && !GC_G(gc_active)) { \
|
||||
GC_BENCH_INC(zobj_remove_from_buffer); \
|
||||
GC_REMOVE_FROM_BUFFER(GC_ADDRESS((obj)->buffered)); \
|
||||
(obj)->buffered = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static zend_always_inline void gc_zval_check_possible_root(zval *z TSRMLS_DC)
|
||||
static zend_always_inline void gc_check_possible_root(zval *z TSRMLS_DC)
|
||||
{
|
||||
if (z->type == IS_ARRAY || z->type == IS_OBJECT) {
|
||||
gc_zval_possible_root(z TSRMLS_CC);
|
||||
ZVAL_DEREF(z);
|
||||
if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
|
||||
gc_possible_root(Z_COUNTED_P(z) TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void gc_remove_from_buffer(gc_root_buffer *root TSRMLS_DC)
|
||||
{
|
||||
root->next->prev = root->prev;
|
||||
root->prev->next = root->next;
|
||||
root->prev = GC_G(unused);
|
||||
GC_G(unused) = root;
|
||||
GC_BENCH_DEC(root_buf_length);
|
||||
}
|
||||
|
||||
#define ALLOC_PERMANENT_ZVAL(z) \
|
||||
do { \
|
||||
(z) = (zval*)malloc(sizeof(zval_gc_info)); \
|
||||
GC_ZVAL_INIT(z); \
|
||||
} while (0)
|
||||
|
||||
/* The following macros override macros from zend_alloc.h */
|
||||
#undef ALLOC_ZVAL
|
||||
#define ALLOC_ZVAL(z) \
|
||||
do { \
|
||||
(z) = (zval*)emalloc(sizeof(zval_gc_info)); \
|
||||
GC_ZVAL_INIT(z); \
|
||||
} while (0)
|
||||
|
||||
#undef FREE_ZVAL
|
||||
#define FREE_ZVAL(z) \
|
||||
do { \
|
||||
GC_REMOVE_ZVAL_FROM_BUFFER(z); \
|
||||
efree(z); \
|
||||
} while (0)
|
||||
|
||||
#undef ALLOC_ZVAL_REL
|
||||
#define ALLOC_ZVAL_REL(z) \
|
||||
do { \
|
||||
(z) = (zval*)emalloc_rel(sizeof(zval_gc_info)); \
|
||||
GC_ZVAL_INIT(z); \
|
||||
} while (0)
|
||||
|
||||
#undef FREE_ZVAL_REL
|
||||
#define FREE_ZVAL_REL(z) \
|
||||
do { \
|
||||
GC_REMOVE_ZVAL_FROM_BUFFER(z); \
|
||||
efree_rel(z); \
|
||||
} while (0)
|
||||
|
||||
#define FREE_ZVAL_EX(z) \
|
||||
efree(z)
|
||||
|
||||
#define FREE_ZVAL_REL_EX(z) \
|
||||
efree_rel(z)
|
||||
|
||||
#endif /* ZEND_GC_H */
|
||||
|
||||
/*
|
||||
|
||||
+115
-176
@@ -27,15 +27,15 @@
|
||||
ZEND_API zend_class_entry *zend_ce_generator;
|
||||
static zend_object_handlers zend_generator_handlers;
|
||||
|
||||
static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC);
|
||||
static zend_object *zend_generator_create(zend_class_entry *class_type TSRMLS_DC);
|
||||
|
||||
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_execute_data *execute_data = generator->execute_data;
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
|
||||
if (generator->send_target) {
|
||||
Z_DELREF_PP(generator->send_target);
|
||||
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
|
||||
generator->send_target = NULL;
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
|
||||
switch (brk_opline->opcode) {
|
||||
case ZEND_SWITCH_FREE:
|
||||
{
|
||||
temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
|
||||
zval_ptr_dtor(&var->var.ptr);
|
||||
zval *var = EX_VAR_2(execute_data, brk_opline->op1.var);
|
||||
zval_ptr_dtor(var);
|
||||
}
|
||||
break;
|
||||
case ZEND_FREE:
|
||||
{
|
||||
temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
|
||||
zval_dtor(&var->tmp_var);
|
||||
zval *var = EX_VAR_2(execute_data, brk_opline->op1.var);
|
||||
zval_dtor(var);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -75,42 +75,32 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear any backed up stack arguments */
|
||||
{
|
||||
void **ptr = generator->stack->top - 1;
|
||||
void **end = zend_vm_stack_frame_base(execute_data);
|
||||
|
||||
for (; ptr >= end; --ptr) {
|
||||
zval_ptr_dtor((zval **) ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* If yield was used as a function argument there may be active
|
||||
* method calls those objects need to be freed */
|
||||
while (execute_data->call >= execute_data->call_slots) {
|
||||
while (execute_data->call) {
|
||||
if (execute_data->call->object) {
|
||||
zval_ptr_dtor(&execute_data->call->object);
|
||||
OBJ_RELEASE(execute_data->call->object);
|
||||
}
|
||||
execute_data->call--;
|
||||
execute_data->call = execute_data->call->prev_nested_call;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (generator->value) {
|
||||
if (Z_TYPE(generator->value) != IS_UNDEF) {
|
||||
zval_ptr_dtor(&generator->value);
|
||||
generator->value = NULL;
|
||||
ZVAL_UNDEF(&generator->value);
|
||||
}
|
||||
|
||||
if (generator->key) {
|
||||
if (Z_TYPE(generator->key) != IS_UNDEF) {
|
||||
zval_ptr_dtor(&generator->key);
|
||||
generator->key = NULL;
|
||||
ZVAL_UNDEF(&generator->key);
|
||||
}
|
||||
|
||||
if (generator->execute_data) {
|
||||
zend_execute_data *execute_data = generator->execute_data;
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
|
||||
if (!execute_data->symbol_table) {
|
||||
zend_free_compiled_variables(execute_data TSRMLS_CC);
|
||||
@@ -118,8 +108,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||
zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (execute_data->current_this) {
|
||||
zval_ptr_dtor(&execute_data->current_this);
|
||||
if (execute_data->object) {
|
||||
OBJ_RELEASE(execute_data->object);
|
||||
}
|
||||
|
||||
/* A fatal error / die occurred during the generator execution. Trying to clean
|
||||
@@ -129,23 +119,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have added an additional stack frame in prev_execute_data, so we
|
||||
* have to free it. It also contains the arguments passed to the
|
||||
* generator (for func_get_args) so those have to be freed too. */
|
||||
{
|
||||
zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
|
||||
void **arguments = prev_execute_data->function_state.arguments;
|
||||
|
||||
if (arguments) {
|
||||
int arguments_count = (int) (zend_uintptr_t) *arguments;
|
||||
zval **arguments_start = (zval **) (arguments - arguments_count);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < arguments_count; ++i) {
|
||||
zval_ptr_dtor(arguments_start + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
zend_vm_stack_free_extra_args(generator->execute_data TSRMLS_CC);
|
||||
|
||||
/* Some cleanups are only necessary if the generator was closued
|
||||
* before it could finish execution (reach a return statement). */
|
||||
@@ -165,24 +139,25 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_generator_dtor_storage(zend_generator *generator, zend_object_handle handle TSRMLS_DC) /* {{{ */
|
||||
static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator*) object;
|
||||
zend_execute_data *ex = generator->execute_data;
|
||||
zend_uint op_num, finally_op_num;
|
||||
int i;
|
||||
|
||||
if (!ex || !ex->op_array->has_finally_block) {
|
||||
if (!ex || !ex->func->op_array.has_finally_block) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* -1 required because we want the last run opcode, not the
|
||||
* next to-be-run one. */
|
||||
op_num = ex->opline - ex->op_array->opcodes - 1;
|
||||
op_num = ex->opline - ex->func->op_array.opcodes - 1;
|
||||
|
||||
/* Find next finally block */
|
||||
finally_op_num = 0;
|
||||
for (i = 0; i < ex->op_array->last_try_catch; i++) {
|
||||
zend_try_catch_element *try_catch = &ex->op_array->try_catch_array[i];
|
||||
for (i = 0; i < ex->func->op_array.last_try_catch; i++) {
|
||||
zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i];
|
||||
|
||||
if (op_num < try_catch->try_op) {
|
||||
break;
|
||||
@@ -196,7 +171,7 @@ static void zend_generator_dtor_storage(zend_generator *generator, zend_object_h
|
||||
/* If a finally block was found we jump directly to it and
|
||||
* resume the generator. */
|
||||
if (finally_op_num) {
|
||||
ex->opline = &ex->op_array->opcodes[finally_op_num];
|
||||
ex->opline = &ex->func->op_array.opcodes[finally_op_num];
|
||||
ex->fast_ret = NULL;
|
||||
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
|
||||
zend_generator_resume(generator TSRMLS_CC);
|
||||
@@ -204,19 +179,23 @@ static void zend_generator_dtor_storage(zend_generator *generator, zend_object_h
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* {{{ */
|
||||
static void zend_generator_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator*) object;
|
||||
|
||||
zend_generator_close(generator, 0 TSRMLS_CC);
|
||||
|
||||
zend_object_std_dtor(&generator->std TSRMLS_CC);
|
||||
efree(generator);
|
||||
|
||||
if (generator->iterator) {
|
||||
zend_iterator_dtor(generator->iterator TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
static zend_object *zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator;
|
||||
zend_object_value object;
|
||||
|
||||
generator = emalloc(sizeof(zend_generator));
|
||||
memset(generator, 0, sizeof(zend_generator));
|
||||
@@ -225,37 +204,28 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM
|
||||
generator->largest_used_integer_key = -1;
|
||||
|
||||
zend_object_std_init(&generator->std, class_type TSRMLS_CC);
|
||||
generator->std.handlers = &zend_generator_handlers;
|
||||
|
||||
object.handle = zend_objects_store_put(generator,
|
||||
(zend_objects_store_dtor_t) zend_generator_dtor_storage,
|
||||
(zend_objects_free_object_storage_t) zend_generator_free_storage,
|
||||
NULL TSRMLS_CC
|
||||
);
|
||||
object.handlers = &zend_generator_handlers;
|
||||
|
||||
return object;
|
||||
return (zend_object*)generator;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void copy_closure_static_var(zval **var TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
|
||||
static int copy_closure_static_var(zval *var TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
|
||||
{
|
||||
HashTable *target = va_arg(args, HashTable *);
|
||||
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(var);
|
||||
Z_ADDREF_PP(var);
|
||||
zend_hash_quick_update(target, key->arKey, key->nKeyLength, key->h, var, sizeof(zval *), NULL);
|
||||
ZVAL_MAKE_REF(var);
|
||||
Z_ADDREF_P(var);
|
||||
zend_hash_update(target, key->key, var);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Requires globals EG(scope), EG(current_scope), EG(This),
|
||||
* EG(active_symbol_table) and EG(current_execute_data). */
|
||||
ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */
|
||||
/* Requires globals EG(scope), EG(This) and EG(current_execute_data). */
|
||||
ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *return_value;
|
||||
zend_generator *generator;
|
||||
zend_execute_data *current_execute_data;
|
||||
zend_op **opline_ptr;
|
||||
HashTable *current_symbol_table;
|
||||
zend_execute_data *execute_data;
|
||||
zend_vm_stack current_stack = EG(argument_stack);
|
||||
|
||||
@@ -275,8 +245,8 @@ ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /*
|
||||
);
|
||||
zend_hash_apply_with_arguments(
|
||||
op_array->static_variables TSRMLS_CC,
|
||||
(apply_func_args_t) copy_closure_static_var,
|
||||
1, op_array_copy->static_variables
|
||||
copy_closure_static_var, 1,
|
||||
op_array_copy->static_variables
|
||||
);
|
||||
}
|
||||
|
||||
@@ -284,41 +254,30 @@ ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /*
|
||||
}
|
||||
|
||||
/* Create new execution context. We have to back up and restore
|
||||
* EG(current_execute_data), EG(opline_ptr) and EG(active_symbol_table)
|
||||
* here because the function modifies or uses them */
|
||||
* EG(current_execute_data) here. */
|
||||
current_execute_data = EG(current_execute_data);
|
||||
opline_ptr = EG(opline_ptr);
|
||||
current_symbol_table = EG(active_symbol_table);
|
||||
EG(active_symbol_table) = NULL;
|
||||
execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC);
|
||||
EG(active_symbol_table) = current_symbol_table;
|
||||
execute_data = zend_create_generator_execute_data(call, op_array, return_value TSRMLS_CC);
|
||||
EG(current_execute_data) = current_execute_data;
|
||||
EG(opline_ptr) = opline_ptr;
|
||||
|
||||
ALLOC_INIT_ZVAL(return_value);
|
||||
object_init_ex(return_value, zend_ce_generator);
|
||||
|
||||
if (EG(This)) {
|
||||
Z_ADDREF_P(EG(This));
|
||||
if (Z_OBJ(EG(This))) {
|
||||
Z_ADDREF(EG(This));
|
||||
}
|
||||
|
||||
/* Back up executor globals. */
|
||||
execute_data->current_scope = EG(scope);
|
||||
execute_data->current_called_scope = EG(called_scope);
|
||||
execute_data->symbol_table = EG(active_symbol_table);
|
||||
execute_data->current_this = EG(This);
|
||||
|
||||
/* Save execution context in generator object. */
|
||||
generator = (zend_generator *) zend_object_store_get_object(return_value TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(return_value);
|
||||
execute_data->prev_execute_data = NULL;
|
||||
generator->execute_data = execute_data;
|
||||
generator->stack = EG(argument_stack);
|
||||
EG(argument_stack) = current_stack;
|
||||
|
||||
return return_value;
|
||||
/* EX(return_value) keeps pointer to zend_object (not a real zval) */
|
||||
execute_data->return_value = (zval*)generator;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* {{{ */
|
||||
static zend_function *zend_generator_get_constructor(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_error(E_RECOVERABLE_ERROR, "The \"Generator\" class is reserved for internal use and cannot be manually instantiated");
|
||||
|
||||
@@ -342,52 +301,39 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
|
||||
|
||||
{
|
||||
/* Backup executor globals */
|
||||
zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
|
||||
zend_execute_data *original_execute_data = EG(current_execute_data);
|
||||
zend_op **original_opline_ptr = EG(opline_ptr);
|
||||
zend_op_array *original_active_op_array = EG(active_op_array);
|
||||
HashTable *original_active_symbol_table = EG(active_symbol_table);
|
||||
zval *original_This = EG(This);
|
||||
zend_object *original_This;
|
||||
zend_class_entry *original_scope = EG(scope);
|
||||
zend_class_entry *original_called_scope = EG(called_scope);
|
||||
zend_vm_stack original_stack = EG(argument_stack);
|
||||
|
||||
/* We (mis)use the return_value_ptr_ptr to provide the generator object
|
||||
* to the executor, so YIELD will be able to set the yielded value */
|
||||
EG(return_value_ptr_ptr) = (zval **) generator;
|
||||
original_This = Z_OBJ(EG(This));
|
||||
|
||||
/* Set executor globals */
|
||||
EG(current_execute_data) = generator->execute_data;
|
||||
EG(opline_ptr) = &generator->execute_data->opline;
|
||||
EG(active_op_array) = generator->execute_data->op_array;
|
||||
EG(active_symbol_table) = generator->execute_data->symbol_table;
|
||||
EG(This) = generator->execute_data->current_this;
|
||||
EG(scope) = generator->execute_data->current_scope;
|
||||
EG(called_scope) = generator->execute_data->current_called_scope;
|
||||
Z_OBJ(EG(This)) = generator->execute_data->object;
|
||||
EG(scope) = generator->execute_data->scope;
|
||||
EG(argument_stack) = generator->stack;
|
||||
|
||||
/* We want the backtrace to look as if the generator function was
|
||||
* called from whatever method we are current running (e.g. next()).
|
||||
* The first prev_execute_data contains an additional stack frame,
|
||||
* which makes the generator function show up in the backtrace and
|
||||
* makes the arguments available to func_get_args(). So we have to
|
||||
* set the prev_execute_data of that prev_execute_data :) */
|
||||
generator->execute_data->prev_execute_data->prev_execute_data = original_execute_data;
|
||||
* So we have to link generator call frame with caller call frames */
|
||||
|
||||
generator->execute_data->prev_execute_data = original_execute_data;
|
||||
|
||||
/* Resume execution */
|
||||
generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
|
||||
zend_execute_ex(generator->execute_data TSRMLS_CC);
|
||||
generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING;
|
||||
|
||||
/* Unlink generator call_frame from the caller */
|
||||
if (generator->execute_data) {
|
||||
generator->execute_data->prev_execute_data = NULL;
|
||||
}
|
||||
|
||||
/* Restore executor globals */
|
||||
EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
|
||||
EG(current_execute_data) = original_execute_data;
|
||||
EG(opline_ptr) = original_opline_ptr;
|
||||
EG(active_op_array) = original_active_op_array;
|
||||
EG(active_symbol_table) = original_active_symbol_table;
|
||||
EG(This) = original_This;
|
||||
Z_OBJ(EG(This)) = original_This;
|
||||
EG(scope) = original_scope;
|
||||
EG(called_scope) = original_called_scope;
|
||||
EG(argument_stack) = original_stack;
|
||||
|
||||
/* If an exception was thrown in the generator we have to internally
|
||||
@@ -401,7 +347,7 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
|
||||
|
||||
static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (generator->execute_data && !generator->value) {
|
||||
if (generator->execute_data && Z_TYPE(generator->value) == IS_UNDEF) {
|
||||
zend_generator_resume(generator TSRMLS_CC);
|
||||
generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD;
|
||||
}
|
||||
@@ -428,7 +374,7 @@ ZEND_METHOD(Generator, rewind)
|
||||
return;
|
||||
}
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_rewind(generator TSRMLS_CC);
|
||||
}
|
||||
@@ -444,11 +390,11 @@ ZEND_METHOD(Generator, valid)
|
||||
return;
|
||||
}
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
RETURN_BOOL(generator->value != NULL);
|
||||
RETURN_BOOL(Z_TYPE(generator->value) != IS_UNDEF);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -462,12 +408,12 @@ ZEND_METHOD(Generator, current)
|
||||
return;
|
||||
}
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
if (generator->value) {
|
||||
RETURN_ZVAL_FAST(generator->value);
|
||||
if (Z_TYPE(generator->value) != IS_UNDEF) {
|
||||
RETURN_ZVAL_FAST(&generator->value);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -482,12 +428,12 @@ ZEND_METHOD(Generator, key)
|
||||
return;
|
||||
}
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
if (generator->key) {
|
||||
RETURN_ZVAL_FAST(generator->key);
|
||||
if (Z_TYPE(generator->key) != IS_UNDEF) {
|
||||
RETURN_ZVAL_FAST(&generator->key);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -502,7 +448,7 @@ ZEND_METHOD(Generator, next)
|
||||
return;
|
||||
}
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
@@ -521,7 +467,7 @@ ZEND_METHOD(Generator, send)
|
||||
return;
|
||||
}
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
@@ -532,15 +478,14 @@ ZEND_METHOD(Generator, send)
|
||||
|
||||
/* Put sent value in the target VAR slot, if it is used */
|
||||
if (generator->send_target) {
|
||||
Z_DELREF_PP(generator->send_target);
|
||||
Z_ADDREF_P(value);
|
||||
*generator->send_target = value;
|
||||
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
|
||||
ZVAL_COPY(generator->send_target, value);
|
||||
}
|
||||
|
||||
zend_generator_resume(generator TSRMLS_CC);
|
||||
|
||||
if (generator->value) {
|
||||
RETURN_ZVAL_FAST(generator->value);
|
||||
if (Z_TYPE(generator->value) != IS_UNDEF) {
|
||||
RETURN_ZVAL_FAST(&generator->value);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -549,17 +494,16 @@ ZEND_METHOD(Generator, send)
|
||||
* Throws an exception into the generator */
|
||||
ZEND_METHOD(Generator, throw)
|
||||
{
|
||||
zval *exception, *exception_copy;
|
||||
zval *exception, exception_copy;
|
||||
zend_generator *generator;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &exception) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ALLOC_ZVAL(exception_copy);
|
||||
MAKE_COPY_ZVAL(&exception, exception_copy);
|
||||
ZVAL_DUP(&exception_copy, exception);
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
generator = (zend_generator *) Z_OBJ_P(getThis());
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
@@ -568,19 +512,19 @@ ZEND_METHOD(Generator, throw)
|
||||
zend_execute_data *current_execute_data = EG(current_execute_data);
|
||||
EG(current_execute_data) = generator->execute_data;
|
||||
|
||||
zend_throw_exception_object(exception_copy TSRMLS_CC);
|
||||
zend_throw_exception_object(&exception_copy TSRMLS_CC);
|
||||
|
||||
EG(current_execute_data) = current_execute_data;
|
||||
|
||||
zend_generator_resume(generator TSRMLS_CC);
|
||||
|
||||
if (generator->value) {
|
||||
RETURN_ZVAL_FAST(generator->value);
|
||||
if (Z_TYPE(generator->value) != IS_UNDEF) {
|
||||
RETURN_ZVAL_FAST(&generator->value);
|
||||
}
|
||||
} else {
|
||||
/* If the generator is already closed throw the exception in the
|
||||
* current context */
|
||||
zend_throw_exception_object(exception_copy TSRMLS_CC);
|
||||
zend_throw_exception_object(&exception_copy TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -605,44 +549,41 @@ ZEND_METHOD(Generator, __wakeup)
|
||||
|
||||
static void zend_generator_iterator_dtor(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *object = ((zend_generator_iterator *) iterator)->object;
|
||||
|
||||
zval_ptr_dtor(&object);
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ(iterator->data);
|
||||
generator->iterator = NULL;
|
||||
zval_ptr_dtor(&iterator->data);
|
||||
zend_iterator_dtor(iterator TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_generator_iterator_valid(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator *) iterator->data;
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ(iterator->data);
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
return generator->value != NULL ? SUCCESS : FAILURE;
|
||||
return Z_TYPE(generator->value) != IS_UNDEF ? SUCCESS : FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_generator_iterator_get_data(zend_object_iterator *iterator, zval ***data TSRMLS_DC) /* {{{ */
|
||||
static zval *zend_generator_iterator_get_data(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator *) iterator->data;
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ(iterator->data);
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
if (generator->value) {
|
||||
*data = &generator->value;
|
||||
} else {
|
||||
*data = NULL;
|
||||
}
|
||||
return &generator->value;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_generator_iterator_get_key(zend_object_iterator *iterator, zval *key TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator *) iterator->data;
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ(iterator->data);
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
if (generator->key) {
|
||||
ZVAL_ZVAL(key, generator->key, 1, 0);
|
||||
if (Z_TYPE(generator->key) != IS_UNDEF) {
|
||||
ZVAL_ZVAL(key, &generator->key, 1, 0);
|
||||
} else {
|
||||
ZVAL_NULL(key);
|
||||
}
|
||||
@@ -651,7 +592,7 @@ static void zend_generator_iterator_get_key(zend_object_iterator *iterator, zval
|
||||
|
||||
static void zend_generator_iterator_move_forward(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator *) iterator->data;
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ(iterator->data);
|
||||
|
||||
zend_generator_ensure_initialized(generator TSRMLS_CC);
|
||||
|
||||
@@ -661,7 +602,7 @@ static void zend_generator_iterator_move_forward(zend_object_iterator *iterator
|
||||
|
||||
static void zend_generator_iterator_rewind(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator = (zend_generator *) iterator->data;
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ(iterator->data);
|
||||
|
||||
zend_generator_rewind(generator TSRMLS_CC);
|
||||
}
|
||||
@@ -678,31 +619,27 @@ static zend_object_iterator_funcs zend_generator_iterator_functions = {
|
||||
|
||||
zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator_iterator *iterator;
|
||||
zend_generator *generator;
|
||||
|
||||
generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC);
|
||||
zend_object_iterator *iterator;
|
||||
zend_generator *generator = (zend_generator*)Z_OBJ_P(object);
|
||||
|
||||
if (!generator->execute_data) {
|
||||
zend_throw_exception(NULL, "Cannot traverse an already closed generator", 0 TSRMLS_CC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (by_ref && !(generator->execute_data->op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
|
||||
if (by_ref && !(generator->execute_data->func->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
|
||||
zend_throw_exception(NULL, "You can only iterate a generator by-reference if it declared that it yields by-reference", 0 TSRMLS_CC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iterator = &generator->iterator;
|
||||
iterator->intern.funcs = &zend_generator_iterator_functions;
|
||||
iterator->intern.data = (void *) generator;
|
||||
iterator = generator->iterator = emalloc(sizeof(zend_object_iterator));
|
||||
|
||||
zend_iterator_init(iterator TSRMLS_CC);
|
||||
|
||||
/* We have to keep a reference to the generator object zval around,
|
||||
* otherwise the generator may be destroyed during iteration. */
|
||||
Z_ADDREF_P(object);
|
||||
iterator->object = object;
|
||||
iterator->funcs = &zend_generator_iterator_functions;
|
||||
ZVAL_COPY(&iterator->data, object);
|
||||
|
||||
return (zend_object_iterator *) iterator;
|
||||
return iterator;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -746,8 +683,10 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */
|
||||
zend_ce_generator->iterator_funcs.funcs = &zend_generator_iterator_functions;
|
||||
|
||||
memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
||||
zend_generator_handlers.get_constructor = zend_generator_get_constructor;
|
||||
zend_generator_handlers.free_obj = zend_generator_free_storage;
|
||||
zend_generator_handlers.dtor_obj = zend_generator_dtor_storage;
|
||||
zend_generator_handlers.clone_obj = NULL;
|
||||
zend_generator_handlers.get_constructor = zend_generator_get_constructor;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
+5
-13
@@ -25,18 +25,10 @@ BEGIN_EXTERN_C()
|
||||
|
||||
extern ZEND_API zend_class_entry *zend_ce_generator;
|
||||
|
||||
typedef struct _zend_generator_iterator {
|
||||
zend_object_iterator intern;
|
||||
|
||||
/* The generator object zval has to be stored, because the iterator is
|
||||
* holding a ref to it, which has to be dtored. */
|
||||
zval *object;
|
||||
} zend_generator_iterator;
|
||||
|
||||
typedef struct _zend_generator {
|
||||
zend_object std;
|
||||
|
||||
zend_generator_iterator iterator;
|
||||
zend_object_iterator *iterator;
|
||||
|
||||
/* The suspended execution context. */
|
||||
zend_execute_data *execute_data;
|
||||
@@ -45,11 +37,11 @@ typedef struct _zend_generator {
|
||||
zend_vm_stack stack;
|
||||
|
||||
/* Current value */
|
||||
zval *value;
|
||||
zval value;
|
||||
/* Current key */
|
||||
zval *key;
|
||||
zval key;
|
||||
/* Variable to put sent value into */
|
||||
zval **send_target;
|
||||
zval *send_target;
|
||||
/* Largest used integer key for auto-incrementing keys */
|
||||
long largest_used_integer_key;
|
||||
|
||||
@@ -62,7 +54,7 @@ static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2;
|
||||
static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4;
|
||||
|
||||
void zend_register_generator_ce(TSRMLS_D);
|
||||
ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC);
|
||||
ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC);
|
||||
ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC);
|
||||
|
||||
|
||||
+24
-36
@@ -36,6 +36,7 @@
|
||||
#include "zend_modules.h"
|
||||
#include "zend_float.h"
|
||||
#include "zend_multibyte.h"
|
||||
#include "zend_arena.h"
|
||||
|
||||
/* Define ZTS if you want a thread-safe Zend */
|
||||
/*#undef ZTS*/
|
||||
@@ -85,7 +86,7 @@ struct _zend_compiler_globals {
|
||||
|
||||
zend_stack function_call_stack;
|
||||
|
||||
char *compiled_filename;
|
||||
zend_string *compiled_filename;
|
||||
|
||||
int zend_lineno;
|
||||
|
||||
@@ -124,12 +125,11 @@ struct _zend_compiler_globals {
|
||||
|
||||
zend_uint access_type;
|
||||
|
||||
char *doc_comment;
|
||||
zend_uint doc_comment_len;
|
||||
zend_string *doc_comment;
|
||||
|
||||
zend_uint compiler_options; /* set of ZEND_COMPILE_* constants */
|
||||
|
||||
zval *current_namespace;
|
||||
zval current_namespace;
|
||||
HashTable *current_import;
|
||||
HashTable *current_import_function;
|
||||
HashTable *current_import_const;
|
||||
@@ -141,14 +141,10 @@ struct _zend_compiler_globals {
|
||||
zend_compiler_context context;
|
||||
zend_stack context_stack;
|
||||
|
||||
/* interned strings */
|
||||
char *interned_strings_start;
|
||||
char *interned_strings_end;
|
||||
char *interned_strings_top;
|
||||
char *interned_strings_snapshot_top;
|
||||
#ifndef ZTS
|
||||
char *interned_empty_string;
|
||||
#endif
|
||||
zend_arena *arena;
|
||||
|
||||
zend_string *empty_string;
|
||||
zend_string *one_char_string[256];
|
||||
|
||||
HashTable interned_strings;
|
||||
|
||||
@@ -159,30 +155,22 @@ struct _zend_compiler_globals {
|
||||
zend_bool encoding_declared;
|
||||
|
||||
#ifdef ZTS
|
||||
zval ***static_members_table;
|
||||
zval **static_members_table;
|
||||
int last_static_member;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct _zend_executor_globals {
|
||||
zval **return_value_ptr_ptr;
|
||||
|
||||
zval uninitialized_zval;
|
||||
zval *uninitialized_zval_ptr;
|
||||
|
||||
zval error_zval;
|
||||
zval *error_zval_ptr;
|
||||
|
||||
/* symbol table cache */
|
||||
HashTable *symtable_cache[SYMTABLE_CACHE_SIZE];
|
||||
HashTable **symtable_cache_limit;
|
||||
HashTable **symtable_cache_ptr;
|
||||
zend_array *symtable_cache[SYMTABLE_CACHE_SIZE];
|
||||
zend_array **symtable_cache_limit;
|
||||
zend_array **symtable_cache_ptr;
|
||||
|
||||
zend_op **opline_ptr;
|
||||
|
||||
HashTable *active_symbol_table;
|
||||
HashTable symbol_table; /* main symbol table */
|
||||
zend_array symbol_table; /* main symbol table */
|
||||
|
||||
HashTable included_files; /* files already included */
|
||||
|
||||
@@ -192,22 +180,18 @@ struct _zend_executor_globals {
|
||||
int orig_error_reporting;
|
||||
int exit_status;
|
||||
|
||||
zend_op_array *active_op_array;
|
||||
|
||||
HashTable *function_table; /* function symbol table */
|
||||
HashTable *class_table; /* class table */
|
||||
HashTable *zend_constants; /* constants table */
|
||||
|
||||
zend_class_entry *scope;
|
||||
zend_class_entry *called_scope; /* Scope of the calling class */
|
||||
|
||||
zval *This;
|
||||
zval This;
|
||||
|
||||
long precision;
|
||||
|
||||
int ticks_count;
|
||||
|
||||
zend_bool in_execution;
|
||||
HashTable *in_autoload;
|
||||
zend_function *autoload_func;
|
||||
zend_bool full_tables_cleanup;
|
||||
@@ -226,11 +210,11 @@ struct _zend_executor_globals {
|
||||
zend_vm_stack argument_stack;
|
||||
|
||||
int user_error_handler_error_reporting;
|
||||
zval *user_error_handler;
|
||||
zval *user_exception_handler;
|
||||
zval user_error_handler;
|
||||
zval user_exception_handler;
|
||||
zend_stack user_error_handlers_error_reporting;
|
||||
zend_ptr_stack user_error_handlers;
|
||||
zend_ptr_stack user_exception_handlers;
|
||||
zend_stack user_error_handlers;
|
||||
zend_stack user_exception_handlers;
|
||||
|
||||
zend_error_handling_t error_handling;
|
||||
zend_class_entry *exception_class;
|
||||
@@ -245,7 +229,7 @@ struct _zend_executor_globals {
|
||||
zend_ini_entry *error_reporting_ini_entry;
|
||||
|
||||
zend_objects_store objects_store;
|
||||
zval *exception, *prev_exception;
|
||||
zend_object *exception, *prev_exception;
|
||||
zend_op *opline_before_exception;
|
||||
zend_op exception_op[3];
|
||||
|
||||
@@ -255,7 +239,8 @@ struct _zend_executor_globals {
|
||||
|
||||
zend_property_info std_property_info;
|
||||
|
||||
zend_bool active;
|
||||
zend_bool active;
|
||||
zend_bool valid_symbol_table;
|
||||
|
||||
zend_op *start_op;
|
||||
|
||||
@@ -313,6 +298,9 @@ struct _zend_php_scanner_globals {
|
||||
zend_encoding_filter input_filter;
|
||||
zend_encoding_filter output_filter;
|
||||
const zend_encoding *script_encoding;
|
||||
|
||||
/* initial string length after scanning to first variable */
|
||||
int scanned_string_len;
|
||||
};
|
||||
|
||||
#endif /* ZEND_GLOBALS_H */
|
||||
|
||||
+1245
-932
File diff suppressed because it is too large
Load Diff
+622
-243
@@ -30,109 +30,103 @@
|
||||
#define HASH_KEY_NON_EXISTENT 3
|
||||
#define HASH_KEY_NON_EXISTANT HASH_KEY_NON_EXISTENT /* Keeping old define (with typo) for backward compatibility */
|
||||
|
||||
#define HASH_UPDATE (1<<0)
|
||||
#define HASH_ADD (1<<1)
|
||||
#define HASH_NEXT_INSERT (1<<2)
|
||||
#define HASH_UPDATE (1<<0)
|
||||
#define HASH_ADD (1<<1)
|
||||
#define HASH_NEXT_INSERT (1<<2)
|
||||
#define HASH_UPDATE_INDIRECT (1<<3)
|
||||
#define HASH_ADD_NEW (1<<4)
|
||||
|
||||
#define HASH_DEL_KEY 0
|
||||
#define HASH_DEL_INDEX 1
|
||||
#define HASH_DEL_KEY_QUICK 2
|
||||
#define INVALID_IDX ((uint)-1)
|
||||
|
||||
#define HASH_UPDATE_KEY_IF_NONE 0
|
||||
#define HASH_UPDATE_KEY_IF_BEFORE 1
|
||||
#define HASH_UPDATE_KEY_IF_AFTER 2
|
||||
#define HASH_UPDATE_KEY_ANYWAY 3
|
||||
|
||||
typedef ulong (*hash_func_t)(const char *arKey, uint nKeyLength);
|
||||
typedef int (*compare_func_t)(const void *, const void * TSRMLS_DC);
|
||||
typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t TSRMLS_DC);
|
||||
typedef void (*dtor_func_t)(void *pDest);
|
||||
typedef void (*copy_ctor_func_t)(void *pElement);
|
||||
typedef void (*copy_ctor_param_func_t)(void *pElement, void *pParam);
|
||||
|
||||
struct _hashtable;
|
||||
|
||||
typedef struct bucket {
|
||||
ulong h; /* Used for numeric indexing */
|
||||
uint nKeyLength;
|
||||
void *pData;
|
||||
void *pDataPtr;
|
||||
struct bucket *pListNext;
|
||||
struct bucket *pListLast;
|
||||
struct bucket *pNext;
|
||||
struct bucket *pLast;
|
||||
const char *arKey;
|
||||
} Bucket;
|
||||
|
||||
typedef struct _hashtable {
|
||||
uint nTableSize;
|
||||
uint nTableMask;
|
||||
uint nNumOfElements;
|
||||
ulong nNextFreeElement;
|
||||
Bucket *pInternalPointer; /* Used for element traversal */
|
||||
Bucket *pListHead;
|
||||
Bucket *pListTail;
|
||||
Bucket **arBuckets;
|
||||
dtor_func_t pDestructor;
|
||||
zend_bool persistent;
|
||||
unsigned char nApplyCount;
|
||||
zend_bool bApplyProtection;
|
||||
#if ZEND_DEBUG
|
||||
int inconsistent;
|
||||
#endif
|
||||
} HashTable;
|
||||
#define HASH_FLAG_PERSISTENT (1<<0)
|
||||
#define HASH_FLAG_APPLY_PROTECTION (1<<1)
|
||||
#define HASH_FLAG_PACKED (1<<2)
|
||||
|
||||
#define HASH_MASK_CONSISTENCY 0x60
|
||||
|
||||
typedef struct _zend_hash_key {
|
||||
const char *arKey;
|
||||
uint nKeyLength;
|
||||
ulong h;
|
||||
ulong h;
|
||||
zend_string *key;
|
||||
} zend_hash_key;
|
||||
|
||||
typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, zval *source_data, zend_hash_key *hash_key, void *pParam);
|
||||
|
||||
typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam);
|
||||
|
||||
typedef Bucket* HashPosition;
|
||||
typedef uint HashPosition;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
/* startup/shutdown */
|
||||
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
|
||||
ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
|
||||
ZEND_API void _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
|
||||
ZEND_API void _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
|
||||
ZEND_API void zend_hash_destroy(HashTable *ht);
|
||||
ZEND_API void zend_hash_clean(HashTable *ht);
|
||||
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pDestructor), (persistent) ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API void zend_hash_real_init(HashTable *ht, int packed);
|
||||
ZEND_API void zend_hash_packed_to_hash(HashTable *ht);
|
||||
ZEND_API void zend_hash_to_packed(HashTable *ht);
|
||||
|
||||
/* additions/updates/changes */
|
||||
ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
|
||||
_zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
|
||||
_zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
|
||||
ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_update(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_update_ind(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_add(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_add_new(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
|
||||
|
||||
ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
|
||||
_zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
|
||||
_zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_update(ht, key, pData) \
|
||||
_zend_hash_update(ht, key, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_update_ind(ht, key, pData) \
|
||||
_zend_hash_update_ind(ht, key, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_add(ht, key, pData) \
|
||||
_zend_hash_add(ht, key, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_add_new(ht, key, pData) \
|
||||
_zend_hash_add_new(ht, key, pData ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
|
||||
_zend_hash_index_update_or_next_insert(ht, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
|
||||
_zend_hash_index_update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
|
||||
ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *key, int len, zval *pData, int flag ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
|
||||
ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint nKeyLength);
|
||||
#define zend_hash_str_update(ht, key, len, pData) \
|
||||
_zend_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_str_update_ind(ht, key, len, pData) \
|
||||
_zend_hash_str_update_ind(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_str_add(ht, key, len, pData) \
|
||||
_zend_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_str_add_new(ht, key, len, pData) \
|
||||
_zend_hash_str_add_new(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API zval *_zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_index_add(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_index_update(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC);
|
||||
|
||||
#define zend_hash_index_add(ht, h, pData) \
|
||||
_zend_hash_index_add(ht, h, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_index_add_new(ht, h, pData) \
|
||||
_zend_hash_index_add_new(ht, h, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_index_update(ht, h, pData) \
|
||||
_zend_hash_index_update(ht, h, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_next_index_insert(ht, pData) \
|
||||
_zend_hash_next_index_insert(ht, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_next_index_insert_new(ht, pData) \
|
||||
_zend_hash_next_index_insert_new(ht, pData ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, ulong h);
|
||||
ZEND_API zval *zend_hash_add_empty_element(HashTable *ht, zend_string *key);
|
||||
ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *key, int len);
|
||||
|
||||
#define ZEND_HASH_APPLY_KEEP 0
|
||||
#define ZEND_HASH_APPLY_REMOVE 1<<0
|
||||
#define ZEND_HASH_APPLY_STOP 1<<1
|
||||
|
||||
typedef int (*apply_func_t)(void *pDest TSRMLS_DC);
|
||||
typedef int (*apply_func_arg_t)(void *pDest, void *argument TSRMLS_DC);
|
||||
typedef int (*apply_func_args_t)(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
|
||||
typedef int (*apply_func_t)(zval *pDest TSRMLS_DC);
|
||||
typedef int (*apply_func_arg_t)(zval *pDest, void *argument TSRMLS_DC);
|
||||
typedef int (*apply_func_args_t)(zval *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
|
||||
|
||||
ZEND_API void zend_hash_graceful_destroy(HashTable *ht);
|
||||
ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht);
|
||||
@@ -150,42 +144,37 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
|
||||
|
||||
|
||||
/* Deletes */
|
||||
ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag);
|
||||
#define zend_hash_del(ht, arKey, nKeyLength) \
|
||||
zend_hash_del_key_or_index(ht, arKey, nKeyLength, 0, HASH_DEL_KEY)
|
||||
#define zend_hash_quick_del(ht, arKey, nKeyLength, h) \
|
||||
zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK)
|
||||
#define zend_hash_index_del(ht, h) \
|
||||
zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX)
|
||||
#define zend_get_hash_value \
|
||||
zend_hash_func
|
||||
ZEND_API int zend_hash_del(HashTable *ht, zend_string *key);
|
||||
ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key);
|
||||
ZEND_API int zend_hash_str_del(HashTable *ht, const char *key, int len);
|
||||
ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *key, int len);
|
||||
ZEND_API int zend_hash_index_del(HashTable *ht, ulong h);
|
||||
|
||||
/* Data retreival */
|
||||
ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData);
|
||||
ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void **pData);
|
||||
ZEND_API int zend_hash_index_find(const HashTable *ht, ulong h, void **pData);
|
||||
ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key);
|
||||
ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *key, int len);
|
||||
ZEND_API zval *zend_hash_index_find(const HashTable *ht, ulong h);
|
||||
|
||||
/* Misc */
|
||||
ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength);
|
||||
ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h);
|
||||
ZEND_API int zend_hash_exists(const HashTable *ht, zend_string *key);
|
||||
ZEND_API int zend_hash_str_exists(const HashTable *ht, const char *str, int len);
|
||||
ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
|
||||
ZEND_API ulong zend_hash_next_free_element(const HashTable *ht);
|
||||
|
||||
/* traversing */
|
||||
#define zend_hash_has_more_elements_ex(ht, pos) \
|
||||
(zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTENT ? FAILURE : SUCCESS)
|
||||
ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos);
|
||||
ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos);
|
||||
ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos);
|
||||
ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, ulong *num_index, zend_bool duplicate, HashPosition *pos);
|
||||
ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos);
|
||||
ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos);
|
||||
ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
|
||||
ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos);
|
||||
ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
|
||||
ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
|
||||
ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos);
|
||||
|
||||
typedef struct _HashPointer {
|
||||
HashPosition pos;
|
||||
HashTable *ht;
|
||||
ulong h;
|
||||
} HashPointer;
|
||||
|
||||
@@ -193,110 +182,44 @@ ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr);
|
||||
ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
|
||||
|
||||
#define zend_hash_has_more_elements(ht) \
|
||||
zend_hash_has_more_elements_ex(ht, NULL)
|
||||
zend_hash_has_more_elements_ex(ht, &(ht)->nInternalPointer)
|
||||
#define zend_hash_move_forward(ht) \
|
||||
zend_hash_move_forward_ex(ht, NULL)
|
||||
zend_hash_move_forward_ex(ht, &(ht)->nInternalPointer)
|
||||
#define zend_hash_move_backwards(ht) \
|
||||
zend_hash_move_backwards_ex(ht, NULL)
|
||||
zend_hash_move_backwards_ex(ht, &(ht)->nInternalPointer)
|
||||
#define zend_hash_get_current_key(ht, str_index, num_index, duplicate) \
|
||||
zend_hash_get_current_key_ex(ht, str_index, NULL, num_index, duplicate, NULL)
|
||||
zend_hash_get_current_key_ex(ht, str_index, num_index, duplicate, &(ht)->nInternalPointer)
|
||||
#define zend_hash_get_current_key_zval(ht, key) \
|
||||
zend_hash_get_current_key_zval_ex(ht, key, NULL)
|
||||
zend_hash_get_current_key_zval_ex(ht, key, &(ht)->nInternalPointer)
|
||||
#define zend_hash_get_current_key_type(ht) \
|
||||
zend_hash_get_current_key_type_ex(ht, NULL)
|
||||
#define zend_hash_get_current_data(ht, pData) \
|
||||
zend_hash_get_current_data_ex(ht, pData, NULL)
|
||||
zend_hash_get_current_key_type_ex(ht, &(ht)->nInternalPointer)
|
||||
#define zend_hash_get_current_data(ht) \
|
||||
zend_hash_get_current_data_ex(ht, &(ht)->nInternalPointer)
|
||||
#define zend_hash_internal_pointer_reset(ht) \
|
||||
zend_hash_internal_pointer_reset_ex(ht, NULL)
|
||||
zend_hash_internal_pointer_reset_ex(ht, &(ht)->nInternalPointer)
|
||||
#define zend_hash_internal_pointer_end(ht) \
|
||||
zend_hash_internal_pointer_end_ex(ht, NULL)
|
||||
#define zend_hash_update_current_key(ht, key_type, str_index, str_length, num_index) \
|
||||
zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, HASH_UPDATE_KEY_ANYWAY, NULL)
|
||||
zend_hash_internal_pointer_end_ex(ht, &(ht)->nInternalPointer)
|
||||
|
||||
/* Copying, merging and sorting */
|
||||
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
|
||||
ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite ZEND_FILE_LINE_DC);
|
||||
ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
|
||||
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor);
|
||||
ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite ZEND_FILE_LINE_DC);
|
||||
ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam);
|
||||
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC);
|
||||
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC);
|
||||
ZEND_API int zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC);
|
||||
ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag TSRMLS_DC);
|
||||
|
||||
#define zend_hash_merge(target, source, pCopyConstructor, tmp, size, overwrite) \
|
||||
_zend_hash_merge(target, source, pCopyConstructor, tmp, size, overwrite ZEND_FILE_LINE_CC)
|
||||
#define zend_hash_merge(target, source, pCopyConstructor, overwrite) \
|
||||
_zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API int zend_hash_num_elements(const HashTable *ht);
|
||||
#define zend_hash_num_elements(ht) \
|
||||
(ht)->nNumOfElements
|
||||
|
||||
#define zend_hash_next_free_element(ht) \
|
||||
(ht)->nNextFreeElement
|
||||
|
||||
ZEND_API int zend_hash_rehash(HashTable *ht);
|
||||
ZEND_API void zend_hash_reindex(HashTable *ht, zend_bool only_integer_keys);
|
||||
|
||||
ZEND_API void _zend_hash_splice(HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor, uint offset, uint length, void **list, uint list_count, HashTable *removed ZEND_FILE_LINE_DC);
|
||||
#define zend_hash_splice(ht, nDataSize, pCopyConstructor, offset, length, list, list_count, removed) \
|
||||
_zend_hash_splice(ht, nDataSize, pCopyConstructor, offset, length, list, list_count, removed ZEND_FILE_LINE_CC)
|
||||
|
||||
/*
|
||||
* DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
|
||||
*
|
||||
* This is Daniel J. Bernstein's popular `times 33' hash function as
|
||||
* posted by him years ago on comp.lang.c. It basically uses a function
|
||||
* like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best
|
||||
* known hash functions for strings. Because it is both computed very
|
||||
* fast and distributes very well.
|
||||
*
|
||||
* The magic of number 33, i.e. why it works better than many other
|
||||
* constants, prime or not, has never been adequately explained by
|
||||
* anyone. So I try an explanation: if one experimentally tests all
|
||||
* multipliers between 1 and 256 (as RSE did now) one detects that even
|
||||
* numbers are not useable at all. The remaining 128 odd numbers
|
||||
* (except for the number 1) work more or less all equally well. They
|
||||
* all distribute in an acceptable way and this way fill a hash table
|
||||
* with an average percent of approx. 86%.
|
||||
*
|
||||
* If one compares the Chi^2 values of the variants, the number 33 not
|
||||
* even has the best value. But the number 33 and a few other equally
|
||||
* good numbers like 17, 31, 63, 127 and 129 have nevertheless a great
|
||||
* advantage to the remaining numbers in the large set of possible
|
||||
* multipliers: their multiply operation can be replaced by a faster
|
||||
* operation based on just one shift plus either a single addition
|
||||
* or subtraction operation. And because a hash function has to both
|
||||
* distribute good _and_ has to be very fast to compute, those few
|
||||
* numbers should be preferred and seems to be the reason why Daniel J.
|
||||
* Bernstein also preferred it.
|
||||
*
|
||||
*
|
||||
* -- Ralf S. Engelschall <rse@engelschall.com>
|
||||
*/
|
||||
|
||||
static inline ulong zend_inline_hash_func(const char *arKey, uint nKeyLength)
|
||||
{
|
||||
register ulong hash = 5381;
|
||||
|
||||
/* variant with the hash unrolled eight times */
|
||||
for (; nKeyLength >= 8; nKeyLength -= 8) {
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
hash = ((hash << 5) + hash) + *arKey++;
|
||||
}
|
||||
switch (nKeyLength) {
|
||||
case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
|
||||
case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
|
||||
case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
|
||||
case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
|
||||
case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
|
||||
case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
|
||||
case 1: hash = ((hash << 5) + hash) + *arKey++; break;
|
||||
case 0: break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API ulong zend_hash_func(const char *arKey, uint nKeyLength);
|
||||
ZEND_API void zend_array_dup(HashTable *target, HashTable *source);
|
||||
|
||||
#if ZEND_DEBUG
|
||||
/* debug */
|
||||
@@ -307,87 +230,543 @@ void zend_hash_display(const HashTable *ht);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_INIT_SYMTABLE(ht) \
|
||||
ZEND_INIT_SYMTABLE_EX(ht, 2, 0)
|
||||
ZEND_INIT_SYMTABLE_EX(ht, 8, 0)
|
||||
|
||||
#define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \
|
||||
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC_EX(key, length, idx, func) do { \
|
||||
register const char *tmp = key; \
|
||||
\
|
||||
if (*tmp == '-') { \
|
||||
tmp++; \
|
||||
} \
|
||||
if (*tmp >= '0' && *tmp <= '9') { /* possibly a numeric index */ \
|
||||
const char *end = key + length - 1; \
|
||||
\
|
||||
if ((*end != '\0') /* not a null terminated string */ \
|
||||
|| (*tmp == '0' && length > 2) /* numbers with leading zeros */ \
|
||||
|| (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */ \
|
||||
|| (SIZEOF_LONG == 4 && \
|
||||
end - tmp == MAX_LENGTH_OF_LONG - 1 && \
|
||||
*tmp > '2')) { /* overflow */ \
|
||||
break; \
|
||||
} \
|
||||
idx = (*tmp - '0'); \
|
||||
while (++tmp != end && *tmp >= '0' && *tmp <= '9') { \
|
||||
idx = (idx * 10) + (*tmp - '0'); \
|
||||
} \
|
||||
if (tmp == end) { \
|
||||
if (*key == '-') { \
|
||||
if (idx-1 > LONG_MAX) { /* overflow */ \
|
||||
break; \
|
||||
} \
|
||||
idx = 0 - idx; \
|
||||
} else if (idx > LONG_MAX) { /* overflow */ \
|
||||
break; \
|
||||
} \
|
||||
func; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC(key, length, func) do { \
|
||||
ulong idx; \
|
||||
\
|
||||
ZEND_HANDLE_NUMERIC_EX(key, length, idx, return func); \
|
||||
} while (0)
|
||||
|
||||
static inline int zend_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) \
|
||||
static inline int _zend_handle_numeric_str(const char *key, int length, ulong *idx)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
|
||||
return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
|
||||
register const char *tmp = key;
|
||||
const char *end;
|
||||
|
||||
if (*tmp > '9') {
|
||||
return 0;
|
||||
} else if (*tmp < '0') {
|
||||
if (*tmp != '-') {
|
||||
return 0;
|
||||
}
|
||||
tmp++;
|
||||
if (*tmp > '9' || *tmp < '0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* possibly a numeric index */
|
||||
end = key + length;
|
||||
|
||||
if ((*end != '\0') /* not a null terminated string */
|
||||
|| (*tmp == '0' && length > 1) /* numbers with leading zeros */
|
||||
|| (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
|
||||
|| (SIZEOF_LONG == 4 &&
|
||||
end - tmp == MAX_LENGTH_OF_LONG - 1 &&
|
||||
*tmp > '2')) { /* overflow */
|
||||
return 0;
|
||||
}
|
||||
*idx = (*tmp - '0');
|
||||
while (1) {
|
||||
++tmp;
|
||||
if (tmp == end) {
|
||||
if (*key == '-') {
|
||||
if (*idx-1 > LONG_MAX) { /* overflow */
|
||||
return 0;
|
||||
}
|
||||
*idx = 0 - *idx;
|
||||
} else if (*idx > LONG_MAX) { /* overflow */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (*tmp <= '9' && *tmp >= '0') {
|
||||
*idx = (*idx * 10) + (*tmp - '0');
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC_STR(key, length, idx) \
|
||||
_zend_handle_numeric_str(key, length, &idx)
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC(key, idx) \
|
||||
_zend_handle_numeric_str((key)->val, (key)->len, &idx)
|
||||
|
||||
|
||||
static inline zval *zend_hash_find_ind(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_find(ht, key);
|
||||
return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ? Z_INDIRECT_P(zv) : zv;
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength)
|
||||
static inline int zend_hash_exists_ind(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
|
||||
return zend_hash_del(ht, arKey, nKeyLength);
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_find(ht, key);
|
||||
return zv && (Z_TYPE_P(zv) != IS_INDIRECT ||
|
||||
Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF);
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData)
|
||||
static inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
|
||||
return zend_hash_find(ht, arKey, nKeyLength, pData);
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_str_find(ht, str, len);
|
||||
return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ? Z_INDIRECT_P(zv) : zv;
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength)
|
||||
static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
|
||||
return zend_hash_exists(ht, arKey, nKeyLength);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_update(ht, key, pData);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int zend_symtable_update_current_key_ex(HashTable *ht, const char *arKey, uint nKeyLength, int mode, HashPosition *pos)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL, 0, idx, mode, pos));
|
||||
return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, arKey, nKeyLength, 0, mode, pos);
|
||||
}
|
||||
#define zend_symtable_update_current_key(ht,arKey,nKeyLength,mode) \
|
||||
zend_symtable_update_current_key_ex(ht, arKey, nKeyLength, mode, NULL)
|
||||
|
||||
static inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zval *pData)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_update_ind(ht, key, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_del(HashTable *ht, zend_string *key)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_del(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_del_ind(HashTable *ht, zend_string *key)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_del_ind(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_find(ht, idx);
|
||||
} else {
|
||||
return zend_hash_find(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_find(ht, idx);
|
||||
} else {
|
||||
return zend_hash_find_ind(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_exists(HashTable *ht, zend_string *key)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_exists(ht, idx);
|
||||
} else {
|
||||
return zend_hash_exists(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_str_update(ht, str, len, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_str_update_ind(ht, str, len, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_del(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_del_ind(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_find(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_find(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_str_exists(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_exists(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_exists(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *zend_hash_add_ptr(HashTable *ht, zend_string *key, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_add(ht, key, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_add_new_ptr(HashTable *ht, zend_string *key, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_add_new(ht, key, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_str_add_ptr(HashTable *ht, const char *str, int len, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_str_add(ht, str, len, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_update_ptr(HashTable *ht, zend_string *key, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_update(ht, key, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_str_update_ptr(HashTable *ht, const char *str, int len, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_str_update(ht, str, len, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_add_mem(HashTable *ht, zend_string *key, void *pData, size_t size)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, NULL);
|
||||
if ((zv = zend_hash_add(ht, key, &tmp))) {
|
||||
Z_PTR_P(zv) = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT);
|
||||
memcpy(Z_PTR_P(zv), pData, size);
|
||||
return Z_PTR_P(zv);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_str_add_mem(HashTable *ht, const char *str, int len, void *pData, size_t size)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, NULL);
|
||||
if ((zv = zend_hash_str_add(ht, str, len, &tmp))) {
|
||||
Z_PTR_P(zv) = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT);
|
||||
memcpy(Z_PTR_P(zv), pData, size);
|
||||
return Z_PTR_P(zv);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_update_mem(HashTable *ht, zend_string *key, void *pData, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT);
|
||||
memcpy(p, pData, size);
|
||||
return zend_hash_update_ptr(ht, key, p);
|
||||
}
|
||||
|
||||
static inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, int len, void *pData, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT);
|
||||
memcpy(p, pData, size);
|
||||
return zend_hash_str_update_ptr(ht, str, len, p);
|
||||
}
|
||||
|
||||
static inline void *zend_hash_index_update_ptr(HashTable *ht, ulong h, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_index_update(ht, h, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_next_index_insert_ptr(HashTable *ht, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_hash_next_index_insert(ht, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_index_update_mem(HashTable *ht, ulong h, void *pData, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT);
|
||||
memcpy(p, pData, size);
|
||||
return zend_hash_index_update_ptr(ht, h, p);
|
||||
}
|
||||
|
||||
static inline void *zend_hash_next_index_insert_mem(HashTable *ht, void *pData, size_t size)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, NULL);
|
||||
if ((zv = zend_hash_next_index_insert(ht, &tmp))) {
|
||||
Z_PTR_P(zv) = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT);
|
||||
memcpy(Z_PTR_P(zv), pData, size);
|
||||
return Z_PTR_P(zv);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_find_ptr(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_find(ht, key);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str, int len)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_str_find(ht, str, len);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_hash_index_find_ptr(const HashTable *ht, ulong h)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_index_find(ht, h);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_find_ptr(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_find_ptr(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPosition *pos)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_hash_get_current_data_ex(ht, pos);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
#define zend_hash_get_current_data_ptr(ht) \
|
||||
zend_hash_get_current_data_ptr_ex(ht, &(ht)->nInternalPointer)
|
||||
|
||||
#define ZEND_HASH_FOREACH(_ht, indirect) do { \
|
||||
uint _idx; \
|
||||
for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \
|
||||
Bucket *_p = (_ht)->arData + _idx; \
|
||||
zval *_z = &_p->val; \
|
||||
if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
|
||||
_z = Z_INDIRECT_P(_z); \
|
||||
} \
|
||||
if (Z_TYPE_P(_z) == IS_UNDEF) continue;
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \
|
||||
uint _idx; \
|
||||
for (_idx = (_ht)->nNumUsed; _idx > 0; _idx--) { \
|
||||
Bucket *_p = (_ht)->arData + _idx - 1; \
|
||||
zval *_z = &_p->val; \
|
||||
if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
|
||||
_z = Z_INDIRECT_P(_z); \
|
||||
} \
|
||||
if (Z_TYPE_P(_z) == IS_UNDEF) continue;
|
||||
|
||||
#define ZEND_HASH_FOREACH_END() \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ZEND_HASH_FOREACH_BUCKET(ht, _bucket) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_bucket = _p;
|
||||
|
||||
#define ZEND_HASH_FOREACH_VAL(ht, _val) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_VAL_IND(ht, _val) \
|
||||
ZEND_HASH_FOREACH(ht, 1); \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_PTR(ht, _ptr) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_ptr = Z_PTR_P(_z);
|
||||
|
||||
#define ZEND_HASH_FOREACH_NUM_KEY(ht, _h) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_h = _p->h;
|
||||
|
||||
#define ZEND_HASH_FOREACH_STR_KEY(ht, _key) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_key = _p->key;
|
||||
|
||||
#define ZEND_HASH_FOREACH_KEY(ht, _h, _key) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_h = _p->h; \
|
||||
_key = _p->key;
|
||||
|
||||
#define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_h = _p->h; \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, _key, _val) \
|
||||
ZEND_HASH_FOREACH(ht, 1); \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \
|
||||
ZEND_HASH_FOREACH(ht, 1); \
|
||||
_h = _p->h; \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_key = _p->key; \
|
||||
_ptr = Z_PTR_P(_z);
|
||||
|
||||
#define ZEND_HASH_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \
|
||||
ZEND_HASH_FOREACH(ht, 0); \
|
||||
_h = _p->h; \
|
||||
_key = _p->key; \
|
||||
_ptr = Z_PTR_P(_z);
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_VAL(ht, _val) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 0); \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_PTR(ht, _ptr) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 0); \
|
||||
_ptr = Z_PTR_P(_z);
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_VAL_IND(ht, _val) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 1); \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_KEY_VAL(ht, _h, _key, _val) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 0); \
|
||||
_h = _p->h; \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_REVERSE_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \
|
||||
ZEND_HASH_REVERSE_FOREACH(ht, 1); \
|
||||
_h = _p->h; \
|
||||
_key = _p->key; \
|
||||
_val = _z;
|
||||
|
||||
#define ZEND_HASH_APPLY_PROTECTION(ht) \
|
||||
((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION)
|
||||
|
||||
#define ZEND_HASH_APPLY_SHIFT 8
|
||||
#define ZEND_HASH_GET_APPLY_COUNT(ht) ((ht)->u.flags >> ZEND_HASH_APPLY_SHIFT)
|
||||
#define ZEND_HASH_INC_APPLY_COUNT(ht) ((ht)->u.flags += (1 << ZEND_HASH_APPLY_SHIFT))
|
||||
#define ZEND_HASH_DEC_APPLY_COUNT(ht) ((ht)->u.flags -= (1 << ZEND_HASH_APPLY_SHIFT))
|
||||
|
||||
#endif /* ZEND_HASH_H */
|
||||
|
||||
|
||||
+13
-12
@@ -92,7 +92,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
zend_printf("<code>");
|
||||
zend_printf("<span style=\"color: %s\">\n", last_color);
|
||||
/* highlight stuff coming back from zendlex() */
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
while ((token_type=lex_scan(&token TSRMLS_CC))) {
|
||||
switch (token_type) {
|
||||
case T_INLINE_HTML:
|
||||
@@ -116,11 +116,11 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
break;
|
||||
case T_WHITESPACE:
|
||||
zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); /* no color needed */
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
if (token.type == 0) {
|
||||
if (Z_TYPE(token) == IS_UNDEF) {
|
||||
next_color = syntax_highlighter_ini->highlight_keyword;
|
||||
} else {
|
||||
next_color = syntax_highlighter_ini->highlight_default;
|
||||
@@ -140,7 +140,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
|
||||
zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);
|
||||
|
||||
if (token.type == IS_STRING) {
|
||||
if (Z_TYPE(token) == IS_STRING) {
|
||||
switch (token_type) {
|
||||
case T_OPEN_TAG:
|
||||
case T_OPEN_TAG_WITH_ECHO:
|
||||
@@ -150,11 +150,11 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
case T_DOC_COMMENT:
|
||||
break;
|
||||
default:
|
||||
str_efree(token.value.str.val);
|
||||
STR_RELEASE(Z_STR(token));
|
||||
break;
|
||||
}
|
||||
}
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
}
|
||||
|
||||
if (last_color != syntax_highlighter_ini->highlight_html) {
|
||||
@@ -170,7 +170,7 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
int token_type;
|
||||
int prev_space = 0;
|
||||
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
while ((token_type=lex_scan(&token TSRMLS_CC))) {
|
||||
switch (token_type) {
|
||||
case T_WHITESPACE:
|
||||
@@ -181,7 +181,7 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
/* lack of break; is intentional */
|
||||
case T_COMMENT:
|
||||
case T_DOC_COMMENT:
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
continue;
|
||||
|
||||
case T_END_HEREDOC:
|
||||
@@ -192,7 +192,7 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
}
|
||||
zend_write("\n", sizeof("\n") - 1);
|
||||
prev_space = 1;
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
continue;
|
||||
|
||||
default:
|
||||
@@ -200,7 +200,7 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
break;
|
||||
}
|
||||
|
||||
if (token.type == IS_STRING) {
|
||||
if (Z_TYPE(token) == IS_STRING) {
|
||||
switch (token_type) {
|
||||
case T_OPEN_TAG:
|
||||
case T_OPEN_TAG_WITH_ECHO:
|
||||
@@ -211,11 +211,12 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
break;
|
||||
|
||||
default:
|
||||
STR_FREE(token.value.str.val);
|
||||
STR_RELEASE(Z_STR(token));
|
||||
break;
|
||||
}
|
||||
}
|
||||
prev_space = token.type = 0;
|
||||
prev_space = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -59,14 +59,14 @@ ZEND_API void zend_indent(TSRMLS_D)
|
||||
memset(emit_whitespace, 0, sizeof(int)*256);
|
||||
|
||||
/* highlight stuff coming back from zendlex() */
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
while ((token_type=lex_scan(&token TSRMLS_CC))) {
|
||||
switch (token_type) {
|
||||
case T_INLINE_HTML:
|
||||
zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
|
||||
break;
|
||||
case T_WHITESPACE: {
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
/* eat whitespace, emit newlines */
|
||||
for (i=0; i<LANG_SCNG(yy_leng); i++) {
|
||||
emit_whitespace[(unsigned char) LANG_SCNG(yy_text)[i]]++;
|
||||
@@ -78,7 +78,7 @@ ZEND_API void zend_indent(TSRMLS_D)
|
||||
in_string = !in_string;
|
||||
/* break missing intentionally */
|
||||
default:
|
||||
if (token.type==0) {
|
||||
if (Z_TYPE(token) == IS_UNDEF) {
|
||||
/* keyword */
|
||||
switch (token_type) {
|
||||
case ',':
|
||||
@@ -131,18 +131,18 @@ dflt_printout:
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (token.type == IS_STRING) {
|
||||
if (Z_TYPE(token) == IS_STRING) {
|
||||
switch (token_type) {
|
||||
case T_OPEN_TAG:
|
||||
case T_CLOSE_TAG:
|
||||
case T_WHITESPACE:
|
||||
break;
|
||||
default:
|
||||
str_efree(token.value.str.val);
|
||||
STR_RELEASE(Z_STR(token));
|
||||
break;
|
||||
}
|
||||
}
|
||||
token.type = 0;
|
||||
ZVAL_UNDEF(&token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+47
-37
@@ -34,9 +34,11 @@ static HashTable *registered_zend_ini_directives;
|
||||
/*
|
||||
* hash_apply functions
|
||||
*/
|
||||
static int zend_remove_ini_entries(zend_ini_entry *ini_entry, int *module_number TSRMLS_DC) /* {{{ */
|
||||
static int zend_remove_ini_entries(zval *el, void *arg TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (ini_entry->module_number == *module_number) {
|
||||
zend_ini_entry *ini_entry = (zend_ini_entry *)Z_PTR_P(el);
|
||||
int module_number = *(int *)arg;
|
||||
if (ini_entry->module_number == module_number) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -76,13 +78,20 @@ static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_restore_ini_entry_wrapper(zend_ini_entry **ini_entry TSRMLS_DC) /* {{{ */
|
||||
static int zend_restore_ini_entry_wrapper(zval *el TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_restore_ini_entry_cb(*ini_entry, ZEND_INI_STAGE_DEACTIVATE TSRMLS_CC);
|
||||
zend_ini_entry *ini_entry = (zend_ini_entry *)Z_PTR_P(el);
|
||||
zend_restore_ini_entry_cb(ini_entry, ZEND_INI_STAGE_DEACTIVATE TSRMLS_CC);
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void _free_ptr(zval *zv) /* {{{ */
|
||||
{
|
||||
free(Z_PTR_P(zv));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Startup / shutdown
|
||||
*/
|
||||
@@ -93,9 +102,7 @@ ZEND_API int zend_ini_startup(TSRMLS_D) /* {{{ */
|
||||
EG(ini_directives) = registered_zend_ini_directives;
|
||||
EG(modified_ini_directives) = NULL;
|
||||
EG(error_reporting_ini_entry) = NULL;
|
||||
if (zend_hash_init_ex(registered_zend_ini_directives, 100, NULL, NULL, 1, 0) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
zend_hash_init_ex(registered_zend_ini_directives, 128, NULL, _free_ptr, 1, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -119,7 +126,7 @@ ZEND_API int zend_ini_global_shutdown(TSRMLS_D) /* {{{ */
|
||||
ZEND_API int zend_ini_deactivate(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if (EG(modified_ini_directives)) {
|
||||
zend_hash_apply(EG(modified_ini_directives), (apply_func_t) zend_restore_ini_entry_wrapper TSRMLS_CC);
|
||||
zend_hash_apply(EG(modified_ini_directives), zend_restore_ini_entry_wrapper TSRMLS_CC);
|
||||
zend_hash_destroy(EG(modified_ini_directives));
|
||||
FREE_HASHTABLE(EG(modified_ini_directives));
|
||||
EG(modified_ini_directives) = NULL;
|
||||
@@ -131,15 +138,11 @@ ZEND_API int zend_ini_deactivate(TSRMLS_D) /* {{{ */
|
||||
#ifdef ZTS
|
||||
ZEND_API int zend_copy_ini_directives(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_ini_entry ini_entry;
|
||||
|
||||
EG(modified_ini_directives) = NULL;
|
||||
EG(error_reporting_ini_entry) = NULL;
|
||||
EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
|
||||
if (zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, NULL, &ini_entry, sizeof(zend_ini_entry));
|
||||
zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0);
|
||||
zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, NULL);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -150,17 +153,17 @@ static int ini_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
|
||||
const Bucket *f;
|
||||
const Bucket *s;
|
||||
|
||||
f = *((const Bucket **) a);
|
||||
s = *((const Bucket **) b);
|
||||
f = (const Bucket *) a;
|
||||
s = (const Bucket *) b;
|
||||
|
||||
if (f->nKeyLength == 0 && s->nKeyLength == 0) { /* both numeric */
|
||||
return ZEND_NORMALIZE_BOOL(f->nKeyLength - s->nKeyLength);
|
||||
} else if (f->nKeyLength == 0) { /* f is numeric, s is not */
|
||||
if (!f->key && !s->key) { /* both numeric */
|
||||
return ZEND_NORMALIZE_BOOL(f->h - s->h);
|
||||
} else if (!f->key) { /* f is numeric, s is not */
|
||||
return -1;
|
||||
} else if (s->nKeyLength == 0) { /* s is numeric, f is not */
|
||||
} else if (!s->key) { /* s is numeric, f is not */
|
||||
return 1;
|
||||
} else { /* both strings */
|
||||
return zend_binary_strcasecmp(f->arKey, f->nKeyLength, s->arKey, s->nKeyLength);
|
||||
return zend_binary_strcasecmp(f->key->val, f->key->len, s->key->val, s->key->len);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -198,7 +201,7 @@ ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int modu
|
||||
|
||||
while (p->name) {
|
||||
config_directive_success = 0;
|
||||
if (zend_hash_add(directives, p->name, p->name_length, (void*)p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry) == FAILURE) {
|
||||
if ((hashed_ini_entry = zend_hash_str_add_mem(directives, p->name, p->name_length, (void*)p, sizeof(zend_ini_entry))) == NULL) {
|
||||
zend_unregister_ini_entries(module_number TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -223,13 +226,16 @@ ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int modu
|
||||
|
||||
ZEND_API void zend_unregister_ini_entries(int module_number TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_hash_apply_with_argument(registered_zend_ini_directives, (apply_func_arg_t) zend_remove_ini_entries, (void *) &module_number TSRMLS_CC);
|
||||
zend_hash_apply_with_argument(registered_zend_ini_directives, zend_remove_ini_entries, (void *) &module_number TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifdef ZTS
|
||||
static int zend_ini_refresh_cache(zend_ini_entry *p, int stage TSRMLS_DC) /* {{{ */
|
||||
static int zend_ini_refresh_cache(zval *el, void *arg TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_ini_entry *p = (zend_ini_entry *)Z_PTR_P(el);
|
||||
int stage = (int)(zend_intptr_t)arg;
|
||||
|
||||
if (p->on_modify) {
|
||||
p->on_modify(p, p->value, p->value_length, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage TSRMLS_CC);
|
||||
}
|
||||
@@ -239,27 +245,27 @@ static int zend_ini_refresh_cache(zend_ini_entry *p, int stage TSRMLS_DC) /* {{{
|
||||
|
||||
ZEND_API void zend_ini_refresh_caches(int stage TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) zend_ini_refresh_cache, (void *)(zend_intptr_t) stage TSRMLS_CC);
|
||||
zend_hash_apply_with_argument(EG(ini_directives), zend_ini_refresh_cache, (void *)(zend_intptr_t) stage TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage) /* {{{ */
|
||||
ZEND_API int zend_alter_ini_entry(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage) /* {{{ */
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
|
||||
return zend_alter_ini_entry_ex(name, name_length, new_value, new_value_length, modify_type, stage, 0 TSRMLS_CC);
|
||||
return zend_alter_ini_entry_ex(name, new_value, new_value_length, modify_type, stage, 0 TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */
|
||||
ZEND_API int zend_alter_ini_entry_ex(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_ini_entry *ini_entry;
|
||||
char *duplicate;
|
||||
zend_bool modifiable;
|
||||
zend_bool modified;
|
||||
|
||||
if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) {
|
||||
if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -285,7 +291,7 @@ ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_val
|
||||
ini_entry->orig_value_length = ini_entry->value_length;
|
||||
ini_entry->orig_modifiable = modifiable;
|
||||
ini_entry->modified = 1;
|
||||
zend_hash_add(EG(modified_ini_directives), name, name_length, &ini_entry, sizeof(zend_ini_entry*), NULL);
|
||||
zend_hash_add_ptr(EG(modified_ini_directives), name, ini_entry);
|
||||
}
|
||||
|
||||
duplicate = estrndup(new_value, new_value_length);
|
||||
@@ -306,19 +312,19 @@ ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_val
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_restore_ini_entry(char *name, uint name_length, int stage) /* {{{ */
|
||||
ZEND_API int zend_restore_ini_entry(zend_string *name, int stage) /* {{{ */
|
||||
{
|
||||
zend_ini_entry *ini_entry;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE ||
|
||||
if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL ||
|
||||
(stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (EG(modified_ini_directives)) {
|
||||
if (zend_restore_ini_entry_cb(ini_entry, stage TSRMLS_CC) == 0) {
|
||||
zend_hash_del(EG(modified_ini_directives), name, name_length);
|
||||
zend_hash_del(EG(modified_ini_directives), name);
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -332,7 +338,8 @@ ZEND_API int zend_ini_register_displayer(char *name, uint name_length, void (*di
|
||||
{
|
||||
zend_ini_entry *ini_entry;
|
||||
|
||||
if (zend_hash_find(registered_zend_ini_directives, name, name_length, (void **) &ini_entry) == FAILURE) {
|
||||
ini_entry = zend_hash_str_find_ptr(registered_zend_ini_directives, name, name_length);
|
||||
if (ini_entry == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -350,7 +357,8 @@ ZEND_API long zend_ini_long(char *name, uint name_length, int orig) /* {{{ */
|
||||
zend_ini_entry *ini_entry;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == SUCCESS) {
|
||||
ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
|
||||
if (ini_entry) {
|
||||
if (orig && ini_entry->modified) {
|
||||
return (ini_entry->orig_value ? strtol(ini_entry->orig_value, NULL, 0) : 0);
|
||||
} else {
|
||||
@@ -367,7 +375,8 @@ ZEND_API double zend_ini_double(char *name, uint name_length, int orig) /* {{{ *
|
||||
zend_ini_entry *ini_entry;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == SUCCESS) {
|
||||
ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
|
||||
if (ini_entry) {
|
||||
if (orig && ini_entry->modified) {
|
||||
return (double) (ini_entry->orig_value ? zend_strtod(ini_entry->orig_value, NULL) : 0.0);
|
||||
} else {
|
||||
@@ -384,7 +393,8 @@ ZEND_API char *zend_ini_string_ex(char *name, uint name_length, int orig, zend_b
|
||||
zend_ini_entry *ini_entry;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == SUCCESS) {
|
||||
ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
|
||||
if (ini_entry) {
|
||||
if (exists) {
|
||||
*exists = 1;
|
||||
}
|
||||
|
||||
+14
-44
@@ -27,53 +27,23 @@
|
||||
|
||||
#define ZEND_INI_ALL (ZEND_INI_USER|ZEND_INI_PERDIR|ZEND_INI_SYSTEM)
|
||||
|
||||
#ifndef XtOffsetOf
|
||||
# if defined(CRAY) || (defined(__ARMCC_VERSION) && !defined(LINUX))
|
||||
# ifdef __STDC__
|
||||
# define XtOffset(p_type, field) _Offsetof(p_type, field)
|
||||
# else
|
||||
# ifdef CRAY2
|
||||
# define XtOffset(p_type, field) \
|
||||
(sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))
|
||||
|
||||
# else /* !CRAY2 */
|
||||
|
||||
# define XtOffset(p_type, field) ((unsigned int)&(((p_type)NULL)->field))
|
||||
|
||||
# endif /* !CRAY2 */
|
||||
# endif /* __STDC__ */
|
||||
# else /* ! (CRAY || __arm) */
|
||||
|
||||
# define XtOffset(p_type, field) \
|
||||
((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
|
||||
|
||||
# endif /* !CRAY */
|
||||
|
||||
# ifdef offsetof
|
||||
# define XtOffsetOf(s_type, field) offsetof(s_type, field)
|
||||
# else
|
||||
# define XtOffsetOf(s_type, field) XtOffset(s_type*, field)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#define ZEND_INI_MH(name) int name(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC)
|
||||
#define ZEND_INI_DISP(name) void name(zend_ini_entry *ini_entry, int type)
|
||||
|
||||
struct _zend_ini_entry {
|
||||
int module_number;
|
||||
int modifiable;
|
||||
char *name;
|
||||
char *name; // TODO: convert into zend_string ???
|
||||
uint name_length;
|
||||
ZEND_INI_MH((*on_modify));
|
||||
void *mh_arg1;
|
||||
void *mh_arg2;
|
||||
void *mh_arg3;
|
||||
|
||||
char *value;
|
||||
char *value; // TODO: convert into zend_string ???
|
||||
uint value_length;
|
||||
|
||||
char *orig_value;
|
||||
char *orig_value; // TODO: convert into zend_string ???
|
||||
uint orig_value_length;
|
||||
int orig_modifiable;
|
||||
int modified;
|
||||
@@ -94,9 +64,9 @@ ZEND_API void zend_ini_sort_entries(TSRMLS_D);
|
||||
ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_unregister_ini_entries(int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_ini_refresh_caches(int stage TSRMLS_DC);
|
||||
ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage);
|
||||
ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC);
|
||||
ZEND_API int zend_restore_ini_entry(char *name, uint name_length, int stage);
|
||||
ZEND_API int zend_alter_ini_entry(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage);
|
||||
ZEND_API int zend_alter_ini_entry_ex(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC);
|
||||
ZEND_API int zend_restore_ini_entry(zend_string *name, int stage);
|
||||
ZEND_API void display_ini_entries(zend_module_entry *module);
|
||||
|
||||
ZEND_API long zend_ini_long(char *name, uint name_length, int orig);
|
||||
@@ -115,7 +85,7 @@ END_EXTERN_C()
|
||||
#define ZEND_INI_END() { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL } };
|
||||
|
||||
#define ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, displayer) \
|
||||
{ 0, modifiable, name, sizeof(name), on_modify, arg1, arg2, arg3, default_value, sizeof(default_value)-1, NULL, 0, 0, 0, displayer },
|
||||
{ 0, modifiable, name, sizeof(name)-1, on_modify, arg1, arg2, arg3, default_value, sizeof(default_value)-1, NULL, 0, 0, 0, displayer },
|
||||
|
||||
#define ZEND_INI_ENTRY3(name, default_value, modifiable, on_modify, arg1, arg2, arg3) \
|
||||
ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, NULL)
|
||||
@@ -154,21 +124,21 @@ END_EXTERN_C()
|
||||
ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr, NULL, zend_ini_boolean_displayer_cb)
|
||||
#endif
|
||||
|
||||
#define INI_INT(name) zend_ini_long((name), sizeof(name), 0)
|
||||
#define INI_FLT(name) zend_ini_double((name), sizeof(name), 0)
|
||||
#define INI_STR(name) zend_ini_string_ex((name), sizeof(name), 0, NULL)
|
||||
#define INI_INT(name) zend_ini_long((name), sizeof(name)-1, 0)
|
||||
#define INI_FLT(name) zend_ini_double((name), sizeof(name)-1, 0)
|
||||
#define INI_STR(name) zend_ini_string_ex((name), sizeof(name)-1, 0, NULL)
|
||||
#define INI_BOOL(name) ((zend_bool) INI_INT(name))
|
||||
|
||||
#define INI_ORIG_INT(name) zend_ini_long((name), sizeof(name), 1)
|
||||
#define INI_ORIG_FLT(name) zend_ini_double((name), sizeof(name), 1)
|
||||
#define INI_ORIG_STR(name) zend_ini_string((name), sizeof(name), 1)
|
||||
#define INI_ORIG_INT(name) zend_ini_long((name), sizeof(name)-1, 1)
|
||||
#define INI_ORIG_FLT(name) zend_ini_double((name), sizeof(name)-1, 1)
|
||||
#define INI_ORIG_STR(name) zend_ini_string((name), sizeof(name)-1, 1)
|
||||
#define INI_ORIG_BOOL(name) ((zend_bool) INI_ORIG_INT(name))
|
||||
|
||||
#define REGISTER_INI_ENTRIES() zend_register_ini_entries(ini_entries, module_number TSRMLS_CC)
|
||||
#define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries(module_number TSRMLS_CC)
|
||||
#define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module)
|
||||
|
||||
#define REGISTER_INI_DISPLAYER(name, displayer) zend_ini_register_displayer((name), sizeof(name), displayer)
|
||||
#define REGISTER_INI_DISPLAYER(name, displayer) zend_ini_register_displayer((name), sizeof(name)-1, displayer)
|
||||
#define REGISTER_INI_BOOLEAN(name) REGISTER_INI_DISPLAYER(name, zend_ini_boolean_displayer_cb)
|
||||
|
||||
/* Standard message handlers */
|
||||
|
||||
+46
-47
@@ -49,13 +49,14 @@ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
{
|
||||
int i_result;
|
||||
int i_op1, i_op2;
|
||||
int str_len;
|
||||
char str_result[MAX_LENGTH_OF_LONG];
|
||||
|
||||
i_op1 = atoi(Z_STRVAL_P(op1));
|
||||
free(Z_STRVAL_P(op1));
|
||||
STR_FREE(Z_STR_P(op1));
|
||||
if (op2) {
|
||||
i_op2 = atoi(Z_STRVAL_P(op2));
|
||||
free(Z_STRVAL_P(op2));
|
||||
STR_FREE(Z_STR_P(op2));
|
||||
} else {
|
||||
i_op2 = 0;
|
||||
}
|
||||
@@ -81,11 +82,8 @@ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
break;
|
||||
}
|
||||
|
||||
Z_STRLEN_P(result) = zend_sprintf(str_result, "%d", i_result);
|
||||
Z_STRVAL_P(result) = (char *) malloc(Z_STRLEN_P(result)+1);
|
||||
memcpy(Z_STRVAL_P(result), str_result, Z_STRLEN_P(result));
|
||||
Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
|
||||
Z_TYPE_P(result) = IS_STRING;
|
||||
str_len = zend_sprintf(str_result, "%d", i_result);
|
||||
ZVAL_PSTRINGL(result, str_result, str_len);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -93,10 +91,7 @@ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
*/
|
||||
static void zend_ini_init_string(zval *result)
|
||||
{
|
||||
Z_STRVAL_P(result) = malloc(1);
|
||||
Z_STRVAL_P(result)[0] = 0;
|
||||
Z_STRLEN_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_STRING;
|
||||
ZVAL_EMPTY_PSTRING(result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -104,13 +99,12 @@ static void zend_ini_init_string(zval *result)
|
||||
*/
|
||||
static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
|
||||
{
|
||||
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
|
||||
int op1_len = Z_STRLEN_P(op1);
|
||||
int length = op1_len + Z_STRLEN_P(op2);
|
||||
|
||||
Z_STRVAL_P(result) = (char *) realloc(Z_STRVAL_P(op1), length+1);
|
||||
memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
|
||||
ZVAL_NEW_STR(result, STR_REALLOC(Z_STR_P(op1), length, 1));
|
||||
memcpy(Z_STRVAL_P(result)+op1_len, Z_STRVAL_P(op2), Z_STRLEN_P(op2));
|
||||
Z_STRVAL_P(result)[length] = 0;
|
||||
Z_STRLEN_P(result) = length;
|
||||
Z_TYPE_P(result) = IS_STRING;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -118,18 +112,25 @@ static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
|
||||
*/
|
||||
static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC)
|
||||
{
|
||||
zval z_constant;
|
||||
zval *c, tmp;
|
||||
|
||||
/* If name contains ':' it is not a constant. Bug #26893. */
|
||||
if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name))
|
||||
&& zend_get_constant(Z_STRVAL_P(name), Z_STRLEN_P(name), &z_constant TSRMLS_CC)) {
|
||||
/* z_constant is emalloc()'d */
|
||||
convert_to_string(&z_constant);
|
||||
Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(z_constant), Z_STRLEN(z_constant));
|
||||
Z_STRLEN_P(result) = Z_STRLEN(z_constant);
|
||||
Z_TYPE_P(result) = Z_TYPE(z_constant);
|
||||
zval_dtor(&z_constant);
|
||||
free(Z_STRVAL_P(name));
|
||||
&& (c = zend_get_constant(Z_STR_P(name) TSRMLS_CC)) != 0) {
|
||||
if (Z_TYPE_P(c) != IS_STRING) {
|
||||
ZVAL_COPY_VALUE(&tmp, c);
|
||||
if (Z_OPT_CONSTANT(tmp)) {
|
||||
zval_update_constant_ex(&tmp, 1, NULL TSRMLS_CC);
|
||||
}
|
||||
zval_opt_copy_ctor(&tmp);
|
||||
convert_to_string(&tmp);
|
||||
c = &tmp;
|
||||
}
|
||||
ZVAL_PSTRINGL(result, Z_STRVAL_P(c), Z_STRLEN_P(c));
|
||||
if (c == &tmp) {
|
||||
zval_dtor(&tmp);
|
||||
}
|
||||
STR_FREE(Z_STR_P(name));
|
||||
} else {
|
||||
*result = *name;
|
||||
}
|
||||
@@ -144,14 +145,12 @@ static void zend_ini_get_var(zval *result, zval *name TSRMLS_DC)
|
||||
char *envvar;
|
||||
|
||||
/* Fetch configuration option value */
|
||||
if (zend_get_configuration_directive(Z_STRVAL_P(name), Z_STRLEN_P(name)+1, &curval) == SUCCESS) {
|
||||
Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(curval), Z_STRLEN(curval));
|
||||
Z_STRLEN_P(result) = Z_STRLEN(curval);
|
||||
if (zend_get_configuration_directive(Z_STRVAL_P(name), Z_STRLEN_P(name), &curval) == SUCCESS) {
|
||||
ZVAL_PSTRINGL(result, Z_STRVAL(curval), Z_STRLEN(curval));
|
||||
/* ..or if not found, try ENV */
|
||||
} else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name) TSRMLS_CC)) != NULL ||
|
||||
(envvar = getenv(Z_STRVAL_P(name))) != NULL) {
|
||||
Z_STRVAL_P(result) = strdup(envvar);
|
||||
Z_STRLEN_P(result) = strlen(envvar);
|
||||
ZVAL_PSTRING(result, envvar);
|
||||
} else {
|
||||
zend_ini_init_string(result);
|
||||
}
|
||||
@@ -160,7 +159,7 @@ static void zend_ini_get_var(zval *result, zval *name TSRMLS_DC)
|
||||
|
||||
/* {{{ ini_error()
|
||||
*/
|
||||
static void ini_error(char *msg)
|
||||
static void ini_error(const char *msg)
|
||||
{
|
||||
char *error_buf;
|
||||
int error_buf_len;
|
||||
@@ -283,26 +282,26 @@ statement:
|
||||
printf("SECTION: [%s]\n", Z_STRVAL($2));
|
||||
#endif
|
||||
ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
|
||||
free(Z_STRVAL($2));
|
||||
STR_RELEASE(Z_STR($2));
|
||||
}
|
||||
| TC_LABEL '=' string_or_value {
|
||||
#if DEBUG_CFG_PARSER
|
||||
printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
|
||||
#endif
|
||||
ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
|
||||
free(Z_STRVAL($1));
|
||||
free(Z_STRVAL($3));
|
||||
STR_RELEASE(Z_STR($1));
|
||||
STR_RELEASE(Z_STR($3));
|
||||
}
|
||||
| TC_OFFSET option_offset ']' '=' string_or_value {
|
||||
#if DEBUG_CFG_PARSER
|
||||
printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
|
||||
#endif
|
||||
ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
|
||||
free(Z_STRVAL($1));
|
||||
free(Z_STRVAL($2));
|
||||
free(Z_STRVAL($5));
|
||||
STR_RELEASE(Z_STR($1));
|
||||
STR_RELEASE(Z_STR($2));
|
||||
STR_RELEASE(Z_STR($5));
|
||||
}
|
||||
| TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); }
|
||||
| TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); STR_RELEASE(Z_STR($1)); }
|
||||
| END_OF_LINE
|
||||
;
|
||||
|
||||
@@ -324,8 +323,8 @@ option_offset:
|
||||
;
|
||||
|
||||
encapsed_list:
|
||||
encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
|
||||
| encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
|
||||
encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
|
||||
| encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
|
||||
| /* empty */ { zend_ini_init_string(&$$); }
|
||||
;
|
||||
|
||||
@@ -333,18 +332,18 @@ var_string_list_section:
|
||||
cfg_var_ref { $$ = $1; }
|
||||
| constant_literal { $$ = $1; }
|
||||
| '"' encapsed_list '"' { $$ = $2; }
|
||||
| var_string_list_section cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
|
||||
| var_string_list_section constant_literal { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
|
||||
| var_string_list_section '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); free(Z_STRVAL($3)); }
|
||||
| var_string_list_section cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
|
||||
| var_string_list_section constant_literal { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
|
||||
| var_string_list_section '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); STR_FREE(Z_STR($3)); }
|
||||
;
|
||||
|
||||
var_string_list:
|
||||
cfg_var_ref { $$ = $1; }
|
||||
| constant_string { $$ = $1; }
|
||||
| '"' encapsed_list '"' { $$ = $2; }
|
||||
| var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
|
||||
| var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
|
||||
| var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); free(Z_STRVAL($3)); }
|
||||
| var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
|
||||
| var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
|
||||
| var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); STR_FREE(Z_STR($3)); }
|
||||
;
|
||||
|
||||
expr:
|
||||
@@ -358,7 +357,7 @@ expr:
|
||||
;
|
||||
|
||||
cfg_var_ref:
|
||||
TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); free(Z_STRVAL($2)); }
|
||||
TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); STR_FREE(Z_STR($2)); }
|
||||
;
|
||||
|
||||
constant_literal:
|
||||
|
||||
+4660
-4663
File diff suppressed because it is too large
Load Diff
@@ -131,11 +131,9 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
|
||||
/* Eat trailing whitespace */
|
||||
#define EAT_TRAILING_WHITESPACE() EAT_TRAILING_WHITESPACE_EX('X')
|
||||
|
||||
#define zend_ini_copy_value(retval, str, len) { \
|
||||
Z_STRVAL_P(retval) = zend_strndup(str, len); \
|
||||
Z_STRLEN_P(retval) = len; \
|
||||
Z_TYPE_P(retval) = IS_STRING; \
|
||||
}
|
||||
#define zend_ini_copy_value(retval, str, len) \
|
||||
ZVAL_NEW_STR(retval, STR_INIT(str, len, 1))
|
||||
|
||||
|
||||
#define RETURN_TOKEN(type, str, len) { \
|
||||
zend_ini_copy_value(ini_lval, str, len); \
|
||||
@@ -144,7 +142,7 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
|
||||
|
||||
static void _yy_push_state(int new_state TSRMLS_DC)
|
||||
{
|
||||
zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
|
||||
zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION());
|
||||
YYSETCONDITION(new_state);
|
||||
}
|
||||
|
||||
@@ -152,8 +150,7 @@ static void _yy_push_state(int new_state TSRMLS_DC)
|
||||
|
||||
static void yy_pop_state(TSRMLS_D)
|
||||
{
|
||||
int *stack_state;
|
||||
zend_stack_top(&SCNG(state_stack), (void **) &stack_state);
|
||||
int *stack_state = zend_stack_top(&SCNG(state_stack));
|
||||
YYSETCONDITION(*stack_state);
|
||||
zend_stack_del_top(&SCNG(state_stack));
|
||||
}
|
||||
@@ -187,7 +184,7 @@ static int init_ini_scanner(int scanner_mode, zend_file_handle *fh TSRMLS_DC)
|
||||
ini_filename = NULL;
|
||||
}
|
||||
|
||||
zend_stack_init(&SCNG(state_stack));
|
||||
zend_stack_init(&SCNG(state_stack), sizeof(int));
|
||||
BEGIN(INITIAL);
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* Generated by re2c 0.13.5 */
|
||||
#line 3 "Zend/zend_ini_scanner_defs.h"
|
||||
|
||||
enum YYCONDTYPE {
|
||||
yycINITIAL,
|
||||
yycST_OFFSET,
|
||||
yycST_SECTION_VALUE,
|
||||
yycST_VALUE,
|
||||
yycST_SECTION_RAW,
|
||||
yycST_DOUBLE_QUOTES,
|
||||
yycST_VARNAME,
|
||||
yycST_RAW,
|
||||
};
|
||||
/* Generated by re2c 0.13.5 */
|
||||
#line 3 "Zend/zend_ini_scanner_defs.h"
|
||||
|
||||
enum YYCONDTYPE {
|
||||
yycINITIAL,
|
||||
yycST_OFFSET,
|
||||
yycST_SECTION_VALUE,
|
||||
yycST_VALUE,
|
||||
yycST_SECTION_RAW,
|
||||
yycST_DOUBLE_QUOTES,
|
||||
yycST_VARNAME,
|
||||
yycST_RAW,
|
||||
};
|
||||
|
||||
+103
-95
@@ -31,24 +31,27 @@ ZEND_API zend_class_entry *zend_ce_serializable;
|
||||
|
||||
/* {{{ zend_call_method
|
||||
Only returns the returned zval if retval_ptr != NULL */
|
||||
ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
|
||||
ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
|
||||
{
|
||||
int result;
|
||||
zend_fcall_info fci;
|
||||
zval z_fname;
|
||||
zval *retval;
|
||||
zval retval;
|
||||
HashTable *function_table;
|
||||
|
||||
zval **params[2];
|
||||
zval params[2];
|
||||
|
||||
params[0] = &arg1;
|
||||
params[1] = &arg2;
|
||||
if (param_count > 0) {
|
||||
ZVAL_COPY_VALUE(¶ms[0], arg1);
|
||||
}
|
||||
if (param_count > 1) {
|
||||
ZVAL_COPY_VALUE(¶ms[1], arg2);
|
||||
}
|
||||
|
||||
fci.size = sizeof(fci);
|
||||
/*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
|
||||
fci.object_ptr = object_pp ? *object_pp : NULL;
|
||||
fci.function_name = &z_fname;
|
||||
fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
|
||||
fci.object = (object && Z_TYPE_P(object) == IS_OBJECT) ? Z_OBJ_P(object) : NULL;
|
||||
ZVAL_STRINGL(&fci.function_name, function_name, function_name_len);
|
||||
fci.retval = retval_ptr ? retval_ptr : &retval;
|
||||
fci.param_count = param_count;
|
||||
fci.params = params;
|
||||
fci.no_separation = 1;
|
||||
@@ -57,15 +60,15 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
|
||||
if (!fn_proxy && !obj_ce) {
|
||||
/* no interest in caching and no information already present that is
|
||||
* needed later inside zend_call_function. */
|
||||
ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
|
||||
fci.function_table = !object_pp ? EG(function_table) : NULL;
|
||||
fci.function_table = !object ? EG(function_table) : NULL;
|
||||
result = zend_call_function(&fci, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&fci.function_name);
|
||||
} else {
|
||||
zend_fcall_info_cache fcic;
|
||||
|
||||
fcic.initialized = 1;
|
||||
if (!obj_ce) {
|
||||
obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
|
||||
obj_ce = object ? Z_OBJCE_P(object) : NULL;
|
||||
}
|
||||
if (obj_ce) {
|
||||
function_table = &obj_ce->function_table;
|
||||
@@ -73,9 +76,9 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
|
||||
function_table = EG(function_table);
|
||||
}
|
||||
if (!fn_proxy || !*fn_proxy) {
|
||||
if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
|
||||
if ((fcic.function_handler = zend_hash_find_ptr(function_table, Z_STR(fci.function_name))) == NULL) {
|
||||
/* error at c-level */
|
||||
zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
|
||||
zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name->val : "", obj_ce ? "::" : "", function_name);
|
||||
}
|
||||
if (fn_proxy) {
|
||||
*fn_proxy = fcic.function_handler;
|
||||
@@ -84,46 +87,50 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
|
||||
fcic.function_handler = *fn_proxy;
|
||||
}
|
||||
fcic.calling_scope = obj_ce;
|
||||
if (object_pp) {
|
||||
fcic.called_scope = Z_OBJCE_PP(object_pp);
|
||||
if (object) {
|
||||
fcic.called_scope = Z_OBJCE_P(object);
|
||||
} else if (obj_ce &&
|
||||
!(EG(called_scope) &&
|
||||
instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
|
||||
!(EG(current_execute_data) &&
|
||||
EG(current_execute_data)->called_scope &&
|
||||
instanceof_function(EG(current_execute_data)->called_scope, obj_ce TSRMLS_CC))) {
|
||||
fcic.called_scope = obj_ce;
|
||||
} else {
|
||||
fcic.called_scope = EG(called_scope);
|
||||
fcic.called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
|
||||
}
|
||||
fcic.object_ptr = object_pp ? *object_pp : NULL;
|
||||
fcic.object = object ? Z_OBJ_P(object) : NULL;
|
||||
result = zend_call_function(&fci, &fcic TSRMLS_CC);
|
||||
zval_ptr_dtor(&fci.function_name);
|
||||
}
|
||||
if (result == FAILURE) {
|
||||
/* error at c-level */
|
||||
if (!obj_ce) {
|
||||
obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
|
||||
obj_ce = object ? Z_OBJCE_P(object) : NULL;
|
||||
}
|
||||
if (!EG(exception)) {
|
||||
zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
|
||||
zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name->val : "", obj_ce ? "::" : "", function_name);
|
||||
}
|
||||
}
|
||||
if (!retval_ptr_ptr) {
|
||||
if (retval) {
|
||||
zval_ptr_dtor(&retval);
|
||||
}
|
||||
/* copy arguments back, they might be changed by references */
|
||||
if (param_count > 0 && Z_ISREF(params[0]) && !Z_ISREF_P(arg1)) {
|
||||
ZVAL_COPY_VALUE(arg1, ¶ms[0]);
|
||||
}
|
||||
if (param_count > 1 && Z_ISREF(params[1]) && !Z_ISREF_P(arg2)) {
|
||||
ZVAL_COPY_VALUE(arg2, ¶ms[1]);
|
||||
}
|
||||
if (!retval_ptr) {
|
||||
zval_ptr_dtor(&retval);
|
||||
return NULL;
|
||||
}
|
||||
return *retval_ptr_ptr;
|
||||
return retval_ptr;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* iterator interface, c-level functions used by engine */
|
||||
|
||||
/* {{{ zend_user_it_new_iterator */
|
||||
ZEND_API zval *zend_user_it_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
|
||||
ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *retval TSRMLS_DC)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
return zend_call_method_with_0_params(&object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
|
||||
|
||||
zend_call_method_with_0_params(object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", retval);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -132,9 +139,9 @@ ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS
|
||||
{
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
|
||||
if (iter->value) {
|
||||
if (!Z_ISUNDEF(iter->value)) {
|
||||
zval_ptr_dtor(&iter->value);
|
||||
iter->value = NULL;
|
||||
ZVAL_UNDEF(&iter->value);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -143,11 +150,10 @@ ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS
|
||||
static void zend_user_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
|
||||
{
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
zval *object = (zval*)iter->it.data;
|
||||
zval *object = &iter->it.data;
|
||||
|
||||
zend_user_it_invalidate_current(_iter TSRMLS_CC);
|
||||
zval_ptr_dtor(&object);
|
||||
efree(iter);
|
||||
zval_ptr_dtor(object);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -156,13 +162,13 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
|
||||
{
|
||||
if (_iter) {
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
zval *object = (zval*)iter->it.data;
|
||||
zval *more;
|
||||
zval *object = &iter->it.data;
|
||||
zval more;
|
||||
int result;
|
||||
|
||||
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
|
||||
if (more) {
|
||||
result = i_zend_is_true(more TSRMLS_CC);
|
||||
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
|
||||
if (Z_TYPE(more) != IS_UNDEF) {
|
||||
result = i_zend_is_true(&more TSRMLS_CC);
|
||||
zval_ptr_dtor(&more);
|
||||
return result ? SUCCESS : FAILURE;
|
||||
}
|
||||
@@ -172,15 +178,15 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_user_it_get_current_data */
|
||||
ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC)
|
||||
ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter TSRMLS_DC)
|
||||
{
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
zval *object = (zval*)iter->it.data;
|
||||
zval *object = &iter->it.data;
|
||||
|
||||
if (!iter->value) {
|
||||
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
|
||||
}
|
||||
*data = &iter->value;
|
||||
if (Z_ISUNDEF(iter->value)) {
|
||||
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
|
||||
}
|
||||
return &iter->value;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -198,30 +204,31 @@ static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, cha
|
||||
ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC)
|
||||
{
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
zval *object = (zval*)iter->it.data;
|
||||
zval *retval;
|
||||
zval *object = &iter->it.data;
|
||||
zval retval;
|
||||
|
||||
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
|
||||
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
|
||||
|
||||
if (retval) {
|
||||
ZVAL_ZVAL(key, retval, 1, 1);
|
||||
if (Z_TYPE(retval) != IS_UNDEF) {
|
||||
ZVAL_ZVAL(key, &retval, 1, 1);
|
||||
} else {
|
||||
if (!EG(exception)) {
|
||||
zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
|
||||
zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name->val);
|
||||
}
|
||||
|
||||
ZVAL_LONG(key, 0);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_user_it_move_forward */
|
||||
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
|
||||
{
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
zval *object = (zval*)iter->it.data;
|
||||
zval *object = &iter->it.data;
|
||||
|
||||
zend_user_it_invalidate_current(_iter TSRMLS_CC);
|
||||
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
|
||||
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -229,10 +236,10 @@ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
|
||||
ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC)
|
||||
{
|
||||
zend_user_iterator *iter = (zend_user_iterator*)_iter;
|
||||
zval *object = (zval*)iter->it.data;
|
||||
zval *object = &iter->it.data;
|
||||
|
||||
zend_user_it_invalidate_current(_iter TSRMLS_CC);
|
||||
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
|
||||
zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -257,11 +264,12 @@ static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zva
|
||||
|
||||
iterator = emalloc(sizeof(zend_user_iterator));
|
||||
|
||||
Z_ADDREF_P(object);
|
||||
iterator->it.data = (void*)object;
|
||||
zend_iterator_init((zend_object_iterator*)iterator TSRMLS_CC);
|
||||
|
||||
ZVAL_COPY(&iterator->it.data, object);
|
||||
iterator->it.funcs = ce->iterator_funcs.funcs;
|
||||
iterator->ce = Z_OBJCE_P(object);
|
||||
iterator->value = NULL;
|
||||
ZVAL_UNDEF(&iterator->value);
|
||||
return (zend_object_iterator*)iterator;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -269,22 +277,23 @@ static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zva
|
||||
/* {{{ zend_user_it_get_new_iterator */
|
||||
ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
|
||||
{
|
||||
zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
|
||||
zval iterator;
|
||||
zend_object_iterator *new_iterator;
|
||||
zend_class_entry *ce_it;
|
||||
|
||||
zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
|
||||
zend_user_it_new_iterator(ce, object, &iterator TSRMLS_CC);
|
||||
ce_it = (Z_TYPE(iterator) == IS_OBJECT &&
|
||||
Z_OBJ_HT(iterator)->get_class_entry) ? Z_OBJCE(iterator) : NULL;
|
||||
|
||||
if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
|
||||
if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && Z_OBJ(iterator) == Z_OBJ_P(object))) {
|
||||
if (!EG(exception)) {
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce ? ce->name : Z_OBJCE_P(object)->name);
|
||||
}
|
||||
if (iterator) {
|
||||
zval_ptr_dtor(&iterator);
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce ? ce->name->val : Z_OBJCE_P(object)->name->val);
|
||||
}
|
||||
zval_ptr_dtor(&iterator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_iterator = ce_it->get_iterator(ce_it, iterator, by_ref TSRMLS_CC);
|
||||
new_iterator = ce_it->get_iterator(ce_it, &iterator, by_ref TSRMLS_CC);
|
||||
zval_ptr_dtor(&iterator);
|
||||
return new_iterator;
|
||||
}
|
||||
@@ -305,10 +314,10 @@ static int zend_implement_traversable(zend_class_entry *interface, zend_class_en
|
||||
}
|
||||
}
|
||||
zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
|
||||
class_type->name,
|
||||
zend_ce_traversable->name,
|
||||
zend_ce_iterator->name,
|
||||
zend_ce_aggregate->name);
|
||||
class_type->name->val,
|
||||
zend_ce_traversable->name->val,
|
||||
zend_ce_iterator->name->val,
|
||||
zend_ce_aggregate->name->val);
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -328,9 +337,9 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr
|
||||
for (i = 0; i < class_type->num_interfaces; i++) {
|
||||
if (class_type->interfaces[i] == zend_ce_iterator) {
|
||||
zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
|
||||
class_type->name,
|
||||
interface->name,
|
||||
zend_ce_iterator->name);
|
||||
class_type->name->val,
|
||||
interface->name->val,
|
||||
zend_ce_iterator->name->val);
|
||||
return FAILURE;
|
||||
}
|
||||
if (class_type->interfaces[i] == zend_ce_traversable) {
|
||||
@@ -360,9 +369,9 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry
|
||||
/* c-level get_iterator cannot be changed */
|
||||
if (class_type->get_iterator == zend_user_it_get_new_iterator) {
|
||||
zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
|
||||
class_type->name,
|
||||
interface->name,
|
||||
zend_ce_aggregate->name);
|
||||
class_type->name->val,
|
||||
interface->name->val,
|
||||
zend_ce_aggregate->name->val);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -400,23 +409,23 @@ static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_en
|
||||
ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
|
||||
{
|
||||
zend_class_entry * ce = Z_OBJCE_P(object);
|
||||
zval *retval;
|
||||
zval retval;
|
||||
int result;
|
||||
|
||||
zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
|
||||
zend_call_method_with_0_params(object, ce, &ce->serialize_func, "serialize", &retval);
|
||||
|
||||
|
||||
if (!retval || EG(exception)) {
|
||||
if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) {
|
||||
result = FAILURE;
|
||||
} else {
|
||||
switch(Z_TYPE_P(retval)) {
|
||||
switch(Z_TYPE(retval)) {
|
||||
case IS_NULL:
|
||||
/* we could also make this '*buf_len = 0' but this allows to skip variables */
|
||||
zval_ptr_dtor(&retval);
|
||||
return FAILURE;
|
||||
case IS_STRING:
|
||||
*buffer = (unsigned char*)estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||
*buf_len = Z_STRLEN_P(retval);
|
||||
*buffer = (unsigned char*)estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
|
||||
*buf_len = Z_STRLEN(retval);
|
||||
result = SUCCESS;
|
||||
break;
|
||||
default: /* failure */
|
||||
@@ -427,23 +436,22 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint
|
||||
}
|
||||
|
||||
if (result == FAILURE && !EG(exception)) {
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name);
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name->val);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_user_unserialize */
|
||||
ZEND_API int zend_user_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
|
||||
ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
|
||||
{
|
||||
zval * zdata;
|
||||
zval zdata;
|
||||
|
||||
object_init_ex(*object, ce);
|
||||
object_init_ex(object, ce);
|
||||
|
||||
MAKE_STD_ZVAL(zdata);
|
||||
ZVAL_STRINGL(zdata, (char*)buf, buf_len, 1);
|
||||
ZVAL_STRINGL(&zdata, (char*)buf, buf_len);
|
||||
|
||||
zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
|
||||
zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, &zdata);
|
||||
|
||||
zval_ptr_dtor(&zdata);
|
||||
|
||||
@@ -458,14 +466,14 @@ ZEND_API int zend_user_unserialize(zval **object, zend_class_entry *ce, const un
|
||||
ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%s' is not allowed", ce->name);
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%s' is not allowed", ce->name->val);
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_class_unserialize_deny(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
|
||||
ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%s' is not allowed", ce->name);
|
||||
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%s' is not allowed", ce->name->val);
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -35,10 +35,10 @@ extern ZEND_API zend_class_entry *zend_ce_serializable;
|
||||
typedef struct _zend_user_iterator {
|
||||
zend_object_iterator it;
|
||||
zend_class_entry *ce;
|
||||
zval *value;
|
||||
zval value;
|
||||
} zend_user_iterator;
|
||||
|
||||
ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC);
|
||||
ZEND_API zval* zend_call_method(zval *object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2 TSRMLS_DC);
|
||||
|
||||
#define zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) \
|
||||
zend_call_method(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, 0, NULL, NULL TSRMLS_CC)
|
||||
@@ -52,20 +52,20 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
|
||||
ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC);
|
||||
ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC);
|
||||
ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC);
|
||||
ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC);
|
||||
ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter TSRMLS_DC);
|
||||
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC);
|
||||
ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC);
|
||||
|
||||
ZEND_API zval *zend_user_it_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC);
|
||||
ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *iterator TSRMLS_DC);
|
||||
ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_register_interfaces(TSRMLS_D);
|
||||
|
||||
ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
|
||||
ZEND_API int zend_user_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
|
||||
ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
|
||||
|
||||
ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
|
||||
ZEND_API int zend_class_unserialize_deny(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
|
||||
ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
||||
+18
-12
@@ -24,8 +24,13 @@
|
||||
|
||||
static zend_class_entry zend_iterator_class_entry;
|
||||
|
||||
static void iter_wrapper_dtor(zend_object *object TSRMLS_DC);
|
||||
|
||||
static zend_object_handlers iterator_object_handlers = {
|
||||
ZEND_OBJECTS_STORE_HANDLERS,
|
||||
0,
|
||||
iter_wrapper_dtor,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, /* prop read */
|
||||
NULL, /* prop write */
|
||||
NULL, /* read dim */
|
||||
@@ -51,26 +56,27 @@ static zend_object_handlers iterator_object_handlers = {
|
||||
ZEND_API void zend_register_iterator_wrapper(TSRMLS_D)
|
||||
{
|
||||
INIT_CLASS_ENTRY(zend_iterator_class_entry, "__iterator_wrapper", NULL);
|
||||
str_free(zend_iterator_class_entry.name);
|
||||
zend_iterator_class_entry.name = "__iterator_wrapper";
|
||||
}
|
||||
|
||||
static void iter_wrapper_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
||||
static void iter_wrapper_dtor(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
zend_object_iterator *iter = (zend_object_iterator*)object;
|
||||
iter->funcs->dtor(iter TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API zval *zend_iterator_wrap(zend_object_iterator *iter TSRMLS_DC)
|
||||
ZEND_API void zend_iterator_init(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
zval *wrapped;
|
||||
zend_object_std_init(&iter->std, &zend_iterator_class_entry TSRMLS_CC);
|
||||
iter->std.handlers = &iterator_object_handlers;
|
||||
}
|
||||
|
||||
MAKE_STD_ZVAL(wrapped);
|
||||
Z_TYPE_P(wrapped) = IS_OBJECT;
|
||||
Z_OBJ_HANDLE_P(wrapped) = zend_objects_store_put(iter, iter_wrapper_dtor, NULL, NULL TSRMLS_CC);
|
||||
Z_OBJ_HT_P(wrapped) = &iterator_object_handlers;
|
||||
ZEND_API void zend_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
if (--GC_REFCOUNT(iter) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
zend_objects_store_del(&iter->std TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(
|
||||
@@ -79,7 +85,7 @@ ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(
|
||||
switch (Z_TYPE_P(array_ptr)) {
|
||||
case IS_OBJECT:
|
||||
if (Z_OBJ_HT_P(array_ptr) == &iterator_object_handlers) {
|
||||
*iter = (zend_object_iterator *)zend_object_store_get_object(array_ptr TSRMLS_CC);
|
||||
*iter = (zend_object_iterator *)Z_OBJ_P(array_ptr);
|
||||
return ZEND_ITER_OBJECT;
|
||||
}
|
||||
if (Z_OBJPROP_P(array_ptr)) {
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef struct _zend_object_iterator_funcs {
|
||||
int (*valid)(zend_object_iterator *iter TSRMLS_DC);
|
||||
|
||||
/* fetch the item data for the current element */
|
||||
void (*get_current_data)(zend_object_iterator *iter, zval ***data TSRMLS_DC);
|
||||
zval *(*get_current_data)(zend_object_iterator *iter TSRMLS_DC);
|
||||
|
||||
/* fetch the key for the current element (optional, may be NULL). The key
|
||||
* should be written into the provided zval* using the ZVAL_* macros. If
|
||||
@@ -55,7 +55,8 @@ typedef struct _zend_object_iterator_funcs {
|
||||
} zend_object_iterator_funcs;
|
||||
|
||||
struct _zend_object_iterator {
|
||||
void *data;
|
||||
zend_object std;
|
||||
zval data;
|
||||
zend_object_iterator_funcs *funcs;
|
||||
ulong index; /* private to fe_reset/fe_fetch opcodes */
|
||||
};
|
||||
@@ -82,7 +83,8 @@ BEGIN_EXTERN_C()
|
||||
ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(zval *array_ptr, zend_object_iterator **iter TSRMLS_DC);
|
||||
|
||||
/* given an iterator, wrap it up as a zval for use by the engine opcodes */
|
||||
ZEND_API zval *zend_iterator_wrap(zend_object_iterator *iter TSRMLS_DC);
|
||||
ZEND_API void zend_iterator_init(zend_object_iterator *iter TSRMLS_DC);
|
||||
ZEND_API void zend_iterator_dtor(zend_object_iterator *iter TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_register_iterator_wrapper(TSRMLS_D);
|
||||
END_EXTERN_C()
|
||||
|
||||
+20
-20
@@ -571,8 +571,8 @@ parameter:
|
||||
|
||||
optional_class_type:
|
||||
/* empty */ { $$.op_type = IS_UNUSED; }
|
||||
| T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; }
|
||||
| T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; }
|
||||
| T_ARRAY { $$.op_type = IS_CONST; Z_TYPE_INFO($$.u.constant)=IS_ARRAY; }
|
||||
| T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE_INFO($$.u.constant)=IS_CALLABLE; }
|
||||
| fully_qualified_class_name { $$ = $1; }
|
||||
;
|
||||
|
||||
@@ -611,9 +611,9 @@ global_var:
|
||||
|
||||
static_var_list:
|
||||
static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
|
||||
| static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
|
||||
| static_var_list ',' T_VARIABLE '=' static_scalar { Z_CONST_FLAGS($5.u.constant) = 0; zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
|
||||
| T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
|
||||
| T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
|
||||
| T_VARIABLE '=' static_scalar { Z_CONST_FLAGS($3.u.constant) = 0; zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
|
||||
|
||||
;
|
||||
|
||||
@@ -667,8 +667,8 @@ trait_precedence:
|
||||
;
|
||||
|
||||
trait_reference_list:
|
||||
fully_qualified_class_name { zend_resolve_class_name(&$1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STRVAL($1.u.constant) TSRMLS_CC); }
|
||||
| trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STRVAL($3.u.constant) TSRMLS_CC); $$ = $1; }
|
||||
fully_qualified_class_name { zend_resolve_class_name(&$1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STR($1.u.constant) TSRMLS_CC); }
|
||||
| trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STR($3.u.constant) TSRMLS_CC); $$ = $1; }
|
||||
;
|
||||
|
||||
trait_method_reference:
|
||||
@@ -738,7 +738,7 @@ echo_expr_list:
|
||||
|
||||
|
||||
for_expr:
|
||||
/* empty */ { $$.op_type = IS_CONST; Z_TYPE($$.u.constant) = IS_BOOL; Z_LVAL($$.u.constant) = 1; }
|
||||
/* empty */ { $$.op_type = IS_CONST; ZVAL_BOOL(&$$.u.constant, 1); }
|
||||
| non_empty_for_expr { $$ = $1; }
|
||||
;
|
||||
|
||||
@@ -812,8 +812,8 @@ expr_without_variable:
|
||||
| expr '%' expr { zend_do_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
| expr T_SL expr { zend_do_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
| expr T_SR expr { zend_do_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
| '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } }
|
||||
| '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } }
|
||||
| '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } }
|
||||
| '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } }
|
||||
| '!' expr { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$2 TSRMLS_CC); }
|
||||
| '~' expr { zend_do_unary_op(ZEND_BW_NOT, &$$, &$2 TSRMLS_CC); }
|
||||
| expr T_IS_IDENTICAL expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
@@ -839,7 +839,7 @@ expr_without_variable:
|
||||
| T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
|
||||
| T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
|
||||
| T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
|
||||
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
|
||||
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, _IS_BOOL TSRMLS_CC); }
|
||||
| T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
|
||||
| T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
|
||||
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
|
||||
@@ -912,16 +912,16 @@ function_call:
|
||||
;
|
||||
|
||||
class_name:
|
||||
T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1, 1);}
|
||||
T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1);}
|
||||
| namespace_name { $$ = $1; }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; }
|
||||
| T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); $$ = $2; }
|
||||
;
|
||||
|
||||
fully_qualified_class_name:
|
||||
namespace_name { $$ = $1; }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; }
|
||||
| T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
@@ -957,7 +957,7 @@ exit_expr:
|
||||
;
|
||||
|
||||
backticks_expr:
|
||||
/* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
/* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
| T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
|
||||
| encaps_list { $$ = $1; }
|
||||
;
|
||||
@@ -981,7 +981,7 @@ common_scalar:
|
||||
| T_FUNC_C { $$ = $1; }
|
||||
| T_NS_C { $$ = $1; }
|
||||
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
|
||||
| T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
| T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
;
|
||||
|
||||
static_class_constant:
|
||||
@@ -997,7 +997,7 @@ static_scalar_value:
|
||||
| static_class_name_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
|
||||
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
|
||||
| T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
|
||||
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; }
|
||||
| '[' static_array_pair_list ']' { $$ = $2; }
|
||||
| static_class_constant { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
|
||||
@@ -1045,7 +1045,7 @@ general_constant:
|
||||
class_constant { $$ = $1; }
|
||||
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 0 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
scalar:
|
||||
@@ -1059,7 +1059,7 @@ scalar:
|
||||
;
|
||||
|
||||
static_array_pair_list:
|
||||
/* empty */ { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
|
||||
/* empty */ { $$.op_type = IS_CONST; array_init(&$$.u.constant); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
|
||||
| non_empty_static_array_pair_list possible_comma { zend_ast_dynamic_shrink(&$1.u.ast); $$ = $1; }
|
||||
;
|
||||
|
||||
@@ -1221,8 +1221,8 @@ assignment_list_element:
|
||||
|
||||
|
||||
array_pair_list:
|
||||
/* empty */ { zend_do_init_array(&$$, NULL, NULL, 0 TSRMLS_CC); }
|
||||
| non_empty_array_pair_list possible_comma { $$ = $1; }
|
||||
/* empty */ { zend_do_init_array(&$$, NULL, NULL, 0 TSRMLS_CC); zend_do_end_array(&$$, &$$ TSRMLS_CC); }
|
||||
| non_empty_array_pair_list possible_comma { zend_do_end_array(&$$, &$1 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
non_empty_array_pair_list:
|
||||
|
||||
+7875
-7857
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ typedef struct _zend_lex_state {
|
||||
|
||||
zend_file_handle *in;
|
||||
uint lineno;
|
||||
char *filename;
|
||||
zend_string *filename;
|
||||
|
||||
/* original (unfiltered) script */
|
||||
unsigned char *script_org;
|
||||
|
||||
+131
-104
@@ -112,9 +112,9 @@ do { \
|
||||
} \
|
||||
}
|
||||
|
||||
/* To save initial string length after scanning to first variable, CG(doc_comment_len) can be reused */
|
||||
#define SET_DOUBLE_QUOTES_SCANNED_LENGTH(len) CG(doc_comment_len) = (len)
|
||||
#define GET_DOUBLE_QUOTES_SCANNED_LENGTH() CG(doc_comment_len)
|
||||
/* To save initial string length after scanning to first variable */
|
||||
#define SET_DOUBLE_QUOTES_SCANNED_LENGTH(len) SCNG(scanned_string_len) = (len)
|
||||
#define GET_DOUBLE_QUOTES_SCANNED_LENGTH() SCNG(scanned_string_len)
|
||||
|
||||
#define IS_LABEL_START(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x7F)
|
||||
|
||||
@@ -152,7 +152,7 @@ internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
|
||||
|
||||
static void _yy_push_state(int new_state TSRMLS_DC)
|
||||
{
|
||||
zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
|
||||
zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION());
|
||||
YYSETCONDITION(new_state);
|
||||
}
|
||||
|
||||
@@ -160,8 +160,7 @@ static void _yy_push_state(int new_state TSRMLS_DC)
|
||||
|
||||
static void yy_pop_state(TSRMLS_D)
|
||||
{
|
||||
int *stack_state;
|
||||
zend_stack_top(&SCNG(state_stack), (void **) &stack_state);
|
||||
int *stack_state = zend_stack_top(&SCNG(state_stack));
|
||||
YYSETCONDITION(*stack_state);
|
||||
zend_stack_del_top(&SCNG(state_stack));
|
||||
}
|
||||
@@ -179,8 +178,7 @@ void startup_scanner(TSRMLS_D)
|
||||
{
|
||||
CG(parse_error) = 0;
|
||||
CG(doc_comment) = NULL;
|
||||
CG(doc_comment_len) = 0;
|
||||
zend_stack_init(&SCNG(state_stack));
|
||||
zend_stack_init(&SCNG(state_stack), sizeof(int));
|
||||
zend_ptr_stack_init(&SCNG(heredoc_label_stack));
|
||||
}
|
||||
|
||||
@@ -207,7 +205,7 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
|
||||
lex_state->yy_limit = SCNG(yy_limit);
|
||||
|
||||
lex_state->state_stack = SCNG(state_stack);
|
||||
zend_stack_init(&SCNG(state_stack));
|
||||
zend_stack_init(&SCNG(state_stack), sizeof(int));
|
||||
|
||||
lex_state->heredoc_label_stack = SCNG(heredoc_label_stack);
|
||||
zend_ptr_stack_init(&SCNG(heredoc_label_stack));
|
||||
@@ -479,6 +477,7 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
|
||||
const char *file_path = NULL;
|
||||
char *buf;
|
||||
size_t size, offset = 0;
|
||||
zend_string *compiled_filename;
|
||||
|
||||
/* The shebang line was read, get the current position to obtain the buffer start */
|
||||
if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
|
||||
@@ -534,7 +533,9 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
|
||||
file_path = file_handle->filename;
|
||||
}
|
||||
|
||||
zend_set_compiled_filename(file_path TSRMLS_CC);
|
||||
compiled_filename = STR_INIT(file_path, strlen(file_path), 0);
|
||||
zend_set_compiled_filename(compiled_filename TSRMLS_CC);
|
||||
STR_RELEASE(compiled_filename);
|
||||
|
||||
if (CG(start_lineno)) {
|
||||
CG(zend_lineno) = CG(start_lineno);
|
||||
@@ -562,7 +563,6 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
|
||||
zend_bool original_in_compilation = CG(in_compilation);
|
||||
|
||||
retval_znode.op_type = IS_CONST;
|
||||
INIT_PZVAL(&retval_znode.u.constant);
|
||||
ZVAL_LONG(&retval_znode.u.constant, 1);
|
||||
|
||||
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
|
||||
@@ -581,7 +581,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
|
||||
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
|
||||
CG(in_compilation) = 1;
|
||||
CG(active_op_array) = op_array;
|
||||
zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
|
||||
zend_stack_push(&CG(context_stack), (void *) &CG(context));
|
||||
zend_init_compiler_context(TSRMLS_C);
|
||||
compiler_result = zendparse(TSRMLS_C);
|
||||
zend_do_return(&retval_znode, 0 TSRMLS_CC);
|
||||
@@ -614,7 +614,7 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
|
||||
zend_op_array *retval;
|
||||
char *opened_path = NULL;
|
||||
|
||||
if (filename->type != IS_STRING) {
|
||||
if (Z_TYPE_P(filename) != IS_STRING) {
|
||||
tmp = *filename;
|
||||
zval_copy_ctor(&tmp);
|
||||
convert_to_string(&tmp);
|
||||
@@ -628,13 +628,11 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
|
||||
|
||||
retval = zend_compile_file(&file_handle, type TSRMLS_CC);
|
||||
if (retval && file_handle.handle.stream.handle) {
|
||||
int dummy = 1;
|
||||
|
||||
if (!file_handle.opened_path) {
|
||||
file_handle.opened_path = opened_path = estrndup(Z_STRVAL_P(filename), Z_STRLEN_P(filename));
|
||||
}
|
||||
|
||||
zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
|
||||
zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path));
|
||||
|
||||
if (opened_path) {
|
||||
efree(opened_path);
|
||||
@@ -651,17 +649,20 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
|
||||
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
|
||||
{
|
||||
char *buf;
|
||||
size_t size;
|
||||
size_t size, old_len;
|
||||
zend_string *new_compiled_filename;
|
||||
|
||||
/* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */
|
||||
Z_STRVAL_P(str) = str_erealloc(Z_STRVAL_P(str), Z_STRLEN_P(str) + ZEND_MMAP_AHEAD);
|
||||
memset(Z_STRVAL_P(str) + Z_STRLEN_P(str), 0, ZEND_MMAP_AHEAD);
|
||||
old_len = Z_STRLEN_P(str);
|
||||
Z_STR_P(str) = STR_REALLOC(Z_STR_P(str), old_len + ZEND_MMAP_AHEAD, 0);
|
||||
Z_TYPE_INFO_P(str) = IS_STRING_EX;
|
||||
memset(Z_STRVAL_P(str) + old_len, 0, ZEND_MMAP_AHEAD + 1);
|
||||
|
||||
SCNG(yy_in) = NULL;
|
||||
SCNG(yy_start) = NULL;
|
||||
|
||||
buf = Z_STRVAL_P(str);
|
||||
size = Z_STRLEN_P(str);
|
||||
size = old_len;
|
||||
|
||||
if (CG(multibyte)) {
|
||||
SCNG(script_org) = (unsigned char*)buf;
|
||||
@@ -682,7 +683,9 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
|
||||
|
||||
yy_scan_buffer(buf, size TSRMLS_CC);
|
||||
|
||||
zend_set_compiled_filename(filename TSRMLS_CC);
|
||||
new_compiled_filename = STR_INIT(filename, strlen(filename), 0);
|
||||
zend_set_compiled_filename(new_compiled_filename TSRMLS_CC);
|
||||
STR_RELEASE(new_compiled_filename);
|
||||
CG(zend_lineno) = 1;
|
||||
CG(increment_lineno) = 0;
|
||||
RESET_DOC_COMMENT();
|
||||
@@ -729,8 +732,7 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
|
||||
|
||||
CG(in_compilation) = 1;
|
||||
|
||||
tmp = *source_string;
|
||||
zval_copy_ctor(&tmp);
|
||||
ZVAL_DUP(&tmp, source_string);
|
||||
convert_to_string(&tmp);
|
||||
source_string = &tmp;
|
||||
|
||||
@@ -745,7 +747,7 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
|
||||
init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
|
||||
CG(interactive) = orig_interactive;
|
||||
CG(active_op_array) = op_array;
|
||||
zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
|
||||
zend_stack_push(&CG(context_stack), (void *) &CG(context));
|
||||
zend_init_compiler_context(TSRMLS_C);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
compiler_result = zendparse(TSRMLS_C);
|
||||
@@ -844,6 +846,9 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
|
||||
"encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
|
||||
}
|
||||
if (SCNG(script_filtered)) {
|
||||
efree(SCNG(script_filtered));
|
||||
}
|
||||
SCNG(script_filtered) = new_yy_start;
|
||||
SCNG(script_filtered_size) = length;
|
||||
}
|
||||
@@ -857,22 +862,33 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
|
||||
}
|
||||
|
||||
|
||||
// TODO: avoid reallocation ???
|
||||
# define zend_copy_value(zendlval, yytext, yyleng) \
|
||||
if (SCNG(output_filter)) { \
|
||||
size_t sz = 0; \
|
||||
SCNG(output_filter)((unsigned char **)&Z_STRVAL_P(zendlval), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \
|
||||
Z_STRLEN_P(zendlval) = sz; \
|
||||
char *s = NULL; \
|
||||
SCNG(output_filter)((unsigned char **)&s, &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \
|
||||
ZVAL_STRINGL(zendlval, s, sz); \
|
||||
efree(s); \
|
||||
} else { \
|
||||
Z_STRVAL_P(zendlval) = (char *) estrndup(yytext, yyleng); \
|
||||
Z_STRLEN_P(zendlval) = yyleng; \
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng); \
|
||||
}
|
||||
|
||||
// TODO: some extensions might need content, but we don't copy it intentional ???
|
||||
#if 0
|
||||
# define DUMMY_STRINGL(zendlval, yytext, yyleng) \
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng)
|
||||
#else
|
||||
# define DUMMY_STRINGL(zendlval, yytext, yyleng) \
|
||||
ZVAL_EMPTY_STRING(zendlval)
|
||||
#endif
|
||||
|
||||
static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
|
||||
{
|
||||
register char *s, *t;
|
||||
char *end;
|
||||
|
||||
ZVAL_STRINGL(zendlval, str, len, 1);
|
||||
ZVAL_STRINGL(zendlval, str, len);
|
||||
|
||||
/* convert escape sequences */
|
||||
s = t = Z_STRVAL_P(zendlval);
|
||||
@@ -979,10 +995,13 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
|
||||
*t = 0;
|
||||
if (SCNG(output_filter)) {
|
||||
size_t sz = 0;
|
||||
unsigned char *str;
|
||||
// TODO: avoid realocation ???
|
||||
s = Z_STRVAL_P(zendlval);
|
||||
SCNG(output_filter)((unsigned char **)&Z_STRVAL_P(zendlval), &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC);
|
||||
Z_STRLEN_P(zendlval) = sz;
|
||||
efree(s);
|
||||
SCNG(output_filter)(&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC);
|
||||
zval_ptr_dtor(zendlval);
|
||||
ZVAL_STRINGL(zendlval, str, sz);
|
||||
efree(str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1173,7 +1192,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
HANDLE_NEWLINES(yytext, yyleng);
|
||||
return T_WHITESPACE;
|
||||
}
|
||||
@@ -1185,7 +1204,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
<ST_LOOKING_FOR_PROPERTY>{LABEL} {
|
||||
yy_pop_state(TSRMLS_C);
|
||||
zend_copy_value(zendlval, yytext, yyleng);
|
||||
zendlval->type = IS_STRING;
|
||||
return T_STRING;
|
||||
}
|
||||
|
||||
@@ -1480,7 +1498,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
<ST_LOOKING_FOR_VARNAME>{LABEL}[[}] {
|
||||
yyless(yyleng - 1);
|
||||
zend_copy_value(zendlval, yytext, yyleng);
|
||||
zendlval->type = IS_STRING;
|
||||
yy_pop_state(TSRMLS_C);
|
||||
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
|
||||
return T_STRING_VARNAME;
|
||||
@@ -1506,11 +1523,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
if (len < SIZEOF_LONG * 8) {
|
||||
if (len == 0) {
|
||||
Z_LVAL_P(zendlval) = 0;
|
||||
ZVAL_LONG(zendlval, 0);
|
||||
} else {
|
||||
Z_LVAL_P(zendlval) = strtol(bin, NULL, 2);
|
||||
ZVAL_LONG(zendlval, strtol(bin, NULL, 2));
|
||||
}
|
||||
zendlval->type = IS_LONG;
|
||||
return T_LNUMBER;
|
||||
} else {
|
||||
ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, NULL));
|
||||
@@ -1520,22 +1536,19 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
<ST_IN_SCRIPTING>{LNUM} {
|
||||
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
|
||||
Z_LVAL_P(zendlval) = strtol(yytext, NULL, 0);
|
||||
ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
|
||||
} else {
|
||||
errno = 0;
|
||||
Z_LVAL_P(zendlval) = strtol(yytext, NULL, 0);
|
||||
ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
|
||||
if (errno == ERANGE) { /* Overflow */
|
||||
if (yytext[0] == '0') { /* octal overflow */
|
||||
Z_DVAL_P(zendlval) = zend_oct_strtod(yytext, NULL);
|
||||
ZVAL_DOUBLE(zendlval, zend_oct_strtod(yytext, NULL));
|
||||
} else {
|
||||
Z_DVAL_P(zendlval) = zend_strtod(yytext, NULL);
|
||||
ZVAL_DOUBLE(zendlval, zend_strtod(yytext, NULL));
|
||||
}
|
||||
zendlval->type = IS_DOUBLE;
|
||||
return T_DNUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
zendlval->type = IS_LONG;
|
||||
return T_LNUMBER;
|
||||
}
|
||||
|
||||
@@ -1551,11 +1564,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
|
||||
if (len == 0) {
|
||||
Z_LVAL_P(zendlval) = 0;
|
||||
ZVAL_LONG(zendlval, 0);
|
||||
} else {
|
||||
Z_LVAL_P(zendlval) = strtol(hex, NULL, 16);
|
||||
ZVAL_LONG(zendlval, strtol(hex, NULL, 16));
|
||||
}
|
||||
zendlval->type = IS_LONG;
|
||||
return T_LNUMBER;
|
||||
} else {
|
||||
ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, NULL));
|
||||
@@ -1567,13 +1579,13 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
|
||||
ZVAL_LONG(zendlval, strtol(yytext, NULL, 10));
|
||||
} else {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 1);
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng);
|
||||
}
|
||||
return T_NUM_STRING;
|
||||
}
|
||||
|
||||
<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 1);
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng);
|
||||
return T_NUM_STRING;
|
||||
}
|
||||
|
||||
@@ -1587,12 +1599,11 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
if (ce && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) {
|
||||
/* We create a special __CLASS__ constant that is going to be resolved
|
||||
at run-time */
|
||||
Z_STRLEN_P(zendlval) = sizeof("__CLASS__")-1;
|
||||
Z_STRVAL_P(zendlval) = estrndup("__CLASS__", Z_STRLEN_P(zendlval));
|
||||
zendlval->type = IS_CONSTANT;
|
||||
ZVAL_STRINGL(zendlval, "__CLASS__", sizeof("__CLASS__") - 1);
|
||||
Z_TYPE_INFO_P(zendlval) = IS_CONSTANT_EX;
|
||||
} else {
|
||||
if (ce && ce->name) {
|
||||
ZVAL_STRINGL(zendlval, ce->name, ce->name_length, 1);
|
||||
ZVAL_STR(zendlval, STR_COPY(ce->name));
|
||||
} else {
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
}
|
||||
@@ -1603,7 +1614,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
<ST_IN_SCRIPTING>"__TRAIT__" {
|
||||
zend_class_entry *ce = CG(active_class_entry);
|
||||
if (ce && ce->name && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) {
|
||||
ZVAL_STRINGL(zendlval, ce->name, ce->name_length, 1);
|
||||
ZVAL_STR(zendlval, STR_COPY(ce->name));
|
||||
} else {
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
}
|
||||
@@ -1613,7 +1624,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
<ST_IN_SCRIPTING>"__FUNCTION__" {
|
||||
zend_op_array *op_array = CG(active_op_array);
|
||||
if (op_array && op_array->function_name) {
|
||||
ZVAL_STRING(zendlval, op_array->function_name, 1);
|
||||
ZVAL_STR(zendlval, STR_COPY(op_array->function_name));
|
||||
} else {
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
}
|
||||
@@ -1621,15 +1632,34 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"__METHOD__" {
|
||||
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;
|
||||
if (CG(active_class_entry)) {
|
||||
int len = 0;
|
||||
|
||||
Z_STRLEN_P(zendlval) = zend_spprintf(&Z_STRVAL_P(zendlval), 0, "%s%s%s",
|
||||
class_name ? class_name : "",
|
||||
class_name && func_name ? "::" : "",
|
||||
func_name ? func_name : ""
|
||||
);
|
||||
zendlval->type = IS_STRING;
|
||||
if (CG(active_class_entry)->name) {
|
||||
len += CG(active_class_entry)->name->len;
|
||||
}
|
||||
if (CG(active_op_array) && CG(active_op_array)->function_name) {
|
||||
len += sizeof("::")-1;
|
||||
len += CG(active_op_array)->function_name->len;
|
||||
}
|
||||
ZVAL_NEW_STR(zendlval, STR_ALLOC(len, 0));
|
||||
len = 0;
|
||||
if (CG(active_class_entry)->name) {
|
||||
memcpy(Z_STRVAL_P(zendlval), CG(active_class_entry)->name->val, CG(active_class_entry)->name->len);
|
||||
len += CG(active_class_entry)->name->len;
|
||||
}
|
||||
if (CG(active_op_array) && CG(active_op_array)->function_name) {
|
||||
memcpy(Z_STRVAL_P(zendlval) + len, "::", sizeof("::")-1);
|
||||
len += sizeof("::")-1;
|
||||
memcpy(Z_STRVAL_P(zendlval) + len, CG(active_op_array)->function_name->val, CG(active_op_array)->function_name->len);
|
||||
len += CG(active_op_array)->function_name->len;
|
||||
}
|
||||
Z_STRVAL_P(zendlval)[len] = 0;
|
||||
} else if (CG(active_op_array) && CG(active_op_array)->function_name) {
|
||||
ZVAL_STR(zendlval, STR_COPY(CG(active_op_array)->function_name));
|
||||
} else {
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
}
|
||||
return T_METHOD_C;
|
||||
}
|
||||
|
||||
@@ -1639,44 +1669,44 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"__FILE__" {
|
||||
char *filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
zend_string *filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
|
||||
if (!filename) {
|
||||
filename = "";
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
} else {
|
||||
ZVAL_STR(zendlval, STR_COPY(filename));
|
||||
}
|
||||
ZVAL_STRING(zendlval, filename, 1);
|
||||
return T_FILE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"__DIR__" {
|
||||
char *filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
const size_t filename_len = strlen(filename);
|
||||
char *dirname;
|
||||
zend_string *filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
zend_string *dirname;
|
||||
|
||||
if (!filename) {
|
||||
filename = "";
|
||||
filename = STR_EMPTY_ALLOC();
|
||||
}
|
||||
|
||||
dirname = estrndup(filename, filename_len);
|
||||
zend_dirname(dirname, filename_len);
|
||||
dirname = STR_INIT(filename->val, filename->len, 0);
|
||||
zend_dirname(dirname->val, dirname->len);
|
||||
|
||||
if (strcmp(dirname, ".") == 0) {
|
||||
dirname = erealloc(dirname, MAXPATHLEN);
|
||||
if (strcmp(dirname->val, ".") == 0) {
|
||||
dirname = STR_REALLOC(dirname, MAXPATHLEN, 0);
|
||||
#if HAVE_GETCWD
|
||||
VCWD_GETCWD(dirname, MAXPATHLEN);
|
||||
VCWD_GETCWD(dirname->val, MAXPATHLEN);
|
||||
#elif HAVE_GETWD
|
||||
VCWD_GETWD(dirname);
|
||||
VCWD_GETWD(dirname->val);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZVAL_STRING(zendlval, dirname, 0);
|
||||
dirname->len = strlen(dirname->val);
|
||||
ZVAL_STR(zendlval, dirname);
|
||||
return T_DIR;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"__NAMESPACE__" {
|
||||
if (CG(current_namespace)) {
|
||||
*zendlval = *CG(current_namespace);
|
||||
zval_copy_ctor(zendlval);
|
||||
if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
|
||||
ZVAL_DUP(zendlval, &CG(current_namespace));
|
||||
} else {
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
}
|
||||
@@ -1693,7 +1723,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
}
|
||||
|
||||
HANDLE_NEWLINES(yytext, yyleng);
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_OPEN_TAG;
|
||||
}
|
||||
@@ -1701,7 +1731,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
<INITIAL>"<%=" {
|
||||
if (CG(asp_tags)) {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_OPEN_TAG_WITH_ECHO;
|
||||
} else {
|
||||
@@ -1711,7 +1741,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
|
||||
<INITIAL>"<?=" {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_OPEN_TAG_WITH_ECHO;
|
||||
}
|
||||
@@ -1719,7 +1749,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
<INITIAL>"<%" {
|
||||
if (CG(asp_tags)) {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_OPEN_TAG;
|
||||
} else {
|
||||
@@ -1729,7 +1759,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
|
||||
<INITIAL>"<?php"([ \t]|{NEWLINE}) {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
HANDLE_NEWLINE(yytext[yyleng-1]);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_OPEN_TAG;
|
||||
@@ -1738,7 +1768,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
|
||||
<INITIAL>"<?" {
|
||||
if (CG(short_tags)) {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_OPEN_TAG;
|
||||
} else {
|
||||
@@ -1791,17 +1821,18 @@ inline_html:
|
||||
|
||||
if (SCNG(output_filter)) {
|
||||
int readsize;
|
||||
char *s = NULL;
|
||||
size_t sz = 0;
|
||||
readsize = SCNG(output_filter)((unsigned char **)&Z_STRVAL_P(zendlval), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC);
|
||||
Z_STRLEN_P(zendlval) = sz;
|
||||
// TODO: avoid reallocation ???
|
||||
readsize = SCNG(output_filter)((unsigned char **)&s, &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC);
|
||||
ZVAL_STRINGL(zendlval, s, sz);
|
||||
efree(s);
|
||||
if (readsize < yyleng) {
|
||||
yyless(readsize);
|
||||
}
|
||||
} else {
|
||||
Z_STRVAL_P(zendlval) = (char *) estrndup(yytext, yyleng);
|
||||
Z_STRLEN_P(zendlval) = yyleng;
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng);
|
||||
}
|
||||
zendlval->type = IS_STRING;
|
||||
HANDLE_NEWLINES(yytext, yyleng);
|
||||
return T_INLINE_HTML;
|
||||
}
|
||||
@@ -1814,7 +1845,6 @@ inline_html:
|
||||
yyless(yyleng - 3);
|
||||
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
|
||||
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
|
||||
zendlval->type = IS_STRING;
|
||||
return T_VARIABLE;
|
||||
}
|
||||
|
||||
@@ -1824,13 +1854,11 @@ inline_html:
|
||||
yyless(yyleng - 1);
|
||||
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
|
||||
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
|
||||
zendlval->type = IS_STRING;
|
||||
return T_VARIABLE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
|
||||
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
|
||||
zendlval->type = IS_STRING;
|
||||
return T_VARIABLE;
|
||||
}
|
||||
|
||||
@@ -1853,7 +1881,6 @@ inline_html:
|
||||
|
||||
<ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
|
||||
zend_copy_value(zendlval, yytext, yyleng);
|
||||
zendlval->type = IS_STRING;
|
||||
return T_STRING;
|
||||
}
|
||||
|
||||
@@ -1918,8 +1945,7 @@ inline_html:
|
||||
HANDLE_NEWLINES(yytext, yyleng);
|
||||
|
||||
if (doc_com) {
|
||||
CG(doc_comment) = estrndup(yytext, yyleng);
|
||||
CG(doc_comment_len) = yyleng;
|
||||
CG(doc_comment) = STR_INIT(yytext, yyleng, 0);
|
||||
return T_DOC_COMMENT;
|
||||
}
|
||||
|
||||
@@ -1927,7 +1953,7 @@ inline_html:
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
BEGIN(INITIAL);
|
||||
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
|
||||
}
|
||||
@@ -1936,7 +1962,7 @@ inline_html:
|
||||
<ST_IN_SCRIPTING>"%>"{NEWLINE}? {
|
||||
if (CG(asp_tags)) {
|
||||
BEGIN(INITIAL);
|
||||
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
|
||||
DUMMY_STRINGL(zendlval, yytext, yyleng);
|
||||
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
|
||||
} else {
|
||||
yyless(1);
|
||||
@@ -1970,7 +1996,7 @@ inline_html:
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_STRINGL(zendlval, yytext+bprefix+1, yyleng-bprefix-2, 1);
|
||||
ZVAL_STRINGL(zendlval, yytext+bprefix+1, yyleng-bprefix-2);
|
||||
|
||||
/* convert escape sequences */
|
||||
s = t = Z_STRVAL_P(zendlval);
|
||||
@@ -2003,9 +2029,11 @@ inline_html:
|
||||
|
||||
if (SCNG(output_filter)) {
|
||||
size_t sz = 0;
|
||||
char *str = NULL;
|
||||
s = Z_STRVAL_P(zendlval);
|
||||
SCNG(output_filter)((unsigned char **)&Z_STRVAL_P(zendlval), &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC);
|
||||
Z_STRLEN_P(zendlval) = sz;
|
||||
// TODO: avoid reallocation ???
|
||||
SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC);
|
||||
ZVAL_STRINGL(zendlval, str, sz);
|
||||
efree(s);
|
||||
}
|
||||
return T_CONSTANT_ENCAPSED_STRING;
|
||||
@@ -2359,7 +2387,6 @@ nowdoc_scan_done:
|
||||
yyleng = YYCURSOR - SCNG(yy_text);
|
||||
|
||||
zend_copy_value(zendlval, yytext, yyleng - newline);
|
||||
zendlval->type = IS_STRING;
|
||||
HANDLE_NEWLINES(yytext, yyleng - newline);
|
||||
return T_ENCAPSED_AND_WHITESPACE;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/* Generated by re2c 0.13.5 */
|
||||
#line 3 "Zend/zend_language_scanner_defs.h"
|
||||
|
||||
enum YYCONDTYPE {
|
||||
yycST_IN_SCRIPTING,
|
||||
yycST_LOOKING_FOR_PROPERTY,
|
||||
yycST_BACKQUOTE,
|
||||
yycST_DOUBLE_QUOTES,
|
||||
yycST_HEREDOC,
|
||||
yycST_LOOKING_FOR_VARNAME,
|
||||
yycST_VAR_OFFSET,
|
||||
yycINITIAL,
|
||||
yycST_END_HEREDOC,
|
||||
yycST_NOWDOC,
|
||||
};
|
||||
/* Generated by re2c 0.13.5 */
|
||||
#line 3 "Zend/zend_language_scanner_defs.h"
|
||||
|
||||
enum YYCONDTYPE {
|
||||
yycST_IN_SCRIPTING,
|
||||
yycST_LOOKING_FOR_PROPERTY,
|
||||
yycST_BACKQUOTE,
|
||||
yycST_DOUBLE_QUOTES,
|
||||
yycST_HEREDOC,
|
||||
yycST_LOOKING_FOR_VARNAME,
|
||||
yycST_VAR_OFFSET,
|
||||
yycINITIAL,
|
||||
yycST_END_HEREDOC,
|
||||
yycST_NOWDOC,
|
||||
};
|
||||
|
||||
+135
-177
@@ -31,88 +31,85 @@ ZEND_API int le_index_ptr;
|
||||
/* true global */
|
||||
static HashTable list_destructors;
|
||||
|
||||
|
||||
ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC)
|
||||
ZEND_API zval *zend_list_insert(void *ptr, int type TSRMLS_DC)
|
||||
{
|
||||
int index;
|
||||
zend_rsrc_list_entry le;
|
||||
|
||||
le.ptr=ptr;
|
||||
le.type=type;
|
||||
le.refcount=1;
|
||||
zval zv;
|
||||
|
||||
index = zend_hash_next_free_element(&EG(regular_list));
|
||||
|
||||
zend_hash_index_update(&EG(regular_list), index, (void *) &le, sizeof(zend_rsrc_list_entry), NULL);
|
||||
return index;
|
||||
if (index == 0) {
|
||||
index = 1;
|
||||
}
|
||||
ZVAL_NEW_RES(&zv, index, ptr, type);
|
||||
return zend_hash_index_add_new(&EG(regular_list), index, &zv);
|
||||
}
|
||||
|
||||
ZEND_API int _zend_list_delete(int id TSRMLS_DC)
|
||||
ZEND_API int _zend_list_delete(zend_resource *res TSRMLS_DC)
|
||||
{
|
||||
zend_rsrc_list_entry *le;
|
||||
if (--GC_REFCOUNT(res) <= 0) {
|
||||
return zend_hash_index_del(&EG(regular_list), res->handle);
|
||||
} else {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int _zend_list_free(zend_resource *res TSRMLS_DC)
|
||||
{
|
||||
if (GC_REFCOUNT(res) <= 0) {
|
||||
return zend_hash_index_del(&EG(regular_list), res->handle);
|
||||
} else {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_resource_dtor(zend_resource *res TSRMLS_DC)
|
||||
{
|
||||
zend_rsrc_list_dtors_entry *ld;
|
||||
|
||||
if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
|
||||
/* printf("del(%d): %d->%d\n", id, le->refcount, le->refcount-1); */
|
||||
if (--le->refcount<=0) {
|
||||
return zend_hash_index_del(&EG(regular_list), id);
|
||||
} else {
|
||||
return SUCCESS;
|
||||
ld = zend_hash_index_find_ptr(&list_destructors, res->type);
|
||||
if (ld) {
|
||||
if (ld->list_dtor_ex) {
|
||||
ld->list_dtor_ex(res TSRMLS_CC);
|
||||
}
|
||||
} else {
|
||||
return FAILURE;
|
||||
zend_error(E_WARNING,"Unknown list entry type (%d)", res->type);
|
||||
}
|
||||
res->ptr = NULL;
|
||||
res->type = -1;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC)
|
||||
ZEND_API int _zend_list_close(zend_resource *res TSRMLS_DC)
|
||||
{
|
||||
zend_rsrc_list_entry *le;
|
||||
|
||||
if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
|
||||
*type = le->type;
|
||||
return le->ptr;
|
||||
} else {
|
||||
*type = -1;
|
||||
return NULL;
|
||||
if (GC_REFCOUNT(res) <= 0) {
|
||||
return zend_list_delete(res);
|
||||
} else if (res->type >= 0) {
|
||||
zend_resource_dtor(res TSRMLS_CC);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
ZEND_API int _zend_list_addref(int id TSRMLS_DC)
|
||||
ZEND_API zend_resource* zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
|
||||
{
|
||||
zend_rsrc_list_entry *le;
|
||||
|
||||
if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
|
||||
/* printf("add(%d): %d->%d\n", id, le->refcount, le->refcount+1); */
|
||||
le->refcount++;
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
zval *zv;
|
||||
|
||||
|
||||
ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
|
||||
{
|
||||
int rsrc_id;
|
||||
|
||||
rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type TSRMLS_CC);
|
||||
zv = zend_list_insert(rsrc_pointer, rsrc_type TSRMLS_CC);
|
||||
|
||||
if (rsrc_result) {
|
||||
rsrc_result->value.lval = rsrc_id;
|
||||
rsrc_result->type = IS_RESOURCE;
|
||||
ZVAL_COPY_VALUE(rsrc_result, zv);
|
||||
return Z_RES_P(rsrc_result);
|
||||
} else {
|
||||
return Z_RES_P(zv);
|
||||
}
|
||||
|
||||
return rsrc_id;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
|
||||
ZEND_API void *zend_fetch_resource(zval *passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
|
||||
{
|
||||
int id;
|
||||
int actual_resource_type;
|
||||
void *resource;
|
||||
// void *resource;
|
||||
va_list resource_types;
|
||||
int i;
|
||||
zend_resource *res;
|
||||
const char *space;
|
||||
const char *class_name;
|
||||
|
||||
@@ -123,26 +120,25 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c
|
||||
zend_error(E_WARNING, "%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
|
||||
}
|
||||
return NULL;
|
||||
} else if ((*passed_id)->type != IS_RESOURCE) {
|
||||
} else if (Z_TYPE_P(passed_id) != IS_RESOURCE) {
|
||||
if (resource_type_name) {
|
||||
class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
zend_error(E_WARNING, "%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
id = (*passed_id)->value.lval;
|
||||
} else {
|
||||
id = default_id;
|
||||
}
|
||||
|
||||
resource = zend_list_find(id, &actual_resource_type);
|
||||
if (!resource) {
|
||||
if (resource_type_name) {
|
||||
class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
zend_error(E_WARNING, "%s%s%s(): %d is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), id, resource_type_name);
|
||||
passed_id = zend_hash_index_find(&EG(regular_list), default_id);
|
||||
if (!passed_id) {
|
||||
if (resource_type_name) {
|
||||
class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
zend_error(E_WARNING, "%s%s%s(): %d is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), default_id, resource_type_name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
res = Z_RES_P(passed_id);
|
||||
actual_resource_type = res->type;
|
||||
|
||||
va_start(resource_types, num_resource_types);
|
||||
for (i=0; i<num_resource_types; i++) {
|
||||
@@ -151,7 +147,7 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c
|
||||
if (found_resource_type) {
|
||||
*found_resource_type = actual_resource_type;
|
||||
}
|
||||
return resource;
|
||||
return res->ptr;
|
||||
}
|
||||
}
|
||||
va_end(resource_types);
|
||||
@@ -164,73 +160,66 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void list_entry_destructor(void *ptr)
|
||||
void list_entry_destructor(zval *zv)
|
||||
{
|
||||
zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
|
||||
zend_rsrc_list_dtors_entry *ld;
|
||||
TSRMLS_FETCH();
|
||||
zend_resource *res = Z_RES_P(zv);
|
||||
|
||||
if (res->type >= 0) {
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
|
||||
switch (ld->type) {
|
||||
case ZEND_RESOURCE_LIST_TYPE_STD:
|
||||
if (ld->list_dtor) {
|
||||
(ld->list_dtor)(le->ptr);
|
||||
}
|
||||
break;
|
||||
case ZEND_RESOURCE_LIST_TYPE_EX:
|
||||
if (ld->list_dtor_ex) {
|
||||
ld->list_dtor_ex(le TSRMLS_CC);
|
||||
}
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
} else {
|
||||
zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", le->type);
|
||||
zend_resource_dtor(res TSRMLS_CC);
|
||||
}
|
||||
efree(res);
|
||||
}
|
||||
|
||||
|
||||
void plist_entry_destructor(void *ptr)
|
||||
void plist_entry_destructor(zval *zv)
|
||||
{
|
||||
zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
|
||||
zend_rsrc_list_dtors_entry *ld;
|
||||
TSRMLS_FETCH();
|
||||
zend_resource *res = Z_RES_P(zv);
|
||||
|
||||
if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
|
||||
switch (ld->type) {
|
||||
case ZEND_RESOURCE_LIST_TYPE_STD:
|
||||
if (ld->plist_dtor) {
|
||||
(ld->plist_dtor)(le->ptr);
|
||||
}
|
||||
break;
|
||||
case ZEND_RESOURCE_LIST_TYPE_EX:
|
||||
if (ld->plist_dtor_ex) {
|
||||
ld->plist_dtor_ex(le TSRMLS_CC);
|
||||
}
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
if (res->type >= 0) {
|
||||
zend_rsrc_list_dtors_entry *ld;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
ld = zend_hash_index_find_ptr(&list_destructors, res->type);
|
||||
if (ld) {
|
||||
if (ld->plist_dtor_ex) {
|
||||
ld->plist_dtor_ex(res TSRMLS_CC);
|
||||
}
|
||||
} else {
|
||||
zend_error(E_WARNING,"Unknown list entry type (%d)", res->type);
|
||||
}
|
||||
} else {
|
||||
zend_error(E_WARNING,"Unknown persistent list entry type in module shutdown (%d)", le->type);
|
||||
}
|
||||
free(res);
|
||||
}
|
||||
|
||||
|
||||
int zend_init_rsrc_list(TSRMLS_D)
|
||||
{
|
||||
if (zend_hash_init(&EG(regular_list), 0, NULL, list_entry_destructor, 0)==SUCCESS) {
|
||||
EG(regular_list).nNextFreeElement=1; /* we don't want resource id 0 */
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
zend_hash_init(&EG(regular_list), 8, NULL, list_entry_destructor, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int zend_init_rsrc_plist(TSRMLS_D)
|
||||
{
|
||||
return zend_hash_init_ex(&EG(persistent_list), 0, NULL, plist_entry_destructor, 1, 0);
|
||||
zend_hash_init_ex(&EG(persistent_list), 8, NULL, plist_entry_destructor, 1, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int zend_close_rsrc(zval *zv TSRMLS_DC)
|
||||
{
|
||||
zend_resource *res = Z_PTR_P(zv);
|
||||
|
||||
if (res->type >= 0) {
|
||||
zend_resource_dtor(res TSRMLS_CC);
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
|
||||
|
||||
void zend_close_rsrc_list(HashTable *ht TSRMLS_DC)
|
||||
{
|
||||
zend_hash_reverse_apply(ht, zend_close_rsrc TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
@@ -239,9 +228,10 @@ void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC)
|
||||
zend_hash_graceful_reverse_destroy(ht);
|
||||
}
|
||||
|
||||
static int clean_module_resource(zend_rsrc_list_entry *le, int *resource_id TSRMLS_DC)
|
||||
static int clean_module_resource(zval *zv, void *arg TSRMLS_DC)
|
||||
{
|
||||
if (le->type == *resource_id) {
|
||||
int resource_id = *(int *)arg;
|
||||
if (Z_RES_TYPE_P(zv) == resource_id) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -249,10 +239,12 @@ static int clean_module_resource(zend_rsrc_list_entry *le, int *resource_id TSRM
|
||||
}
|
||||
|
||||
|
||||
static int zend_clean_module_rsrc_dtors_cb(zend_rsrc_list_dtors_entry *ld, int *module_number TSRMLS_DC)
|
||||
static int zend_clean_module_rsrc_dtors_cb(zval *zv, void *arg TSRMLS_DC)
|
||||
{
|
||||
if (ld->module_number == *module_number) {
|
||||
zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) clean_module_resource, (void *) &(ld->resource_id) TSRMLS_CC);
|
||||
zend_rsrc_list_dtors_entry *ld = (zend_rsrc_list_dtors_entry *)Z_PTR_P(zv);
|
||||
int module_number = *(int *)arg;
|
||||
if (ld->module_number == module_number) {
|
||||
zend_hash_apply_with_argument(&EG(persistent_list), clean_module_resource, (void *) &(ld->resource_id) TSRMLS_CC);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -262,83 +254,52 @@ static int zend_clean_module_rsrc_dtors_cb(zend_rsrc_list_dtors_entry *ld, int *
|
||||
|
||||
void zend_clean_module_rsrc_dtors(int module_number TSRMLS_DC)
|
||||
{
|
||||
zend_hash_apply_with_argument(&list_destructors, (apply_func_arg_t) zend_clean_module_rsrc_dtors_cb, (void *) &module_number TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number)
|
||||
{
|
||||
zend_rsrc_list_dtors_entry lde;
|
||||
|
||||
#if 0
|
||||
printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
|
||||
#endif
|
||||
|
||||
lde.list_dtor=(void (*)(void *)) ld;
|
||||
lde.plist_dtor=(void (*)(void *)) pld;
|
||||
lde.list_dtor_ex = lde.plist_dtor_ex = NULL;
|
||||
lde.module_number = module_number;
|
||||
lde.resource_id = list_destructors.nNextFreeElement;
|
||||
lde.type = ZEND_RESOURCE_LIST_TYPE_STD;
|
||||
lde.type_name = NULL;
|
||||
|
||||
if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
return list_destructors.nNextFreeElement-1;
|
||||
zend_hash_apply_with_argument(&list_destructors, zend_clean_module_rsrc_dtors_cb, (void *) &module_number TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
|
||||
{
|
||||
zend_rsrc_list_dtors_entry lde;
|
||||
zend_rsrc_list_dtors_entry *lde;
|
||||
zval zv;
|
||||
|
||||
#if 0
|
||||
printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
|
||||
#endif
|
||||
|
||||
lde.list_dtor = NULL;
|
||||
lde.plist_dtor = NULL;
|
||||
lde.list_dtor_ex = ld;
|
||||
lde.plist_dtor_ex = pld;
|
||||
lde.module_number = module_number;
|
||||
lde.resource_id = list_destructors.nNextFreeElement;
|
||||
lde.type = ZEND_RESOURCE_LIST_TYPE_EX;
|
||||
lde.type_name = type_name;
|
||||
lde = malloc(sizeof(zend_rsrc_list_dtors_entry));
|
||||
lde->list_dtor_ex = ld;
|
||||
lde->plist_dtor_ex = pld;
|
||||
lde->module_number = module_number;
|
||||
lde->resource_id = list_destructors.nNextFreeElement;
|
||||
lde->type_name = type_name;
|
||||
ZVAL_PTR(&zv, lde);
|
||||
|
||||
if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
|
||||
if (zend_hash_next_index_insert(&list_destructors, &zv) == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
return list_destructors.nNextFreeElement-1;
|
||||
}
|
||||
|
||||
ZEND_API int zend_fetch_list_dtor_id(char *type_name)
|
||||
ZEND_API int zend_fetch_list_dtor_id(const char *type_name)
|
||||
{
|
||||
zend_rsrc_list_dtors_entry *lde;
|
||||
HashPosition pos;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(&list_destructors, &pos);
|
||||
while (zend_hash_get_current_data_ex(&list_destructors, (void **)&lde, &pos) == SUCCESS) {
|
||||
ZEND_HASH_FOREACH_PTR(&list_destructors, lde) {
|
||||
if (lde->type_name && (strcmp(type_name, lde->type_name) == 0)) {
|
||||
#if 0
|
||||
printf("Found resource id %d for resource type %s\n", (*lde).resource_id, type_name);
|
||||
#endif
|
||||
return lde->resource_id;
|
||||
}
|
||||
zend_hash_move_forward_ex(&list_destructors, &pos);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void list_destructors_dtor(zval *zv)
|
||||
{
|
||||
free(Z_PTR_P(zv));
|
||||
}
|
||||
|
||||
int zend_init_rsrc_list_dtors(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = zend_hash_init(&list_destructors, 50, NULL, NULL, 1);
|
||||
zend_hash_init(&list_destructors, 64, NULL, list_destructors_dtor, 1);
|
||||
list_destructors.nNextFreeElement=1; /* we don't want resource type 0 */
|
||||
|
||||
return retval;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -348,15 +309,12 @@ void zend_destroy_rsrc_list_dtors(void)
|
||||
}
|
||||
|
||||
|
||||
const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC)
|
||||
const char *zend_rsrc_list_get_rsrc_type(zend_resource *res TSRMLS_DC)
|
||||
{
|
||||
zend_rsrc_list_dtors_entry *lde;
|
||||
int rsrc_type;
|
||||
|
||||
if (!zend_list_find(resource, &rsrc_type))
|
||||
return NULL;
|
||||
|
||||
if (zend_hash_index_find(&list_destructors, rsrc_type, (void **) &lde)==SUCCESS) {
|
||||
lde = zend_hash_index_find_ptr(&list_destructors, res->type);
|
||||
if (lde) {
|
||||
return lde->type_name;
|
||||
} else {
|
||||
return NULL;
|
||||
|
||||
+16
-32
@@ -27,24 +27,10 @@
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
#define ZEND_RESOURCE_LIST_TYPE_STD 1
|
||||
#define ZEND_RESOURCE_LIST_TYPE_EX 2
|
||||
|
||||
typedef struct _zend_rsrc_list_entry {
|
||||
void *ptr;
|
||||
int type;
|
||||
int refcount;
|
||||
} zend_rsrc_list_entry;
|
||||
|
||||
typedef void (*rsrc_dtor_func_t)(zend_rsrc_list_entry *rsrc TSRMLS_DC);
|
||||
#define ZEND_RSRC_DTOR_FUNC(name) void name(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
typedef void (*rsrc_dtor_func_t)(zend_resource *res TSRMLS_DC);
|
||||
#define ZEND_RSRC_DTOR_FUNC(name) void name(zend_resource *res TSRMLS_DC)
|
||||
|
||||
typedef struct _zend_rsrc_list_dtors_entry {
|
||||
/* old style destructors */
|
||||
void (*list_dtor)(void *);
|
||||
void (*plist_dtor)(void *);
|
||||
|
||||
/* new style destructors */
|
||||
rsrc_dtor_func_t list_dtor_ex;
|
||||
rsrc_dtor_func_t plist_dtor_ex;
|
||||
|
||||
@@ -52,38 +38,36 @@ typedef struct _zend_rsrc_list_dtors_entry {
|
||||
|
||||
int module_number;
|
||||
int resource_id;
|
||||
unsigned char type;
|
||||
} zend_rsrc_list_dtors_entry;
|
||||
|
||||
|
||||
#define register_list_destructors(ld, pld) zend_register_list_destructors((void (*)(void *))ld, (void (*)(void *))pld, module_number);
|
||||
ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number);
|
||||
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number);
|
||||
|
||||
void list_entry_destructor(void *ptr);
|
||||
void plist_entry_destructor(void *ptr);
|
||||
void list_entry_destructor(zval *ptr);
|
||||
void plist_entry_destructor(zval *ptr);
|
||||
|
||||
void zend_clean_module_rsrc_dtors(int module_number TSRMLS_DC);
|
||||
int zend_init_rsrc_list(TSRMLS_D);
|
||||
int zend_init_rsrc_plist(TSRMLS_D);
|
||||
void zend_close_rsrc_list(HashTable *ht TSRMLS_DC);
|
||||
void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC);
|
||||
int zend_init_rsrc_list_dtors(void);
|
||||
void zend_destroy_rsrc_list_dtors(void);
|
||||
|
||||
ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC);
|
||||
ZEND_API int _zend_list_addref(int id TSRMLS_DC);
|
||||
ZEND_API int _zend_list_delete(int id TSRMLS_DC);
|
||||
ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC);
|
||||
ZEND_API zval *zend_list_insert(void *ptr, int type TSRMLS_DC);
|
||||
ZEND_API int _zend_list_free(zend_resource *res TSRMLS_DC);
|
||||
ZEND_API int _zend_list_delete(zend_resource *res TSRMLS_DC);
|
||||
ZEND_API int _zend_list_close(zend_resource *res TSRMLS_DC);
|
||||
|
||||
#define zend_list_addref(id) _zend_list_addref(id TSRMLS_CC)
|
||||
#define zend_list_delete(id) _zend_list_delete(id TSRMLS_CC)
|
||||
#define zend_list_find(id, type) _zend_list_find(id, type TSRMLS_CC)
|
||||
#define zend_list_free(res) _zend_list_free(res TSRMLS_CC)
|
||||
#define zend_list_delete(res) _zend_list_delete(res TSRMLS_CC)
|
||||
#define zend_list_close(res) _zend_list_close(res TSRMLS_CC)
|
||||
|
||||
ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC);
|
||||
ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...);
|
||||
ZEND_API zend_resource *zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC);
|
||||
ZEND_API void *zend_fetch_resource(zval *passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...);
|
||||
|
||||
ZEND_API const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC);
|
||||
ZEND_API int zend_fetch_list_dtor_id(char *type_name);
|
||||
ZEND_API const char *zend_rsrc_list_get_rsrc_type(zend_resource *res TSRMLS_DC);
|
||||
ZEND_API int zend_fetch_list_dtor_id(const char *type_name);
|
||||
|
||||
extern ZEND_API int le_index_ptr; /* list entry type for index pointers */
|
||||
|
||||
|
||||
+1
-3
@@ -33,7 +33,7 @@
|
||||
#define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC
|
||||
#define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC
|
||||
|
||||
#define ZEND_MODULE_API_NO 20131227
|
||||
#define ZEND_MODULE_API_NO 20140815
|
||||
#ifdef ZTS
|
||||
#define USING_ZTS 1
|
||||
#else
|
||||
@@ -125,11 +125,9 @@ struct _zend_module_dep {
|
||||
extern ZEND_API HashTable module_registry;
|
||||
|
||||
void module_destructor(zend_module_entry *module);
|
||||
int module_registry_cleanup(zend_module_entry *module TSRMLS_DC);
|
||||
int module_registry_request_startup(zend_module_entry *module TSRMLS_DC);
|
||||
int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC);
|
||||
|
||||
#define ZEND_MODULE_DTOR (void (*)(void *)) module_destructor
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -114,7 +114,7 @@ ZEND_API int zend_multibyte_set_functions(const zend_multibyte_functions *functi
|
||||
* populated, we need to reinitialize script_encoding here.
|
||||
*/
|
||||
{
|
||||
const char *value = zend_ini_string("zend.script_encoding", sizeof("zend.script_encoding"), 0);
|
||||
const char *value = zend_ini_string("zend.script_encoding", sizeof("zend.script_encoding") - 1, 0);
|
||||
zend_multibyte_set_script_encoding_by_string(value, strlen(value) TSRMLS_CC);
|
||||
}
|
||||
return SUCCESS;
|
||||
@@ -168,7 +168,7 @@ ZEND_API const zend_encoding *zend_multibyte_get_script_encoding(TSRMLS_D)
|
||||
ZEND_API int zend_multibyte_set_script_encoding(const zend_encoding **encoding_list, size_t encoding_list_size TSRMLS_DC)
|
||||
{
|
||||
if (CG(script_encoding_list)) {
|
||||
free(CG(script_encoding_list));
|
||||
free((char*)CG(script_encoding_list));
|
||||
}
|
||||
CG(script_encoding_list) = encoding_list;
|
||||
CG(script_encoding_list_size) = encoding_list_size;
|
||||
@@ -195,7 +195,7 @@ ZEND_API int zend_multibyte_set_script_encoding_by_string(const char *new_value,
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
pefree(list, 1);
|
||||
pefree((void*)list, 1);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
+615
-619
File diff suppressed because it is too large
Load Diff
+29
-29
@@ -24,17 +24,16 @@
|
||||
|
||||
union _zend_function;
|
||||
struct _zend_property_info;
|
||||
struct _zend_literal;
|
||||
|
||||
/* The following rule applies to read_property() and read_dimension() implementations:
|
||||
If you return a zval which is not otherwise referenced by the extension or the engine's
|
||||
symbol table, its reference count should be 0.
|
||||
*/
|
||||
/* Used to fetch property from the object, read-only */
|
||||
typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC);
|
||||
typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC);
|
||||
|
||||
/* Used to fetch dimension from the object, read-only */
|
||||
typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type TSRMLS_DC);
|
||||
typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type, zval *rv TSRMLS_DC);
|
||||
|
||||
|
||||
/* The following rule applies to write_property() and write_dimension() implementations:
|
||||
@@ -43,23 +42,23 @@ typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int ty
|
||||
any changes. You should NOT modify the reference count of the value passed to you.
|
||||
*/
|
||||
/* Used to set property of the object */
|
||||
typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC);
|
||||
typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to set dimension of the object */
|
||||
typedef void (*zend_object_write_dimension_t)(zval *object, zval *offset, zval *value TSRMLS_DC);
|
||||
|
||||
|
||||
/* Used to create pointer to the property of the object, for future direct r/w access */
|
||||
typedef zval **(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC);
|
||||
typedef zval *(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to set object value. Can be used to override assignments and scalar
|
||||
write ops (like ++, +=) on the object */
|
||||
typedef void (*zend_object_set_t)(zval **object, zval *value TSRMLS_DC);
|
||||
typedef void (*zend_object_set_t)(zval *object, zval *value TSRMLS_DC);
|
||||
|
||||
/* Used to get object value. Can be used when converting object value to
|
||||
* one of the basic types and when using scalar ops (like ++, +=) on the object
|
||||
*/
|
||||
typedef zval* (*zend_object_get_t)(zval *object TSRMLS_DC);
|
||||
typedef zval* (*zend_object_get_t)(zval *object, zval *rv TSRMLS_DC);
|
||||
|
||||
/* Used to check if a property of the object exists */
|
||||
/* param has_set_exists:
|
||||
@@ -67,13 +66,13 @@ typedef zval* (*zend_object_get_t)(zval *object TSRMLS_DC);
|
||||
* 1 (set) whether property exists and is true
|
||||
* 2 (exists) whether property exists
|
||||
*/
|
||||
typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, const struct _zend_literal *key TSRMLS_DC);
|
||||
typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to check if a dimension of the object exists */
|
||||
typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty TSRMLS_DC);
|
||||
|
||||
/* Used to remove a property of the object */
|
||||
typedef void (*zend_object_unset_property_t)(zval *object, zval *member, const struct _zend_literal *key TSRMLS_DC);
|
||||
typedef void (*zend_object_unset_property_t)(zval *object, zval *member, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to remove a dimension of the object */
|
||||
typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
|
||||
@@ -87,18 +86,17 @@ typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp TS
|
||||
/* args on stack! */
|
||||
/* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this.
|
||||
*/
|
||||
typedef int (*zend_object_call_method_t)(const char *method, INTERNAL_FUNCTION_PARAMETERS);
|
||||
typedef union _zend_function *(*zend_object_get_method_t)(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC);
|
||||
typedef union _zend_function *(*zend_object_get_constructor_t)(zval *object TSRMLS_DC);
|
||||
typedef int (*zend_object_call_method_t)(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS);
|
||||
typedef union _zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key TSRMLS_DC);
|
||||
typedef union _zend_function *(*zend_object_get_constructor_t)(zend_object *object TSRMLS_DC);
|
||||
|
||||
/* Object maintenance/destruction */
|
||||
typedef void (*zend_object_add_ref_t)(zval *object TSRMLS_DC);
|
||||
typedef void (*zend_object_del_ref_t)(zval *object TSRMLS_DC);
|
||||
typedef void (*zend_object_delete_obj_t)(zval *object TSRMLS_DC);
|
||||
typedef zend_object_value (*zend_object_clone_obj_t)(zval *object TSRMLS_DC);
|
||||
typedef void (*zend_object_dtor_obj_t)(zend_object *object TSRMLS_DC);
|
||||
typedef void (*zend_object_free_obj_t)(zend_object *object TSRMLS_DC);
|
||||
typedef zend_object* (*zend_object_clone_obj_t)(zval *object TSRMLS_DC);
|
||||
|
||||
typedef zend_class_entry *(*zend_object_get_class_entry_t)(const zval *object TSRMLS_DC);
|
||||
typedef int (*zend_object_get_class_name_t)(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC);
|
||||
typedef zend_class_entry *(*zend_object_get_class_entry_t)(const zend_object *object TSRMLS_DC);
|
||||
typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object, int parent TSRMLS_DC);
|
||||
typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC);
|
||||
typedef int (*zend_object_compare_zvals_t)(zval *resul, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
@@ -110,16 +108,18 @@ typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type TSRMLS_D
|
||||
* Returns FAILURE if the object does not have any sense of overloaded dimensions */
|
||||
typedef int (*zend_object_count_elements_t)(zval *object, long *count TSRMLS_DC);
|
||||
|
||||
typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
|
||||
typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zend_object **obj_ptr TSRMLS_DC);
|
||||
|
||||
typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval ***table, int *n TSRMLS_DC);
|
||||
typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval **table, int *n TSRMLS_DC);
|
||||
|
||||
typedef int (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
struct _zend_object_handlers {
|
||||
/* offset of real object header (usually zero) */
|
||||
int offset;
|
||||
/* general object functions */
|
||||
zend_object_add_ref_t add_ref;
|
||||
zend_object_del_ref_t del_ref;
|
||||
zend_object_free_obj_t free_obj;
|
||||
zend_object_dtor_obj_t dtor_obj;
|
||||
zend_object_clone_obj_t clone_obj;
|
||||
/* individual object functions */
|
||||
zend_object_read_property_t read_property;
|
||||
@@ -155,26 +155,26 @@ extern ZEND_API zend_object_handlers std_object_handlers;
|
||||
((fbc)->common.prototype ? (fbc)->common.prototype->common.scope : (fbc)->common.scope)
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce, const char *function_name_strval, int function_name_strlen, const struct _zend_literal *key TSRMLS_DC);
|
||||
ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, const struct _zend_literal *key TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, const struct _zend_literal *key TSRMLS_DC);
|
||||
ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC);
|
||||
ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name_strval, const zval *key TSRMLS_DC);
|
||||
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, void **cache_slot TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name, void **cache_slot TSRMLS_DC);
|
||||
ZEND_API union _zend_function *zend_std_get_constructor(zend_object *object TSRMLS_DC);
|
||||
ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC);
|
||||
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 void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC);
|
||||
ZEND_API void rebuild_object_properties(zend_object *zobj);
|
||||
|
||||
|
||||
#define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL))
|
||||
#define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL)
|
||||
|
||||
ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC);
|
||||
ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, zend_string *function_name TSRMLS_DC);
|
||||
|
||||
ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope);
|
||||
|
||||
ZEND_API int zend_check_property_access(zend_object *zobj, const char *prop_info_name, int prop_info_name_len TSRMLS_DC);
|
||||
ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_info_name TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS);
|
||||
END_EXTERN_C()
|
||||
|
||||
+67
-102
@@ -28,14 +28,27 @@
|
||||
|
||||
ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
GC_REFCOUNT(object) = 1;
|
||||
GC_TYPE_INFO(object) = IS_OBJECT;
|
||||
object->ce = ce;
|
||||
object->properties = NULL;
|
||||
object->properties_table = NULL;
|
||||
object->guards = NULL;
|
||||
zend_objects_store_put(object TSRMLS_CC);
|
||||
if (EXPECTED(ce->default_properties_count != 0)) {
|
||||
zval *p = object->properties_table;
|
||||
zval *end = p + ce->default_properties_count;
|
||||
|
||||
do {
|
||||
ZVAL_UNDEF(p);
|
||||
p++;
|
||||
} while (p != end);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (object->guards) {
|
||||
zend_hash_destroy(object->guards);
|
||||
FREE_HASHTABLE(object->guards);
|
||||
@@ -43,29 +56,19 @@ ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
|
||||
if (object->properties) {
|
||||
zend_hash_destroy(object->properties);
|
||||
FREE_HASHTABLE(object->properties);
|
||||
if (object->properties_table) {
|
||||
efree(object->properties_table);
|
||||
}
|
||||
} else if (object->properties_table) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < object->ce->default_properties_count; i++) {
|
||||
if (object->properties_table[i]) {
|
||||
zval_ptr_dtor(&object->properties_table[i]);
|
||||
}
|
||||
}
|
||||
efree(object->properties_table);
|
||||
}
|
||||
for (i = 0; i < object->ce->default_properties_count; i++) {
|
||||
zval_ptr_dtor(&object->properties_table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC)
|
||||
ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
zend_function *destructor = object ? object->ce->destructor : NULL;
|
||||
|
||||
if (destructor) {
|
||||
zval *old_exception;
|
||||
zval *obj;
|
||||
zend_object_store_bucket *obj_bucket;
|
||||
zend_object *old_exception;
|
||||
zval obj;
|
||||
|
||||
if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
|
||||
if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
@@ -74,11 +77,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
|
||||
if (object->ce != EG(scope)) {
|
||||
zend_class_entry *ce = object->ce;
|
||||
|
||||
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
|
||||
zend_error(EG(current_execute_data) ? E_ERROR : E_WARNING,
|
||||
"Call to private %s::__destruct() from context '%s'%s",
|
||||
ce->name,
|
||||
EG(scope) ? EG(scope)->name : "",
|
||||
EG(in_execution) ? "" : " during shutdown ignored");
|
||||
ce->name->val,
|
||||
EG(scope) ? EG(scope)->name->val : "",
|
||||
EG(current_execute_data) ? "" : " during shutdown ignored");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -87,25 +90,18 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
|
||||
if (!zend_check_protected(zend_get_function_root_class(destructor), EG(scope))) {
|
||||
zend_class_entry *ce = object->ce;
|
||||
|
||||
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
|
||||
zend_error(EG(current_execute_data) ? E_ERROR : E_WARNING,
|
||||
"Call to protected %s::__destruct() from context '%s'%s",
|
||||
ce->name,
|
||||
EG(scope) ? EG(scope)->name : "",
|
||||
EG(in_execution) ? "" : " during shutdown ignored");
|
||||
ce->name->val,
|
||||
EG(scope) ? EG(scope)->name->val : "",
|
||||
EG(current_execute_data) ? "" : " during shutdown ignored");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MAKE_STD_ZVAL(obj);
|
||||
Z_TYPE_P(obj) = IS_OBJECT;
|
||||
Z_OBJ_HANDLE_P(obj) = handle;
|
||||
obj_bucket = &EG(objects_store).object_buckets[handle];
|
||||
if (!obj_bucket->bucket.obj.handlers) {
|
||||
obj_bucket->bucket.obj.handlers = &std_object_handlers;
|
||||
}
|
||||
Z_OBJ_HT_P(obj) = obj_bucket->bucket.obj.handlers;
|
||||
zval_copy_ctor(obj);
|
||||
ZVAL_OBJ(&obj, object);
|
||||
Z_ADDREF(obj);
|
||||
|
||||
/* Make sure that destructors are protected from previously thrown exceptions.
|
||||
* For example, if an exception was thrown in a function and when the function's
|
||||
@@ -113,7 +109,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
|
||||
*/
|
||||
old_exception = NULL;
|
||||
if (EG(exception)) {
|
||||
if (Z_OBJ_HANDLE_P(EG(exception)) == handle) {
|
||||
if (EG(exception) == object) {
|
||||
zend_error(E_ERROR, "Attempt to destruct pending exception");
|
||||
} else {
|
||||
old_exception = EG(exception);
|
||||
@@ -132,104 +128,73 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_objects_free_object_storage(zend_object *object TSRMLS_DC)
|
||||
ZEND_API zend_object *zend_objects_new(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
zend_object_std_dtor(object TSRMLS_CC);
|
||||
efree(object);
|
||||
zend_object *object = emalloc(sizeof(zend_object) + sizeof(zval) * (ce->default_properties_count - 1));
|
||||
|
||||
zend_object_std_init(object, ce TSRMLS_CC);
|
||||
object->handlers = &std_object_handlers;
|
||||
return object;
|
||||
}
|
||||
|
||||
ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type TSRMLS_DC)
|
||||
{
|
||||
zend_object_value retval;
|
||||
|
||||
*object = emalloc(sizeof(zend_object));
|
||||
(*object)->ce = class_type;
|
||||
(*object)->properties = NULL;
|
||||
(*object)->properties_table = NULL;
|
||||
(*object)->guards = NULL;
|
||||
retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
|
||||
retval.handlers = &std_object_handlers;
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API zend_object *zend_objects_get_address(const zval *zobject TSRMLS_DC)
|
||||
{
|
||||
return (zend_object *)zend_object_store_get_object(zobject TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC)
|
||||
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *old_object TSRMLS_DC)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (old_object->properties_table) {
|
||||
if (!new_object->properties_table) {
|
||||
new_object->properties_table = emalloc(sizeof(zval*) * old_object->ce->default_properties_count);
|
||||
memset(new_object->properties_table, 0, sizeof(zval*) * old_object->ce->default_properties_count);
|
||||
}
|
||||
if (old_object->ce->default_properties_count) {
|
||||
for (i = 0; i < old_object->ce->default_properties_count; i++) {
|
||||
if (!new_object->properties) {
|
||||
if (new_object->properties_table[i]) {
|
||||
zval_ptr_dtor(&new_object->properties_table[i]);
|
||||
}
|
||||
}
|
||||
if (!old_object->properties) {
|
||||
new_object->properties_table[i] = old_object->properties_table[i];
|
||||
if (new_object->properties_table[i]) {
|
||||
Z_ADDREF_P(new_object->properties_table[i]);
|
||||
}
|
||||
}
|
||||
zval_ptr_dtor(&new_object->properties_table[i]);
|
||||
ZVAL_COPY(&new_object->properties_table[i], &old_object->properties_table[i]);
|
||||
}
|
||||
}
|
||||
if (old_object->properties) {
|
||||
zval *prop, new_prop;
|
||||
ulong num_key;
|
||||
zend_string *key;
|
||||
|
||||
if (!new_object->properties) {
|
||||
ALLOC_HASHTABLE(new_object->properties);
|
||||
zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_init(new_object->properties, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
}
|
||||
zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
|
||||
if (old_object->properties_table) {
|
||||
HashPosition pos;
|
||||
zend_property_info *prop_info;
|
||||
for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos);
|
||||
zend_hash_get_current_data_ex(&old_object->ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
|
||||
zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) {
|
||||
if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
|
||||
if (zend_hash_quick_find(new_object->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&new_object->properties_table[prop_info->offset]) == FAILURE) {
|
||||
new_object->properties_table[prop_info->offset] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_HASH_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) {
|
||||
if (Z_TYPE_P(prop) == IS_INDIRECT) {
|
||||
ZVAL_INDIRECT(&new_prop, new_object->properties_table + (Z_INDIRECT_P(prop) - old_object->properties_table));
|
||||
} else {
|
||||
ZVAL_COPY_VALUE(&new_prop, prop);
|
||||
zval_add_ref(&new_prop);
|
||||
}
|
||||
}
|
||||
if (key) {
|
||||
zend_hash_update(new_object->properties, key, &new_prop);
|
||||
} else {
|
||||
zend_hash_index_update(new_object->properties, num_key, &new_prop);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
if (old_object->ce->clone) {
|
||||
zval *new_obj;
|
||||
|
||||
MAKE_STD_ZVAL(new_obj);
|
||||
new_obj->type = IS_OBJECT;
|
||||
new_obj->value.obj = new_obj_val;
|
||||
zval_copy_ctor(new_obj);
|
||||
zval new_obj;
|
||||
|
||||
ZVAL_OBJ(&new_obj, new_object);
|
||||
zval_copy_ctor(&new_obj);
|
||||
zend_call_method_with_0_params(&new_obj, old_object->ce, &old_object->ce->clone, ZEND_CLONE_FUNC_NAME, NULL);
|
||||
|
||||
zval_ptr_dtor(&new_obj);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
|
||||
ZEND_API zend_object *zend_objects_clone_obj(zval *zobject TSRMLS_DC)
|
||||
{
|
||||
zend_object_value new_obj_val;
|
||||
zend_object *old_object;
|
||||
zend_object *new_object;
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
||||
|
||||
/* assume that create isn't overwritten, so when clone depends on the
|
||||
* overwritten one then it must itself be overwritten */
|
||||
old_object = zend_objects_get_address(zobject TSRMLS_CC);
|
||||
new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
|
||||
old_object = Z_OBJ_P(zobject);
|
||||
new_object = zend_objects_new(old_object->ce TSRMLS_CC);
|
||||
|
||||
zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
|
||||
zend_objects_clone_members(new_object, old_object TSRMLS_CC);
|
||||
|
||||
return new_obj_val;
|
||||
return new_object;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+4
-6
@@ -27,12 +27,10 @@
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC);
|
||||
ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC);
|
||||
ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type TSRMLS_DC);
|
||||
ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC);
|
||||
ZEND_API zend_object *zend_objects_get_address(const zval *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC);
|
||||
ZEND_API zend_object_value zend_objects_clone_obj(zval *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_free_object_storage(zend_object *object TSRMLS_DC);
|
||||
ZEND_API zend_object *zend_objects_new(zend_class_entry *ce TSRMLS_DC);
|
||||
ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *old_object TSRMLS_DC);
|
||||
ZEND_API zend_object *zend_objects_clone_obj(zval *object TSRMLS_DC);
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* ZEND_OBJECTS_H */
|
||||
|
||||
+123
-217
@@ -23,17 +23,15 @@
|
||||
#include "zend_globals.h"
|
||||
#include "zend_variables.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_objects_API.h"
|
||||
|
||||
#define ZEND_DEBUG_OBJECTS 0
|
||||
#include "zend_objects_API.h"
|
||||
|
||||
ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size)
|
||||
{
|
||||
objects->object_buckets = (zend_object_store_bucket *) emalloc(init_size * sizeof(zend_object_store_bucket));
|
||||
objects->object_buckets = (zend_object **) emalloc(init_size * sizeof(zend_object*));
|
||||
objects->top = 1; /* Skip 0 so that handles are true */
|
||||
objects->size = init_size;
|
||||
objects->free_list_head = -1;
|
||||
memset(&objects->object_buckets[0], 0, sizeof(zend_object_store_bucket));
|
||||
memset(&objects->object_buckets[0], 0, sizeof(zend_object*));
|
||||
}
|
||||
|
||||
ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
|
||||
@@ -44,25 +42,17 @@ ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
|
||||
|
||||
ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC)
|
||||
{
|
||||
zend_uint i = 1;
|
||||
zend_uint i;
|
||||
|
||||
for (i = 1; i < objects->top ; i++) {
|
||||
if (objects->object_buckets[i].valid) {
|
||||
struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
|
||||
zend_object *obj = objects->object_buckets[i];
|
||||
|
||||
if (!objects->object_buckets[i].destructor_called) {
|
||||
objects->object_buckets[i].destructor_called = 1;
|
||||
if (obj->dtor && obj->object) {
|
||||
obj->refcount++;
|
||||
obj->dtor(obj->object, i TSRMLS_CC);
|
||||
obj = &objects->object_buckets[i].bucket.obj;
|
||||
obj->refcount--;
|
||||
|
||||
if (obj->refcount == 0) {
|
||||
/* in case gc_collect_cycle is triggered before free_storage */
|
||||
GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
|
||||
}
|
||||
}
|
||||
if (IS_OBJ_VALID(obj)) {
|
||||
if (!(GC_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) {
|
||||
GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED;
|
||||
GC_REFCOUNT(obj)++;
|
||||
obj->handlers->dtor_obj(obj TSRMLS_CC);
|
||||
GC_REFCOUNT(obj)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,27 +66,43 @@ ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSR
|
||||
return;
|
||||
}
|
||||
for (i = 1; i < objects->top ; i++) {
|
||||
if (objects->object_buckets[i].valid) {
|
||||
objects->object_buckets[i].destructor_called = 1;
|
||||
zend_object *obj = objects->object_buckets[i];
|
||||
|
||||
if (IS_OBJ_VALID(obj)) {
|
||||
GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC)
|
||||
{
|
||||
zend_uint i = 1;
|
||||
zend_uint i;
|
||||
|
||||
for (i = 1; i < objects->top ; i++) {
|
||||
if (objects->object_buckets[i].valid) {
|
||||
struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
|
||||
/* Free object properties but don't free object their selves */
|
||||
for (i = objects->top - 1; i > 0 ; i--) {
|
||||
zend_object *obj = objects->object_buckets[i];
|
||||
|
||||
GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
|
||||
|
||||
objects->object_buckets[i].valid = 0;
|
||||
if (obj->free_storage) {
|
||||
obj->free_storage(obj->object TSRMLS_CC);
|
||||
if (IS_OBJ_VALID(obj)) {
|
||||
if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
|
||||
GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED;
|
||||
if (obj->handlers->free_obj) {
|
||||
GC_REFCOUNT(obj)++;
|
||||
obj->handlers->free_obj(obj TSRMLS_CC);
|
||||
GC_REFCOUNT(obj)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now free objects theirselves */
|
||||
for (i = 1; i < objects->top ; i++) {
|
||||
zend_object *obj = objects->object_buckets[i];
|
||||
|
||||
if (IS_OBJ_VALID(obj)) {
|
||||
/* Not adding to free list as we are shutting down anyway */
|
||||
void *ptr = ((char*)obj) - obj->handlers->offset;
|
||||
GC_REMOVE_FROM_BUFFER(obj);
|
||||
efree(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,188 +110,97 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects
|
||||
|
||||
/* Store objects API */
|
||||
|
||||
ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_free_object_storage_t free_storage, zend_objects_store_clone_t clone TSRMLS_DC)
|
||||
ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle;
|
||||
struct _store_object *obj;
|
||||
int handle;
|
||||
|
||||
if (EG(objects_store).free_list_head != -1) {
|
||||
handle = EG(objects_store).free_list_head;
|
||||
EG(objects_store).free_list_head = EG(objects_store).object_buckets[handle].bucket.free_list.next;
|
||||
EG(objects_store).free_list_head = GET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle]);
|
||||
} else {
|
||||
if (EG(objects_store).top == EG(objects_store).size) {
|
||||
EG(objects_store).size <<= 1;
|
||||
EG(objects_store).object_buckets = (zend_object_store_bucket *) erealloc(EG(objects_store).object_buckets, EG(objects_store).size * sizeof(zend_object_store_bucket));
|
||||
EG(objects_store).object_buckets = (zend_object **) erealloc(EG(objects_store).object_buckets, EG(objects_store).size * sizeof(zend_object*));
|
||||
}
|
||||
handle = EG(objects_store).top++;
|
||||
}
|
||||
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
EG(objects_store).object_buckets[handle].destructor_called = 0;
|
||||
EG(objects_store).object_buckets[handle].valid = 1;
|
||||
EG(objects_store).object_buckets[handle].apply_count = 0;
|
||||
|
||||
obj->refcount = 1;
|
||||
GC_OBJ_INIT(obj);
|
||||
obj->object = object;
|
||||
obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
|
||||
obj->free_storage = free_storage;
|
||||
obj->clone = clone;
|
||||
obj->handlers = NULL;
|
||||
|
||||
#if ZEND_DEBUG_OBJECTS
|
||||
fprintf(stderr, "Allocated object id #%d\n", handle);
|
||||
#endif
|
||||
return handle;
|
||||
object->handle = handle;
|
||||
EG(objects_store).object_buckets[handle] = object;
|
||||
}
|
||||
|
||||
ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
|
||||
#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle) \
|
||||
SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle], EG(objects_store).free_list_head); \
|
||||
EG(objects_store).free_list_head = handle;
|
||||
|
||||
return EG(objects_store).object_buckets[handle].bucket.obj.refcount;
|
||||
ZEND_API void zend_objects_store_free(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_uint handle = object->handle;
|
||||
void *ptr = ((char*)object) - object->handlers->offset;
|
||||
|
||||
GC_REMOVE_FROM_BUFFER(object);
|
||||
efree(ptr);
|
||||
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC)
|
||||
ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(object);
|
||||
|
||||
EG(objects_store).object_buckets[handle].bucket.obj.refcount++;
|
||||
#if ZEND_DEBUG_OBJECTS
|
||||
fprintf(stderr, "Increased refcount of object id #%d\n", handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a reference to an objects store entry given the object handle.
|
||||
*/
|
||||
ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC)
|
||||
{
|
||||
EG(objects_store).object_buckets[handle].bucket.obj.refcount++;
|
||||
}
|
||||
|
||||
#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST() \
|
||||
EG(objects_store).object_buckets[handle].bucket.free_list.next = EG(objects_store).free_list_head; \
|
||||
EG(objects_store).free_list_head = handle; \
|
||||
EG(objects_store).object_buckets[handle].valid = 0;
|
||||
|
||||
ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle;
|
||||
|
||||
handle = Z_OBJ_HANDLE_P(zobject);
|
||||
|
||||
Z_ADDREF_P(zobject);
|
||||
zend_objects_store_del_ref_by_handle_ex(handle, Z_OBJ_HT_P(zobject) TSRMLS_CC);
|
||||
Z_DELREF_P(zobject);
|
||||
|
||||
GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a reference to an objects store entry given the object handle.
|
||||
*/
|
||||
ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
struct _store_object *obj;
|
||||
int failure = 0;
|
||||
|
||||
if (!EG(objects_store).object_buckets) {
|
||||
return;
|
||||
}
|
||||
|
||||
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
|
||||
/* Make sure we hold a reference count during the destructor call
|
||||
otherwise, when the destructor ends the storage might be freed
|
||||
when the refcount reaches 0 a second time
|
||||
*/
|
||||
if (EG(objects_store).object_buckets[handle].valid) {
|
||||
if (obj->refcount == 1) {
|
||||
if (!EG(objects_store).object_buckets[handle].destructor_called) {
|
||||
EG(objects_store).object_buckets[handle].destructor_called = 1;
|
||||
if (EG(objects_store).object_buckets &&
|
||||
IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle])) {
|
||||
if (GC_REFCOUNT(object) == 0) {
|
||||
int failure = 0;
|
||||
|
||||
if (obj->dtor) {
|
||||
if (handlers && !obj->handlers) {
|
||||
obj->handlers = handlers;
|
||||
}
|
||||
if (!(GC_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) {
|
||||
GC_FLAGS(object) |= IS_OBJ_DESTRUCTOR_CALLED;
|
||||
|
||||
if (object->handlers->dtor_obj) {
|
||||
GC_REFCOUNT(object)++;
|
||||
zend_try {
|
||||
obj->dtor(obj->object, handle TSRMLS_CC);
|
||||
object->handlers->dtor_obj(object TSRMLS_CC);
|
||||
} zend_catch {
|
||||
failure = 1;
|
||||
} zend_end_try();
|
||||
GC_REFCOUNT(object)--;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-read the object from the object store as the store might have been reallocated in the dtor */
|
||||
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
if (GC_REFCOUNT(object) == 0) {
|
||||
zend_uint handle = object->handle;
|
||||
void *ptr;
|
||||
|
||||
if (obj->refcount == 1) {
|
||||
GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
|
||||
if (obj->free_storage) {
|
||||
zend_try {
|
||||
obj->free_storage(obj->object TSRMLS_CC);
|
||||
} zend_catch {
|
||||
failure = 1;
|
||||
} zend_end_try();
|
||||
EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object);
|
||||
if (!(GC_FLAGS(object) & IS_OBJ_FREE_CALLED)) {
|
||||
GC_FLAGS(object) |= IS_OBJ_FREE_CALLED;
|
||||
if (object->handlers->free_obj) {
|
||||
zend_try {
|
||||
GC_REFCOUNT(object)++;
|
||||
object->handlers->free_obj(object TSRMLS_CC);
|
||||
GC_REFCOUNT(object)--;
|
||||
} zend_catch {
|
||||
failure = 1;
|
||||
} zend_end_try();
|
||||
}
|
||||
}
|
||||
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST();
|
||||
ptr = ((char*)object) - object->handlers->offset;
|
||||
GC_REMOVE_FROM_BUFFER(object);
|
||||
efree(ptr);
|
||||
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle);
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
zend_bailout();
|
||||
}
|
||||
} else {
|
||||
GC_REFCOUNT(object)--;
|
||||
}
|
||||
}
|
||||
|
||||
obj->refcount--;
|
||||
|
||||
#if ZEND_DEBUG_OBJECTS
|
||||
if (obj->refcount == 0) {
|
||||
fprintf(stderr, "Deallocated object id #%d\n", handle);
|
||||
} else {
|
||||
fprintf(stderr, "Decreased refcount of object id #%d\n", handle);
|
||||
}
|
||||
#endif
|
||||
if (failure) {
|
||||
zend_bailout();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
|
||||
{
|
||||
zend_object_value retval;
|
||||
void *new_object;
|
||||
struct _store_object *obj;
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
||||
|
||||
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
|
||||
if (obj->clone == NULL) {
|
||||
zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name);
|
||||
}
|
||||
|
||||
obj->clone(obj->object, &new_object TSRMLS_CC);
|
||||
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
|
||||
retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->free_storage, obj->clone TSRMLS_CC);
|
||||
retval.handlers = Z_OBJ_HT_P(zobject);
|
||||
EG(objects_store).object_buckets[handle].bucket.obj.handlers = retval.handlers;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API void *zend_object_store_get_object(const zval *zobject TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
||||
|
||||
return EG(objects_store).object_buckets[handle].bucket.obj.object;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve an entry from the objects store given the object handle.
|
||||
*/
|
||||
ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle TSRMLS_DC)
|
||||
{
|
||||
return EG(objects_store).object_buckets[handle].bucket.obj.object;
|
||||
}
|
||||
|
||||
/* zend_object_store_set_object:
|
||||
* It is ONLY valid to call this function from within the constructor of an
|
||||
* overloaded object. Its purpose is to set the object pointer for the object
|
||||
@@ -293,34 +208,27 @@ ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle
|
||||
* from the constructor function. You MUST NOT use this function for any other
|
||||
* weird games, or call it at any other time after the object is constructed.
|
||||
* */
|
||||
ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC)
|
||||
ZEND_API void zend_object_store_set_object(zval *zobject, zend_object *object TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
||||
|
||||
EG(objects_store).object_buckets[handle].bucket.obj.object = object;
|
||||
EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zobject)] = object;
|
||||
}
|
||||
|
||||
|
||||
/* Called when the ctor was terminated by an exception */
|
||||
ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC)
|
||||
ZEND_API void zend_object_store_ctor_failed(zend_object *obj TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
||||
zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle];
|
||||
|
||||
obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);;
|
||||
obj_bucket->destructor_called = 1;
|
||||
GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED;
|
||||
}
|
||||
|
||||
|
||||
/* Proxy objects workings */
|
||||
typedef struct _zend_proxy_object {
|
||||
zval *object;
|
||||
zval *property;
|
||||
zend_object std;
|
||||
zval object;
|
||||
zval property;
|
||||
} zend_proxy_object;
|
||||
|
||||
static zend_object_handlers zend_object_proxy_handlers;
|
||||
|
||||
ZEND_API void zend_objects_proxy_destroy(zend_object *object, zend_object_handle handle TSRMLS_DC)
|
||||
ZEND_API void zend_objects_proxy_destroy(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -336,46 +244,44 @@ ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_obj
|
||||
*object_clone = emalloc(sizeof(zend_proxy_object));
|
||||
(*object_clone)->object = object->object;
|
||||
(*object_clone)->property = object->property;
|
||||
zval_add_ref(&(*object_clone)->property);
|
||||
zval_add_ref(&(*object_clone)->object);
|
||||
Z_ADDREF_P(&(*object_clone)->property);
|
||||
Z_ADDREF_P(&(*object_clone)->object);
|
||||
}
|
||||
|
||||
ZEND_API zval *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC)
|
||||
ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC)
|
||||
{
|
||||
zend_proxy_object *pobj = emalloc(sizeof(zend_proxy_object));
|
||||
zval *retval;
|
||||
zend_proxy_object *obj = emalloc(sizeof(zend_proxy_object));
|
||||
|
||||
pobj->object = object;
|
||||
zval_add_ref(&pobj->object);
|
||||
ALLOC_ZVAL(pobj->property);
|
||||
INIT_PZVAL_COPY(pobj->property, member);
|
||||
zval_copy_ctor(pobj->property);
|
||||
GC_REFCOUNT(obj) = 1;
|
||||
GC_TYPE_INFO(obj) = IS_OBJECT;
|
||||
obj->std.ce = NULL;
|
||||
obj->std.properties = NULL;
|
||||
obj->std.guards = NULL;
|
||||
obj->std.handlers = &zend_object_proxy_handlers;
|
||||
|
||||
ZVAL_COPY(&obj->object, object);
|
||||
ZVAL_DUP(&obj->property, member);
|
||||
|
||||
MAKE_STD_ZVAL(retval);
|
||||
Z_TYPE_P(retval) = IS_OBJECT;
|
||||
Z_OBJ_HANDLE_P(retval) = zend_objects_store_put(pobj, (zend_objects_store_dtor_t)zend_objects_proxy_destroy, (zend_objects_free_object_storage_t) zend_objects_proxy_free_storage, (zend_objects_store_clone_t) zend_objects_proxy_clone TSRMLS_CC);
|
||||
Z_OBJ_HT_P(retval) = &zend_object_proxy_handlers;
|
||||
|
||||
return retval;
|
||||
return (zend_object*)obj;
|
||||
}
|
||||
|
||||
ZEND_API void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC)
|
||||
ZEND_API void zend_object_proxy_set(zval *property, zval *value TSRMLS_DC)
|
||||
{
|
||||
zend_proxy_object *probj = zend_object_store_get_object(*property TSRMLS_CC);
|
||||
zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property);
|
||||
|
||||
if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->write_property) {
|
||||
Z_OBJ_HT_P(probj->object)->write_property(probj->object, probj->property, value, 0 TSRMLS_CC);
|
||||
if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->write_property) {
|
||||
Z_OBJ_HT(probj->object)->write_property(&probj->object, &probj->property, value, NULL TSRMLS_CC);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Cannot write property of object - no write handler defined");
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API zval* zend_object_proxy_get(zval *property TSRMLS_DC)
|
||||
ZEND_API zval* zend_object_proxy_get(zval *property, zval *rv TSRMLS_DC)
|
||||
{
|
||||
zend_proxy_object *probj = zend_object_store_get_object(property TSRMLS_CC);
|
||||
zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property);
|
||||
|
||||
if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->read_property) {
|
||||
return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property, BP_VAR_R, 0 TSRMLS_CC);
|
||||
if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->read_property) {
|
||||
return Z_OBJ_HT(probj->object)->read_property(&probj->object, &probj->property, BP_VAR_R, NULL, rv TSRMLS_CC);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Cannot read property of object - no read handler defined");
|
||||
}
|
||||
|
||||
+28
-39
@@ -24,32 +24,30 @@
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
typedef void (*zend_objects_store_dtor_t)(void *object, zend_object_handle handle TSRMLS_DC);
|
||||
typedef void (*zend_objects_free_object_storage_t)(void *object TSRMLS_DC);
|
||||
typedef void (*zend_objects_store_clone_t)(void *object, void **object_clone TSRMLS_DC);
|
||||
#define OBJ_BUCKET_INVALID (1<<0)
|
||||
|
||||
typedef struct _zend_object_store_bucket {
|
||||
zend_bool destructor_called;
|
||||
zend_bool valid;
|
||||
zend_uchar apply_count;
|
||||
union _store_bucket {
|
||||
struct _store_object {
|
||||
void *object;
|
||||
zend_objects_store_dtor_t dtor;
|
||||
zend_objects_free_object_storage_t free_storage;
|
||||
zend_objects_store_clone_t clone;
|
||||
const zend_object_handlers *handlers;
|
||||
zend_uint refcount;
|
||||
gc_root_buffer *buffered;
|
||||
} obj;
|
||||
struct {
|
||||
int next;
|
||||
} free_list;
|
||||
} bucket;
|
||||
} zend_object_store_bucket;
|
||||
#define IS_OBJ_VALID(o) (!(((zend_uintptr_t)(o)) & OBJ_BUCKET_INVALID))
|
||||
|
||||
#define SET_OBJ_INVALID(o) ((zend_object*)((((zend_uintptr_t)(o)) | OBJ_BUCKET_INVALID)))
|
||||
|
||||
#define GET_OBJ_BUCKET_NUMBER(o) (((zend_intptr_t)(o)) >> 1)
|
||||
|
||||
#define SET_OBJ_BUCKET_NUMBER(o, n) do { \
|
||||
(o) = (zend_object*)((((zend_uintptr_t)(n)) << 1) | OBJ_BUCKET_INVALID); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define OBJ_RELEASE(obj) do { \
|
||||
zend_object *_obj = (obj); \
|
||||
if (--GC_REFCOUNT(_obj) == 0) { \
|
||||
zend_objects_store_del(_obj TSRMLS_CC); \
|
||||
} else { \
|
||||
gc_possible_root(&_obj->gc TSRMLS_CC); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct _zend_objects_store {
|
||||
zend_object_store_bucket *object_buckets;
|
||||
zend_object **object_buckets;
|
||||
zend_uint top;
|
||||
zend_uint size;
|
||||
int free_list_head;
|
||||
@@ -63,28 +61,19 @@ ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSR
|
||||
ZEND_API void zend_objects_store_destroy(zend_objects_store *objects);
|
||||
|
||||
/* Store API functions */
|
||||
ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_free_object_storage_t storage, zend_objects_store_clone_t clone TSRMLS_DC);
|
||||
ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_store_free(zend_object *object TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_store_del_ref(zval *object TSRMLS_DC);
|
||||
ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC);
|
||||
ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC);
|
||||
static zend_always_inline void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) {
|
||||
zend_objects_store_del_ref_by_handle_ex(handle, NULL TSRMLS_CC);
|
||||
}
|
||||
ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC);
|
||||
ZEND_API zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC);
|
||||
ZEND_API void *zend_object_store_get_object(const zval *object TSRMLS_DC);
|
||||
ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle TSRMLS_DC);
|
||||
/* See comment in zend_objects_API.c before you use this */
|
||||
ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC);
|
||||
ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC);
|
||||
ZEND_API void zend_object_store_set_object(zval *zobject, zend_object *object TSRMLS_DC);
|
||||
ZEND_API void zend_object_store_ctor_failed(zend_object *object TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC);
|
||||
|
||||
#define ZEND_OBJECTS_STORE_HANDLERS zend_objects_store_add_ref, zend_objects_store_del_ref, zend_objects_store_clone_obj
|
||||
#define ZEND_OBJECTS_STORE_HANDLERS 0, zend_object_std_dtor, zend_objects_destroy_object, zend_objects_clone_obj
|
||||
|
||||
ZEND_API zval *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC);
|
||||
ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC);
|
||||
|
||||
ZEND_API zend_object_handlers *zend_get_std_object_handlers(void);
|
||||
END_EXTERN_C()
|
||||
|
||||
+86
-93
@@ -70,13 +70,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
|
||||
|
||||
op_array->T = 0;
|
||||
|
||||
op_array->nested_calls = 0;
|
||||
op_array->used_stack = 0;
|
||||
|
||||
op_array->function_name = NULL;
|
||||
op_array->filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
op_array->doc_comment = NULL;
|
||||
op_array->doc_comment_len = 0;
|
||||
|
||||
op_array->arg_info = NULL;
|
||||
op_array->num_args = 0;
|
||||
@@ -116,66 +112,65 @@ ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC)
|
||||
destroy_op_array((zend_op_array *) function TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
if (function->common.function_name) {
|
||||
STR_RELEASE(function->common.function_name);
|
||||
}
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_function_dtor(zend_function *function)
|
||||
ZEND_API void zend_function_dtor(zval *zv)
|
||||
{
|
||||
zend_function *function = Z_PTR_P(zv);
|
||||
TSRMLS_FETCH();
|
||||
|
||||
destroy_zend_function(function TSRMLS_CC);
|
||||
if (function->type == ZEND_INTERNAL_FUNCTION) {
|
||||
pefree(function, 1);
|
||||
} else if (!function->common.function_name) {
|
||||
efree(function);
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_cleanup_op_array_data(zend_op_array *op_array)
|
||||
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
|
||||
{
|
||||
if (op_array->static_variables) {
|
||||
zend_hash_clean(op_array->static_variables);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC)
|
||||
{
|
||||
if (function->type == ZEND_USER_FUNCTION) {
|
||||
zend_cleanup_op_array_data((zend_op_array *) function);
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
} else {
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC)
|
||||
{
|
||||
if (function->type == ZEND_USER_FUNCTION) {
|
||||
zend_cleanup_op_array_data((zend_op_array *) function);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC)
|
||||
ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
/* Clean all parts that can contain run-time data */
|
||||
/* Note that only run-time accessed data need to be cleaned up, pre-defined data can
|
||||
not contain objects and thus are not probelmatic */
|
||||
if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
|
||||
zend_hash_apply(&ce->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
|
||||
zend_function *func;
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
|
||||
if (func->type == ZEND_USER_FUNCTION) {
|
||||
zend_cleanup_op_array_data((zend_op_array *) func);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
if (ce->static_members_table) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ce->default_static_members_count; i++) {
|
||||
if (ce->static_members_table[i]) {
|
||||
zval *p = ce->static_members_table[i];
|
||||
ce->static_members_table[i] = NULL;
|
||||
zval_ptr_dtor(&p);
|
||||
if (Z_TYPE(ce->static_members_table[i]) != IS_UNDEF) {
|
||||
zval tmp;
|
||||
|
||||
ZVAL_COPY_VALUE(&tmp, &ce->static_members_table[i]);
|
||||
ZVAL_UNDEF(&ce->static_members_table[i]);
|
||||
zval_ptr_dtor(&tmp);
|
||||
}
|
||||
}
|
||||
ce->static_members_table = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC)
|
||||
ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
if (CE_STATIC_MEMBERS(ce)) {
|
||||
int i;
|
||||
@@ -192,31 +187,6 @@ static inline void cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
cleanup_internal_class_data(ce TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API int zend_cleanup_user_class_data(zend_class_entry **pce TSRMLS_DC)
|
||||
{
|
||||
if ((*pce)->type == ZEND_USER_CLASS) {
|
||||
cleanup_user_class_data(*pce TSRMLS_CC);
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
} else {
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
|
||||
{
|
||||
if ((*pce)->type == ZEND_USER_CLASS) {
|
||||
cleanup_user_class_data(*pce TSRMLS_CC);
|
||||
} else {
|
||||
cleanup_internal_class_data(*pce TSRMLS_CC);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _destroy_zend_class_traits_info(zend_class_entry *ce)
|
||||
{
|
||||
if (ce->num_traits > 0 && ce->traits) {
|
||||
@@ -228,16 +198,16 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
|
||||
while (ce->trait_aliases[i]) {
|
||||
if (ce->trait_aliases[i]->trait_method) {
|
||||
if (ce->trait_aliases[i]->trait_method->method_name) {
|
||||
efree((char*)ce->trait_aliases[i]->trait_method->method_name);
|
||||
STR_RELEASE(ce->trait_aliases[i]->trait_method->method_name);
|
||||
}
|
||||
if (ce->trait_aliases[i]->trait_method->class_name) {
|
||||
efree((char*)ce->trait_aliases[i]->trait_method->class_name);
|
||||
STR_RELEASE(ce->trait_aliases[i]->trait_method->class_name);
|
||||
}
|
||||
efree(ce->trait_aliases[i]->trait_method);
|
||||
}
|
||||
|
||||
if (ce->trait_aliases[i]->alias) {
|
||||
efree((char*)ce->trait_aliases[i]->alias);
|
||||
STR_RELEASE(ce->trait_aliases[i]->alias);
|
||||
}
|
||||
|
||||
efree(ce->trait_aliases[i]);
|
||||
@@ -251,8 +221,8 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
|
||||
size_t i = 0;
|
||||
|
||||
while (ce->trait_precedences[i]) {
|
||||
efree((char*)ce->trait_precedences[i]->trait_method->method_name);
|
||||
efree((char*)ce->trait_precedences[i]->trait_method->class_name);
|
||||
STR_RELEASE(ce->trait_precedences[i]->trait_method->method_name);
|
||||
STR_RELEASE(ce->trait_precedences[i]->trait_method->class_name);
|
||||
efree(ce->trait_precedences[i]->trait_method);
|
||||
|
||||
if (ce->trait_precedences[i]->exclude_from_classes) {
|
||||
@@ -266,9 +236,9 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void destroy_zend_class(zend_class_entry **pce)
|
||||
ZEND_API void destroy_zend_class(zval *zv)
|
||||
{
|
||||
zend_class_entry *ce = *pce;
|
||||
zend_class_entry *ce = Z_PTR_P(zv);
|
||||
|
||||
if (--ce->refcount > 0) {
|
||||
return;
|
||||
@@ -279,7 +249,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ce->default_properties_count; i++) {
|
||||
if (ce->default_properties_table[i]) {
|
||||
if (Z_TYPE(ce->default_properties_table[i]) != IS_UNDEF) {
|
||||
zval_ptr_dtor(&ce->default_properties_table[i]);
|
||||
}
|
||||
}
|
||||
@@ -289,33 +259,32 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ce->default_static_members_count; i++) {
|
||||
if (ce->default_static_members_table[i]) {
|
||||
if (Z_TYPE(ce->default_static_members_table[i]) != IS_UNDEF) {
|
||||
zval_ptr_dtor(&ce->default_static_members_table[i]);
|
||||
}
|
||||
}
|
||||
efree(ce->default_static_members_table);
|
||||
}
|
||||
zend_hash_destroy(&ce->properties_info);
|
||||
str_efree(ce->name);
|
||||
STR_RELEASE(ce->name);
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
zend_hash_destroy(&ce->constants_table);
|
||||
if (ce->num_interfaces > 0 && ce->interfaces) {
|
||||
efree(ce->interfaces);
|
||||
}
|
||||
if (ce->info.user.doc_comment) {
|
||||
efree((char*)ce->info.user.doc_comment);
|
||||
STR_RELEASE(ce->info.user.doc_comment);
|
||||
}
|
||||
|
||||
_destroy_zend_class_traits_info(ce);
|
||||
|
||||
efree(ce);
|
||||
break;
|
||||
case ZEND_INTERNAL_CLASS:
|
||||
if (ce->default_properties_table) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ce->default_properties_count; i++) {
|
||||
if (ce->default_properties_table[i]) {
|
||||
if (Z_TYPE(ce->default_properties_table[i]) != IS_UNDEF) {
|
||||
zval_internal_ptr_dtor(&ce->default_properties_table[i]);
|
||||
}
|
||||
}
|
||||
@@ -330,7 +299,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
|
||||
free(ce->default_static_members_table);
|
||||
}
|
||||
zend_hash_destroy(&ce->properties_info);
|
||||
str_free(ce->name);
|
||||
STR_RELEASE(ce->name);
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
zend_hash_destroy(&ce->constants_table);
|
||||
if (ce->num_interfaces > 0) {
|
||||
@@ -341,15 +310,17 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
|
||||
}
|
||||
}
|
||||
|
||||
void zend_class_add_ref(zend_class_entry **ce)
|
||||
void zend_class_add_ref(zval *zv)
|
||||
{
|
||||
(*ce)->refcount++;
|
||||
zend_class_entry *ce = Z_PTR_P(zv);
|
||||
|
||||
ce->refcount++;
|
||||
}
|
||||
|
||||
ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
{
|
||||
zend_literal *literal = op_array->literals;
|
||||
zend_literal *end;
|
||||
zval *literal = op_array->literals;
|
||||
zval *end;
|
||||
zend_uint i;
|
||||
|
||||
if (op_array->static_variables) {
|
||||
@@ -357,7 +328,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
FREE_HASHTABLE(op_array->static_variables);
|
||||
}
|
||||
|
||||
if (op_array->run_time_cache) {
|
||||
if (op_array->run_time_cache && !op_array->function_name) {
|
||||
efree(op_array->run_time_cache);
|
||||
}
|
||||
|
||||
@@ -371,7 +342,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
i = op_array->last_var;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
str_efree(op_array->vars[i].name);
|
||||
STR_RELEASE(op_array->vars[i]);
|
||||
}
|
||||
efree(op_array->vars);
|
||||
}
|
||||
@@ -379,7 +350,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
if (literal) {
|
||||
end = literal + op_array->last_literal;
|
||||
while (literal < end) {
|
||||
zval_dtor(&literal->constant);
|
||||
zval_dtor(literal);
|
||||
literal++;
|
||||
}
|
||||
efree(op_array->literals);
|
||||
@@ -387,10 +358,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
efree(op_array->opcodes);
|
||||
|
||||
if (op_array->function_name) {
|
||||
efree((char*)op_array->function_name);
|
||||
STR_RELEASE(op_array->function_name);
|
||||
}
|
||||
if (op_array->doc_comment) {
|
||||
efree((char*)op_array->doc_comment);
|
||||
STR_RELEASE(op_array->doc_comment);
|
||||
}
|
||||
if (op_array->brk_cont_array) {
|
||||
efree(op_array->brk_cont_array);
|
||||
@@ -403,9 +374,9 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
}
|
||||
if (op_array->arg_info) {
|
||||
for (i=0; i<op_array->num_args; i++) {
|
||||
str_efree(op_array->arg_info[i].name);
|
||||
efree((char*)op_array->arg_info[i].name);
|
||||
if (op_array->arg_info[i].class_name) {
|
||||
str_efree(op_array->arg_info[i].class_name);
|
||||
efree((char*)op_array->arg_info[i].class_name);
|
||||
}
|
||||
}
|
||||
efree(op_array->arg_info);
|
||||
@@ -677,7 +648,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
|
||||
int nest_levels, array_offset;
|
||||
zend_brk_cont_element *jmp_to;
|
||||
|
||||
nest_levels = Z_LVAL(op_array->literals[opline->op2.constant].constant);
|
||||
nest_levels = Z_LVAL(op_array->literals[opline->op2.constant]);
|
||||
if ((array_offset = opline->op1.opline_num) != -1) {
|
||||
do {
|
||||
jmp_to = &op_array->brk_cont_array[array_offset];
|
||||
@@ -690,9 +661,9 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
case ZEND_GOTO:
|
||||
if (Z_TYPE(op_array->literals[opline->op2.constant].constant) != IS_LONG) {
|
||||
if (Z_TYPE(op_array->literals[opline->op2.constant]) != IS_LONG) {
|
||||
zend_uint num = opline->op2.constant;
|
||||
opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
|
||||
opline->op2.zv = &op_array->literals[opline->op2.constant];
|
||||
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
|
||||
opline->op2.constant = num;
|
||||
}
|
||||
@@ -716,7 +687,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 (!ZEND_USER_CODE(op_array->type)) {
|
||||
return 0;
|
||||
}
|
||||
if (op_array->has_finally_block) {
|
||||
@@ -730,7 +701,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
}
|
||||
|
||||
if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) {
|
||||
op_array->vars = (zend_compiled_variable *) erealloc(op_array->vars, sizeof(zend_compiled_variable)*op_array->last_var);
|
||||
op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
|
||||
CG(context).vars_size = op_array->last_var;
|
||||
}
|
||||
if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) {
|
||||
@@ -738,20 +709,30 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
CG(context).opcodes_size = op_array->last;
|
||||
}
|
||||
if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) {
|
||||
op_array->literals = (zend_literal*)erealloc(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
|
||||
op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
|
||||
CG(context).literals_size = op_array->last_literal;
|
||||
}
|
||||
|
||||
opline = op_array->opcodes;
|
||||
end = opline + op_array->last;
|
||||
while (opline < end) {
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
|
||||
opline->op1.zv = &op_array->literals[opline->op1.constant];
|
||||
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
opline->op1.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op1.var);
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
|
||||
opline->op2.zv = &op_array->literals[opline->op2.constant];
|
||||
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
opline->op2.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op2.var);
|
||||
}
|
||||
if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
opline->result.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->result.var);
|
||||
}
|
||||
switch (opline->opcode) {
|
||||
case ZEND_DECLARE_INHERITED_CLASS:
|
||||
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
|
||||
opline->extended_value = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->extended_value);
|
||||
break;
|
||||
case ZEND_GOTO:
|
||||
if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
|
||||
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
|
||||
@@ -761,12 +742,19 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
case ZEND_FAST_CALL:
|
||||
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
|
||||
break;
|
||||
case ZEND_JMPZNZ:
|
||||
/* absolute index to relative offset */
|
||||
opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline;
|
||||
/* break omitted intentionally */
|
||||
case ZEND_JMPZ:
|
||||
case ZEND_JMPNZ:
|
||||
case ZEND_JMPZ_EX:
|
||||
case ZEND_JMPNZ_EX:
|
||||
case ZEND_JMP_SET:
|
||||
case ZEND_JMP_SET_VAR:
|
||||
case ZEND_NEW:
|
||||
case ZEND_FE_RESET:
|
||||
case ZEND_FE_FETCH:
|
||||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
|
||||
break;
|
||||
case ZEND_RETURN:
|
||||
@@ -789,11 +777,16 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pass_two_wrapper(zval *el TSRMLS_DC)
|
||||
{
|
||||
return pass_two((zend_op_array *) Z_PTR_P(el) TSRMLS_CC);
|
||||
}
|
||||
|
||||
int print_class(zend_class_entry *class_entry TSRMLS_DC)
|
||||
{
|
||||
printf("Class %s:\n", class_entry->name);
|
||||
zend_hash_apply(&class_entry->function_table, (apply_func_t) pass_two TSRMLS_CC);
|
||||
printf("End of class %s.\n\n", class_entry->name);
|
||||
printf("Class %s:\n", class_entry->name->val);
|
||||
zend_hash_apply(&class_entry->function_table, pass_two_wrapper TSRMLS_CC);
|
||||
printf("End of class %s.\n\n", class_entry->name->val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+645
-481
File diff suppressed because it is too large
Load Diff
+236
-167
@@ -270,6 +270,8 @@ static inline zend_uchar is_numeric_string(const char *str, int length, long *lv
|
||||
return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
|
||||
}
|
||||
|
||||
ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval);
|
||||
|
||||
static inline const char *
|
||||
zend_memnstr(const char *haystack, const char *needle, int needle_len, char *end)
|
||||
{
|
||||
@@ -337,10 +339,29 @@ ZEND_API void convert_to_object(zval *op);
|
||||
ZEND_API void multi_convert_to_long_ex(int argc, ...);
|
||||
ZEND_API void multi_convert_to_double_ex(int argc, ...);
|
||||
ZEND_API void multi_convert_to_string_ex(int argc, ...);
|
||||
|
||||
ZEND_API long _zval_get_long_func(zval *op TSRMLS_DC);
|
||||
ZEND_API double _zval_get_double_func(zval *op TSRMLS_DC);
|
||||
ZEND_API zend_string *_zval_get_string_func(zval *op TSRMLS_DC);
|
||||
|
||||
static zend_always_inline long _zval_get_long(zval *op TSRMLS_DC) {
|
||||
return Z_TYPE_P(op) == IS_LONG ? Z_LVAL_P(op) : _zval_get_long_func(op TSRMLS_CC);
|
||||
}
|
||||
static zend_always_inline double _zval_get_double(zval *op TSRMLS_DC) {
|
||||
return Z_TYPE_P(op) == IS_DOUBLE ? Z_DVAL_P(op) : _zval_get_double_func(op TSRMLS_CC);
|
||||
}
|
||||
static zend_always_inline zend_string *_zval_get_string(zval *op TSRMLS_DC) {
|
||||
return Z_TYPE_P(op) == IS_STRING ? STR_COPY(Z_STR_P(op)) : _zval_get_string_func(op TSRMLS_CC);
|
||||
}
|
||||
|
||||
#define zval_get_long(op) _zval_get_long((op) TSRMLS_CC)
|
||||
#define zval_get_double(op) _zval_get_double((op) TSRMLS_CC)
|
||||
#define zval_get_string(op) _zval_get_string((op) TSRMLS_CC)
|
||||
|
||||
ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2);
|
||||
ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2);
|
||||
#define convert_to_cstring(op) if ((op)->type != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
|
||||
#define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
|
||||
#define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
|
||||
#define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
|
||||
|
||||
ZEND_API double zend_string_to_double(const char *number, zend_uint length);
|
||||
|
||||
@@ -366,6 +387,7 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint
|
||||
ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
|
||||
ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2);
|
||||
ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
|
||||
ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2);
|
||||
ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length);
|
||||
|
||||
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
|
||||
@@ -379,10 +401,10 @@ ZEND_API long zend_atol(const char *str, int str_len);
|
||||
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
|
||||
if (Z_TYPE_PP(ppzv)!=IS_##upper_type) { \
|
||||
SEPARATE_ZVAL_IF_NOT_REF(ppzv); \
|
||||
convert_to_##lower_type(*ppzv); \
|
||||
#define convert_to_ex_master(pzv, lower_type, upper_type) \
|
||||
if (Z_TYPE_P(pzv)!=upper_type) { \
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pzv); \
|
||||
convert_to_##lower_type(pzv); \
|
||||
}
|
||||
|
||||
#define convert_to_explicit_type(pzv, type) \
|
||||
@@ -397,7 +419,7 @@ END_EXTERN_C()
|
||||
case IS_DOUBLE: \
|
||||
convert_to_double(pzv); \
|
||||
break; \
|
||||
case IS_BOOL: \
|
||||
case _IS_BOOL: \
|
||||
convert_to_boolean(pzv); \
|
||||
break; \
|
||||
case IS_ARRAY: \
|
||||
@@ -415,81 +437,26 @@ END_EXTERN_C()
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define convert_to_explicit_type_ex(ppzv, str_type) \
|
||||
if (Z_TYPE_PP(ppzv) != str_type) { \
|
||||
SEPARATE_ZVAL_IF_NOT_REF(ppzv); \
|
||||
convert_to_explicit_type(*ppzv, str_type); \
|
||||
#define convert_to_explicit_type_ex(pzv, str_type) \
|
||||
if (Z_TYPE_P(pzv) != str_type) { \
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pzv); \
|
||||
convert_to_explicit_type(pzv, str_type); \
|
||||
}
|
||||
|
||||
#define convert_to_boolean_ex(ppzv) convert_to_ex_master(ppzv, boolean, BOOL)
|
||||
#define convert_to_long_ex(ppzv) convert_to_ex_master(ppzv, long, LONG)
|
||||
#define convert_to_double_ex(ppzv) convert_to_ex_master(ppzv, double, DOUBLE)
|
||||
#define convert_to_string_ex(ppzv) convert_to_ex_master(ppzv, string, STRING)
|
||||
#define convert_to_array_ex(ppzv) convert_to_ex_master(ppzv, array, ARRAY)
|
||||
#define convert_to_object_ex(ppzv) convert_to_ex_master(ppzv, object, OBJECT)
|
||||
#define convert_to_null_ex(ppzv) convert_to_ex_master(ppzv, null, NULL)
|
||||
#define convert_to_boolean_ex(pzv) convert_to_ex_master(pzv, boolean, _IS_BOOL)
|
||||
#define convert_to_long_ex(pzv) convert_to_ex_master(pzv, long, IS_LONG)
|
||||
#define convert_to_double_ex(pzv) convert_to_ex_master(pzv, double, IS_DOUBLE)
|
||||
#define convert_to_string_ex(pzv) convert_to_ex_master(pzv, string, IS_STRING)
|
||||
#define convert_to_array_ex(pzv) convert_to_ex_master(pzv, array, IS_ARRAY)
|
||||
#define convert_to_object_ex(pzv) convert_to_ex_master(pzv, object, IS_OBJECT)
|
||||
#define convert_to_null_ex(pzv) convert_to_ex_master(pzv, null, IS_NULL)
|
||||
|
||||
#define convert_scalar_to_number_ex(ppzv) \
|
||||
if (Z_TYPE_PP(ppzv)!=IS_LONG && Z_TYPE_PP(ppzv)!=IS_DOUBLE) { \
|
||||
if (!Z_ISREF_PP(ppzv)) { \
|
||||
SEPARATE_ZVAL(ppzv); \
|
||||
} \
|
||||
convert_scalar_to_number(*ppzv TSRMLS_CC); \
|
||||
#define convert_scalar_to_number_ex(pzv) \
|
||||
if (Z_TYPE_P(pzv)!=IS_LONG && Z_TYPE_P(pzv)!=IS_DOUBLE) { \
|
||||
SEPARATE_ZVAL_IF_NOT_REF(pzv); \
|
||||
convert_scalar_to_number(pzv TSRMLS_CC); \
|
||||
}
|
||||
|
||||
|
||||
#define Z_LVAL(zval) (zval).value.lval
|
||||
#define Z_BVAL(zval) ((zend_bool)(zval).value.lval)
|
||||
#define Z_DVAL(zval) (zval).value.dval
|
||||
#define Z_STRVAL(zval) (zval).value.str.val
|
||||
#define Z_STRLEN(zval) (zval).value.str.len
|
||||
#define Z_ARRVAL(zval) (zval).value.ht
|
||||
#define Z_AST(zval) (zval).value.ast
|
||||
#define Z_OBJVAL(zval) (zval).value.obj
|
||||
#define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle
|
||||
#define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers
|
||||
#define Z_OBJCE(zval) zend_get_class_entry(&(zval) TSRMLS_CC)
|
||||
#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
|
||||
#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
|
||||
#define Z_RESVAL(zval) (zval).value.lval
|
||||
#define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
|
||||
|
||||
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p)
|
||||
#define Z_BVAL_P(zval_p) Z_BVAL(*zval_p)
|
||||
#define Z_DVAL_P(zval_p) Z_DVAL(*zval_p)
|
||||
#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
|
||||
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
|
||||
#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
|
||||
#define Z_AST_P(zval_p) Z_AST(*zval_p)
|
||||
#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
|
||||
#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
|
||||
#define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p)
|
||||
#define Z_OBJVAL_P(zval_p) Z_OBJVAL(*zval_p)
|
||||
#define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p)
|
||||
#define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p)
|
||||
#define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h)
|
||||
#define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp)
|
||||
|
||||
#define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp)
|
||||
#define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp)
|
||||
#define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp)
|
||||
#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
|
||||
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
|
||||
#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
|
||||
#define Z_AST_PP(zval_p) Z_AST(**zval_p)
|
||||
#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
|
||||
#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
|
||||
#define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp)
|
||||
#define Z_OBJVAL_PP(zval_pp) Z_OBJVAL(**zval_pp)
|
||||
#define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
|
||||
#define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p)
|
||||
#define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h)
|
||||
#define Z_OBJDEBUG_PP(zval_pp,is_tmp) Z_OBJDEBUG(**zval_pp,is_tmp)
|
||||
|
||||
#define Z_TYPE(zval) (zval).type
|
||||
#define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
|
||||
#define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp)
|
||||
|
||||
#if HAVE_SETLOCALE && defined(ZEND_WIN32) && !defined(ZTS) && defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
/* This is performance improvement of tolower() on Windows and VC2005
|
||||
* Gives 10-18% on bench.php
|
||||
@@ -505,7 +472,7 @@ ZEND_API void zend_update_current_locale(void);
|
||||
|
||||
/* The offset in bytes between the value and type fields of a zval */
|
||||
#define ZVAL_OFFSETOF_TYPE \
|
||||
(offsetof(zval,type) - offsetof(zval,value))
|
||||
(offsetof(zval, u1.type_info) - offsetof(zval, value))
|
||||
|
||||
static zend_always_inline int fast_increment_function(zval *op1)
|
||||
{
|
||||
@@ -516,7 +483,7 @@ static zend_always_inline int fast_increment_function(zval *op1)
|
||||
"jno 0f\n\t"
|
||||
"movl $0x0, (%0)\n\t"
|
||||
"movl $0x41e00000, 0x4(%0)\n\t"
|
||||
"movb %1, %c2(%0)\n"
|
||||
"movl %1, %c2(%0)\n"
|
||||
"0:"
|
||||
:
|
||||
: "r"(&op1->value),
|
||||
@@ -529,7 +496,7 @@ static zend_always_inline int fast_increment_function(zval *op1)
|
||||
"jno 0f\n\t"
|
||||
"movl $0x0, (%0)\n\t"
|
||||
"movl $0x43e00000, 0x4(%0)\n\t"
|
||||
"movb %1, %c2(%0)\n"
|
||||
"movl %1, %c2(%0)\n"
|
||||
"0:"
|
||||
:
|
||||
: "r"(&op1->value),
|
||||
@@ -539,8 +506,7 @@ static zend_always_inline int fast_increment_function(zval *op1)
|
||||
#else
|
||||
if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
|
||||
/* switch to double */
|
||||
Z_DVAL_P(op1) = (double)LONG_MAX + 1.0;
|
||||
Z_TYPE_P(op1) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(op1, (double)LONG_MAX + 1.0);
|
||||
} else {
|
||||
Z_LVAL_P(op1)++;
|
||||
}
|
||||
@@ -559,7 +525,7 @@ static zend_always_inline int fast_decrement_function(zval *op1)
|
||||
"jno 0f\n\t"
|
||||
"movl $0x00200000, (%0)\n\t"
|
||||
"movl $0xc1e00000, 0x4(%0)\n\t"
|
||||
"movb %1,%c2(%0)\n"
|
||||
"movl %1,%c2(%0)\n"
|
||||
"0:"
|
||||
:
|
||||
: "r"(&op1->value),
|
||||
@@ -572,7 +538,7 @@ static zend_always_inline int fast_decrement_function(zval *op1)
|
||||
"jno 0f\n\t"
|
||||
"movl $0x00000000, (%0)\n\t"
|
||||
"movl $0xc3e00000, 0x4(%0)\n\t"
|
||||
"movb %1,%c2(%0)\n"
|
||||
"movl %1,%c2(%0)\n"
|
||||
"0:"
|
||||
:
|
||||
: "r"(&op1->value),
|
||||
@@ -582,8 +548,7 @@ static zend_always_inline int fast_decrement_function(zval *op1)
|
||||
#else
|
||||
if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
|
||||
/* switch to double */
|
||||
Z_DVAL_P(op1) = (double)LONG_MIN - 1.0;
|
||||
Z_TYPE_P(op1) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(op1, (double)LONG_MIN - 1.0);
|
||||
} else {
|
||||
Z_LVAL_P(op1)--;
|
||||
}
|
||||
@@ -603,13 +568,13 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
|
||||
"addl (%2), %%eax\n\t"
|
||||
"jo 0f\n\t"
|
||||
"movl %%eax, (%0)\n\t"
|
||||
"movb %3, %c5(%0)\n\t"
|
||||
"movl %3, %c5(%0)\n\t"
|
||||
"jmp 1f\n"
|
||||
"0:\n\t"
|
||||
"fildl (%1)\n\t"
|
||||
"fildl (%2)\n\t"
|
||||
"faddp %%st, %%st(1)\n\t"
|
||||
"movb %4, %c5(%0)\n\t"
|
||||
"movl %4, %c5(%0)\n\t"
|
||||
"fstpl (%0)\n"
|
||||
"1:"
|
||||
:
|
||||
@@ -626,13 +591,13 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
|
||||
"addq (%2), %%rax\n\t"
|
||||
"jo 0f\n\t"
|
||||
"movq %%rax, (%0)\n\t"
|
||||
"movb %3, %c5(%0)\n\t"
|
||||
"movl %3, %c5(%0)\n\t"
|
||||
"jmp 1f\n"
|
||||
"0:\n\t"
|
||||
"fildq (%1)\n\t"
|
||||
"fildq (%2)\n\t"
|
||||
"faddp %%st, %%st(1)\n\t"
|
||||
"movb %4, %c5(%0)\n\t"
|
||||
"movl %4, %c5(%0)\n\t"
|
||||
"fstpl (%0)\n"
|
||||
"1:"
|
||||
:
|
||||
@@ -652,27 +617,22 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
|
||||
|
||||
if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
|
||||
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
|
||||
Z_DVAL_P(result) = (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
|
||||
} else {
|
||||
Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_LONG;
|
||||
ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2));
|
||||
}
|
||||
#endif
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) + Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2));
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -689,7 +649,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
|
||||
"subl (%2), %%eax\n\t"
|
||||
"jo 0f\n\t"
|
||||
"movl %%eax, (%0)\n\t"
|
||||
"movb %3, %c5(%0)\n\t"
|
||||
"movl %3, %c5(%0)\n\t"
|
||||
"jmp 1f\n"
|
||||
"0:\n\t"
|
||||
"fildl (%2)\n\t"
|
||||
@@ -699,7 +659,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
|
||||
#else
|
||||
"fsubp %%st, %%st(1)\n\t"
|
||||
#endif
|
||||
"movb %4, %c5(%0)\n\t"
|
||||
"movl %4, %c5(%0)\n\t"
|
||||
"fstpl (%0)\n"
|
||||
"1:"
|
||||
:
|
||||
@@ -716,7 +676,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
|
||||
"subq (%2), %%rax\n\t"
|
||||
"jo 0f\n\t"
|
||||
"movq %%rax, (%0)\n\t"
|
||||
"movb %3, %c5(%0)\n\t"
|
||||
"movl %3, %c5(%0)\n\t"
|
||||
"jmp 1f\n"
|
||||
"0:\n\t"
|
||||
"fildq (%2)\n\t"
|
||||
@@ -726,7 +686,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
|
||||
#else
|
||||
"fsubp %%st, %%st(1)\n\t"
|
||||
#endif
|
||||
"movb %4, %c5(%0)\n\t"
|
||||
"movl %4, %c5(%0)\n\t"
|
||||
"fstpl (%0)\n"
|
||||
"1:"
|
||||
:
|
||||
@@ -738,30 +698,24 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
|
||||
"n"(ZVAL_OFFSETOF_TYPE)
|
||||
: "rax","cc");
|
||||
#else
|
||||
Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);
|
||||
ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
|
||||
|
||||
if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
|
||||
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
|
||||
Z_DVAL_P(result) = (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
} else {
|
||||
Z_TYPE_P(result) = IS_LONG;
|
||||
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
|
||||
}
|
||||
#endif
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2));
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -775,21 +729,18 @@ static zend_always_inline int fast_mul_function(zval *result, zval *op1, zval *o
|
||||
long overflow;
|
||||
|
||||
ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
|
||||
Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
|
||||
Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) * Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2));
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -803,53 +754,43 @@ static zend_always_inline int fast_div_function(zval *result, zval *op1, zval *o
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
|
||||
zend_error(E_WARNING, "Division by zero");
|
||||
Z_LVAL_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_BOOL;
|
||||
ZVAL_BOOL(result, 0);
|
||||
return FAILURE;
|
||||
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN)) {
|
||||
/* Prevent overflow error/crash */
|
||||
Z_DVAL_P(result) = (double) LONG_MIN / -1;
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
|
||||
} else if (EXPECTED(Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0)) {
|
||||
/* integer */
|
||||
Z_LVAL_P(result) = Z_LVAL_P(op1) / Z_LVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_LONG;
|
||||
ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
|
||||
} else {
|
||||
Z_DVAL_P(result) = ((double) Z_LVAL_P(op1)) / ((double)Z_LVAL_P(op2));
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / ((double)Z_LVAL_P(op2)));
|
||||
}
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
|
||||
zend_error(E_WARNING, "Division by zero");
|
||||
Z_LVAL_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_BOOL;
|
||||
ZVAL_BOOL(result, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) / Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) / Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE) && 0) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
|
||||
zend_error(E_WARNING, "Division by zero");
|
||||
Z_LVAL_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_BOOL;
|
||||
ZVAL_BOOL(result, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) / Z_DVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
|
||||
return SUCCESS;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
|
||||
zend_error(E_WARNING, "Division by zero");
|
||||
Z_LVAL_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_BOOL;
|
||||
ZVAL_BOOL(result, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
Z_DVAL_P(result) = Z_DVAL_P(op1) / ((double)Z_LVAL_P(op2));
|
||||
Z_TYPE_P(result) = IS_DOUBLE;
|
||||
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / ((double)Z_LVAL_P(op2)));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -863,24 +804,21 @@ static zend_always_inline int fast_mod_function(zval *result, zval *op1, zval *o
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
|
||||
zend_error(E_WARNING, "Division by zero");
|
||||
Z_LVAL_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_BOOL;
|
||||
ZVAL_BOOL(result, 0);
|
||||
return FAILURE;
|
||||
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
|
||||
/* Prevent overflow error/crash if op1==LONG_MIN */
|
||||
Z_LVAL_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_LONG;
|
||||
ZVAL_LONG(result, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
Z_LVAL_P(result) = Z_LVAL_P(op1) % Z_LVAL_P(op2);
|
||||
Z_TYPE_P(result) = IS_LONG;
|
||||
ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
return mod_function(result, op1, op2 TSRMLS_CC);
|
||||
}
|
||||
|
||||
static zend_always_inline int fast_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
static zend_always_inline int fast_equal_check_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
@@ -894,66 +832,173 @@ static zend_always_inline int fast_equal_function(zval *result, zval *op1, zval
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2));
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
return 1;
|
||||
} else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
|
||||
if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
|
||||
return 0;
|
||||
} else {
|
||||
return memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0;
|
||||
}
|
||||
} else {
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
return Z_LVAL_P(result) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
return Z_LVAL_P(result) == 0;
|
||||
}
|
||||
|
||||
static zend_always_inline int fast_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
static zend_always_inline void fast_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_LVAL_P(op1) != Z_LVAL_P(op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(op1) == Z_LVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
return ((double)Z_LVAL_P(op1)) != Z_DVAL_P(op2);
|
||||
ZVAL_BOOL(result, (double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
return Z_DVAL_P(op1) != Z_DVAL_P(op2);
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) == Z_DVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2));
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_TRUE(result);
|
||||
return;
|
||||
} else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
|
||||
if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
|
||||
ZVAL_FALSE(result);
|
||||
return;
|
||||
} else {
|
||||
ZVAL_BOOL(result, memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
return Z_LVAL_P(result) != 0;
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
|
||||
}
|
||||
|
||||
static zend_always_inline int fast_is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
static zend_always_inline void fast_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_LVAL_P(op1) < Z_LVAL_P(op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(op1) != Z_LVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
return ((double)Z_LVAL_P(op1)) < Z_DVAL_P(op2);
|
||||
ZVAL_BOOL(result, (double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
return Z_DVAL_P(op1) < Z_DVAL_P(op2);
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) != Z_DVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_DVAL_P(op1) < ((double)Z_LVAL_P(op2));
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_FALSE(result);
|
||||
return;
|
||||
} else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
|
||||
if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
|
||||
ZVAL_TRUE(result);
|
||||
return;
|
||||
} else {
|
||||
ZVAL_BOOL(result, memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) != 0);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
return Z_LVAL_P(result) < 0;
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
|
||||
}
|
||||
|
||||
static zend_always_inline int fast_is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
static zend_always_inline void fast_is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_LVAL_P(op1) <= Z_LVAL_P(op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(op1) < Z_LVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
return ((double)Z_LVAL_P(op1)) <= Z_DVAL_P(op2);
|
||||
ZVAL_BOOL(result, (double)Z_LVAL_P(op1) < Z_DVAL_P(op2));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
return Z_DVAL_P(op1) <= Z_DVAL_P(op2);
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) < Z_DVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_DVAL_P(op1) <= ((double)Z_LVAL_P(op2));
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) < ((double)Z_LVAL_P(op2)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
return Z_LVAL_P(result) <= 0;
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) < 0);
|
||||
}
|
||||
|
||||
static zend_always_inline void fast_is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
ZVAL_BOOL(result, Z_LVAL_P(op1) <= Z_LVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
ZVAL_BOOL(result, (double)Z_LVAL_P(op1) <= Z_DVAL_P(op2));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) <= Z_DVAL_P(op2));
|
||||
return;
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) <= ((double)Z_LVAL_P(op2)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) <= 0);
|
||||
}
|
||||
|
||||
static zend_always_inline void fast_is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
|
||||
ZVAL_BOOL(result, 0);
|
||||
return;
|
||||
}
|
||||
is_identical_function(result, op1, op2 TSRMLS_CC);
|
||||
}
|
||||
|
||||
static zend_always_inline void fast_is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
{
|
||||
if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
|
||||
ZVAL_BOOL(result, 1);
|
||||
return;
|
||||
}
|
||||
is_identical_function(result, op1, op2 TSRMLS_CC);
|
||||
ZVAL_BOOL(result, Z_TYPE_P(result) != IS_TRUE);
|
||||
}
|
||||
|
||||
#define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode) \
|
||||
@@ -974,6 +1019,30 @@ static zend_always_inline int fast_is_smaller_or_equal_function(zval *result, zv
|
||||
return SUCCESS; \
|
||||
}
|
||||
|
||||
/* input: buf points to the END of the buffer */
|
||||
#define _zend_print_unsigned_to_buf(buf, num, vartype, result) do { \
|
||||
char *__p = (buf); \
|
||||
vartype __num = (num); \
|
||||
*__p = '\0'; \
|
||||
do { \
|
||||
*--__p = (char) (__num % 10) + '0'; \
|
||||
__num /= 10; \
|
||||
} while (__num > 0); \
|
||||
result = __p; \
|
||||
} while (0)
|
||||
|
||||
/* buf points to the END of the buffer */
|
||||
#define _zend_print_signed_to_buf(buf, num, vartype, result) do { \
|
||||
if (num < 0) { \
|
||||
_zend_print_unsigned_to_buf((buf), -(vartype)(num), vartype, (result)); \
|
||||
*--(result) = '-'; \
|
||||
} else { \
|
||||
_zend_print_unsigned_to_buf((buf), (num), vartype, (result)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ZEND_API zend_string *zend_long_to_str(long num);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
+42
-38
@@ -22,80 +22,66 @@
|
||||
#include "zend.h"
|
||||
#include "zend_stack.h"
|
||||
|
||||
ZEND_API int zend_stack_init(zend_stack *stack)
|
||||
#define ZEND_STACK_ELEMENT(stack, n) ((void *)((char *) (stack)->elements + (stack)->size * (n)))
|
||||
|
||||
ZEND_API int zend_stack_init(zend_stack *stack, int size)
|
||||
{
|
||||
stack->size = size;
|
||||
stack->top = 0;
|
||||
stack->max = 0;
|
||||
stack->elements = NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
ZEND_API int zend_stack_push(zend_stack *stack, const void *element, int size)
|
||||
ZEND_API int zend_stack_push(zend_stack *stack, const void *element)
|
||||
{
|
||||
if (stack->top >= stack->max) { /* we need to allocate more memory */
|
||||
stack->elements = (void **) erealloc(stack->elements,
|
||||
(sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)));
|
||||
if (!stack->elements) {
|
||||
return FAILURE;
|
||||
}
|
||||
/* We need to allocate more memory */
|
||||
if (stack->top >= stack->max) {
|
||||
stack->max += STACK_BLOCK_SIZE;
|
||||
stack->elements = safe_erealloc(stack->elements, stack->size, stack->max, 0);
|
||||
}
|
||||
stack->elements[stack->top] = (void *) emalloc(size);
|
||||
memcpy(stack->elements[stack->top], element, size);
|
||||
memcpy(ZEND_STACK_ELEMENT(stack, stack->top), element, stack->size);
|
||||
return stack->top++;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_stack_top(const zend_stack *stack, void **element)
|
||||
ZEND_API void *zend_stack_top(const zend_stack *stack)
|
||||
{
|
||||
if (stack->top > 0) {
|
||||
*element = stack->elements[stack->top - 1];
|
||||
return SUCCESS;
|
||||
return ZEND_STACK_ELEMENT(stack, stack->top - 1);
|
||||
} else {
|
||||
*element = NULL;
|
||||
return FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_stack_del_top(zend_stack *stack)
|
||||
{
|
||||
if (stack->top > 0) {
|
||||
efree(stack->elements[--stack->top]);
|
||||
}
|
||||
--stack->top;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_stack_int_top(const zend_stack *stack)
|
||||
{
|
||||
int *e;
|
||||
|
||||
if (zend_stack_top(stack, (void **) &e) == FAILURE) {
|
||||
return FAILURE; /* this must be a negative number, since negative numbers can't be address numbers */
|
||||
} else {
|
||||
int *e = zend_stack_top(stack);
|
||||
if (e) {
|
||||
return *e;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_stack_is_empty(const zend_stack *stack)
|
||||
{
|
||||
if (stack->top == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return stack->top == 0;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_stack_destroy(zend_stack *stack)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (stack->elements) {
|
||||
for (i = 0; i < stack->top; i++) {
|
||||
efree(stack->elements[i]);
|
||||
}
|
||||
efree(stack->elements);
|
||||
stack->elements = NULL;
|
||||
}
|
||||
@@ -104,7 +90,7 @@ ZEND_API int zend_stack_destroy(zend_stack *stack)
|
||||
}
|
||||
|
||||
|
||||
ZEND_API void **zend_stack_base(const zend_stack *stack)
|
||||
ZEND_API void *zend_stack_base(const zend_stack *stack)
|
||||
{
|
||||
return stack->elements;
|
||||
}
|
||||
@@ -123,14 +109,14 @@ ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function
|
||||
switch (type) {
|
||||
case ZEND_STACK_APPLY_TOPDOWN:
|
||||
for (i=stack->top-1; i>=0; i--) {
|
||||
if (apply_function(stack->elements[i])) {
|
||||
if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_STACK_APPLY_BOTTOMUP:
|
||||
for (i=0; i<stack->top; i++) {
|
||||
if (apply_function(stack->elements[i])) {
|
||||
if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -146,14 +132,14 @@ ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*
|
||||
switch (type) {
|
||||
case ZEND_STACK_APPLY_TOPDOWN:
|
||||
for (i=stack->top-1; i>=0; i--) {
|
||||
if (apply_function(stack->elements[i], arg)) {
|
||||
if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_STACK_APPLY_BOTTOMUP:
|
||||
for (i=0; i<stack->top; i++) {
|
||||
if (apply_function(stack->elements[i], arg)) {
|
||||
if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -161,6 +147,24 @@ ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_stack_clean(zend_stack *stack, void (*func)(void *), zend_bool free_elements)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (func) {
|
||||
for (i = 0; i < stack->top; i++) {
|
||||
func(ZEND_STACK_ELEMENT(stack, i));
|
||||
}
|
||||
}
|
||||
if (free_elements) {
|
||||
if (stack->elements) {
|
||||
efree(stack->elements);
|
||||
stack->elements = NULL;
|
||||
}
|
||||
stack->top = stack->max = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
||||
+8
-7
@@ -23,25 +23,26 @@
|
||||
#define ZEND_STACK_H
|
||||
|
||||
typedef struct _zend_stack {
|
||||
int top, max;
|
||||
void **elements;
|
||||
int size, top, max;
|
||||
void *elements;
|
||||
} zend_stack;
|
||||
|
||||
|
||||
#define STACK_BLOCK_SIZE 64
|
||||
#define STACK_BLOCK_SIZE 16
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API int zend_stack_init(zend_stack *stack);
|
||||
ZEND_API int zend_stack_push(zend_stack *stack, const void *element, int size);
|
||||
ZEND_API int zend_stack_top(const zend_stack *stack, void **element);
|
||||
ZEND_API int zend_stack_init(zend_stack *stack, int size);
|
||||
ZEND_API int zend_stack_push(zend_stack *stack, const void *element);
|
||||
ZEND_API void *zend_stack_top(const zend_stack *stack);
|
||||
ZEND_API int zend_stack_del_top(zend_stack *stack);
|
||||
ZEND_API int zend_stack_int_top(const zend_stack *stack);
|
||||
ZEND_API int zend_stack_is_empty(const zend_stack *stack);
|
||||
ZEND_API int zend_stack_destroy(zend_stack *stack);
|
||||
ZEND_API void **zend_stack_base(const zend_stack *stack);
|
||||
ZEND_API void *zend_stack_base(const zend_stack *stack);
|
||||
ZEND_API int zend_stack_count(const zend_stack *stack);
|
||||
ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element));
|
||||
ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg);
|
||||
ZEND_API void zend_stack_clean(zend_stack *stack, void (*func)(void *), zend_bool free_elements);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_STACK_APPLY_TOPDOWN 1
|
||||
|
||||
+107
-135
@@ -21,49 +21,52 @@
|
||||
#include "zend.h"
|
||||
#include "zend_globals.h"
|
||||
|
||||
#ifndef ZEND_DEBUG_INTERNED_STRINGS
|
||||
# define ZEND_DEBUG_INTERNED_STRINGS 0
|
||||
#endif
|
||||
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
ZEND_API const char *(*zend_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
|
||||
ZEND_API zend_string *(*zend_new_interned_string)(zend_string *str TSRMLS_DC);
|
||||
ZEND_API void (*zend_interned_strings_snapshot)(TSRMLS_D);
|
||||
ZEND_API void (*zend_interned_strings_restore)(TSRMLS_D);
|
||||
|
||||
static const char *zend_new_interned_string_int(const char *str, int len, int free_src TSRMLS_DC);
|
||||
static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC);
|
||||
static void zend_interned_strings_snapshot_int(TSRMLS_D);
|
||||
static void zend_interned_strings_restore_int(TSRMLS_D);
|
||||
|
||||
ZEND_API zend_ulong zend_hash_func(const char *str, uint len)
|
||||
{
|
||||
return zend_inline_hash_func(str, len);
|
||||
}
|
||||
|
||||
static void _str_dtor(zval *zv)
|
||||
{
|
||||
zend_string *str = Z_STR_P(zv);
|
||||
GC_FLAGS(str) &= ~IS_STR_INTERNED;
|
||||
GC_REFCOUNT(str) = 1;
|
||||
}
|
||||
|
||||
void zend_interned_strings_init(TSRMLS_D)
|
||||
{
|
||||
zend_string *str;
|
||||
|
||||
#ifndef ZTS
|
||||
size_t size = 1024 * 1024;
|
||||
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
CG(interned_strings_start) = valloc(size);
|
||||
#else
|
||||
CG(interned_strings_start) = malloc(size);
|
||||
#endif
|
||||
|
||||
CG(interned_strings_top) = CG(interned_strings_start);
|
||||
CG(interned_strings_snapshot_top) = CG(interned_strings_start);
|
||||
CG(interned_strings_end) = CG(interned_strings_start) + size;
|
||||
|
||||
zend_hash_init(&CG(interned_strings), 0, NULL, NULL, 1);
|
||||
zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
|
||||
|
||||
CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
|
||||
CG(interned_strings).arBuckets = (Bucket **) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket *), CG(interned_strings).persistent);
|
||||
CG(interned_strings).arData = (Bucket*) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket), 1);
|
||||
CG(interned_strings).arHash = (zend_uint*) pecalloc(CG(interned_strings).nTableSize, sizeof(zend_uint), 1);
|
||||
memset(CG(interned_strings).arHash, INVALID_IDX, CG(interned_strings).nTableSize * sizeof(zend_uint));
|
||||
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
|
||||
/* interned empty string */
|
||||
str = STR_ALLOC(sizeof("")-1, 1);
|
||||
str->val[0] = '\000';
|
||||
CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC);
|
||||
#else
|
||||
str = STR_ALLOC(sizeof("")-1, 1);
|
||||
str->val[0] = '\000';
|
||||
STR_HASH_VAL(str);
|
||||
str->gc.u.v.flags |= IS_STR_INTERNED;
|
||||
CG(empty_string) = str;
|
||||
#endif
|
||||
|
||||
/* interned empty string */
|
||||
CG(interned_empty_string) = zend_new_interned_string_int("", sizeof(""), 0 TSRMLS_CC);
|
||||
#endif
|
||||
/* one char strings (the actual interned strings are going to be created by ext/opcache) */
|
||||
memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));
|
||||
|
||||
zend_new_interned_string = zend_new_interned_string_int;
|
||||
zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
|
||||
@@ -73,94 +76,50 @@ void zend_interned_strings_init(TSRMLS_D)
|
||||
void zend_interned_strings_dtor(TSRMLS_D)
|
||||
{
|
||||
#ifndef ZTS
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
|
||||
#endif
|
||||
free(CG(interned_strings).arBuckets);
|
||||
free(CG(interned_strings_start));
|
||||
zend_hash_destroy(&CG(interned_strings));
|
||||
#else
|
||||
free(CG(empty_string));
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *zend_new_interned_string_int(const char *arKey, int nKeyLength, int free_src TSRMLS_DC)
|
||||
static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC)
|
||||
{
|
||||
#ifndef ZTS
|
||||
ulong h;
|
||||
uint nIndex;
|
||||
uint idx;
|
||||
Bucket *p;
|
||||
|
||||
if (IS_INTERNED(arKey)) {
|
||||
return arKey;
|
||||
if (IS_INTERNED(str)) {
|
||||
return str;
|
||||
}
|
||||
|
||||
h = zend_inline_hash_func(arKey, nKeyLength);
|
||||
h = STR_HASH_VAL(str);
|
||||
nIndex = h & CG(interned_strings).nTableMask;
|
||||
p = CG(interned_strings).arBuckets[nIndex];
|
||||
while (p != NULL) {
|
||||
if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
|
||||
if (!memcmp(p->arKey, arKey, nKeyLength)) {
|
||||
if (free_src) {
|
||||
efree((void *)arKey);
|
||||
}
|
||||
return p->arKey;
|
||||
idx = CG(interned_strings).arHash[nIndex];
|
||||
while (idx != INVALID_IDX) {
|
||||
p = CG(interned_strings).arData + idx;
|
||||
if ((p->h == h) && (p->key->len == str->len)) {
|
||||
if (!memcmp(p->key->val, str->val, str->len)) {
|
||||
STR_RELEASE(str);
|
||||
return p->key;
|
||||
}
|
||||
}
|
||||
p = p->pNext;
|
||||
idx = Z_NEXT(p->val);
|
||||
}
|
||||
|
||||
if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
|
||||
CG(interned_strings_end)) {
|
||||
/* no memory */
|
||||
return arKey;
|
||||
}
|
||||
GC_REFCOUNT(str) = 1;
|
||||
GC_FLAGS(str) |= IS_STR_INTERNED;
|
||||
|
||||
p = (Bucket *) CG(interned_strings_top);
|
||||
CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
|
||||
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE);
|
||||
#endif
|
||||
|
||||
p->arKey = (char*)(p+1);
|
||||
memcpy((char*)p->arKey, arKey, nKeyLength);
|
||||
if (free_src) {
|
||||
efree((void *)arKey);
|
||||
}
|
||||
p->nKeyLength = nKeyLength;
|
||||
p->h = h;
|
||||
p->pData = &p->pDataPtr;
|
||||
p->pDataPtr = p;
|
||||
|
||||
p->pNext = CG(interned_strings).arBuckets[nIndex];
|
||||
p->pLast = NULL;
|
||||
if (p->pNext) {
|
||||
p->pNext->pLast = p;
|
||||
}
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
p->pListLast = CG(interned_strings).pListTail;
|
||||
CG(interned_strings).pListTail = p;
|
||||
p->pListNext = NULL;
|
||||
if (p->pListLast != NULL) {
|
||||
p->pListLast->pListNext = p;
|
||||
}
|
||||
if (!CG(interned_strings).pListHead) {
|
||||
CG(interned_strings).pListHead = p;
|
||||
}
|
||||
|
||||
CG(interned_strings).arBuckets[nIndex] = p;
|
||||
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
|
||||
CG(interned_strings).nNumOfElements++;
|
||||
|
||||
if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) {
|
||||
if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
|
||||
if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */
|
||||
Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent);
|
||||
Bucket *d = (Bucket *) perealloc_recoverable(CG(interned_strings).arData, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket), 1);
|
||||
zend_uint *h = (zend_uint *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(zend_uint), 1);
|
||||
|
||||
if (t) {
|
||||
if (d && h) {
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
CG(interned_strings).arBuckets = t;
|
||||
CG(interned_strings).arData = d;
|
||||
CG(interned_strings).arHash = h;
|
||||
CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
|
||||
CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
|
||||
zend_hash_rehash(&CG(interned_strings));
|
||||
@@ -169,60 +128,73 @@ static const char *zend_new_interned_string_int(const char *arKey, int nKeyLengt
|
||||
}
|
||||
}
|
||||
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
|
||||
#endif
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
idx = CG(interned_strings).nNumUsed++;
|
||||
CG(interned_strings).nNumOfElements++;
|
||||
p = CG(interned_strings).arData + idx;
|
||||
p->h = h;
|
||||
p->key = str;
|
||||
Z_STR(p->val) = str;
|
||||
Z_TYPE_INFO(p->val) = IS_INTERNED_STRING_EX;
|
||||
nIndex = h & CG(interned_strings).nTableMask;
|
||||
Z_NEXT(p->val) = CG(interned_strings).arHash[nIndex];
|
||||
CG(interned_strings).arHash[nIndex] = idx;
|
||||
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
|
||||
return p->arKey;
|
||||
return str;
|
||||
#else
|
||||
return arKey;
|
||||
return str;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void zend_interned_strings_snapshot_int(TSRMLS_D)
|
||||
{
|
||||
CG(interned_strings_snapshot_top) = CG(interned_strings_top);
|
||||
#ifndef ZTS
|
||||
uint idx;
|
||||
Bucket *p;
|
||||
|
||||
idx = CG(interned_strings).nNumUsed;
|
||||
while (idx > 0) {
|
||||
idx--;
|
||||
p = CG(interned_strings).arData + idx;
|
||||
ZEND_ASSERT(GC_FLAGS(p->key) & IS_STR_PERSISTENT);
|
||||
GC_FLAGS(p->key) |= IS_STR_PERMANENT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void zend_interned_strings_restore_int(TSRMLS_D)
|
||||
{
|
||||
#ifndef ZTS
|
||||
uint nIndex;
|
||||
uint idx;
|
||||
Bucket *p;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
CG(interned_strings_top) = CG(interned_strings_snapshot_top);
|
||||
idx = CG(interned_strings).nNumUsed;
|
||||
while (idx > 0) {
|
||||
idx--;
|
||||
p = CG(interned_strings).arData + idx;
|
||||
if (GC_FLAGS(p->key) & IS_STR_PERMANENT) break;
|
||||
CG(interned_strings).nNumUsed--;
|
||||
CG(interned_strings).nNumOfElements--;
|
||||
|
||||
#ifndef ZTS
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
|
||||
#endif
|
||||
GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
|
||||
GC_REFCOUNT(p->key) = 1;
|
||||
STR_FREE(p->key);
|
||||
|
||||
for (i = 0; i < CG(interned_strings).nTableSize; i++) {
|
||||
p = CG(interned_strings).arBuckets[i];
|
||||
while (p && p->arKey > CG(interned_strings_top)) {
|
||||
CG(interned_strings).nNumOfElements--;
|
||||
if (p->pListLast != NULL) {
|
||||
p->pListLast->pListNext = p->pListNext;
|
||||
} else {
|
||||
CG(interned_strings).pListHead = p->pListNext;
|
||||
}
|
||||
if (p->pListNext != NULL) {
|
||||
p->pListNext->pListLast = p->pListLast;
|
||||
} else {
|
||||
CG(interned_strings).pListTail = p->pListLast;
|
||||
}
|
||||
p = p->pNext;
|
||||
}
|
||||
if (p) {
|
||||
p->pLast = NULL;
|
||||
}
|
||||
CG(interned_strings).arBuckets[i] = p;
|
||||
}
|
||||
|
||||
#if ZEND_DEBUG_INTERNED_STRINGS
|
||||
mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
|
||||
#endif
|
||||
nIndex = p->h & CG(interned_strings).nTableMask;
|
||||
if (CG(interned_strings).arHash[nIndex] == idx) {
|
||||
CG(interned_strings).arHash[nIndex] = Z_NEXT(p->val);
|
||||
} else {
|
||||
uint prev = CG(interned_strings).arHash[nIndex];
|
||||
while (Z_NEXT(CG(interned_strings).arData[prev].val) != idx) {
|
||||
prev = Z_NEXT(CG(interned_strings).arData[prev].val);
|
||||
}
|
||||
Z_NEXT(CG(interned_strings).arData[prev].val) = Z_NEXT(p->val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+243
-46
@@ -24,70 +24,267 @@
|
||||
#include "zend.h"
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API extern const char *(*zend_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
|
||||
|
||||
ZEND_API extern zend_string *(*zend_new_interned_string)(zend_string *str TSRMLS_DC);
|
||||
ZEND_API extern void (*zend_interned_strings_snapshot)(TSRMLS_D);
|
||||
ZEND_API extern void (*zend_interned_strings_restore)(TSRMLS_D);
|
||||
|
||||
ZEND_API zend_ulong zend_hash_func(const char *str, uint len);
|
||||
void zend_interned_strings_init(TSRMLS_D);
|
||||
void zend_interned_strings_dtor(TSRMLS_D);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#ifndef ZTS
|
||||
#define IS_INTERNED(s) (GC_FLAGS(s) & IS_STR_INTERNED)
|
||||
|
||||
#define IS_INTERNED(s) \
|
||||
(((s) >= CG(interned_strings_start)) && ((s) < CG(interned_strings_end)))
|
||||
#define STR_HASH_VAL(s) zend_str_hash_val(s)
|
||||
#define STR_FORGET_HASH_VAL(s) zend_str_forget_hash_val(s)
|
||||
|
||||
#else
|
||||
#define STR_REFCOUNT(s) zend_str_refcount(s)
|
||||
#define STR_ADDREF(s) zend_str_addref(s)
|
||||
#define STR_DELREF(s) zend_str_delref(s)
|
||||
#define STR_ALLOC(len, persistent) zend_str_alloc(len, persistent)
|
||||
#define STR_SAFE_ALLOC(n, m, l, p) zend_str_safe_alloc(n, m, l, p)
|
||||
#define STR_INIT(str, len, persistent) zend_str_init(str, len, persistent)
|
||||
#define STR_COPY(s) zend_str_copy(s)
|
||||
#define STR_DUP(s, persistent) zend_str_dup(s, persistent)
|
||||
#define STR_REALLOC(s, len, persistent) zend_str_realloc(s, len, persistent)
|
||||
#define STR_SAFE_REALLOC(s, n, m, l, p) zend_str_safe_realloc(s, n, m, l, p)
|
||||
#define STR_FREE(s) zend_str_free(s)
|
||||
#define STR_RELEASE(s) zend_str_release(s)
|
||||
#define STR_EMPTY_ALLOC() CG(empty_string)
|
||||
|
||||
#define IS_INTERNED(s) \
|
||||
(0)
|
||||
#define _STR_HEADER_SIZE XtOffsetOf(zend_string, val)
|
||||
|
||||
#endif
|
||||
#define STR_ALLOCA_ALLOC(str, _len, use_heap) do { \
|
||||
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + (_len) + 1), (use_heap)); \
|
||||
GC_REFCOUNT(str) = 1; \
|
||||
(str)->h = 0; \
|
||||
(str)->len = (_len); \
|
||||
} while (0)
|
||||
#define STR_ALLOCA_INIT(str, s, len, use_heap) do { \
|
||||
STR_ALLOCA_ALLOC(str, len, use_heap); \
|
||||
memcpy((str)->val, (s), (len)); \
|
||||
(str)->val[(len)] = '\0'; \
|
||||
} while (0)
|
||||
|
||||
#define INTERNED_LEN(s) \
|
||||
(((Bucket*)(((char*)(s))-sizeof(Bucket)))->nKeyLength)
|
||||
#define STR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap)
|
||||
|
||||
#define INTERNED_HASH(s) \
|
||||
(((Bucket*)(((char*)(s))-sizeof(Bucket)))->h)
|
||||
|
||||
#define str_efree(s) do { \
|
||||
if (!IS_INTERNED(s)) { \
|
||||
efree((char*)s); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define str_efree_rel(s) do { \
|
||||
if (!IS_INTERNED(s)) { \
|
||||
efree_rel((char *)s); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define str_free(s) do { \
|
||||
if (!IS_INTERNED(s)) { \
|
||||
free((char*)s); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define str_erealloc(str, new_len) \
|
||||
(IS_INTERNED(str) \
|
||||
? _str_erealloc(str, new_len, INTERNED_LEN(str)) \
|
||||
: erealloc(str, new_len))
|
||||
|
||||
static inline char *_str_erealloc(char *str, size_t new_len, size_t old_len) {
|
||||
char *buf = (char *) emalloc(new_len);
|
||||
memcpy(buf, str, old_len);
|
||||
return buf;
|
||||
static zend_always_inline zend_ulong zend_str_hash_val(zend_string *s)
|
||||
{
|
||||
if (!s->h) {
|
||||
s->h = zend_hash_func(s->val, s->len);
|
||||
}
|
||||
return s->h;
|
||||
}
|
||||
|
||||
#define str_estrndup(str, len) \
|
||||
(IS_INTERNED(str) ? (str) : estrndup((str), (len)))
|
||||
static zend_always_inline void zend_str_forget_hash_val(zend_string *s)
|
||||
{
|
||||
s->h = 0;
|
||||
}
|
||||
|
||||
#define str_strndup(str, len) \
|
||||
(IS_INTERNED(str) ? (str) : zend_strndup((str), (len)));
|
||||
static zend_always_inline zend_uint zend_str_refcount(zend_string *s)
|
||||
{
|
||||
if (!IS_INTERNED(s)) {
|
||||
return GC_REFCOUNT(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define str_hash(str, len) \
|
||||
(IS_INTERNED(str) ? INTERNED_HASH(str) : zend_hash_func((str), (len)+1))
|
||||
static zend_always_inline zend_uint zend_str_addref(zend_string *s)
|
||||
{
|
||||
if (!IS_INTERNED(s)) {
|
||||
return ++GC_REFCOUNT(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_uint zend_str_delref(zend_string *s)
|
||||
{
|
||||
if (!IS_INTERNED(s)) {
|
||||
return --GC_REFCOUNT(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)
|
||||
{
|
||||
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
|
||||
|
||||
GC_REFCOUNT(ret) = 1;
|
||||
#if 1
|
||||
/* optimized single assignment */
|
||||
GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
|
||||
#else
|
||||
GC_TYPE(ret) = IS_STRING;
|
||||
GC_FLAGS(ret) = (persistent ? IS_STR_PERSISTENT : 0);
|
||||
GC_INFO(ret) = 0;
|
||||
#endif
|
||||
ret->h = 0;
|
||||
ret->len = len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_safe_alloc(size_t n, size_t m, size_t l, int persistent)
|
||||
{
|
||||
zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
|
||||
|
||||
GC_REFCOUNT(ret) = 1;
|
||||
#if 1
|
||||
/* optimized single assignment */
|
||||
GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
|
||||
#else
|
||||
GC_TYPE(ret) = IS_STRING;
|
||||
GC_FLAGS(ret) = (persistent ? IS_STR_PERSISTENT : 0);
|
||||
GC_INFO(ret) = 0;
|
||||
#endif
|
||||
ret->h = 0;
|
||||
ret->len = (n * m) + l;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_init(const char *str, int len, int persistent)
|
||||
{
|
||||
zend_string *ret = STR_ALLOC(len, persistent);
|
||||
|
||||
memcpy(ret->val, str, len);
|
||||
ret->val[len] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_copy(zend_string *s)
|
||||
{
|
||||
if (!IS_INTERNED(s)) {
|
||||
STR_ADDREF(s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_dup(zend_string *s, int persistent)
|
||||
{
|
||||
if (IS_INTERNED(s)) {
|
||||
return s;
|
||||
} else {
|
||||
return STR_INIT(s->val, s->len, persistent);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_realloc(zend_string *s, int len, int persistent)
|
||||
{
|
||||
zend_string *ret;
|
||||
|
||||
if (IS_INTERNED(s)) {
|
||||
ret = STR_ALLOC(len, persistent);
|
||||
memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
|
||||
} else if (EXPECTED(STR_REFCOUNT(s) == 1)) {
|
||||
ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
|
||||
ret->len = len;
|
||||
STR_FORGET_HASH_VAL(ret);
|
||||
} else {
|
||||
ret = STR_ALLOC(len, persistent);
|
||||
memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
|
||||
STR_DELREF(s);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_string *zend_str_safe_realloc(zend_string *s, size_t n, size_t m, size_t l, int persistent)
|
||||
{
|
||||
zend_string *ret;
|
||||
|
||||
if (IS_INTERNED(s)) {
|
||||
ret = STR_SAFE_ALLOC(n, m, l, persistent);
|
||||
memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
|
||||
} else if (STR_REFCOUNT(s) == 1) {
|
||||
ret = (zend_string *)safe_perealloc(s, n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
|
||||
ret->len = (n * m) + l;
|
||||
STR_FORGET_HASH_VAL(ret);
|
||||
} else {
|
||||
ret = STR_SAFE_ALLOC(n, m, l, persistent);
|
||||
memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
|
||||
STR_DELREF(s);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_str_free(zend_string *s)
|
||||
{
|
||||
if (!IS_INTERNED(s)) {
|
||||
ZEND_ASSERT(STR_REFCOUNT(s) <= 1);
|
||||
pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_str_release(zend_string *s)
|
||||
{
|
||||
if (!IS_INTERNED(s)) {
|
||||
if (STR_DELREF(s) == 0) {
|
||||
pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
|
||||
*
|
||||
* This is Daniel J. Bernstein's popular `times 33' hash function as
|
||||
* posted by him years ago on comp.lang.c. It basically uses a function
|
||||
* like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best
|
||||
* known hash functions for strings. Because it is both computed very
|
||||
* fast and distributes very well.
|
||||
*
|
||||
* The magic of number 33, i.e. why it works better than many other
|
||||
* constants, prime or not, has never been adequately explained by
|
||||
* anyone. So I try an explanation: if one experimentally tests all
|
||||
* multipliers between 1 and 256 (as RSE did now) one detects that even
|
||||
* numbers are not useable at all. The remaining 128 odd numbers
|
||||
* (except for the number 1) work more or less all equally well. They
|
||||
* all distribute in an acceptable way and this way fill a hash table
|
||||
* with an average percent of approx. 86%.
|
||||
*
|
||||
* If one compares the Chi^2 values of the variants, the number 33 not
|
||||
* even has the best value. But the number 33 and a few other equally
|
||||
* good numbers like 17, 31, 63, 127 and 129 have nevertheless a great
|
||||
* advantage to the remaining numbers in the large set of possible
|
||||
* multipliers: their multiply operation can be replaced by a faster
|
||||
* operation based on just one shift plus either a single addition
|
||||
* or subtraction operation. And because a hash function has to both
|
||||
* distribute good _and_ has to be very fast to compute, those few
|
||||
* numbers should be preferred and seems to be the reason why Daniel J.
|
||||
* Bernstein also preferred it.
|
||||
*
|
||||
*
|
||||
* -- Ralf S. Engelschall <rse@engelschall.com>
|
||||
*/
|
||||
|
||||
static inline ulong zend_inline_hash_func(const char *str, uint len)
|
||||
{
|
||||
register ulong hash = 5381;
|
||||
|
||||
/* variant with the hash unrolled eight times */
|
||||
for (; len >= 8; len -= 8) {
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
hash = ((hash << 5) + hash) + *str++;
|
||||
}
|
||||
switch (len) {
|
||||
case 7: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
|
||||
case 6: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
|
||||
case 5: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
|
||||
case 4: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
|
||||
case 3: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
|
||||
case 2: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
|
||||
case 1: hash = ((hash << 5) + hash) + *str++; break;
|
||||
case 0: break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
#endif /* ZEND_STRING_H */
|
||||
|
||||
|
||||
+70
-75
@@ -59,24 +59,24 @@ static void end_write(TsHashTable *ht)
|
||||
}
|
||||
|
||||
/* delegates */
|
||||
ZEND_API int _zend_ts_hash_init(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
|
||||
ZEND_API void _zend_ts_hash_init(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
|
||||
{
|
||||
#ifdef ZTS
|
||||
ht->mx_reader = tsrm_mutex_alloc();
|
||||
ht->mx_writer = tsrm_mutex_alloc();
|
||||
ht->reader = 0;
|
||||
#endif
|
||||
return _zend_hash_init(TS_HASH(ht), nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
|
||||
_zend_hash_init(TS_HASH(ht), nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
|
||||
}
|
||||
|
||||
ZEND_API int _zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
|
||||
ZEND_API void _zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
|
||||
{
|
||||
#ifdef ZTS
|
||||
ht->mx_reader = tsrm_mutex_alloc();
|
||||
ht->mx_writer = tsrm_mutex_alloc();
|
||||
ht->reader = 0;
|
||||
#endif
|
||||
return _zend_hash_init_ex(TS_HASH(ht), nSize, pDestructor, persistent, bApplyProtection ZEND_FILE_LINE_RELAY_CC);
|
||||
_zend_hash_init_ex(TS_HASH(ht), nSize, pDestructor, persistent, bApplyProtection ZEND_FILE_LINE_RELAY_CC);
|
||||
}
|
||||
|
||||
ZEND_API void zend_ts_hash_destroy(TsHashTable *ht)
|
||||
@@ -99,45 +99,34 @@ ZEND_API void zend_ts_hash_clean(TsHashTable *ht)
|
||||
end_write(ht);
|
||||
}
|
||||
|
||||
ZEND_API int _zend_ts_hash_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
|
||||
ZEND_API zval *_zend_ts_hash_add_or_update(TsHashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC)
|
||||
{
|
||||
int retval;
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = _zend_hash_add_or_update(TS_HASH(ht), arKey, nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_RELAY_CC);
|
||||
retval = _zend_hash_add_or_update(TS_HASH(ht), key, pData, flag ZEND_FILE_LINE_RELAY_CC);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int _zend_ts_hash_quick_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
|
||||
ZEND_API zval *_zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC)
|
||||
{
|
||||
int retval;
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = _zend_hash_quick_add_or_update(TS_HASH(ht), arKey, nKeyLength, h, pData, nDataSize, pDest, flag ZEND_FILE_LINE_RELAY_CC);
|
||||
retval = _zend_hash_index_update_or_next_insert(TS_HASH(ht), h, pData, flag ZEND_FILE_LINE_RELAY_CC);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int _zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
|
||||
ZEND_API zval *zend_ts_hash_add_empty_element(TsHashTable *ht, zend_string *key)
|
||||
{
|
||||
int retval;
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = _zend_hash_index_update_or_next_insert(TS_HASH(ht), h, pData, nDataSize, pDest, flag ZEND_FILE_LINE_RELAY_CC);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_add_empty_element(TsHashTable *ht, char *arKey, uint nKeyLength)
|
||||
{
|
||||
int retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_add_empty_element(TS_HASH(ht), arKey, nKeyLength);
|
||||
retval = zend_hash_add_empty_element(TS_HASH(ht), key);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
@@ -187,67 +176,56 @@ ZEND_API void zend_ts_hash_reverse_apply(TsHashTable *ht, apply_func_t apply_fun
|
||||
end_write(ht);
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_del_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag)
|
||||
ZEND_API int zend_ts_hash_del(TsHashTable *ht, zend_string *key)
|
||||
{
|
||||
int retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_del_key_or_index(TS_HASH(ht), arKey, nKeyLength, h, flag);
|
||||
retval = zend_hash_del(TS_HASH(ht), key);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API ulong zend_ts_get_hash_value(TsHashTable *ht, char *arKey, uint nKeyLength)
|
||||
ZEND_API int zend_ts_hash_index_del(TsHashTable *ht, ulong h)
|
||||
{
|
||||
ulong retval;
|
||||
int retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_index_del(TS_HASH(ht), h);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API zval *zend_ts_hash_find(TsHashTable *ht, zend_string *key)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_get_hash_value(arKey, nKeyLength);
|
||||
retval = zend_hash_find(TS_HASH(ht), key);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_find(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData)
|
||||
ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, ulong h)
|
||||
{
|
||||
int retval;
|
||||
zval *retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, pData);
|
||||
retval = zend_hash_index_find(TS_HASH(ht), h);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_quick_find(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData)
|
||||
ZEND_API int zend_ts_hash_exists(TsHashTable *ht, zend_string *key)
|
||||
{
|
||||
int retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_hash_quick_find(TS_HASH(ht), arKey, nKeyLength, h, pData);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_index_find(TsHashTable *ht, ulong h, void **pData)
|
||||
{
|
||||
int retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_hash_index_find(TS_HASH(ht), h, pData);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_exists(TsHashTable *ht, char *arKey, uint nKeyLength)
|
||||
{
|
||||
int retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_hash_exists(TS_HASH(ht), arKey, nKeyLength);
|
||||
retval = zend_hash_exists(TS_HASH(ht), key);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
@@ -264,36 +242,36 @@ ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, ulong h)
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
|
||||
ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor)
|
||||
{
|
||||
begin_read(source);
|
||||
begin_write(target);
|
||||
zend_hash_copy(TS_HASH(target), TS_HASH(source), pCopyConstructor, tmp, size);
|
||||
zend_hash_copy(TS_HASH(target), TS_HASH(source), pCopyConstructor);
|
||||
end_write(target);
|
||||
end_read(source);
|
||||
}
|
||||
|
||||
ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
|
||||
ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor)
|
||||
{
|
||||
begin_read(source);
|
||||
zend_hash_copy(target, TS_HASH(source), pCopyConstructor, tmp, size);
|
||||
zend_hash_copy(target, TS_HASH(source), pCopyConstructor);
|
||||
end_read(source);
|
||||
}
|
||||
|
||||
ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite)
|
||||
ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite)
|
||||
{
|
||||
begin_read(source);
|
||||
begin_write(target);
|
||||
zend_hash_merge(TS_HASH(target), TS_HASH(source), pCopyConstructor, tmp, size, overwrite);
|
||||
zend_hash_merge(TS_HASH(target), TS_HASH(source), pCopyConstructor, overwrite);
|
||||
end_write(target);
|
||||
end_read(source);
|
||||
}
|
||||
|
||||
ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam)
|
||||
ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
|
||||
{
|
||||
begin_read(source);
|
||||
begin_write(target);
|
||||
zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, size, pMergeSource, pParam);
|
||||
zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, pMergeSource, pParam);
|
||||
end_write(target);
|
||||
end_read(source);
|
||||
}
|
||||
@@ -322,12 +300,12 @@ ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_fu
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC)
|
||||
ZEND_API zval *zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag TSRMLS_DC)
|
||||
{
|
||||
int retval;
|
||||
zval *retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_hash_minmax(TS_HASH(ht), compar, flag, pData TSRMLS_CC);
|
||||
retval = zend_hash_minmax(TS_HASH(ht), compar, flag TSRMLS_CC);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
@@ -355,21 +333,38 @@ ZEND_API int zend_ts_hash_rehash(TsHashTable *ht)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if ZEND_DEBUG
|
||||
void zend_ts_hash_display_pListTail(TsHashTable *ht)
|
||||
ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
begin_read(ht);
|
||||
zend_hash_display_pListTail(TS_HASH(ht));
|
||||
retval = zend_hash_str_find(TS_HASH(ht), key, len);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void zend_ts_hash_display(TsHashTable *ht)
|
||||
ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC)
|
||||
{
|
||||
begin_read(ht);
|
||||
zend_hash_display(TS_HASH(ht));
|
||||
end_read(ht);
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_str_update(TS_HASH(ht), key, len, pData);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_str_add(TS_HASH(ht), key, len, pData);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
+58
-37
@@ -37,8 +37,8 @@ BEGIN_EXTERN_C()
|
||||
#define TS_HASH(table) (&(table->hash))
|
||||
|
||||
/* startup/shutdown */
|
||||
ZEND_API int _zend_ts_hash_init(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
|
||||
ZEND_API int _zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
|
||||
ZEND_API void _zend_ts_hash_init(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
|
||||
ZEND_API void _zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
|
||||
ZEND_API void zend_ts_hash_destroy(TsHashTable *ht);
|
||||
ZEND_API void zend_ts_hash_clean(TsHashTable *ht);
|
||||
|
||||
@@ -49,25 +49,19 @@ ZEND_API void zend_ts_hash_clean(TsHashTable *ht);
|
||||
|
||||
|
||||
/* additions/updates/changes */
|
||||
ZEND_API int _zend_ts_hash_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_ts_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
|
||||
_zend_ts_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
|
||||
_zend_ts_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
|
||||
ZEND_API zval *_zend_ts_hash_add_or_update(TsHashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_ts_hash_update(ht, key, pData) \
|
||||
_zend_ts_hash_add_or_update(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_add(ht, key, pData) \
|
||||
_zend_ts_hash_add_or_update(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API int _zend_ts_hash_quick_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_ts_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
|
||||
_zend_ts_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
|
||||
_zend_ts_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
|
||||
ZEND_API zval *_zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_ts_hash_index_update(ht, h, pData) \
|
||||
_zend_ts_hash_index_update_or_next_insert(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_next_index_insert(ht, pData) \
|
||||
_zend_ts_hash_index_update_or_next_insert(ht, 0, pData, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API int _zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
|
||||
#define zend_ts_hash_index_update(ht, h, pData, nDataSize, pDest) \
|
||||
_zend_ts_hash_index_update_or_next_insert(ht, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_next_index_insert(ht, pData, nDataSize, pDest) \
|
||||
_zend_ts_hash_index_update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
|
||||
|
||||
ZEND_API int zend_ts_hash_add_empty_element(TsHashTable *ht, char *arKey, uint nKeyLength);
|
||||
ZEND_API zval* zend_ts_hash_add_empty_element(TsHashTable *ht, zend_string *key);
|
||||
|
||||
ZEND_API void zend_ts_hash_graceful_destroy(TsHashTable *ht);
|
||||
ZEND_API void zend_ts_hash_apply(TsHashTable *ht, apply_func_t apply_func TSRMLS_DC);
|
||||
@@ -78,44 +72,71 @@ ZEND_API void zend_ts_hash_reverse_apply(TsHashTable *ht, apply_func_t apply_fun
|
||||
|
||||
|
||||
/* Deletes */
|
||||
ZEND_API int zend_ts_hash_del_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag);
|
||||
#define zend_ts_hash_del(ht, arKey, nKeyLength) \
|
||||
zend_ts_hash_del_key_or_index(ht, arKey, nKeyLength, 0, HASH_DEL_KEY)
|
||||
#define zend_ts_hash_index_del(ht, h) \
|
||||
zend_ts_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX)
|
||||
|
||||
ZEND_API ulong zend_ts_get_hash_value(TsHashTable *ht, char *arKey, uint nKeyLength);
|
||||
ZEND_API int zend_ts_hash_del(TsHashTable *ht, zend_string *key);
|
||||
ZEND_API int zend_ts_hash_index_del(TsHashTable *ht, ulong h);
|
||||
|
||||
/* Data retreival */
|
||||
ZEND_API int zend_ts_hash_find(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData);
|
||||
ZEND_API int zend_ts_hash_quick_find(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData);
|
||||
ZEND_API int zend_ts_hash_index_find(TsHashTable *ht, ulong h, void **pData);
|
||||
ZEND_API zval *zend_ts_hash_find(TsHashTable *ht, zend_string *key);
|
||||
ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, ulong);
|
||||
|
||||
/* Misc */
|
||||
ZEND_API int zend_ts_hash_exists(TsHashTable *ht, char *arKey, uint nKeyLength);
|
||||
ZEND_API int zend_ts_hash_exists(TsHashTable *ht, zend_string *key);
|
||||
ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, ulong h);
|
||||
|
||||
/* Copying, merging and sorting */
|
||||
ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
|
||||
ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
|
||||
ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
|
||||
ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
|
||||
ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor);
|
||||
ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor);
|
||||
ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite);
|
||||
ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam);
|
||||
ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC);
|
||||
ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC);
|
||||
ZEND_API int zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC);
|
||||
ZEND_API zval *zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag TSRMLS_DC);
|
||||
|
||||
ZEND_API int zend_ts_hash_num_elements(TsHashTable *ht);
|
||||
|
||||
ZEND_API int zend_ts_hash_rehash(TsHashTable *ht);
|
||||
|
||||
ZEND_API ulong zend_ts_hash_func(char *arKey, uint nKeyLength);
|
||||
|
||||
#if ZEND_DEBUG
|
||||
/* debug */
|
||||
void zend_ts_hash_display_pListTail(TsHashTable *ht);
|
||||
void zend_ts_hash_display(TsHashTable *ht);
|
||||
#endif
|
||||
|
||||
ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len);
|
||||
ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
|
||||
#define zend_ts_hash_str_update(ht, key, len, pData) \
|
||||
_zend_ts_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_str_add(ht, key, len, pData) \
|
||||
_zend_ts_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
|
||||
static inline void *zend_ts_hash_str_find_ptr(TsHashTable *ht, const char *str, int len)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_ts_hash_str_find(ht, str, len);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_ts_hash_str_update_ptr(TsHashTable *ht, const char *str, int len, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_ts_hash_str_update(ht, str, len, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_ts_hash_str_add_ptr(TsHashTable *ht, const char *str, int len, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_ts_hash_str_add(ht, str, len, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_TS_INIT_SYMTABLE(ht) \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user