mirror of
https://github.com/bdnugget/php-src.git
synced 2026-11-08 17:50:50 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ebd7f36b1 | ||
|
|
3e7c52454f | ||
|
|
b0a5e5835a | ||
|
|
4e1b2bcc59 | ||
|
|
4490467c2e | ||
|
|
4e676c7b1c | ||
|
|
e0a7e0670a | ||
|
|
08daf96c92 |
No files matched your search
+3
-12
@@ -1,6 +1,6 @@
|
||||
version: "{branch}.build.{build}"
|
||||
|
||||
image: Visual Studio 2019
|
||||
image: Visual Studio 2017
|
||||
|
||||
branches:
|
||||
except:
|
||||
@@ -9,13 +9,6 @@ branches:
|
||||
|
||||
clone_depth: 64
|
||||
|
||||
skip_commits:
|
||||
files:
|
||||
- docs/*
|
||||
- NEWS
|
||||
- UPGRADING
|
||||
- UPGRADING.INTERNALS
|
||||
|
||||
cache:
|
||||
- c:\build-cache
|
||||
|
||||
@@ -23,8 +16,8 @@ environment:
|
||||
PHP_BUILD_CACHE_BASE_DIR: c:\build-cache
|
||||
PHP_BUILD_OBJ_DIR: c:\obj
|
||||
PHP_BUILD_CACHE_SDK_DIR: c:\build-cache\sdk
|
||||
PHP_BUILD_SDK_BRANCH: php-sdk-2.2.0
|
||||
PHP_BUILD_CRT: vs16
|
||||
PHP_BUILD_SDK_BRANCH: php-sdk-2.2.0beta3
|
||||
PHP_BUILD_CRT: vc15
|
||||
# ext and env setup for tests
|
||||
#MYSQL_TEST_PASSWD: Password12!
|
||||
#MYSQL_TEST_USER: root
|
||||
@@ -37,10 +30,8 @@ environment:
|
||||
matrix:
|
||||
- THREAD_SAFE: 0
|
||||
OPCACHE: 0
|
||||
PARALLEL: -j2
|
||||
- THREAD_SAFE: 1
|
||||
OPCACHE: 1
|
||||
PARALLEL: -j2
|
||||
INTRINSICS: AVX
|
||||
|
||||
services:
|
||||
|
||||
+19
-18
@@ -1,34 +1,35 @@
|
||||
# https://editorconfig.org/
|
||||
# http://editorconfig.org/
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
[*.{c,h,awk,w32,bat,mk,frag}]
|
||||
charset = utf-8
|
||||
tab_width = 4
|
||||
|
||||
[{*.{awk,bat,c,cpp,d,h,l,re,skl,w32,y},Makefile*}]
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{dtd,html,inc,php,phpt,rng,wsdl,xml,xsd,xsl}]
|
||||
[*.{php,phpt}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{ac,m4,sh,yml}]
|
||||
[*.{yml,m4,sh}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
max_line_length = 80
|
||||
|
||||
[COMMIT_EDITMSG]
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
max_line_length = 80
|
||||
|
||||
[*.patch]
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = true
|
||||
@@ -11,7 +11,9 @@ end
|
||||
|
||||
define ____executor_globals
|
||||
if basic_functions_module.zts
|
||||
set $tsrm_ls = _tsrm_ls_cache
|
||||
if !$tsrm_ls
|
||||
set $tsrm_ls = ts_resource_ex(0, 0)
|
||||
end
|
||||
set $eg = ((zend_executor_globals*) (*((void ***) $tsrm_ls))[executor_globals_id-1])
|
||||
set $cg = ((zend_compiler_globals*) (*((void ***) $tsrm_ls))[compiler_globals_id-1])
|
||||
set $eg_ptr = $eg
|
||||
@@ -163,7 +165,7 @@ define ____printzv_contents
|
||||
set $type = $zvalue->u1.v.type
|
||||
|
||||
# 15 == IS_INDIRECT
|
||||
if $type > 5 && $type < 12
|
||||
if $type > 5 && $type != 15
|
||||
printf "(refcount=%d) ", $zvalue->value.counted->gc.refcount
|
||||
end
|
||||
|
||||
@@ -213,8 +215,12 @@ define ____printzv_contents
|
||||
if ! $arg1
|
||||
if $handlers->get_properties == &zend_std_get_properties
|
||||
if $zobj->properties
|
||||
printf "\nProperties "
|
||||
set $ht = $zobj->properties
|
||||
else
|
||||
set $ht = &$zobj->ce->properties_info
|
||||
end
|
||||
printf "\nProperties "
|
||||
if $ht
|
||||
set $ind = $ind + 1
|
||||
____print_ht $ht 1
|
||||
set $ind = $ind - 1
|
||||
@@ -224,19 +230,7 @@ define ____printzv_contents
|
||||
set $i = $i - 1
|
||||
end
|
||||
else
|
||||
printf " {\n"
|
||||
set $ht = &$zobj->ce->properties_info
|
||||
set $k = 0
|
||||
set $num = $ht->nNumUsed
|
||||
while $k < $num
|
||||
set $p = (Bucket*)($ht->arData + $k)
|
||||
set $name = $p->key
|
||||
set $prop = (zend_property_info*)$p->val.value.ptr
|
||||
set $val = (zval*)((char*)$zobj + $prop->offset)
|
||||
printf "%s => ", $name->val
|
||||
printzv $val
|
||||
set $k = $k + 1
|
||||
end
|
||||
echo "not found"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -250,25 +244,34 @@ define ____printzv_contents
|
||||
____printzv &$zvalue->value.ref->val $arg1
|
||||
end
|
||||
if $type == 11
|
||||
printf "CONSTANT_AST"
|
||||
printf "const: %s", $zvalue->value.str->val
|
||||
end
|
||||
if $type == 12
|
||||
printf "CONSTANT_AST"
|
||||
end
|
||||
if $type == 13
|
||||
printf "_BOOL"
|
||||
end
|
||||
if $type == 14
|
||||
printf "CALLABLE"
|
||||
end
|
||||
if $type == 15
|
||||
printf "indirect: "
|
||||
____printzv $zvalue->value.zv $arg1
|
||||
end
|
||||
if $type == 13
|
||||
if $type == 17
|
||||
printf "pointer: %p", $zvalue->value.ptr
|
||||
end
|
||||
if $type == 15
|
||||
if $type == 18
|
||||
printf "ITERABLE"
|
||||
end
|
||||
if $type == 19
|
||||
printf "VOID"
|
||||
end
|
||||
if $type == 20
|
||||
printf "_ERROR"
|
||||
end
|
||||
if $type == 16
|
||||
printf "_BOOL"
|
||||
end
|
||||
if $type == 17
|
||||
printf "_NUMBER"
|
||||
end
|
||||
if $type > 17
|
||||
if $type == 16 || $type > 20
|
||||
printf "unknown type %d", $type
|
||||
end
|
||||
printf "\n"
|
||||
@@ -338,8 +341,7 @@ define ____print_ht
|
||||
end
|
||||
printf "[%d] ", $i
|
||||
if $p->key
|
||||
____print_str $p->key->val $p->key->len
|
||||
printf " => "
|
||||
printf "%s => ", $p->key->val
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
|
||||
+159
-19
@@ -1,19 +1,159 @@
|
||||
# Replace $Id$ strings with 40-character hexadecimal blob object name.
|
||||
/ext/ext_skel.php ident
|
||||
/ext/phar/phar/pharcommand.inc ident
|
||||
/ext/dba/libinifile/inifile.c ident
|
||||
/ext/dba/libflatfile/flatfile.c ident
|
||||
/ext/dba/libcdb/cdb_make.c ident
|
||||
/ext/dba/libcdb/cdb.c ident
|
||||
/run-tests.php ident
|
||||
|
||||
# A custom merge driver to avoid automatic merges. These are manually merged.
|
||||
# See https://wiki.php.net/vcs/gitfaq
|
||||
/NEWS merge=NEWS
|
||||
/UPGRADING merge=NEWS
|
||||
/UPGRADING.INTERNALS merge=NEWS
|
||||
|
||||
# Enable commit diffs for binary PHP test files. Some PHP test files include
|
||||
# special characters, such as ASCII control characters. Git recognizes these as
|
||||
# binary and wouldn't generate diffs.
|
||||
*.phpt diff
|
||||
ext/mysqlnd/mysqlnd.h ident
|
||||
ext/ext_skel.php ident
|
||||
ext/phar/phar/pharcommand.inc ident
|
||||
ext/dba/libinifile/inifile.c ident
|
||||
ext/dba/libflatfile/flatfile.c ident
|
||||
ext/dba/libcdb/cdb_make.c ident
|
||||
ext/dba/libcdb/cdb.c ident
|
||||
run-tests.php ident
|
||||
NEWS merge=NEWS
|
||||
UPGRADING merge=NEWS
|
||||
UPGRADING.INTERNALS merge=NEWS
|
||||
/ext/bz2/tests/with_strings.phpt -crlf
|
||||
/ext/dom/tests/bug40836.phpt -crlf
|
||||
/ext/dom/tests/domelement.phpt -crlf
|
||||
/ext/iconv/tests/iconv004.phpt -crlf
|
||||
/ext/iconv/tests/iconv_basic.phpt -crlf
|
||||
/ext/iconv/tests/iconv_strpos.phpt -crlf
|
||||
/ext/iconv/tests/iconv_strpos_variation2.phpt -crlf
|
||||
/ext/mbstring/tests/mb_strtoupper_error2.phpt -crlf
|
||||
/ext/phar/tests/delete_in_phar_confirm.phpt -crlf
|
||||
/ext/phar/tests/frontcontroller12.phpt -crlf
|
||||
/ext/phar/tests/security.phpt -crlf
|
||||
/ext/phar/tests/test_signaturealgos.phpt -crlf
|
||||
/ext/reflection/tests/ReflectionMethod_invokeArgs_basic.phpt -crlf
|
||||
/ext/reflection/tests/ReflectionProperty_getModifiers_basic.phpt -crlf
|
||||
/ext/spl/tests/dllist_007.phpt -crlf
|
||||
/ext/spl/tests/iterator_012.phpt -crlf
|
||||
/ext/spl/tests/SplArray_fromArray.phpt -crlf
|
||||
/ext/standard/tests/dir/scandir_variation3.phpt -crlf
|
||||
/ext/standard/tests/general_functions/escapeshellcmd-win32.phpt -crlf
|
||||
/ext/standard/tests/strings/bug26817.phpt -crlf
|
||||
/ext/standard/tests/strings/bug26973.phpt -crlf
|
||||
/ext/standard/tests/strings/bug27457.phpt -crlf
|
||||
/ext/standard/tests/strings/bug28386.phpt -crlf
|
||||
/ext/standard/tests/strings/bug37262.phpt -crlf
|
||||
/ext/standard/tests/strings/bug40637.phpt -crlf
|
||||
/ext/standard/tests/strings/bug40915.phpt -crlf
|
||||
/ext/standard/tests/strings/bug61374.phpt -crlf
|
||||
/ext/standard/tests/strings/chop_error.phpt -crlf
|
||||
/ext/standard/tests/strings/chop_variation2.phpt -crlf
|
||||
/ext/standard/tests/strings/chunk_split_variation10.phpt -crlf
|
||||
/ext/standard/tests/strings/chunk_split_variation8.phpt -crlf
|
||||
/ext/standard/tests/strings/count_chars_variation2.phpt -crlf
|
||||
/ext/standard/tests/strings/dirname_error.phpt -crlf
|
||||
/ext/standard/tests/strings/fprintf_variation_007_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/highlight_file.phpt -crlf
|
||||
/ext/standard/tests/strings/htmlentities03.phpt -crlf
|
||||
/ext/standard/tests/strings/htmlentities04.phpt -crlf
|
||||
/ext/standard/tests/strings/htmlentities08.phpt -crlf
|
||||
/ext/standard/tests/strings/htmlentities15.phpt -crlf
|
||||
/ext/standard/tests/strings/http_build_query.phpt -crlf
|
||||
/ext/standard/tests/strings/metaphone.phpt -crlf
|
||||
/ext/standard/tests/strings/ord_error.phpt -crlf
|
||||
/ext/standard/tests/strings/printf_basic2.phpt -crlf
|
||||
/ext/standard/tests/strings/printf_variation2.phpt -crlf
|
||||
/ext/standard/tests/strings/quoted_printable_decode_basic.phpt -crlf
|
||||
/ext/standard/tests/strings/rtrim.phpt -crlf
|
||||
/ext/standard/tests/strings/setlocale_variation1.phpt -crlf
|
||||
/ext/standard/tests/strings/sha1_basic.phpt -crlf
|
||||
/ext/standard/tests/strings/similar_text_basic.phpt -crlf
|
||||
/ext/standard/tests/strings/soundex.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_basic1.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_basic4.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_basic7.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation12.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation28.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation29.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation30.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation31.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation38.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation42.phpt -crlf
|
||||
/ext/standard/tests/strings/sprintf_variation6.phpt -crlf
|
||||
/ext/standard/tests/strings/sscanf_basic2.phpt -crlf
|
||||
/ext/standard/tests/strings/sscanf_basic3.phpt -crlf
|
||||
/ext/standard/tests/strings/str_getcsv_001.phpt -crlf
|
||||
/ext/standard/tests/strings/stripcslashes_basic.phpt -crlf
|
||||
/ext/standard/tests/strings/stripos_variation11.phpt -crlf
|
||||
/ext/standard/tests/strings/stripos_variation13.phpt -crlf
|
||||
/ext/standard/tests/strings/stripslashes_variation1.phpt -crlf
|
||||
/ext/standard/tests/strings/stripslashes_variation2.phpt -crlf
|
||||
/ext/standard/tests/strings/stristr_error.phpt -crlf
|
||||
/ext/standard/tests/strings/strnatcasecmp_basic.phpt -crlf
|
||||
/ext/standard/tests/strings/strncasecmp_variation6.phpt -crlf
|
||||
/ext/standard/tests/strings/strncasecmp_variation7.phpt -crlf
|
||||
/ext/standard/tests/strings/strncasecmp_variation8.phpt -crlf
|
||||
/ext/standard/tests/strings/strrchr_error.phpt -crlf
|
||||
/ext/standard/tests/strings/strrchr.phpt -crlf
|
||||
/ext/standard/tests/strings/strrchr_variation11.phpt -crlf
|
||||
/ext/standard/tests/strings/strrpos_error.phpt -crlf
|
||||
/ext/standard/tests/strings/strrpos_variation4.phpt -crlf
|
||||
/ext/standard/tests/strings/strrpos_variation8.phpt -crlf
|
||||
/ext/standard/tests/strings/strstr2.phpt -crlf
|
||||
/ext/standard/tests/strings/strtok_error.phpt -crlf
|
||||
/ext/standard/tests/strings/strtok_variation2.phpt -crlf
|
||||
/ext/standard/tests/strings/strtolower-win32.phpt -crlf
|
||||
/ext/standard/tests/strings/substr_compare.phpt -crlf
|
||||
/ext/standard/tests/strings/ucwords_variation1.phpt -crlf
|
||||
/ext/standard/tests/strings/unpack.phpt -crlf
|
||||
/ext/standard/tests/strings/vfprintf_basic7_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vfprintf_variation11_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vfprintf_variation12_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vfprintf_variation12.phpt -crlf
|
||||
/ext/standard/tests/strings/vfprintf_variation13_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vfprintf_variation7.phpt -crlf
|
||||
/ext/standard/tests/strings/vprintf_basic2.phpt -crlf
|
||||
/ext/standard/tests/strings/vprintf_basic7_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vprintf_variation10.phpt -crlf
|
||||
/ext/standard/tests/strings/vprintf_variation14_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vprintf_variation17.phpt -crlf
|
||||
/ext/standard/tests/strings/vprintf_variation4.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_basic4.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_basic8.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_variation12_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_variation13_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_variation15_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_variation17.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_variation4_64bit.phpt -crlf
|
||||
/ext/standard/tests/strings/vsprintf_variation7.phpt -crlf
|
||||
/ext/standard/tests/strings/wordwrap.phpt -crlf
|
||||
/ext/standard/tests/strings/wordwrap_variation5.phpt -crlf
|
||||
/ext/standard/tests/url/rawurldecode_variation_001.phpt -crlf
|
||||
/ext/tidy/tests/009.phpt -crlf
|
||||
/ext/tidy/tests/013.phpt -crlf
|
||||
/ext/tidy/tests/021.phpt -crlf
|
||||
/ext/tidy/tests/tidy_error.phpt -crlf
|
||||
/ext/tokenizer/tests/002.phpt -crlf
|
||||
/ext/tokenizer/tests/bug26463.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_error.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation11.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation12.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation13.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation14.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation15.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation18.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation19.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation1.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation2.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation3.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation5.phpt -crlf
|
||||
/ext/tokenizer/tests/token_get_all_variation8.phpt -crlf
|
||||
/ext/xml/tests/bug32001b.phpt -crlf
|
||||
/ext/xmlwriter/tests/OO_003.phpt -crlf
|
||||
/ext/xmlwriter/tests/xmlwriter_write_attribute_ns_error_001.phpt -crlf
|
||||
/ext/zlib/tests/008.phpt -crlf
|
||||
/ext/zlib/tests/gzopen_variation4.phpt -crlf
|
||||
/ext/zlib/tests/gzrewind_error.phpt -crlf
|
||||
/ext/zlib/tests/readgzfile_variation7.phpt -crlf
|
||||
/ext/zlib/tests/readgzfile_variation8.phpt -crlf
|
||||
/ext/zlib/tests/zlib_scheme_stat_basic.phpt -crlf
|
||||
/sapi/cli/tests/006.phpt -crlf
|
||||
/tests/run-test/test009.phpt -crlf
|
||||
/Zend/tests/012.phpt -crlf
|
||||
/Zend/tests/bug28072.phpt -crlf
|
||||
/Zend/tests/bug38624.phpt -crlf
|
||||
/Zend/tests/bug40784.phpt -crlf
|
||||
/Zend/tests/bug43053.phpt -crlf
|
||||
/Zend/tests/bug51176.phpt -crlf
|
||||
/Zend/tests/each_003.phpt -crlf
|
||||
/Zend/tests/errmsg_006.phpt -crlf
|
||||
+177
-252
@@ -1,223 +1,197 @@
|
||||
# These files are generated during building or development and are intentionally
|
||||
# untracked to ignore by Git. For other development environment specific files,
|
||||
# such as editor configuration, a good practice is to exclude them using the
|
||||
# .git/info/exclude in the cloned repository or a global .gitignore file.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Common files ignored across the repository
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Backup copies created by various editors or development tools
|
||||
# General ignores
|
||||
*~
|
||||
|
||||
# Patches downloaded to patch files or to apply open source contributions
|
||||
*.patch
|
||||
|
||||
# Swap files created by editors and tools to indicate a locked file
|
||||
*.swp
|
||||
|
||||
# Various temporary generated files
|
||||
*.tmp
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Generated by the PHP build system
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Archive library containing .o files, generated during build process
|
||||
*.a
|
||||
|
||||
# Libtool library files generated during build process
|
||||
.#*
|
||||
*.
|
||||
*.slo
|
||||
*.mk
|
||||
*.mem
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.la
|
||||
|
||||
# Directories created by Libtool for storing generated library files
|
||||
.libs/
|
||||
|
||||
# Library object files generated during build process
|
||||
*.lo
|
||||
|
||||
# Temporary library object files generated by compiler and libtool due to failure
|
||||
*.loT
|
||||
|
||||
# Standard object files generated during build process
|
||||
*.o
|
||||
|
||||
# Cache directories created by Autoconf tools
|
||||
autom4te.cache/
|
||||
|
||||
# Cache file(s) generated by Autoconf's configure when run as `configure -C`
|
||||
config.cache
|
||||
|
||||
# A log file(s) generated by Autoconf during *nix build system
|
||||
config.log
|
||||
|
||||
# Helper(s) generated by *nix build system to save the last configure command
|
||||
config.nice
|
||||
|
||||
# Generated by Autoconf's configure script for instantiating templates
|
||||
config.status
|
||||
|
||||
# Main *nix build system configuration script(s) generated by Autoconf
|
||||
configure
|
||||
|
||||
# Generated by `./configure` when test programs create temporary files
|
||||
confdefs.h
|
||||
conftest*
|
||||
|
||||
# Generated by configure scripts on all systems
|
||||
/main/internal_functions.c
|
||||
/main/internal_functions_cli.c
|
||||
|
||||
# The Libtool script(s) generated by the *nix build system
|
||||
libtool
|
||||
|
||||
# Makefile(s) generated from Makefile fragment templates by `./configure`
|
||||
*.a
|
||||
*.ncb
|
||||
*.opt
|
||||
*.plg
|
||||
*swp
|
||||
*.patch
|
||||
*.tgz
|
||||
*.tar.gz
|
||||
*.tar.bz2
|
||||
*.tar.xz
|
||||
*.tar.gz.asc
|
||||
*.tar.bz2.asc
|
||||
*.tar.xz.asc
|
||||
.FBCIndex
|
||||
.FBCLockFolder
|
||||
.libs
|
||||
phpt.*
|
||||
core
|
||||
dynlib.m4
|
||||
Makefile
|
||||
Makefile.fragments
|
||||
Makefile.objects
|
||||
|
||||
# Directories for shared object files and headers generated by `./configure`
|
||||
include/
|
||||
libs/
|
||||
modules/
|
||||
|
||||
# Used by build/gen_stub.php
|
||||
build/PHP-Parser-*
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configuration headers generated by the PHP build system
|
||||
# ------------------------------------------------------------------------------
|
||||
_libs
|
||||
acconfig.h
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
bsd_converted
|
||||
buildconf.stamp
|
||||
buildmk.stamp
|
||||
confdefs.h
|
||||
config.h
|
||||
config.guess
|
||||
config.cache
|
||||
config.h.in
|
||||
/ext/date/lib/timelib_config.h
|
||||
/main/build-defs.h
|
||||
/main/php_config.h.in
|
||||
/main/php_config.h
|
||||
/Zend/zend_config.h
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Manual (man 1 and 8) pages generated from templates for *nix alike systems
|
||||
# ------------------------------------------------------------------------------
|
||||
/ext/phar/phar.1
|
||||
/ext/phar/phar.phar.1
|
||||
/sapi/cgi/php-cgi.1
|
||||
/sapi/cli/php.1
|
||||
/sapi/fpm/php-fpm.1
|
||||
/sapi/fpm/php-fpm.8
|
||||
/sapi/phpdbg/phpdbg.1
|
||||
/scripts/man1/*.1
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# SAPIs specific ignores
|
||||
# ------------------------------------------------------------------------------
|
||||
/sapi/apache2handler/libphp.module
|
||||
/sapi/fpm/fpm/php-cgi
|
||||
/sapi/fpm/init.d.php-fpm
|
||||
/sapi/fpm/php-fpm.conf
|
||||
/sapi/fpm/php-fpm.service
|
||||
/sapi/fpm/status.html
|
||||
/sapi/fpm/www.conf
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Executable binaries and scripts generated during the build process
|
||||
# ------------------------------------------------------------------------------
|
||||
/ext/phar/phar.phar
|
||||
/ext/phar/phar.php
|
||||
/pear/install-pear-nozlib.phar
|
||||
/sapi/cgi/php-cgi
|
||||
/sapi/fpm/php-fpm
|
||||
/sapi/phpdbg/phpdbg
|
||||
/scripts/php-config
|
||||
/scripts/phpize
|
||||
config.log
|
||||
config.nice
|
||||
config.status
|
||||
config.sub
|
||||
config_vars.mk
|
||||
configuration-parser.c
|
||||
configuration-parser.h
|
||||
configuration-parser.output
|
||||
configuration-scanner.c
|
||||
configure
|
||||
conftest
|
||||
conftest.c
|
||||
debug.log
|
||||
diff
|
||||
generated_lists
|
||||
include
|
||||
install-sh
|
||||
internal_functions.c
|
||||
lcov_data
|
||||
lcov_html
|
||||
libs
|
||||
libtool
|
||||
meta_cc
|
||||
meta_ccld
|
||||
missing
|
||||
mkinstalldirs
|
||||
modules
|
||||
php
|
||||
php7.spec
|
||||
php_lcov.info
|
||||
php_test_results_*.txt
|
||||
php_version.h
|
||||
results.txt
|
||||
shlibtool
|
||||
stamp-h
|
||||
test.php3
|
||||
tmp-php.ini
|
||||
stamp-h.in
|
||||
scan_makefile_in.awk
|
||||
main/php_config.h
|
||||
main/php_config.h.in
|
||||
main/build-defs.h
|
||||
main/internal_functions_cli.c
|
||||
main/config.w32.h
|
||||
main/stamp-h1
|
||||
main/streams/build-defs.h
|
||||
main/streams/stamp-h1
|
||||
pear/install-pear-nozlib.phar
|
||||
pear/phpize
|
||||
pear/run-tests
|
||||
pear/php-config
|
||||
pear/scripts
|
||||
sapi/apache2handler/libphp7.module
|
||||
sapi/cgi/php-cgi
|
||||
sapi/cgi/php-cgi.1
|
||||
sapi/cli/php.1
|
||||
sapi/fpm/php-fpm
|
||||
sapi/fpm/php-fpm.1
|
||||
sapi/fpm/init.d.php-fpm
|
||||
sapi/fpm/php-fpm.conf
|
||||
sapi/fpm/fpm/php-cgi
|
||||
sapi/fpm/php-fpm.8
|
||||
sapi/fpm/php-fpm.service
|
||||
sapi/fpm/status.html
|
||||
sapi/fpm/www.conf
|
||||
sapi/phpdbg/phpdbg_parser.c
|
||||
sapi/phpdbg/phpdbg_parser.h
|
||||
sapi/phpdbg/phpdbg
|
||||
sapi/phpdbg/phpdbg.1
|
||||
sapi/phpdbg/build
|
||||
sapi/phpdbg/*.output
|
||||
scripts/php-config
|
||||
scripts/phpize
|
||||
scripts/man1/*.1
|
||||
TSRM/tsrm_config.h
|
||||
win32/*.suo
|
||||
win32/*.aps
|
||||
win32/*.positions
|
||||
win32/ext
|
||||
win32/phpts.def
|
||||
win32/wsyslog.h
|
||||
Zend/zend_config.h
|
||||
Zend/zend_dtrace_gen.h
|
||||
Zend/zend_dtrace_gen.hbak
|
||||
Zend/zend_ini_parser.c
|
||||
Zend/zend_ini_parser.h
|
||||
Zend/zend_ini_parser.output
|
||||
Zend/zend_language_parser.c
|
||||
Zend/zend_language_parser.h
|
||||
Zend/zend_language_parser.output
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Lexer files generated by re2c
|
||||
# ------------------------------------------------------------------------------
|
||||
/ext/json/json_scanner.c
|
||||
/ext/json/php_json_scanner_defs.h
|
||||
/ext/pdo/pdo_sql_parser.c
|
||||
/ext/phar/phar_path_check.c
|
||||
/ext/standard/url_scanner_ex.c
|
||||
/ext/standard/var_unserializer.c
|
||||
/sapi/phpdbg/phpdbg_lexer.c
|
||||
/Zend/zend_ini_scanner.c
|
||||
/Zend/zend_ini_scanner_defs.h
|
||||
/Zend/zend_language_scanner.c
|
||||
/Zend/zend_language_scanner_defs.h
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# PHP parser files generated by bison during the build process
|
||||
# ------------------------------------------------------------------------------
|
||||
/ext/json/json_parser.tab.h
|
||||
/ext/json/json_parser.tab.c
|
||||
/sapi/phpdbg/phpdbg_parser.c
|
||||
/sapi/phpdbg/phpdbg_parser.h
|
||||
/sapi/phpdbg/phpdbg_parser.output
|
||||
/Zend/zend_ini_parser.c
|
||||
/Zend/zend_ini_parser.h
|
||||
/Zend/zend_ini_parser.output
|
||||
/Zend/zend_language_parser.c
|
||||
/Zend/zend_language_parser.h
|
||||
/Zend/zend_language_parser.output
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Extensions files
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Miscellaneous extensions files
|
||||
/ext/opcache/jit/zend_jit_x86.c
|
||||
/ext/opcache/minilua
|
||||
|
||||
# Generated by `cd ext/name && phpize && ./configure`
|
||||
/ext/*/build/
|
||||
/ext/*/configure.ac
|
||||
/ext/*/run-tests.php
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Generated by Windows build system
|
||||
# ------------------------------------------------------------------------------
|
||||
# Extension specific ignores
|
||||
ext/*/configure.ac
|
||||
ext/*/ltmain.sh
|
||||
ext/*/libs.mk
|
||||
ext/*/build
|
||||
ext/*/scan_makefile_in.awk
|
||||
ext/*/Makefile.global
|
||||
ext/*/acinclude.m4
|
||||
ext/*/config.sub
|
||||
ext/date/lib/timelib_config.h
|
||||
ext/iconv/php_have_bsd_iconv.h
|
||||
ext/iconv/php_have_ibm_iconv.h
|
||||
ext/iconv/php_have_libiconv.h
|
||||
ext/iconv/php_php_iconv_h_path.h
|
||||
ext/iconv/php_have_glibc_iconv.h
|
||||
ext/iconv/php_php_iconv_impl.h
|
||||
ext/iconv/php_have_iconv.h
|
||||
ext/iconv/php_iconv_supports_errno.h
|
||||
ext/iconv/php_iconv_broken_ignore.h
|
||||
ext/iconv/php_iconv_aliased_libiconv.h
|
||||
ext/mbstring/oniguruma/oniguruma.h
|
||||
ext/oci8/tests/*.vglog
|
||||
ext/pdo/conftest*
|
||||
ext/pdo_firebird/conftest*
|
||||
ext/pdo_mysql/conftest*
|
||||
ext/pdo_oci/conftest*
|
||||
ext/pdo_odbc/tests/*.mdb
|
||||
ext/pdo_pgsql/conftest*
|
||||
ext/pdo_sqlite/conftest*
|
||||
ext/pdo_sqlite/sqlite3.h
|
||||
ext/phar/phar.phar
|
||||
ext/phar/phar.1
|
||||
ext/phar/phar.phar.1
|
||||
ext/phar/phar.php
|
||||
ext/reflection/xml
|
||||
ext/reflection/html
|
||||
ext/reflection/spl.chm
|
||||
ext/spl/examples/.htaccess
|
||||
ext/spl/examples/*.phps
|
||||
ext/sqlite3/tests/phpsql*
|
||||
|
||||
# ------------------------------------------------------------------------------ Windows
|
||||
# Generated by `/buildconf.bat`
|
||||
/configure.bat
|
||||
/configure.js
|
||||
|
||||
# Generated by `/configure.(bat|js)` (architecture dependent)
|
||||
# Generated by `/configure.(bat|js)` (architecture dependend)
|
||||
/config.nice.bat
|
||||
|
||||
# NTS debug build x86
|
||||
/Debug/
|
||||
|
||||
# ZTS debug build x86
|
||||
/Debug_TS/
|
||||
|
||||
# NTS build x86
|
||||
/Release/
|
||||
|
||||
# ZTS build x86
|
||||
/Release_TS/
|
||||
|
||||
# Generated by x64 compiler, includes Debug, Debug_TS, Release, Release_TS
|
||||
/x64/
|
||||
|
||||
# Miscellaneous files generated by Windows build system
|
||||
/main/config.w32.h
|
||||
/win32/build/deplister.exe
|
||||
/win32/build/deplister.obj
|
||||
/win32/*.aps
|
||||
/win32/*.positions
|
||||
/win32/*.suo
|
||||
/win32/ext
|
||||
/win32/syslog.reg
|
||||
/win32/wsyslog.h
|
||||
|
||||
# Standard object files generated by Visual Studio
|
||||
*.obj
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Tests
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Generated by `./run-tests.php` upon failure
|
||||
# ------------------------------------------------------------------------------ Tests
|
||||
# Generated by `/run-tests.php` upon failure
|
||||
**/tests/**/*.diff
|
||||
**/tests/**/*.out*
|
||||
**/tests/**/*.php
|
||||
@@ -225,61 +199,12 @@ php
|
||||
**/tests/**/*.log
|
||||
**/tests/**/*.sh
|
||||
|
||||
# Generated by some test cases
|
||||
# Used by some test cases.
|
||||
**/tests/**/*.db
|
||||
**/tests/**/*.txt
|
||||
**/tests/**/*.tmp
|
||||
|
||||
# Microsoft Access database created for passing to tests
|
||||
/ext/pdo_odbc/tests/*.mdb
|
||||
|
||||
# Files generated by `./run-tests.php -m` when checking for memory leaks
|
||||
**/tests/**/*.mem
|
||||
|
||||
# Test results generated by `./run-tests.php`
|
||||
php_test_results_*.txt
|
||||
|
||||
# Temporary test information generated by `./run-tests.php`
|
||||
/run-test-info.php
|
||||
|
||||
# Temporary POST data placeholder files generated by `./run-tests.php`
|
||||
phpt.*
|
||||
|
||||
# Temporary PHP INI configuration file(s) for tests, generated by `make test`
|
||||
tmp-php.ini
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Generated by GCC's gcov and LCOV via build/Makefile.gcov and gcov.php.net
|
||||
# ------------------------------------------------------------------------------
|
||||
*.gcda
|
||||
*.gcno
|
||||
/gcovr.xml
|
||||
/gcovr_html/
|
||||
/lcov_html/
|
||||
/php_lcov.info
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Archives generated during the PHP release process
|
||||
# ------------------------------------------------------------------------------
|
||||
/*.tar.gz
|
||||
/*.tar.bz2
|
||||
/*.tar.xz
|
||||
/*.tar.gz.asc
|
||||
/*.tar.bz2.asc
|
||||
/*.tar.xz.asc
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Generated by `./configure --enable-dtrace` for using DTrace framework
|
||||
# ------------------------------------------------------------------------------
|
||||
/ext/oci8/oci8_dtrace_gen.h
|
||||
/ext/oci8/oci8_dtrace_gen.h.bak
|
||||
/Zend/zend_dtrace_gen.h
|
||||
/Zend/zend_dtrace_gen.h.bak
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Special cases to invert previous ignore patterns
|
||||
# ------------------------------------------------------------------------------
|
||||
!/ext/bcmath/libbcmath/src/config.h
|
||||
!/ext/fileinfo/libmagic/config.h
|
||||
!/ext/fileinfo/libmagic.patch
|
||||
!/ext/fileinfo/magicdata.patch
|
||||
!/ext/pcre/pcre2lib/config.h
|
||||
!/win32/build/Makefile
|
||||
# Special cases to invert previous ignore rules
|
||||
!ext/fileinfo/libmagic.patch
|
||||
!ext/mbstring/oniguruma.patch
|
||||
!ext/pcre/pcre2lib/config.h
|
||||
+18
-43
@@ -1,45 +1,27 @@
|
||||
git:
|
||||
quiet: true
|
||||
|
||||
dist: bionic
|
||||
dist: trusty
|
||||
language: c
|
||||
os: linux
|
||||
sudo: required
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- locales
|
||||
- language-pack-de
|
||||
- re2c
|
||||
- ccache
|
||||
- mysql-server
|
||||
- libaspell-dev
|
||||
- libbz2-dev
|
||||
- libcurl4-gnutls-dev
|
||||
- libenchant-dev
|
||||
- libfreetype6-dev
|
||||
- libgmp-dev
|
||||
- libicu-dev
|
||||
- libjpeg-dev
|
||||
- libkrb5-dev
|
||||
- libonig-dev
|
||||
- libpng-dev
|
||||
- libpq-dev
|
||||
- libpspell-dev
|
||||
- libsasl2-dev
|
||||
- libsqlite3-dev
|
||||
- libsodium-dev
|
||||
- libtidy-dev
|
||||
- libwebp-dev
|
||||
- libxml2-dev
|
||||
- libenchant-dev
|
||||
- libaspell-dev
|
||||
- libpspell-dev
|
||||
- librecode-dev
|
||||
- libsasl2-dev
|
||||
- libxpm-dev
|
||||
- libxslt1-dev
|
||||
- libt1-dev
|
||||
- libzip-dev
|
||||
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_failure: change
|
||||
@@ -63,17 +45,10 @@ env:
|
||||
- PDO_MYSQL_TEST_USER=travis
|
||||
- PDO_MYSQL_TEST_PASS=
|
||||
- PDO_MYSQL_TEST_HOST=127.0.0.1
|
||||
- PDO_PGSQL_TEST_DSN="pgsql:host=localhost port=5432 dbname=test user=postgres password="
|
||||
- REPORT_EXIT_STATUS=1
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- env: ENABLE_ZTS=1 ENABLE_DEBUG=1 SKIP_IO_CAPTURE_TESTS=1 ARM64=1
|
||||
arch: arm64
|
||||
if: type = cron
|
||||
- env: ENABLE_ZTS=1 ENABLE_DEBUG=1 SKIP_IO_CAPTURE_TESTS=1 S390X=1
|
||||
arch: s390x
|
||||
if: type = cron
|
||||
matrix:
|
||||
- ENABLE_MAINTAINER_ZTS=0 ENABLE_DEBUG=0
|
||||
- ENABLE_MAINTAINER_ZTS=1 ENABLE_DEBUG=1
|
||||
|
||||
before_script:
|
||||
- ccache --version
|
||||
@@ -82,17 +57,17 @@ before_script:
|
||||
# Enable IPv6
|
||||
- sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'
|
||||
# Compile PHP
|
||||
- travis_wait ./travis/compile.sh
|
||||
- ./travis/compile.sh
|
||||
# Setup Extensions
|
||||
- ./travis/setup-mysql.sh
|
||||
- ./travis/setup-pgsql.sh
|
||||
- . ./travis/ext/mysql/setup.sh
|
||||
- . ./travis/ext/mysqli/setup.sh
|
||||
- . ./travis/ext/pdo_mysql/setup.sh
|
||||
- . ./travis/ext/pgsql/setup.sh
|
||||
- . ./travis/ext/pdo_pgsql/setup.sh
|
||||
|
||||
# Run PHPs run-tests.php
|
||||
script:
|
||||
# ARM64 CI reports nproc=32, which is excessive.
|
||||
- if [ -z "$ARM64" ]; then export JOBS=$(nproc); else export JOBS=16; fi
|
||||
- ./sapi/cli/php run-tests.php -P -d extension=`pwd`/modules/zend_test.so $(if [ $ENABLE_DEBUG == 0 ]; then echo "-d opcache.enable_cli=1 -d opcache.protect_memory=1 -d opcache.jit_buffer_size=16M -d zend_extension=`pwd`/modules/opcache.so"; fi) -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --offline --show-diff --show-slow 1000 --set-timeout 120 -j$JOBS
|
||||
- sapi/cli/php -d extension_dir=`pwd`/modules -r 'dl("zend_test");'
|
||||
- ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php $(if [ $ENABLE_DEBUG == 0 ]; then echo "-d opcache.enable_cli=1 -d zend_extension=`pwd`/modules/opcache.so"; fi) -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --offline --show-diff --show-slow 1000 --set-timeout 120
|
||||
|
||||
after_success:
|
||||
- ccache --show-stats
|
||||
@@ -0,0 +1,322 @@
|
||||
========================
|
||||
PHP Coding Standards
|
||||
========================
|
||||
|
||||
This file lists several standards that any programmer adding or changing
|
||||
code in PHP should follow. Since this file was added at a very late
|
||||
stage of the development of PHP v3.0, the code base does not fully
|
||||
follow it, but new features are going in that general direction. Many
|
||||
sections have been recoded to use these rules.
|
||||
|
||||
Code Implementation
|
||||
-------------------
|
||||
|
||||
0. Document your code in source files and the manual. [tm]
|
||||
|
||||
1. Functions that are given pointers to resources should not free them
|
||||
|
||||
For instance, ``function int mail(char *to, char *from)`` should NOT free
|
||||
to and/or from.
|
||||
|
||||
Exceptions:
|
||||
|
||||
- The function's designated behavior is freeing that resource. E.g. efree()
|
||||
|
||||
- The function is given a boolean argument, that controls whether or not
|
||||
the function may free its arguments (if true - the function must free its
|
||||
arguments, if false - it must not)
|
||||
|
||||
- Low-level parser routines, that are tightly integrated with the token
|
||||
cache and the bison code for minimum memory copying overhead.
|
||||
|
||||
2. Functions that are tightly integrated with other functions within the
|
||||
same module, and rely on each other non-trivial behavior, should be
|
||||
documented as such and declared 'static'. They should be avoided if
|
||||
possible.
|
||||
|
||||
3. Use definitions and macros whenever possible, so that constants have
|
||||
meaningful names and can be easily manipulated. The only exceptions
|
||||
to this rule are 0 and 1, when used as false and true (respectively).
|
||||
Any other use of a numeric constant to specify different behavior
|
||||
or actions should be done through a #define.
|
||||
|
||||
4. When writing functions that deal with strings, be sure to remember
|
||||
that PHP holds the length property of each string, and that it
|
||||
shouldn't be calculated with strlen(). Write your functions in such
|
||||
a way so that they'll take advantage of the length property, both
|
||||
for efficiency and in order for them to be binary-safe.
|
||||
Functions that change strings and obtain their new lengths while
|
||||
doing so, should return that new length, so it doesn't have to be
|
||||
recalculated with strlen() (e.g. php_addslashes())
|
||||
|
||||
5. NEVER USE strncat(). If you're absolutely sure you know what you're doing,
|
||||
check its man page again, and only then, consider using it, and even then,
|
||||
try avoiding it.
|
||||
|
||||
6. Use ``PHP_*`` macros in the PHP source, and ``ZEND_*`` macros in the Zend
|
||||
part of the source. Although the ``PHP_*`` macro's are mostly aliased to the
|
||||
``ZEND_*`` macros it gives a better understanding on what kind of macro
|
||||
you're calling.
|
||||
|
||||
7. When commenting out code using a #if statement, do NOT use 0 only. Instead
|
||||
use "<git username here>_0". For example, #if FOO_0, where FOO is your
|
||||
git user foo. This allows easier tracking of why code was commented out,
|
||||
especially in bundled libraries.
|
||||
|
||||
8. Do not define functions that are not available. For instance, if a
|
||||
library is missing a function, do not define the PHP version of the
|
||||
function, and do not raise a run-time error about the function not
|
||||
existing. End users should use function_exists() to test for the
|
||||
existence of a function
|
||||
|
||||
9. Prefer emalloc(), efree(), estrdup(), etc. to their standard C library
|
||||
counterparts. These functions implement an internal "safety-net"
|
||||
mechanism that ensures the deallocation of any unfreed memory at the
|
||||
end of a request. They also provide useful allocation and overflow
|
||||
information while running in debug mode.
|
||||
|
||||
In almost all cases, memory returned to the engine must be allocated
|
||||
using emalloc().
|
||||
|
||||
The use of malloc() should be limited to cases where a third-party
|
||||
library may need to control or free the memory, or when the memory in
|
||||
question needs to survive between multiple requests.
|
||||
|
||||
User Functions/Methods Naming Conventions
|
||||
------------------
|
||||
|
||||
1. Function names for user-level functions should be enclosed with in
|
||||
the PHP_FUNCTION() macro. They should be in lowercase, with words
|
||||
underscore delimited, with care taken to minimize the letter count.
|
||||
Abbreviations should not be used when they greatly decrease the
|
||||
readability of the function name itself::
|
||||
|
||||
Good:
|
||||
'str_word_count'
|
||||
'array_key_exists'
|
||||
|
||||
Ok:
|
||||
'date_interval_create_from_date_string'
|
||||
(could be 'date_intvl_create_from_date_str'?)
|
||||
'get_html_translation_table'
|
||||
(could be 'html_get_trans_table'?)
|
||||
|
||||
Bad:
|
||||
'hw_GetObjectByQueryCollObj'
|
||||
'pg_setclientencoding'
|
||||
'jf_n_s_i'
|
||||
|
||||
2. If they are part of a "parent set" of functions, that parent should
|
||||
be included in the user function name, and should be clearly related
|
||||
to the parent program or function family. This should be in the form
|
||||
of ``parent_*``::
|
||||
|
||||
A family of 'foo' functions, for example:
|
||||
|
||||
Good:
|
||||
'foo_select_bar'
|
||||
'foo_insert_baz'
|
||||
'foo_delete_baz'
|
||||
|
||||
Bad:
|
||||
'fooselect_bar'
|
||||
'fooinsertbaz'
|
||||
'delete_foo_baz'
|
||||
|
||||
3. Function names used by user functions should be prefixed
|
||||
with ``_php_``, and followed by a word or an underscore-delimited list of
|
||||
words, in lowercase letters, that describes the function. If applicable,
|
||||
they should be declared 'static'.
|
||||
|
||||
4. Variable names must be meaningful. One letter variable names must be
|
||||
avoided, except for places where the variable has no real meaning or
|
||||
a trivial meaning (e.g. for (i=0; i<100; i++) ...).
|
||||
|
||||
5. Variable names should be in lowercase. Use underscores to separate
|
||||
between words.
|
||||
|
||||
6. Method names follow the 'studlyCaps' (also referred to as 'bumpy case'
|
||||
or 'camel caps') naming convention, with care taken to minimize the
|
||||
letter count. The initial letter of the name is lowercase, and each
|
||||
letter that starts a new 'word' is capitalized::
|
||||
|
||||
Good:
|
||||
'connect()'
|
||||
'getData()'
|
||||
'buildSomeWidget()'
|
||||
|
||||
Bad:
|
||||
'get_Data()'
|
||||
'buildsomewidget'
|
||||
'getI()'
|
||||
|
||||
7. Class names should be descriptive nouns in PascalCase and as short as
|
||||
possible. Each word in the class name should start with a capital letter,
|
||||
without underscore delimiters. The class name should be prefixed with the
|
||||
name of the "parent set" (e.g. the name of the extension) if no namespaces
|
||||
are used. Abbreviations and acronyms as well as initialisms should be
|
||||
avoided wherever possible, unless they are much more widely used than the
|
||||
long form (e.g. HTTP or URL). Abbreviations start with a capital letter
|
||||
followed by lowercase letters, whereas acronyms and initialisms are written
|
||||
according to their standard notation. Usage of acronyms and initialisms is
|
||||
not allowed if they are not widely adopted and recognized as such.
|
||||
|
||||
Good:
|
||||
'Curl'
|
||||
'CurlResponse'
|
||||
'HTTPStatusCode'
|
||||
'URL'
|
||||
'BTreeMap' (B-tree Map)
|
||||
'Id' (Identifier)
|
||||
'ID' (Identity Document)
|
||||
'Char' (Character)
|
||||
'Intl' (Internationalization)
|
||||
'Radar' (Radio Detecting and Ranging)
|
||||
|
||||
Bad:
|
||||
'curl'
|
||||
'curl_response'
|
||||
'HttpStatusCode'
|
||||
'Url'
|
||||
'BtreeMap'
|
||||
'ID' (Identifier)
|
||||
'CHAR'
|
||||
'INTL'
|
||||
'RADAR' (Radio Detecting and Ranging)
|
||||
|
||||
Internal Function Naming Conventions
|
||||
----------------------
|
||||
|
||||
1. Functions that are part of the external API should be named
|
||||
'php_modulename_function()' to avoid symbol collision. They should be in
|
||||
lowercase, with words underscore delimited. Exposed API must be defined
|
||||
in 'php_modulename.h'.
|
||||
|
||||
PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS);
|
||||
|
||||
Unexposed module function should be static and should not be defined in
|
||||
'php_modulename.h'.
|
||||
|
||||
static int php_session_destroy()
|
||||
|
||||
2. Main module source file must be named 'modulename.c'.
|
||||
|
||||
3. Header file that is used by other sources must be named 'php_modulename.h'.
|
||||
|
||||
|
||||
Syntax and indentation
|
||||
----------------------
|
||||
|
||||
1. Never use C++ style comments (i.e. // comment). Always use C-style
|
||||
comments instead. PHP is written in C, and is aimed at compiling
|
||||
under any ANSI-C compliant compiler. Even though many compilers
|
||||
accept C++-style comments in C code, you have to ensure that your
|
||||
code would compile with other compilers as well.
|
||||
The only exception to this rule is code that is Win32-specific,
|
||||
because the Win32 port is MS-Visual C++ specific, and this compiler
|
||||
is known to accept C++-style comments in C code.
|
||||
|
||||
2. Use K&R-style. Of course, we can't and don't want to
|
||||
force anybody to use a style he or she is not used to, but,
|
||||
at the very least, when you write code that goes into the core
|
||||
of PHP or one of its standard modules, please maintain the K&R
|
||||
style. This applies to just about everything, starting with
|
||||
indentation and comment styles and up to function declaration
|
||||
syntax. Also see Indentstyle.
|
||||
|
||||
Indentstyle: http://www.catb.org/~esr/jargon/html/I/indent-style.html
|
||||
|
||||
3. Be generous with whitespace and braces. Keep one empty line between the
|
||||
variable declaration section and the statements in a block, as well as
|
||||
between logical statement groups in a block. Maintain at least one empty
|
||||
line between two functions, preferably two. Always prefer::
|
||||
|
||||
if (foo) {
|
||||
bar;
|
||||
}
|
||||
|
||||
to:
|
||||
|
||||
if(foo)bar;
|
||||
|
||||
4. When indenting, use the tab character. A tab is expected to represent
|
||||
four spaces. It is important to maintain consistency in indenture so
|
||||
that definitions, comments, and control structures line up correctly.
|
||||
|
||||
5. Preprocessor statements (#if and such) MUST start at column one. To
|
||||
indent preprocessor directives you should put the # at the beginning
|
||||
of a line, followed by any number of whitespace.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
1. Extensions should be well tested using *.phpt tests. Read about that
|
||||
in README.TESTING.
|
||||
|
||||
Documentation and Folding Hooks
|
||||
-------------------------------
|
||||
|
||||
In order to make sure that the online documentation stays in line with
|
||||
the code, each user-level function should have its user-level function
|
||||
prototype before it along with a brief one-line description of what the
|
||||
function does. It would look like this::
|
||||
|
||||
/* {{{ proto int abs(int number)
|
||||
Returns the absolute value of the number */
|
||||
PHP_FUNCTION(abs)
|
||||
{
|
||||
...
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
The {{{ symbols are the default folding symbols for the folding mode in
|
||||
Emacs and vim (set fdm=marker). Folding is very useful when dealing with
|
||||
large files because you can scroll through the file quickly and just unfold
|
||||
the function you wish to work on. The }}} at the end of each function marks
|
||||
the end of the fold, and should be on a separate line.
|
||||
|
||||
The "proto" keyword there is just a helper for the doc/genfuncsummary script
|
||||
which generates a full function summary. Having this keyword in front of the
|
||||
function prototypes allows us to put folds elsewhere in the code without
|
||||
messing up the function summary.
|
||||
|
||||
Optional arguments are written like this::
|
||||
|
||||
/* {{{ proto object imap_header(int stream_id, int msg_no [, int from_length [, int subject_length [, string default_host]]])
|
||||
Returns a header object with the defined parameters */
|
||||
|
||||
And yes, please keep the prototype on a single line, even if that line
|
||||
is massive.
|
||||
|
||||
New and Experimental Functions
|
||||
-----------------------------------
|
||||
To reduce the problems normally associated with the first public
|
||||
implementation of a new set of functions, it has been suggested
|
||||
that the first implementation include a file labeled 'EXPERIMENTAL'
|
||||
in the function directory, and that the functions follow the
|
||||
standard prefixing conventions during their initial implementation.
|
||||
|
||||
The file labelled 'EXPERIMENTAL' should include the following
|
||||
information::
|
||||
|
||||
Any authoring information (known bugs, future directions of the module).
|
||||
Ongoing status notes which may not be appropriate for Git comments.
|
||||
|
||||
In general new features should go to PECL or experimental branches until
|
||||
there are specific reasons for directly adding it to the core distribution.
|
||||
|
||||
Aliases & Legacy Documentation
|
||||
-----------------------------------
|
||||
You may also have some deprecated aliases with close to duplicate
|
||||
names, for example, somedb_select_result and somedb_selectresult. For
|
||||
documentation purposes, these will only be documented by the most
|
||||
current name, with the aliases listed in the documentation for
|
||||
the parent function. For ease of reference, user-functions with
|
||||
completely different names, that alias to the same function (such as
|
||||
highlight_file and show_source), will be separately documented. The
|
||||
proto should still be included, describing which function is aliased.
|
||||
|
||||
Backwards compatible functions and names should be maintained as long
|
||||
as the code can be reasonably be kept as part of the codebase. See the
|
||||
README in the PHP documentation repository for more information on
|
||||
documentation.
|
||||
@@ -1,320 +0,0 @@
|
||||
# PHP coding standards
|
||||
|
||||
This file lists several standards that any programmer adding or changing code in
|
||||
PHP should follow. Since this file was added at a very late stage of the
|
||||
development of PHP v3.0, the code base does not fully follow it, but new
|
||||
features are going in that general direction. Many sections have been recoded to
|
||||
use these rules.
|
||||
|
||||
## Code implementation
|
||||
|
||||
1. Document your code in source files and the manual. (tm)
|
||||
|
||||
2. Functions that are given pointers to resources should not free them.
|
||||
|
||||
For instance, `function int mail(char *to, char *from)` should NOT free to
|
||||
and/or from.
|
||||
|
||||
Exceptions:
|
||||
|
||||
* The function's designated behavior is freeing that resource. E.g.
|
||||
`efree()`
|
||||
|
||||
* The function is given a boolean argument, that controls whether or not the
|
||||
function may free its arguments (if true - the function must free its
|
||||
arguments, if false - it must not)
|
||||
|
||||
* Low-level parser routines, that are tightly integrated with the token
|
||||
cache and the bison code for minimum memory copying overhead.
|
||||
|
||||
3. Functions that are tightly integrated with other functions within the same
|
||||
module, and rely on each other non-trivial behavior, should be documented as
|
||||
such and declared `static`. They should be avoided if possible.
|
||||
|
||||
4. Use definitions and macros whenever possible, so that constants have
|
||||
meaningful names and can be easily manipulated. The only exceptions to this
|
||||
rule are 0 and 1, when used as `false` and `true` (respectively). Any other
|
||||
use of a numeric constant to specify different behavior or actions should be
|
||||
done through a `#define`.
|
||||
|
||||
5. When writing functions that deal with strings, be sure to remember that PHP
|
||||
holds the length property of each string, and that it shouldn't be
|
||||
calculated with `strlen()`. Write your functions in such a way so that
|
||||
they'll take advantage of the length property, both for efficiency and in
|
||||
order for them to be binary-safe. Functions that change strings and obtain
|
||||
their new lengths while doing so, should return that new length, so it
|
||||
doesn't have to be recalculated with `strlen()` (e.g. `php_addslashes()`).
|
||||
|
||||
6. NEVER USE `strncat()`. If you're absolutely sure you know what you're doing,
|
||||
check its man page again, and only then, consider using it, and even then,
|
||||
try avoiding it.
|
||||
|
||||
7. Use `PHP_*` macros in the PHP source, and `ZEND_*` macros in the Zend part of
|
||||
the source. Although the `PHP_*` macros are mostly aliased to the `ZEND_*`
|
||||
macros it gives a better understanding on what kind of macro you're calling.
|
||||
|
||||
8. When commenting out code using a `#if` statement, do NOT use `0` only.
|
||||
Instead use `"<git username here>_0"`. For example, `#if FOO_0`, where `FOO`
|
||||
is your git user `foo`. This allows easier tracking of why code was
|
||||
commented out, especially in bundled libraries.
|
||||
|
||||
9. Do not define functions that are not available. For instance, if a library is
|
||||
missing a function, do not define the PHP version of the function, and do
|
||||
not raise a run-time error about the function not existing. End users should
|
||||
use `function_exists()` to test for the existence of a function.
|
||||
|
||||
10. Prefer `emalloc()`, `efree()`, `estrdup()`, etc. to their standard C library
|
||||
counterparts. These functions implement an internal "safety-net" mechanism
|
||||
that ensures the deallocation of any unfreed memory at the end of a request.
|
||||
They also provide useful allocation and overflow information while running
|
||||
in debug mode.
|
||||
|
||||
In almost all cases, memory returned to the engine must be allocated using
|
||||
`emalloc()`.
|
||||
|
||||
The use of `malloc()` should be limited to cases where a third-party library
|
||||
may need to control or free the memory, or when the memory in question needs
|
||||
to survive between multiple requests.
|
||||
|
||||
## User functions/methods naming conventions
|
||||
|
||||
1. Function names for user-level functions should be enclosed with in the
|
||||
`PHP_FUNCTION()` macro. They should be in lowercase, with words underscore
|
||||
delimited, with care taken to minimize the letter count. Abbreviations
|
||||
should not be used when they greatly decrease the readability of the
|
||||
function name itself:
|
||||
|
||||
Good:
|
||||
|
||||
```php
|
||||
str_word_count
|
||||
array_key_exists
|
||||
```
|
||||
|
||||
Ok:
|
||||
|
||||
```php
|
||||
date_interval_create_from_date_string
|
||||
// Could be 'date_intvl_create_from_date_str'?
|
||||
get_html_translation_table()
|
||||
// Could be 'html_get_trans_table'?
|
||||
```
|
||||
|
||||
Bad:
|
||||
|
||||
```php
|
||||
hw_GetObjectByQueryCollObj
|
||||
pg_setclientencoding
|
||||
jf_n_s_i
|
||||
```
|
||||
|
||||
2. If they are part of a "parent set" of functions, that parent should be
|
||||
included in the user function name, and should be clearly related to the
|
||||
parent program or function family. This should be in the form of `parent_*`:
|
||||
|
||||
A family of `foo` functions, for example:
|
||||
|
||||
Good:
|
||||
|
||||
```php
|
||||
foo_select_bar
|
||||
foo_insert_baz
|
||||
foo_delete_baz
|
||||
```
|
||||
|
||||
Bad:
|
||||
|
||||
```php
|
||||
fooselect_bar
|
||||
fooinsertbaz
|
||||
delete_foo_baz
|
||||
```
|
||||
|
||||
3. Function names used by user functions should be prefixed with `_php_`, and
|
||||
followed by a word or an underscore-delimited list of words, in lowercase
|
||||
letters, that describes the function. If applicable, they should be declared
|
||||
`static`.
|
||||
|
||||
4. Variable names must be meaningful. One letter variable names must be avoided,
|
||||
except for places where the variable has no real meaning or a trivial
|
||||
meaning (e.g. `for (i=0; i<100; i++) ...`).
|
||||
|
||||
5. Variable names should be in lowercase. Use underscores to separate between
|
||||
words.
|
||||
|
||||
6. Method names follow the *studlyCaps* (also referred to as *bumpy case* or
|
||||
*camel caps*) naming convention, with care taken to minimize the letter
|
||||
count. The initial letter of the name is lowercase, and each letter that
|
||||
starts a new `word` is capitalized:
|
||||
|
||||
Good:
|
||||
|
||||
```php
|
||||
connect()
|
||||
getData()
|
||||
buildSomeWidget()
|
||||
```
|
||||
|
||||
Bad:
|
||||
|
||||
```php
|
||||
get_Data()
|
||||
buildsomewidget()
|
||||
getI()
|
||||
```
|
||||
|
||||
7. Class names should be descriptive nouns in *PascalCase* and as short as
|
||||
possible. Each word in the class name should start with a capital letter,
|
||||
without underscore delimiters. The class name should be prefixed with the
|
||||
name of the "parent set" (e.g. the name of the extension) if no namespaces
|
||||
are used. Abbreviations and acronyms as well as initialisms should be
|
||||
avoided wherever possible, unless they are much more widely used than the
|
||||
long form (e.g. HTTP or URL). Abbreviations start with a capital letter
|
||||
followed by lowercase letters, whereas acronyms and initialisms are written
|
||||
according to their standard notation. Usage of acronyms and initialisms is
|
||||
not allowed if they are not widely adopted and recognized as such.
|
||||
|
||||
Good:
|
||||
|
||||
```php
|
||||
Curl
|
||||
CurlResponse
|
||||
HTTPStatusCode
|
||||
URL
|
||||
BTreeMap // B-tree Map
|
||||
Id // Identifier
|
||||
ID // Identity Document
|
||||
Char // Character
|
||||
Intl // Internationalization
|
||||
Radar // Radio Detecting and Ranging
|
||||
```
|
||||
|
||||
Bad:
|
||||
|
||||
```php
|
||||
curl
|
||||
curl_response
|
||||
HttpStatusCode
|
||||
Url
|
||||
BtreeMap
|
||||
ID // Identifier
|
||||
CHAR
|
||||
INTL
|
||||
RADAR // Radio Detecting and Ranging
|
||||
```
|
||||
|
||||
## Internal function naming conventions
|
||||
|
||||
1. Functions that are part of the external API should be named
|
||||
`php_modulename_function()` to avoid symbol collision. They should be in
|
||||
lowercase, with words underscore delimited. Exposed API must be defined in
|
||||
`php_modulename.h`.
|
||||
|
||||
```c
|
||||
PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS);
|
||||
```
|
||||
|
||||
Unexposed module function should be static and should not be defined in
|
||||
`php_modulename.h`.
|
||||
|
||||
```c
|
||||
static int php_session_destroy()
|
||||
```
|
||||
|
||||
2. Main module source file must be named `modulename.c`.
|
||||
|
||||
3. Header file that is used by other sources must be named `php_modulename.h`.
|
||||
|
||||
## Syntax and indentation
|
||||
|
||||
1. Never use C++ style comments (i.e. `//` comment). Always use C-style comments
|
||||
instead. PHP is written in C, and is aimed at compiling under any ANSI-C
|
||||
compliant compiler. Even though many compilers accept C++-style comments in
|
||||
C code, you have to ensure that your code would compile with other compilers
|
||||
as well. The only exception to this rule is code that is Win32-specific,
|
||||
because the Win32 port is MS-Visual C++ specific, and this compiler is known
|
||||
to accept C++-style comments in C code.
|
||||
|
||||
2. Use K&R-style. Of course, we can't and don't want to force anybody to use a
|
||||
style he or she is not used to, but, at the very least, when you write code
|
||||
that goes into the core of PHP or one of its standard modules, please
|
||||
maintain the K&R style. This applies to just about everything, starting with
|
||||
indentation and comment styles and up to function declaration syntax. Also
|
||||
see [Indentstyle](http://www.catb.org/~esr/jargon/html/I/indent-style.html).
|
||||
|
||||
3. Be generous with whitespace and braces. Keep one empty line between the
|
||||
variable declaration section and the statements in a block, as well as
|
||||
between logical statement groups in a block. Maintain at least one empty
|
||||
line between two functions, preferably two. Always prefer:
|
||||
|
||||
```c
|
||||
if (foo) {
|
||||
bar;
|
||||
}
|
||||
```
|
||||
|
||||
to:
|
||||
|
||||
```c
|
||||
if(foo)bar;
|
||||
```
|
||||
|
||||
4. When indenting, use the tab character. A tab is expected to represent four
|
||||
spaces. It is important to maintain consistency in indenture so that
|
||||
definitions, comments, and control structures line up correctly.
|
||||
|
||||
5. Preprocessor statements (`#if` and such) MUST start at column one. To indent
|
||||
preprocessor directives you should put the `#` at the beginning of a line,
|
||||
followed by any number of whitespace.
|
||||
|
||||
## Testing
|
||||
|
||||
1. Extensions should be well tested using `*.phpt` tests. Read about that at
|
||||
[qa.php.net](https://qa.php.net/write-test.php) documentation.
|
||||
|
||||
## Folding hooks
|
||||
|
||||
Use `{{{` symbols for the folding mode in Emacs and vim (`set fdm=marker`).
|
||||
Folding is very useful when dealing with large files because you can scroll
|
||||
through the file quickly and just unfold the function you wish to work on.
|
||||
The `}}}` at the end of each function marks the end of the fold, and should
|
||||
be on a separate line.
|
||||
|
||||
```c
|
||||
/* {{{ Returns the absolute value of the number */
|
||||
PHP_FUNCTION(abs)
|
||||
{
|
||||
...
|
||||
}
|
||||
/* }}} */
|
||||
```
|
||||
|
||||
## New and experimental functions
|
||||
|
||||
To reduce the problems normally associated with the first public implementation
|
||||
of a new set of functions, it has been suggested that the first implementation
|
||||
include a file labeled `EXPERIMENTAL` in the function directory, and that the
|
||||
functions follow the standard prefixing conventions during their initial
|
||||
implementation.
|
||||
|
||||
The file labelled `EXPERIMENTAL` should include the following information:
|
||||
|
||||
* Any authoring information (known bugs, future directions of the module).
|
||||
* Ongoing status notes which may not be appropriate for Git comments.
|
||||
|
||||
In general new features should go to PECL or experimental branches until there
|
||||
are specific reasons for directly adding it to the core distribution.
|
||||
|
||||
## Aliases & legacy documentation
|
||||
|
||||
You may also have some deprecated aliases with close to duplicate names, for
|
||||
example, `somedb_select_result` and `somedb_selectresult`. For documentation
|
||||
purposes, these will only be documented by the most current name, with the
|
||||
aliases listed in the documentation for the parent function. For ease of
|
||||
reference, user-functions with completely different names, that alias to the
|
||||
same function (such as `highlight_file` and `show_source`), will be separately
|
||||
documented.
|
||||
|
||||
Backwards compatible functions and names should be maintained as long as the
|
||||
code can be reasonably be kept as part of the codebase. See the `README` in the
|
||||
PHP documentation repository for more information on documentation.
|
||||
+21
-368
@@ -1,30 +1,10 @@
|
||||
# Contributing to PHP
|
||||
|
||||
Anybody who programs in PHP can be a contributing member of the community that
|
||||
develops and deploys it; the task of deploying PHP, documentation and associated
|
||||
websites is a never ending one. With every release, or release candidate comes a
|
||||
wave of work, which takes a lot of organization and co-ordination.
|
||||
|
||||
You don't need any special access to download, build, debug and begin submitting
|
||||
PHP or PECL code, tests or documentation. Once you've followed this guide and
|
||||
had several contributions accepted, commit privileges are often quickly granted.
|
||||
|
||||
## Index
|
||||
|
||||
* [Pull requests](#pull-requests)
|
||||
* [Filing bugs](#filing-bugs)
|
||||
* [Feature requests](#feature-requests)
|
||||
* [Writing tests](#writing-tests)
|
||||
* [Writing documentation](#writing-documentation)
|
||||
* [Getting help](#getting-help)
|
||||
* [PHP source code directory structure](#php-source-code-directory-structure)
|
||||
* [PHP internals](#php-internals)
|
||||
* [PECL extensions](#pecl-extensions)
|
||||
* [Checklist for submitting contribution](#checklist-for-submitting-contribution)
|
||||
* [What happens after submitting contribution?](#what-happens-after-submitting-contribution)
|
||||
* [What happens when your contribution is applied?](#what-happens-when-your-contribution-is-applied)
|
||||
* [Git commit rules](#git-commit-rules)
|
||||
* [Copyright and license headers](#copyright-and-license-headers)
|
||||
develops and deploys it; the task of deploying PHP, documentation and
|
||||
associated websites is a never ending one. With every release, or release
|
||||
candidate comes a wave of work, which takes a lot of organization and
|
||||
co-ordination.
|
||||
|
||||
## Pull requests
|
||||
|
||||
@@ -33,28 +13,18 @@ implement RFCs. Please be sure to include tests as appropriate!
|
||||
|
||||
If you are fixing a bug, then please submit your PR against the lowest actively
|
||||
supported branch of PHP that the bug affects (only green branches on
|
||||
[the supported version page](https://www.php.net/supported-versions.php) are
|
||||
supported). For example, at the time of writing, the lowest supported version is
|
||||
PHP 7.3, which corresponds to the `PHP-7.3` branch in Git. Please also make sure
|
||||
you add a link to the PR in the bug on [the bug tracker](https://bugs.php.net/).
|
||||
[the supported version page](http://php.net/supported-versions.php) are supported).
|
||||
For example, at the time of writing in early-2018, the lowest supported version is
|
||||
PHP 7.1, which corresponds to the `PHP-7.1` branch in Git. Please also make sure you
|
||||
add a link to the PR in the bug on [the bug tracker](https://bugs.php.net/).
|
||||
|
||||
Pull requests implementing RFCs should be submitted against `master`.
|
||||
|
||||
Pull requests should *never* be submitted against `PHP-x.y.z` branches, as these
|
||||
are only used for release management.
|
||||
Pull requests should *never* be submitted against `PHP-x.y.z` branches, as
|
||||
these are only used for release management.
|
||||
|
||||
If your pull request exhibits conflicts with the base branch, please resolve
|
||||
them by using `git rebase` instead of `git merge`.
|
||||
|
||||
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](https://bugs.php.net/).
|
||||
|
||||
Read [Git access page](https://www.php.net/git.php) for help on using Git to get
|
||||
and build PHP source code. We recommend to look at our
|
||||
[workflow](https://wiki.php.net/vcs/gitworkflow) and our
|
||||
[FAQ](https://wiki.php.net/vcs/gitfaq).
|
||||
If your pull request exhibits conflicts with the base branch, please resolve them
|
||||
by using `git rebase` instead of `git merge`.
|
||||
|
||||
## Filing bugs
|
||||
|
||||
@@ -67,19 +37,12 @@ Where possible, please include a self-contained reproduction case!
|
||||
## Feature requests
|
||||
|
||||
Feature requests are generally submitted in the form of
|
||||
[Requests for Comments (RFC)](https://wiki.php.net/rfc/howto), ideally
|
||||
accompanied by [pull requests](#pull-requests). You can find the extremely large
|
||||
list of RFCs that have been previously considered on the
|
||||
[Requests for Comment](https://wiki.php.net/rfc/howto), ideally accompanied by
|
||||
[pull requests](#pull-requests). You can find the extremely large list of RFCs
|
||||
that have been previously considered on the
|
||||
[PHP Wiki](https://wiki.php.net/rfc).
|
||||
|
||||
To create a RFC, discuss it with the extension maintainer, and discuss it on the
|
||||
development mailing list internals@lists.php.net. RFC Wiki accounts can be
|
||||
requested on https://wiki.php.net/start?do=register. PHP extension maintainers
|
||||
can be found in the [EXTENSIONS](/EXTENSIONS) file in the PHP source code
|
||||
repository. Mailing list subscription is explained on the
|
||||
[mailing lists page](https://www.php.net/mailing-lists.php).
|
||||
|
||||
You may also want to read
|
||||
You may want to read
|
||||
[The Mysterious PHP RFC Process](https://blogs.oracle.com/opal/entry/the_mysterious_php_rfc_process)
|
||||
for additional notes on the best way to approach submitting an RFC.
|
||||
|
||||
@@ -88,19 +51,10 @@ for additional notes on the best way to approach submitting an RFC.
|
||||
We love getting new tests! PHP is a huge project and improving code coverage is
|
||||
a huge win for every PHP user.
|
||||
|
||||
[Our QA site includes a page detailing how to write test cases.](https://qa.php.net/write-test.php)
|
||||
|
||||
Submitting test scripts helps us to understand what functionality has changed.
|
||||
It is important for the stability and maintainability of PHP that tests are
|
||||
comprehensive.
|
||||
|
||||
Failure conditions of `zend_parse_parameters`, `ZEND_PARSE_PARAMETERS()` and
|
||||
similar functions should not be tested. These parameter parsing APIs are already
|
||||
extensively tested, and additional tests only complicate future modifications.
|
||||
|
||||
For newly created tests, a `--CREDITS--` section should no longer be included,
|
||||
as test authorship is already accurately tracked by Git. If multiple authors
|
||||
should be credited, the `Co-authored-by` tag in the commit message may be used.
|
||||
[Our QA site includes a page detailing how to write test cases.](http://qa.php.net/write-test.php)
|
||||
Please note that the section on submitting pull requests is outdated: in
|
||||
addition to the process listed there, you can also
|
||||
[submit pull requests](#pull-requests).
|
||||
|
||||
## Writing documentation
|
||||
|
||||
@@ -121,305 +75,4 @@ issues.
|
||||
|
||||
Although not a formal channel, you can also find a number of core developers on
|
||||
the #php.pecl channel on [EFnet](http://www.efnet.org/). Similarly, many
|
||||
documentation writers can be found on #php.doc. Windows development IRC channel
|
||||
is available at #winphp-dev on FreeNode.
|
||||
|
||||
## PHP source code directory structure
|
||||
|
||||
PHP source code also includes several files generated during development and
|
||||
several parts where maintenance is happening upstream in their respective
|
||||
locations.
|
||||
|
||||
```bash
|
||||
<php-src>/
|
||||
├─ .git/ # Git configuration and source directory
|
||||
├─ TSRM/ # Thread Safe Resource Manager
|
||||
└─ Zend/ # Zend Engine
|
||||
├─ zend_vm_execute.h # Generated by `Zend/zend_vm_gen.php`
|
||||
├─ zend_vm_opcodes.c # Generated by `Zend/zend_vm_gen.php`
|
||||
├─ zend_vm_opcodes.h # Generated by `Zend/zend_vm_gen.php`
|
||||
└─ ...
|
||||
├─ appveyor/ # Appveyor CI service files
|
||||
└─ build/ # *nix build system files
|
||||
├─ ax_*.m4 # https://github.com/autoconf-archive/autoconf-archive
|
||||
├─ config.guess # https://git.savannah.gnu.org/cgit/config.git
|
||||
├─ config.sub # https://git.savannah.gnu.org/cgit/config.git
|
||||
├─ libtool.m4 # https://git.savannah.gnu.org/cgit/libtool.git
|
||||
├─ ltmain.sh # https://git.savannah.gnu.org/cgit/libtool.git
|
||||
├─ shtool # https://www.gnu.org/software/shtool/
|
||||
└─ ...
|
||||
├─ docs/ # PHP internals and repository documentation
|
||||
└─ ext/ # PHP core extensions
|
||||
└─ bcmath/
|
||||
├─ libbcmath/ # Forked and maintained in php-src
|
||||
└─ ...
|
||||
└─ curl/
|
||||
├─ sync-constants.php # The curl symbols checker
|
||||
└─ ...
|
||||
└─ date/
|
||||
└─ lib/ # Bundled datetime library https://github.com/derickr/timelib
|
||||
├─ parse_date.c # Generated by re2c 0.15.3
|
||||
├─ parse_iso_intervals.c # Generated by re2c 0.15.3
|
||||
└─ ...
|
||||
└─ ...
|
||||
└─ ffi/
|
||||
├─ ffi_parser.c # Generated by https://github.com/dstogov/llk
|
||||
└─ ...
|
||||
└─ fileinfo/
|
||||
├─ libmagic/ # Modified libmagic https://github.com/file/file
|
||||
├─ data_file.c # Generated by `ext/fileinfo/create_data_file.php`
|
||||
├─ libmagic.patch # Modifications patch from upstream libmagic
|
||||
├─ magicdata.patch # Modifications patch from upstream libmagic
|
||||
└─ ...
|
||||
└─ gd/
|
||||
├─ libgd/ # Bundled and modified GD library https://github.com/libgd/libgd
|
||||
└─ ...
|
||||
└─ mbstring/
|
||||
├─ libmbfl/ # Forked and maintained in php-src
|
||||
├─ unicode_data.h # Generated by `ext/mbstring/ucgendat/ucgendat.php`
|
||||
└─ ...
|
||||
└─ pcre/
|
||||
├─ pcre2lib/ # https://www.pcre.org/
|
||||
└─ ...
|
||||
└─ pdo_mysql/
|
||||
├─ php_pdo_mysql_sqlstate.h # Generated by `ext/pdo_mysql/get_error_codes.php`
|
||||
└─ ...
|
||||
└─ skeleton/ # Skeleton for developing new extensions with `ext/ext_skel.php`
|
||||
└─ ...
|
||||
└─ standard/
|
||||
└─ html_tables/
|
||||
├─ mappings/ # https://www.unicode.org/Public/MAPPINGS/
|
||||
└─ ...
|
||||
├─ credits_ext.h # Generated by `scripts/dev/credits`
|
||||
├─ credits_sapi.h # Generated by `scripts/dev/credits`
|
||||
├─ html_tables.h # Generated by `ext/standard/html_tables/html_table_gen.php`
|
||||
└─ ...
|
||||
└─ tokenizer/
|
||||
├─ tokenizer_data.c # Generated by `ext/tokenizer/tokenizer_data_gen.sh`
|
||||
└─ ...
|
||||
└─ zend_test # For testing internal APIs. Not needed for regular builds.
|
||||
└─ ...
|
||||
└─ zip/ # Bundled https://github.com/pierrejoye/php_zip
|
||||
└─ ...
|
||||
└─ ...
|
||||
└─ main/ # Binding that ties extensions, SAPIs, and engine together
|
||||
├─ streams/ # Streams layer subsystem
|
||||
├─ php_version.h # Generated by release managers using `configure`
|
||||
└─ ...
|
||||
├─ pear/ # PEAR installation
|
||||
└─ sapi/ # PHP SAPI modules
|
||||
└─ cli/
|
||||
├─ mime_type_map.h # Generated by `sapi/cli/generate_mime_type_map.php`
|
||||
└─ ...
|
||||
└─ ...
|
||||
├─ scripts/ # php-config, phpize and internal development scripts
|
||||
├─ tests/ # Core features tests
|
||||
├─ travis/ # Travis CI service files
|
||||
└─ win32/ # Windows build system files
|
||||
├─ cp_enc_map.c # Generated by `win32/cp_enc_map_gen.exe`
|
||||
└─ ...
|
||||
└─ ...
|
||||
```
|
||||
|
||||
## PHP internals
|
||||
|
||||
For information on PHP internal C functions see
|
||||
[References about Maintaining and Extending PHP](https://wiki.php.net/internals/references).
|
||||
Various external resources can be found on the web. A standard printed reference
|
||||
is the book "Extending and Embedding PHP" by Sara Golemon.
|
||||
|
||||
## PECL extensions
|
||||
|
||||
If you are fixing broken functionality in a [PECL](https://pecl.php.net)
|
||||
extension then create a bug or identify an existing bug at
|
||||
[bugs.php.net](https://bugs.php.net). A bug can be used to track the change
|
||||
progress and prevent your changes getting lost in the PHP mail archives. Some
|
||||
PECL extensions have their own bug tracker locations and different contributing
|
||||
procedures.
|
||||
|
||||
If your change is large then create a
|
||||
[Request for Comments (RFC)](https://wiki.php.net/rfc), discuss it with the
|
||||
extension maintainer, and discuss it on the development mailing list
|
||||
pecl-dev@lists.php.net depending on the extension. PECL mailing list
|
||||
subscription is explained on the
|
||||
[PECL support page](https://pecl.php.net/support.php).
|
||||
|
||||
Update any open bugs and add a link to the source of your change. Send the patch
|
||||
or pointer to the bug to pecl-dev@lists.php.net. Also CC the extension
|
||||
maintainer. Explain what has been changed by your patch. Test scripts should be
|
||||
included.
|
||||
|
||||
## Checklist for submitting contribution
|
||||
|
||||
- Read [Coding standards](/CODING_STANDARDS.md) before you start working.
|
||||
- Update git source just before running your final `diff` and before testing.
|
||||
- Add in-line comments and/or have external documentation ready. Use only
|
||||
`/* */` style comments, not `//`.
|
||||
- Create test scripts for use with `make test`.
|
||||
- Run `make test` to check your change doesn't break other features.
|
||||
- Rebuild PHP with `--enable-debug` which will show some kinds of memory errors
|
||||
and check the PHP and web server error logs after running your PHP tests.
|
||||
- Rebuild PHP with `--enable-zts` to check your change compiles and operates
|
||||
correctly in a thread safe PHP.
|
||||
- Review the change once more just before submitting it.
|
||||
|
||||
## What happens after submitting contribution?
|
||||
|
||||
If your change is easy to review and obviously has no side-effects, it might be
|
||||
committed relatively quickly.
|
||||
|
||||
Because PHP is a volunteer-driven effort more complex changes will require
|
||||
patience on your side. If you do not receive feedback in a few days, consider
|
||||
bumping. Before doing this think about these questions:
|
||||
|
||||
- Did I send the patch to the right mailing list?
|
||||
- Did I review the mailing list archives to see if these kind of changes had
|
||||
been discussed before?
|
||||
- Did I explain my change clearly?
|
||||
- Is my change too hard to review? Because of what factors?
|
||||
|
||||
## What happens when your contribution is applied?
|
||||
|
||||
Your name will likely be included in the Git commit log. If your change affects
|
||||
end users, a brief description and your name might be added to the [NEWS](/NEWS)
|
||||
file.
|
||||
|
||||
## Git commit rules
|
||||
|
||||
This section refers to contributors that have Git push access and make commit
|
||||
changes themselves. We'll assume you're basically familiar with Git, but feel
|
||||
free to post your questions on the mailing list. Please have a look at the more
|
||||
detailed [information on Git](https://git-scm.com/).
|
||||
|
||||
PHP is developed through the efforts of a large number of people. Collaboration
|
||||
is a Good Thing(tm), and Git lets us do this. Thus, following some basic rules
|
||||
with regards to Git usage will:
|
||||
|
||||
* Make everybody happier, especially those responsible for maintaining PHP
|
||||
itself.
|
||||
* Keep the changes consistently well documented and easily trackable.
|
||||
* Prevent some of those 'Oops' moments.
|
||||
* Increase the general level of good will on planet Earth.
|
||||
|
||||
Having said that, here are the organizational rules:
|
||||
|
||||
1. Respect other people working on the project.
|
||||
|
||||
2. Discuss any significant changes on the list before committing and get
|
||||
confirmation from the release manager for the given branch.
|
||||
|
||||
3. Look at [EXTENSIONS](/EXTENSIONS) file to see who is the primary maintainer
|
||||
of the code you want to contribute to.
|
||||
|
||||
4. If you "strongly disagree" about something another person did, don't start
|
||||
fighting publicly - take it up in private email.
|
||||
|
||||
5. If you don't know how to do something, ask first!
|
||||
|
||||
6. Test your changes before committing them. We mean it. Really. To do so use
|
||||
`make test`.
|
||||
|
||||
7. For development use the `--enable-debug` switch to avoid memory leaks and the
|
||||
`--enable-zts` switch to ensure your code handles TSRM correctly and doesn't
|
||||
break for those who need that.
|
||||
|
||||
Currently we have the following branches in use:
|
||||
|
||||
| Branch | |
|
||||
| --------- | --------- |
|
||||
| master | Active development branch for PHP 8.0, which is open for backwards incompatible changes and major internal API changes. |
|
||||
| PHP-7.4 | Is used to release the PHP 7.4.x series. This is a current stable version and is open for bugfixes only. |
|
||||
| PHP-7.3 | Is used to release the PHP 7.3.x series. This is a current stable version and is open for bugfixes only. |
|
||||
| PHP-7.2 | Is used to release the PHP 7.2.x series. This is an old stable version and is open for security fixes only. |
|
||||
| PHP-7.1 | This branch is closed. |
|
||||
| PHP-7.0 | This branch is closed. |
|
||||
| PHP-5.6 | This branch is closed. |
|
||||
| PHP-5.5 | This branch is closed. |
|
||||
| PHP-5.4 | This branch is closed. |
|
||||
| PHP-5.3 | This branch is closed. |
|
||||
| PHP-5.2 | This branch is closed. |
|
||||
| PHP-5.1 | This branch is closed. |
|
||||
| PHP-4.4 | This branch is closed. |
|
||||
| PHP-X.Y.Z | These branches are used for the release managers for tagging the releases, hence they are closed to the general public. |
|
||||
|
||||
The next few rules are more of a technical nature:
|
||||
|
||||
1. All non-security bugfix changes should first go to the lowest bugfix branch
|
||||
(i.e. 7.3) and then get merged up to all other branches. All security fixes
|
||||
should go to the lowest security fixes branch (i.e 7.2). If a change is not
|
||||
needed for later branches (i.e. fixes for features which were dropped from
|
||||
later branches) an empty merge should be done.
|
||||
|
||||
2. All news updates intended for public viewing, such as new features, bug
|
||||
fixes, improvements, etc., should go into the NEWS file of *any stable
|
||||
release* version with the given change. In other words, news about a bug fix
|
||||
which went into PHP-5.4, PHP-5.5 and master should be noted in both
|
||||
PHP-5.4/NEWS and PHP-5.5/NEWS but not master, which is not a public released
|
||||
version yet.
|
||||
|
||||
3. Do not commit multiple files and dump all messages in one commit. If you
|
||||
modified several unrelated files, commit each group separately and provide a
|
||||
nice commit message for each one. See example below.
|
||||
|
||||
4. Do write your commit message in such a way that it makes sense even without
|
||||
the corresponding diff. One should be able to look at it, and immediately
|
||||
know what was modified. Definitely include the function name in the message
|
||||
as shown below.
|
||||
|
||||
5. In your commit messages, keep each line shorter than 80 characters. And try
|
||||
to align your lines vertically, if they wrap. It looks bad otherwise.
|
||||
|
||||
6. If you modified a function that is callable from PHP, prepend PHP to the
|
||||
function name as shown below.
|
||||
|
||||
The format of the commit messages is pretty simple.
|
||||
|
||||
<max 79 characters short description>\n
|
||||
\n
|
||||
<long description, 79 chars per line>
|
||||
\n
|
||||
|
||||
An Example from the git project (commit 2b34e486bc):
|
||||
|
||||
pack-objects: Fix compilation with NO_PTHREDS
|
||||
|
||||
It looks like commit 99fb6e04 (pack-objects: convert to use parse_options(),
|
||||
2012-02-01) moved the #ifdef NO_PTHREDS around but hasn't noticed that the
|
||||
'arg' variable no longer is available.
|
||||
|
||||
If you fix some bugs, you should note the bug ID numbers in your commit message.
|
||||
Bug ID should be prefixed by `#`.
|
||||
|
||||
Example:
|
||||
|
||||
Fixed bug #14016 (pgsql notice handler double free crash bug.)
|
||||
|
||||
When you change the NEWS file for a bug fix, then please keep the bugs sorted in
|
||||
decreasing order under the fixed version.
|
||||
|
||||
You can use [gitweb](https://git.php.net/) to look at PHP Git repository in
|
||||
various ways.
|
||||
|
||||
## Copyright and license headers
|
||||
|
||||
New source code files should include the following header block:
|
||||
|
||||
```c
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| https://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
```
|
||||
|
||||
Thank you for contributing to PHP!
|
||||
documentation writers can be found on #php.doc.
|
||||
@@ -0,0 +1,3 @@
|
||||
For the list of people who've put work into PHP, please see
|
||||
|
||||
https://www.php.net/credits.php
|
||||
+31
-36
@@ -36,8 +36,7 @@ MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: cli
|
||||
PRIMARY MAINTAINER: Marcus Börger <helly@php.net>, Edin Kadribasic <edink@php.net>
|
||||
MAINTENANCE: Xinchen Hui <laruence@php.net> (2013 - 2020)
|
||||
MAINTENANCE: Marcus Börger <helly@php.net>, Edin Kadribasic <edink@php.net>
|
||||
STATUS: Working
|
||||
SINCE: 4.3.0
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -59,8 +58,7 @@ STATUS: Working
|
||||
SINCE: 5.3
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: phpdbg
|
||||
PRIMARY MAINTAINER: Joe Watkins <krakjoe@php.net>, Bob Weinand <bwoebi@php.net>
|
||||
MAINTENANCE: Unknown
|
||||
MAINTENANCE: Joe Watkins <krakjoe@php.net>, Bob Weinand <bwoebi@php.net>
|
||||
STATUS: 5.6
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -76,6 +74,11 @@ MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
COMMENT: DBM abstraction for db2, db3, db4, dbm, ndbm, gdbm, ini
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: interbase
|
||||
PRIMARY MAINTAINER: Ard Biesheuvel <ard@ard.nu> (2003 - 2005)
|
||||
MAINTENANCE: Odd fixes
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mysqli
|
||||
PRIMARY MAINTAINER: Georg Richter <georg@php.net> (2003 - 2006)
|
||||
Andrey Hristov <andrey@php.net> (2003 - 2016)
|
||||
@@ -166,7 +169,6 @@ COMMENT: Use PostgreSQL 7.0.x or later. PostgreSQL 6.5.3 or less hav
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sqlite3
|
||||
PRIMARY MAINTAINER: Scott MacVicar <scottmac@php.net> (2008 - 2011)
|
||||
Christoph M. Becker <cmb@php.net> (2016 - 2020)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 5.3
|
||||
@@ -196,6 +198,11 @@ PRIMARY MAINTAINER: Dmitry Stogov <dmitry@php.net> (2004 - 2018)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: wddx
|
||||
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net> (1999 - 2003)
|
||||
MAINTENANCE: Orphaned
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xml
|
||||
PRIMARY MAINTAINER: Thies C. Arntzen <thies@thieso.net> (1999 - 2002)
|
||||
Rob Richards <rrichards@php.net> (2003 - 2013)
|
||||
@@ -209,14 +216,18 @@ MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xmlreader
|
||||
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net> (2004 - 2010)
|
||||
Christian Stocker <chregu@php.net> (2004 - 2004)
|
||||
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net>, Christian Stocker <chregu@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xmlrpc
|
||||
PRIMARY MAINTAINER: Unknown
|
||||
MAINTENANCE: Orphaned
|
||||
STATUS: Experimental
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xmlwriter
|
||||
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net> (2004 - 2010)
|
||||
Pierre-Alain Joye <pajoye@php.net> (2005-2009)
|
||||
Christian Stocker <chregu@php.net> (2004 - 2004)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -233,8 +244,7 @@ SINCE: 5.0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: bcmath
|
||||
PRIMARY MAINTAINER: Andi Gutmans <andi@php.net> (2000 - 2004)
|
||||
MAINTENANCE: Unknown
|
||||
MAINTENANCE: Andi Gutmans <andi@php.net> (2000 - 2004)
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: bz2
|
||||
@@ -250,7 +260,6 @@ STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: com_dotnet
|
||||
PRIMARY MAINTAINER: Wez Furlong <wez@php.net> (2003 - 2005)
|
||||
Christoph M. Becker <cmb@php.net> (2018 - 2020)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Windows
|
||||
SINCE: 5.0
|
||||
@@ -285,15 +294,9 @@ MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: ffi
|
||||
PRIMARY MAINTAINER: Dmitry Stogov <dmitry@php.net> (2018 - 2019)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 7.4.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: fileinfo
|
||||
PRIMARY MAINTAINER: Derick Rethans <derick@php.net> (2004 - 2008)
|
||||
Anatol Belski <ab@php.net> (2012 - 2020)
|
||||
Anatol Belski <ab@php.net> (2012 - 2018)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 5.3
|
||||
@@ -313,19 +316,17 @@ STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: gd
|
||||
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net> (2002 - 2016)
|
||||
Christoph M. Becker <cmb@php.net> (2015 - 2020)
|
||||
Christoph M. Becker <cmb@php.net> (2015 - 2018)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: gettext
|
||||
PRIMARY MAINTAINER: Unknown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: gmp
|
||||
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net> (2000 - 2019)
|
||||
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net> (2000 - 2018)
|
||||
Antony Dovgal <tony2001@php.net> (2005 - 2010)
|
||||
Nikita Popov <nikic@php.net> (2013 - 2020)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.0.4
|
||||
@@ -344,7 +345,7 @@ MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: intl
|
||||
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net> (2008 - 2019)
|
||||
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net> (2008 - 2018)
|
||||
Anatol Belski <ab@php.net> (2017 - 2018)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
@@ -354,7 +355,6 @@ EXTENSION: imap
|
||||
PRIMARY MAINTAINER: Chuck Hagenbuch <chuck@horde.org> (1999 - 2004)
|
||||
Ilia Alshanetsky <iliaa@php.net> (2002 - 2010)
|
||||
Pierre-Alain Joye <pajoye@php.net> (2008 - 2010)
|
||||
Bishop Bettini <bishop@php.net> (2018 - 2019)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -374,14 +374,12 @@ STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mbstring
|
||||
PRIMARY MAINTAINER: Rui Hirokawa <hirokawa@php.net> (2001 - 2013)
|
||||
Nikita Popov <nikic@php.net> (2017 - 2020)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: opcache
|
||||
PRIMARY MAINTAINER: Dmitry Stogov <dmitry@php.net> (2013 - 2018)
|
||||
Xinchen Hui <laruence@php.net> (2013 - 2020)
|
||||
Nikita Popov <nikic@php.net> (2016 - 2020)
|
||||
Xinchen Hui <laruence@php.net> (2013 - 2018)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 5.5.0
|
||||
@@ -409,7 +407,6 @@ EXTENSION: phar
|
||||
PRIMARY MAINTAINER: Greg Beaver <cellog@php.net> (2008 - 2009)
|
||||
Marcus Börger <helly@php.net> (2008 - 2008)
|
||||
Steph Fox <sfox@php.net> (2008 - 2008)
|
||||
Bishop Bettini <bishop@php.net> (2018 - 2019)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 5.3
|
||||
@@ -426,14 +423,17 @@ STATUS: Working
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: readline
|
||||
PRIMARY MAINTAINER: Unknown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: recode
|
||||
PRIMARY MAINTAINER: Kristian Köhntopp <kris@koehntopp.de> (2000 - 2000)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: reflection
|
||||
PRIMARY MAINTAINER: Marcus Börger <helly@php.net> (2003 - 2009)
|
||||
Johannes Schlüter <johannes@php.net> (2006 - 2014)
|
||||
Nikita Popov <nikic@php.net> (2019 - 2020)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -476,17 +476,14 @@ STATUS: Working
|
||||
SINCE: 5.0.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvmsg
|
||||
PRIMARY MAINTAINER: Unknown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvsem
|
||||
PRIMARY MAINTAINER: Unknown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvshm
|
||||
PRIMARY MAINTAINER: Unknown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -499,13 +496,11 @@ STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: tokenizer
|
||||
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net> (2002 - 2002)
|
||||
Nikita Popov <nikic@php.net> (2013 - 2020)
|
||||
MAINTENANCE: Maintained
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: zip
|
||||
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net> (2006 - 2011)
|
||||
Remi Collet <remi@php.net> (2013-2020)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
For installation of PHP, please refer to the online documentation available at:
|
||||
|
||||
https://php.net/install
|
||||
@@ -1,6 +1,6 @@
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, version 3.01
|
||||
Copyright (c) 1999 - 2021 The PHP Group. All rights reserved.
|
||||
Copyright (c) 1999 - 2018 The PHP Group. All rights reserved.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Zend
|
||||
#
|
||||
|
||||
$(builddir)/zend_language_scanner.lo: $(srcdir)/zend_language_parser.h
|
||||
$(builddir)/zend_ini_scanner.lo: $(srcdir)/zend_ini_parser.h
|
||||
|
||||
$(srcdir)/zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
|
||||
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l)
|
||||
|
||||
$(srcdir)/zend_language_parser.h: $(srcdir)/zend_language_parser.c
|
||||
$(srcdir)/zend_language_parser.c: $(srcdir)/zend_language_parser.y
|
||||
@$(YACC) -p zend -v -d $(srcdir)/zend_language_parser.y -o $@
|
||||
|
||||
$(srcdir)/zend_ini_parser.h: $(srcdir)/zend_ini_parser.c
|
||||
$(srcdir)/zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
|
||||
@$(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o $@
|
||||
|
||||
$(srcdir)/zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
|
||||
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
|
||||
|
||||
$(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(srcdir)/zend_language_parser.h
|
||||
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# LCOV
|
||||
#
|
||||
|
||||
LCOV_INCLUDE="."
|
||||
|
||||
lcov: lcov-html
|
||||
|
||||
lcov-test: lcov-clean-data test
|
||||
|
||||
php_lcov.info: lcov-test
|
||||
@echo "Generating data for $@"
|
||||
@rm -rf lcov_data/
|
||||
@$(mkinstalldirs) lcov_data/
|
||||
@echo
|
||||
-@files=`find . -name \*.gcda -o -name \*.gcno -o -name \*.da -o -name \*.c -o -name \*.h | sed -e 's/^\.\///' | sed -e 's/\.gcda//g' -e 's/\.gcno//g' -e 's/\.da//g' | $(EGREP) $(LCOV_INCLUDE) | sed -e 's/.libs/zzzz/g' | sort | sed -e 's/zzzz/.libs/g' | uniq` ;\
|
||||
for x in $$files; do \
|
||||
echo -n . ;\
|
||||
y=`echo $$x | sed -e 's!\.libs/!!'`; \
|
||||
dir=lcov_data/`dirname $$x`; \
|
||||
test -d "$$dir" || $(mkinstalldirs) "$$dir"; \
|
||||
if test -f "$(top_srcdir)/$$y.c"; then \
|
||||
ln -f -s $(top_srcdir)/$$y.c lcov_data/$$y.c; \
|
||||
fi; \
|
||||
if test -f "$(top_srcdir)/$$y.h"; then \
|
||||
ln -f -s $(top_srcdir)/$$y.h lcov_data/$$y.h; \
|
||||
fi; \
|
||||
if test -f "$(top_srcdir)/$$y.re"; then \
|
||||
ln -f -s $(top_srcdir)/$$y.re lcov_data/$$y.re; \
|
||||
fi; \
|
||||
if test -f "$(top_srcdir)/$$y.y"; then \
|
||||
ln -f -s $(top_srcdir)/$$y.y lcov_data/$$y.y; \
|
||||
fi; \
|
||||
if test -f "$(top_srcdir)/$$y.l"; then \
|
||||
ln -f -s $(top_srcdir)/$$y.l lcov_data/$$y.l; \
|
||||
fi; \
|
||||
if test -f "$(top_srcdir)/$$y"; then \
|
||||
ln -f -s $(top_srcdir)/$$y lcov_data/$$y; \
|
||||
fi; \
|
||||
if test -f "$(top_builddir)/$$y.c"; then \
|
||||
ln -f -s $(top_builddir)/$$y.c lcov_data/$$y.c; \
|
||||
fi; \
|
||||
if test -f "$$x.gcno"; then \
|
||||
cp $$x.gcno lcov_data/$$y.gcno ; \
|
||||
fi; \
|
||||
if test -f "$$x.gcda"; then \
|
||||
cp $$x.gcda lcov_data/$$y.gcda ; \
|
||||
fi; \
|
||||
if test -f "$$x.da"; then \
|
||||
cp $$x.da lcov_data/$$y.da ; \
|
||||
fi; \
|
||||
if test -f "$$x.bb"; then \
|
||||
cp $$x.bb lcov_data/$$y.bb ; \
|
||||
fi; \
|
||||
if test -f "$$x.bbg"; then \
|
||||
cp $$x.bbg lcov_data/$$y.bbg ; \
|
||||
fi; \
|
||||
done; \
|
||||
for dir in ext/bcmath/libbcmath ext/date/lib ext/fileinfo/libmagic ext/gd/libgd ext/mbstring/libmbfl ext/mbstring/oniguruma ext/pcre/pcrelib ext/pdo_sqlite/libsqlite ext/sqlite3/libsqlite ext/xmlrpc/libxmlrpc ext/zip/lib; do \
|
||||
if test -d lcov_data/$$dir; then \
|
||||
rm -rf lcov_data/$$dir ; \
|
||||
fi; \
|
||||
done
|
||||
@echo
|
||||
@echo "Generating $@"
|
||||
@$(LTP) --directory lcov_data/ --capture --base-directory=lcov_data --output-file $@
|
||||
|
||||
lcov-html: php_lcov.info
|
||||
@echo "Generating lcov HTML"
|
||||
@$(LTP_GENHTML) --legend --output-directory lcov_html/ --title "PHP Code Coverage" php_lcov.info
|
||||
|
||||
lcov-clean:
|
||||
rm -f php_lcov.info
|
||||
rm -rf lcov_data/
|
||||
rm -rf lcov_html/
|
||||
|
||||
lcov-clean-data:
|
||||
@find . -name \*.gcda -o -name \*.da -o -name \*.bbg? | xargs rm -f
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
mkinstalldirs = $(top_srcdir)/build/shtool mkdir -p
|
||||
INSTALL = $(top_srcdir)/build/shtool install -c
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
|
||||
DEFS = -DPHP_ATOM_INC -I$(top_builddir)/include -I$(top_builddir)/main -I$(top_srcdir)
|
||||
COMMON_FLAGS = $(DEFS) $(INCLUDES) $(EXTRA_INCLUDES) $(CPPFLAGS) $(PHP_FRAMEWORKPATH)
|
||||
|
||||
all: $(all_targets)
|
||||
@echo
|
||||
@echo "Build complete."
|
||||
@echo "Don't forget to run 'make test'."
|
||||
@echo
|
||||
|
||||
build-modules: $(PHP_MODULES) $(PHP_ZEND_EX)
|
||||
|
||||
build-binaries: $(PHP_BINARIES)
|
||||
|
||||
libphp$(PHP_MAJOR_VERSION).la: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
|
||||
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@
|
||||
-@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1
|
||||
|
||||
libs/libphp$(PHP_MAJOR_VERSION).bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
|
||||
$(CC) $(MH_BUNDLE_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ && cp $@ libs/libphp$(PHP_MAJOR_VERSION).so
|
||||
|
||||
install: $(all_targets) $(install_targets)
|
||||
|
||||
install-sapi: $(OVERALL_TARGET)
|
||||
@echo "Installing PHP SAPI module: $(PHP_SAPI)"
|
||||
-@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
|
||||
-@if test ! -r $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME); then \
|
||||
for i in 0.0.0 0.0 0; do \
|
||||
if test -r $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME).$$i; then \
|
||||
$(LN_S) $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME).$$i $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME); \
|
||||
break; \
|
||||
fi; \
|
||||
done; \
|
||||
fi
|
||||
@$(INSTALL_IT)
|
||||
|
||||
install-binaries: build-binaries $(install_binary_targets)
|
||||
|
||||
install-modules: build-modules
|
||||
@test -d modules && \
|
||||
$(mkinstalldirs) $(INSTALL_ROOT)$(EXTENSION_DIR)
|
||||
@echo "Installing shared extensions: $(INSTALL_ROOT)$(EXTENSION_DIR)/"
|
||||
@rm -f modules/*.la >/dev/null 2>&1
|
||||
@$(INSTALL) modules/* $(INSTALL_ROOT)$(EXTENSION_DIR)
|
||||
|
||||
install-headers:
|
||||
-@if test "$(INSTALL_HEADERS)"; then \
|
||||
for i in `echo $(INSTALL_HEADERS)`; do \
|
||||
i=`$(top_srcdir)/build/shtool path -d $$i`; \
|
||||
paths="$$paths $(INSTALL_ROOT)$(phpincludedir)/$$i"; \
|
||||
done; \
|
||||
$(mkinstalldirs) $$paths && \
|
||||
echo "Installing header files: $(INSTALL_ROOT)$(phpincludedir)/" && \
|
||||
for i in `echo $(INSTALL_HEADERS)`; do \
|
||||
if test "$(PHP_PECL_EXTENSION)"; then \
|
||||
src=`echo $$i | $(SED) -e "s#ext/$(PHP_PECL_EXTENSION)/##g"`; \
|
||||
else \
|
||||
src=$$i; \
|
||||
fi; \
|
||||
if test -f "$(top_srcdir)/$$src"; then \
|
||||
$(INSTALL_DATA) $(top_srcdir)/$$src $(INSTALL_ROOT)$(phpincludedir)/$$i; \
|
||||
elif test -f "$(top_builddir)/$$src"; then \
|
||||
$(INSTALL_DATA) $(top_builddir)/$$src $(INSTALL_ROOT)$(phpincludedir)/$$i; \
|
||||
else \
|
||||
(cd $(top_srcdir)/$$src && $(INSTALL_DATA) *.h $(INSTALL_ROOT)$(phpincludedir)/$$i; \
|
||||
cd $(top_builddir)/$$src && $(INSTALL_DATA) *.h $(INSTALL_ROOT)$(phpincludedir)/$$i) 2>/dev/null || true; \
|
||||
fi \
|
||||
done; \
|
||||
fi
|
||||
|
||||
PHP_TEST_SETTINGS = -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1'
|
||||
PHP_TEST_SHARED_EXTENSIONS = ` \
|
||||
if test "x$(PHP_MODULES)" != "x"; then \
|
||||
for i in $(PHP_MODULES)""; do \
|
||||
. $$i; $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \
|
||||
done; \
|
||||
fi; \
|
||||
if test "x$(PHP_ZEND_EX)" != "x"; then \
|
||||
for i in $(PHP_ZEND_EX)""; do \
|
||||
. $$i; $(top_srcdir)/build/shtool echo -n -- " -d $(ZEND_EXT_TYPE)=$(top_builddir)/modules/$$dlname"; \
|
||||
done; \
|
||||
fi`
|
||||
PHP_DEPRECATED_DIRECTIVES_REGEX = '^(magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?)[\t\ ]*='
|
||||
|
||||
test: all
|
||||
@if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \
|
||||
INI_FILE=`$(PHP_EXECUTABLE) -d 'display_errors=stderr' -r 'echo php_ini_loaded_file();' 2> /dev/null`; \
|
||||
if test "$$INI_FILE"; then \
|
||||
$(EGREP) -h -v $(PHP_DEPRECATED_DIRECTIVES_REGEX) "$$INI_FILE" > $(top_builddir)/tmp-php.ini; \
|
||||
else \
|
||||
echo > $(top_builddir)/tmp-php.ini; \
|
||||
fi; \
|
||||
INI_SCANNED_PATH=`$(PHP_EXECUTABLE) -d 'display_errors=stderr' -r '$$a = explode(",\n", trim(php_ini_scanned_files())); echo $$a[0];' 2> /dev/null`; \
|
||||
if test "$$INI_SCANNED_PATH"; then \
|
||||
INI_SCANNED_PATH=`$(top_srcdir)/build/shtool path -d $$INI_SCANNED_PATH`; \
|
||||
$(EGREP) -h -v $(PHP_DEPRECATED_DIRECTIVES_REGEX) "$$INI_SCANNED_PATH"/*.ini >> $(top_builddir)/tmp-php.ini; \
|
||||
fi; \
|
||||
TEST_PHP_EXECUTABLE=$(PHP_EXECUTABLE) \
|
||||
TEST_PHP_SRCDIR=$(top_srcdir) \
|
||||
CC="$(CC)" \
|
||||
$(PHP_EXECUTABLE) -n -c $(top_builddir)/tmp-php.ini $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -n -c $(top_builddir)/tmp-php.ini -d extension_dir=$(top_builddir)/modules/ $(PHP_TEST_SHARED_EXTENSIONS) $(TESTS); \
|
||||
TEST_RESULT_EXIT_CODE=$$?; \
|
||||
rm $(top_builddir)/tmp-php.ini; \
|
||||
exit $$TEST_RESULT_EXIT_CODE; \
|
||||
else \
|
||||
echo "ERROR: Cannot run tests without CLI sapi."; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
find . -name \*.gcno -o -name \*.gcda | xargs rm -f
|
||||
find . -name \*.lo -o -name \*.o | xargs rm -f
|
||||
find . -name \*.la -o -name \*.a | xargs rm -f
|
||||
find . -name \*.so | xargs rm -f
|
||||
find . -name .libs -a -type d|xargs rm -rf
|
||||
rm -f libphp$(PHP_MAJOR_VERSION).la $(SAPI_CLI_PATH) $(SAPI_CGI_PATH) $(SAPI_LITESPEED_PATH) $(SAPI_FPM_PATH) $(OVERALL_TARGET) modules/* libs/*
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h main/internal_functions_cli.c main/internal_functions.c stamp-h buildmk.stamp Zend/zend_dtrace_gen.h Zend/zend_dtrace_gen.h.bak Zend/zend_config.h TSRM/tsrm_config.h
|
||||
rm -f php7.spec main/build-defs.h scripts/phpize
|
||||
rm -f ext/date/lib/timelib_config.h ext/mbstring/oniguruma/config.h ext/mbstring/libmbfl/config.h ext/oci8/oci8_dtrace_gen.h ext/oci8/oci8_dtrace_gen.h.bak
|
||||
rm -f scripts/man1/phpize.1 scripts/php-config scripts/man1/php-config.1 sapi/cli/php.1 sapi/cgi/php-cgi.1 sapi/phpdbg/phpdbg.1 ext/phar/phar.1 ext/phar/phar.phar.1
|
||||
rm -f sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.service sapi/fpm/php-fpm.8 sapi/fpm/status.html
|
||||
rm -f ext/iconv/php_have_bsd_iconv.h ext/iconv/php_have_glibc_iconv.h ext/iconv/php_have_ibm_iconv.h ext/iconv/php_have_iconv.h ext/iconv/php_have_libiconv.h ext/iconv/php_iconv_aliased_libiconv.h ext/iconv/php_iconv_supports_errno.h ext/iconv/php_php_iconv_h_path.h ext/iconv/php_php_iconv_impl.h
|
||||
rm -f ext/phar/phar.phar ext/phar/phar.php
|
||||
if test "$(srcdir)" != "$(builddir)"; then \
|
||||
rm -f ext/phar/phar/phar.inc; \
|
||||
fi
|
||||
$(EGREP) define'.*include/php' $(top_srcdir)/configure | $(SED) 's/.*>//'|xargs rm -f
|
||||
|
||||
prof-gen:
|
||||
CCACHE_DISABLE=1 $(MAKE) PROF_FLAGS=-fprofile-generate all
|
||||
|
||||
prof-clean:
|
||||
find . -name \*.lo -o -name \*.o | xargs rm -f
|
||||
find . -name \*.la -o -name \*.a | xargs rm -f
|
||||
find . -name \*.so | xargs rm -f
|
||||
rm -f libphp$(PHP_MAJOR_VERSION).la $(SAPI_CLI_PATH) $(SAPI_CGI_PATH) $(SAPI_LITESPEED_PATH) $(SAPI_FPM_PATH) $(OVERALL_TARGET) modules/* libs/*
|
||||
|
||||
prof-use:
|
||||
CCACHE_DISABLE=1 $(MAKE) PROF_FLAGS=-fprofile-use all
|
||||
|
||||
|
||||
.PHONY: all clean install distclean test prof-gen prof-clean prof-use
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,43 @@
|
||||
WHAT IT IS
|
||||
|
||||
It's a tool for automatically creating the basic framework for a PHP extension.
|
||||
|
||||
HOW TO USE IT
|
||||
|
||||
Very simple. First, change to the ext/ directory of the PHP sources. Then
|
||||
run the following
|
||||
|
||||
php ext_skel.php --ext extension_name
|
||||
|
||||
and everything you need will be placed in directory ext/extension_name.
|
||||
|
||||
If you don't need to test the existence of any external header files,
|
||||
libraries or functions in them, the extension is ready to be compiled in
|
||||
PHP. To compile the extension, run the following:
|
||||
|
||||
./buildconf; ./configure --enable-extension_name; make
|
||||
|
||||
The definition of PHP_extension_NAME_VERSION will be present in the
|
||||
php_extension_name.h and injected into the zend_extension_entry definition. This
|
||||
is required by the PECL website for the version string conformity checks
|
||||
against package.xml
|
||||
|
||||
SOURCE AND HEADER FILE NAME
|
||||
|
||||
The ext_skel.php script generates 'extension_name.c' and 'php_extension_name.h'
|
||||
as the main source and header files. Keep these names.
|
||||
|
||||
extension functions (User functions) must be named
|
||||
|
||||
extension_name_function()
|
||||
|
||||
When you need to expose extension functions to other extensions, expose functions
|
||||
strictly needed by others. Exposed internal function must be named
|
||||
|
||||
php_extension_name_function()
|
||||
|
||||
See also CODING_STANDARDS.
|
||||
|
||||
OTHER OPTIONS
|
||||
|
||||
Run php ext_skel.php --help to see the available options.
|
||||
@@ -0,0 +1,141 @@
|
||||
====================
|
||||
Git Commit Rules
|
||||
====================
|
||||
|
||||
This is the first file you should be reading when contributing code via Git.
|
||||
We'll assume you're basically familiar with Git, but feel free to post
|
||||
your questions on the mailing list. Please have a look at
|
||||
http://git-scm.com/ for more detailed information on Git.
|
||||
|
||||
PHP is developed through the efforts of a large number of people.
|
||||
Collaboration is a Good Thing(tm), and Git lets us do this. Thus, following
|
||||
some basic rules with regards to Git usage will::
|
||||
|
||||
a. Make everybody happier, especially those responsible for maintaining
|
||||
PHP itself.
|
||||
|
||||
b. Keep the changes consistently well documented and easily trackable.
|
||||
|
||||
c. Prevent some of those 'Oops' moments.
|
||||
|
||||
d. Increase the general level of good will on planet Earth.
|
||||
|
||||
Having said that, here are the organizational rules::
|
||||
|
||||
1. Respect other people working on the project.
|
||||
|
||||
2. Discuss any significant changes on the list before committing and get
|
||||
confirmation from the release manager for the given branch.
|
||||
|
||||
3. Look at EXTENSIONS file to see who is the primary maintainer of
|
||||
the code you want to contribute to.
|
||||
|
||||
4. If you "strongly disagree" about something another person did, don't
|
||||
start fighting publicly - take it up in private email.
|
||||
|
||||
5. If you don't know how to do something, ask first!
|
||||
|
||||
6. Test your changes before committing them. We mean it. Really.
|
||||
To do so use "make test".
|
||||
|
||||
7. For development use the --enable-debug switch to avoid memory leaks
|
||||
and the --enable-maintainer-zts switch to ensure your code handles
|
||||
TSRM correctly and doesn't break for those who need that.
|
||||
|
||||
Currently we have the following branches in use::
|
||||
|
||||
master The active development branch.
|
||||
|
||||
PHP-7.2 Is used to release the PHP 7.2.x series. This is a current
|
||||
stable version and is open for bugfixes only.
|
||||
|
||||
PHP-7.1 Is used to release the PHP 7.1.x series. This is a current
|
||||
stable version and is open for bugfixes only.
|
||||
|
||||
PHP-7.0 Is used to release the PHP 7.0.x series. This is an old
|
||||
stable version and is open for security fixes only.
|
||||
|
||||
PHP-5.6 Is used to release the PHP 5.6.x series. This is an old
|
||||
stable version and is open for security fixes only.
|
||||
|
||||
PHP-5.5 This branch is closed.
|
||||
|
||||
PHP-5.4 This branch is closed.
|
||||
|
||||
PHP-5.3 This branch is closed.
|
||||
|
||||
PHP-5.2 This branch is closed.
|
||||
|
||||
PHP-5.1 This branch is closed.
|
||||
|
||||
PHP-4.4 This branch is closed.
|
||||
|
||||
PHP-X.Y.Z These branches are used for the release managers for tagging
|
||||
the releases, hence they are closed to the general public.
|
||||
|
||||
The next few rules are more of a technical nature::
|
||||
|
||||
1. All changes should first go to the lowest branch (i.e. 5.6) and then
|
||||
get merged up to all other branches. If a change is not needed for
|
||||
later branches (i.e. fixes for features which were dropped from later
|
||||
branches) an empty merge should be done.
|
||||
|
||||
2. All news updates intended for public viewing, such as new features,
|
||||
bug fixes, improvements, etc., should go into the NEWS file of *any
|
||||
stable release* version with the given change. In other words,
|
||||
news about a bug fix which went into PHP-5.4, PHP-5.5 and master
|
||||
should be noted in both PHP-5.4/NEWS and PHP-5.5/NEWS but
|
||||
not master, which is not a public released version yet.
|
||||
|
||||
3. Do not commit multiple files and dump all messages in one commit. If you
|
||||
modified several unrelated files, commit each group separately and
|
||||
provide a nice commit message for each one. See example below.
|
||||
|
||||
4. Do write your commit message in such a way that it makes sense even
|
||||
without the corresponding diff. One should be able to look at it, and
|
||||
immediately know what was modified. Definitely include the function name
|
||||
in the message as shown below.
|
||||
|
||||
5. In your commit messages, keep each line shorter than 80 characters. And
|
||||
try to align your lines vertically, if they wrap. It looks bad otherwise.
|
||||
|
||||
6. If you modified a function that is callable from PHP, prepend PHP to
|
||||
the function name as shown below.
|
||||
|
||||
|
||||
The format of the commit messages is pretty simple.
|
||||
|
||||
<max 79 characters short description>\n
|
||||
\n
|
||||
<long description, 79 chars per line>
|
||||
\n
|
||||
|
||||
An Example from the git project (commit 2b34e486bc):
|
||||
|
||||
pack-objects: Fix compilation with NO_PTHREDS
|
||||
|
||||
It looks like commit 99fb6e04 (pack-objects: convert to use
|
||||
parse_options(), 2012-02-01) moved the #ifdef NO_PTHREDS around but
|
||||
hasn't noticed that the 'arg' variable no longer is available.
|
||||
|
||||
If you fix some bugs, you should note the bug ID numbers in your
|
||||
commit message. Bug ID should be prefixed by "#" for easier access to
|
||||
bug report when developers are browsing CVS via LXR or Bonsai.
|
||||
|
||||
Example:
|
||||
|
||||
Fixed bug #14016 (pgsql notice handler double free crash bug.)
|
||||
|
||||
When you change the NEWS file for a bug fix, then please keep the bugs
|
||||
sorted in decreasing order under the fixed version.
|
||||
|
||||
You can use OpenGrok (http://lxr.php.net/) and gitweb (http://git.php.net/)
|
||||
to look at PHP Git repository in various ways.
|
||||
|
||||
|
||||
For further information on the process and further details please refer to
|
||||
https://wiki.php.net/vcs/gitworkflow and https://wiki.php.net/vcs/gitfaq
|
||||
|
||||
Happy hacking,
|
||||
|
||||
PHP Team
|
||||
@@ -0,0 +1,79 @@
|
||||
====================
|
||||
Mailinglist Rules
|
||||
====================
|
||||
|
||||
This is the first file you should be reading before doing any posts on PHP
|
||||
mailinglists. Following these rules is considered imperative to the success of
|
||||
the PHP project. Therefore expect your contributions to be of much less positive
|
||||
impact if you do not follow these rules. More importantly you can actually
|
||||
assume that not following these rules will hurt the PHP project.
|
||||
|
||||
PHP is developed through the efforts of a large number of people.
|
||||
Collaboration is a Good Thing(tm), and mailinglists lets us do this. Thus,
|
||||
following some basic rules with regards to mailinglist usage will:
|
||||
|
||||
a. Make everybody happier, especially those responsible for developing PHP
|
||||
itself.
|
||||
|
||||
b. Help in making sure we all use our time more efficiently.
|
||||
|
||||
c. Prevent you from making a fool of yourself in public.
|
||||
|
||||
d. Increase the general level of good will on planet Earth.
|
||||
|
||||
|
||||
Having said that, here are the organizational rules:
|
||||
|
||||
1. Respect other people working on the project.
|
||||
|
||||
2. Do not post when you are angry. Any post can wait a few hours. Review
|
||||
your post after a good breather or a good nights sleep.
|
||||
|
||||
3. Make sure you pick the right mailinglist for your posting. Please review
|
||||
the descriptions on the mailinglist overview page
|
||||
(http://www.php.net/mailing-lists.php). When in doubt ask a friend or
|
||||
someone you trust on IRC.
|
||||
|
||||
4. Make sure you know what you are talking about. PHP is a very large project
|
||||
that strives to be very open. The flip side is that the core developers
|
||||
are faced with a lot of requests. Make sure that you have done your
|
||||
research before posting to the entire developer community.
|
||||
|
||||
5. Patches have a much greater chance of acceptance than just asking the
|
||||
PHP developers to implement a feature for you. For one it makes the
|
||||
discussion more concrete and it shows that the poster put thought and time
|
||||
into the request.
|
||||
|
||||
6. If you are posting to an existing thread, make sure that you know what
|
||||
previous posters have said. This is even more important the longer the
|
||||
thread is already.
|
||||
|
||||
7. Please configure your email client to use a real name and keep message
|
||||
signatures to a maximum of 2 lines if at all necessary.
|
||||
|
||||
The next few rules are more some general hints:
|
||||
|
||||
1. If you notice that your posting ratio is much higher than that of other
|
||||
people, double check the above rules. Try to wait a bit longer before
|
||||
sending your replies to give other people more time to digest your answers
|
||||
and more importantly give you the opportunity to make sure that you
|
||||
aggregate your current position into a single mail instead of multiple
|
||||
ones.
|
||||
|
||||
2. Consider taking a step back from a very active thread now and then. Maybe
|
||||
talking to some friends and fellow developers will help in understanding
|
||||
the other opinions better.
|
||||
|
||||
3. Do not top post. Place your answer underneath anyone you wish to quote
|
||||
and remove any previous comment that is not relevant to your post.
|
||||
|
||||
4. Do not high-jack threads, by bringing up entirely new topics. Please
|
||||
create an entirely new thread copying anything you wish to quote into the
|
||||
new thread.
|
||||
|
||||
Finally, additional hints on how to behave inside the virtual community can be
|
||||
found in RFC 1855 (http://www.faqs.org/rfcs/rfc1855.html).
|
||||
|
||||
Happy hacking,
|
||||
|
||||
PHP Team
|
||||
@@ -0,0 +1,139 @@
|
||||
API adjustment to the old output control code:
|
||||
|
||||
Everything now resides beneath the php_output namespace,
|
||||
and there's an API call for every output handler op.
|
||||
|
||||
Checking output control layers status:
|
||||
// Using OG()
|
||||
php_output_get_status();
|
||||
|
||||
Starting the default output handler:
|
||||
// php_start_ob_buffer(NULL, 0, 1);
|
||||
php_output_start_default();
|
||||
|
||||
Starting an user handler by zval:
|
||||
// php_start_ob_buffer(zhandler, chunk_size, erase);
|
||||
php_output_start_user(zhandler, chunk_size, flags);
|
||||
|
||||
Starting an internal handler without context:
|
||||
// php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase);
|
||||
php_output_start_internal(handler_name, handler_name_len, my_php_output_handler_func_t, chunk_size, flags);
|
||||
|
||||
Starting an internal handler with context:
|
||||
// not possible with old API
|
||||
php_output_handler *h;
|
||||
h = php_output_handler_create_internal(handler_name, handler_name_len, my_php_output_handler_context_func_t, chunk_size, flags);
|
||||
php_output_handler_set_context(h, my_context, my_context_dtor);
|
||||
php_output_handler_start(h);
|
||||
|
||||
Testing whether a certain output handler has already been started:
|
||||
// php_ob_handler_used("output handler name");
|
||||
php_output_handler_started(handler_name, handler_name_len);
|
||||
|
||||
Flushing one output buffer:
|
||||
// php_end_ob_buffer(1, 1);
|
||||
php_output_flush();
|
||||
|
||||
Flushing all output buffers:
|
||||
// not possible with old API
|
||||
php_output_flush_all();
|
||||
|
||||
Cleaning one output buffer:
|
||||
// php_ob_end_buffer(0, 1);
|
||||
php_output_clean();
|
||||
|
||||
Cleaning all output buffers:
|
||||
// not possible with old API
|
||||
php_output_clean_all();
|
||||
|
||||
Discarding one output buffer:
|
||||
// php_ob_end_buffer(0, 0);
|
||||
php_output_discard();
|
||||
|
||||
Discarding all output buffers:
|
||||
// php_ob_end_buffers(0);
|
||||
php_output_discard_all();
|
||||
|
||||
Stopping (and dropping) one output buffer:
|
||||
// php_ob_end_buffer(1, 0)
|
||||
php_output_end();
|
||||
|
||||
Stopping (and dropping) all output buffers:
|
||||
// php_ob_end_buffers(1, 0);
|
||||
php_output_end_all();
|
||||
|
||||
Retrieving output buffers contents:
|
||||
// php_ob_get_buffer(zstring);
|
||||
php_output_get_contents(zstring);
|
||||
|
||||
Retrieving output buffers length:
|
||||
// php_ob_get_length(zlength);
|
||||
php_output_get_length(zlength);
|
||||
|
||||
Retrieving output buffering level:
|
||||
// OG(nesting_level);
|
||||
php_output_get_level();
|
||||
|
||||
Issue a warning because of an output handler conflict:
|
||||
// php_ob_init_conflict("to be started handler name", "to be tested if already started handler name");
|
||||
php_output_handler_conflict(new_handler_name, new_handler_name_len, set_handler_name, set_handler_name_len);
|
||||
|
||||
Registering a conflict checking function, which will be checked prior starting the handler:
|
||||
// not possible with old API, unless hardcoding into output.c
|
||||
php_output_handler_conflict_register(handler_name, handler_name_len, my_php_output_handler_conflict_check_t);
|
||||
|
||||
Registering a reverse conflict checking function, which will be checked prior starting the specified foreign handler:
|
||||
// not possible with old API
|
||||
php_output_handler_reverse_conflict_register(foreign_handler_name, foreign_handler_name_len, my_php_output_handler_conflict_check_t);
|
||||
|
||||
Facilitating a context from within an output handler callable with ob_start():
|
||||
// not possible with old API
|
||||
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr);
|
||||
|
||||
Disabling of the output handler by itself:
|
||||
//not possible with old API
|
||||
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL);
|
||||
|
||||
Marking an output handler immutable by itself because of irreversibility of its operation:
|
||||
// not possible with old API
|
||||
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL);
|
||||
|
||||
Restarting the output handler because of a CLEAN operation:
|
||||
// not possible with old API
|
||||
if (flags & PHP_OUTPUT_HANDLER_CLEAN) { ... }
|
||||
|
||||
Recognizing by the output handler itself if it gets discarded:
|
||||
// not possible with old API
|
||||
if ((flags & PHP_OUTPUT_HANDLER_CLEAN) && (flags & PHP_OUTPUT_HANDLER_FINAL)) { ... }
|
||||
|
||||
|
||||
Output handler hooks
|
||||
|
||||
The output handler can change its abilities at runtime. Eg. the gz handler can
|
||||
remove the CLEANABLE and REMOVABLE bits when the first output has passed through it;
|
||||
or handlers implemented in C to be used with ob_start() can contain a non-global
|
||||
context:
|
||||
PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ
|
||||
pass a void*** pointer as second arg to receive the address of a pointer
|
||||
pointer to the opaque field of the output handler context
|
||||
PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS
|
||||
pass a int* pointer as second arg to receive the flags set for the output handler
|
||||
PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL
|
||||
pass a int* pointer as second arg to receive the level of this output handler
|
||||
(starts with 0)
|
||||
PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE
|
||||
the second arg is ignored; marks the output handler to be neither cleanable
|
||||
nor removable
|
||||
PHP_OUTPUT_HANDLER_HOOK_DISABLE
|
||||
the second arg is ignored; marks the output handler as disabled
|
||||
|
||||
|
||||
Open questions
|
||||
|
||||
Should the userland API be adjusted and unified?
|
||||
|
||||
Many bits of the manual (and very first implementation) do not comply
|
||||
with the behaviour of the current (to be obsoleted) code, thus should
|
||||
the manual or the behaviour be adjusted?
|
||||
|
||||
END
|
||||
@@ -0,0 +1,235 @@
|
||||
New parameter parsing functions
|
||||
===============================
|
||||
|
||||
It should be easier to parse input parameters to an extension function.
|
||||
Hence, borrowing from Python's example, there are now a set of functions
|
||||
that given the string of type specifiers, can parse the input parameters
|
||||
and store the results in the user specified variables. This avoids most
|
||||
of the IS_* checks and convert_to_* conversions. The functions also
|
||||
check for the appropriate number of parameters, and try to output
|
||||
meaningful error messages.
|
||||
|
||||
|
||||
Prototypes
|
||||
----------
|
||||
/* Implemented. */
|
||||
int zend_parse_parameters(int num_args, char *type_spec, ...);
|
||||
int zend_parse_parameters_ex(int flags, int num_args, char *type_spec, ...);
|
||||
|
||||
The zend_parse_parameters() function takes the number of parameters
|
||||
passed to the extension function, the type specifier string, and the
|
||||
list of pointers to variables to store the results in. The _ex() version
|
||||
also takes 'flags' argument -- current only ZEND_PARSE_PARAMS_QUIET can
|
||||
be used as 'flags' to specify that the function should operate quietly
|
||||
and not output any error messages.
|
||||
|
||||
Both functions return SUCCESS or FAILURE depending on the result.
|
||||
|
||||
The auto-conversions are performed as necessary. Arrays, objects, and
|
||||
resources cannot be auto-converted.
|
||||
|
||||
PHP 5.3 includes a new function (actually implemented as macro):
|
||||
|
||||
int zend_parse_parameters_none();
|
||||
|
||||
This returns SUCCESS if no argument has been passed to the function,
|
||||
FAILURE otherwise.
|
||||
|
||||
PHP 5.5 includes a new function:
|
||||
|
||||
int zend_parse_parameter(int flags, int arg_num, zval **arg, const char *spec, ...);
|
||||
|
||||
This function behaves like zend_parse_parameters_ex() except that instead of
|
||||
reading the arguments from the stack, it receives a single zval to convert
|
||||
(passed with double indirection). The passed zval may be changed in place as
|
||||
part of the conversion process.
|
||||
|
||||
See also https://wiki.php.net/rfc/zpp_improv#expose_zend_parse_arg_as_zend_parse_parameter
|
||||
|
||||
|
||||
Type specifiers
|
||||
---------------
|
||||
The following list shows the type specifier, its meaning and the parameter
|
||||
types that need to be passed by address. All passed parameters are set
|
||||
if the PHP parameter is non optional and untouched if optional and the
|
||||
parameter is not present. The only exception is O where the zend_class_entry*
|
||||
has to be provided on input and is used to verify the PHP parameter is an
|
||||
instance of that class.
|
||||
|
||||
a - array (zval*)
|
||||
A - array or object (zval*)
|
||||
b - boolean (zend_bool)
|
||||
C - class (zend_class_entry*)
|
||||
d - double (double)
|
||||
f - function or array containing php method call info (returned as
|
||||
zend_fcall_info and zend_fcall_info_cache)
|
||||
h - array (returned as HashTable*)
|
||||
H - array or HASH_OF(object) (returned as HashTable*)
|
||||
l - long (zend_long)
|
||||
L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (zend_long, ZEND_LONG_MAX/ZEND_LONG_MIN)
|
||||
o - object of any type (zval*)
|
||||
O - object of specific type given by class entry (zval*, zend_class_entry)
|
||||
p - valid path (string without null bytes in the middle) and its length (char*, size_t)
|
||||
P - valid path (string without null bytes in the middle) as zend_string (zend_string*)
|
||||
r - resource (zval*)
|
||||
s - string (with possible null bytes) and its length (char*, size_t)
|
||||
S - string (with possible null bytes) as zend_string (zend_string*)
|
||||
z - the actual zval (zval*)
|
||||
* - variable arguments list (0 or more)
|
||||
+ - variable arguments list (1 or more)
|
||||
|
||||
The following characters also have a meaning in the specifier string:
|
||||
| - indicates that the remaining parameters are optional, they
|
||||
should be initialized to default values by the extension since they
|
||||
will not be touched by the parsing function if they are not
|
||||
passed to it.
|
||||
/ - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
|
||||
! - the parameter it follows can be of specified type or NULL. If NULL is
|
||||
passed and the output for such type is a pointer, then the output
|
||||
pointer is set to a native NULL pointer.
|
||||
For 'b', 'l' and 'd', an extra argument of type zend_bool* must be
|
||||
passed after the corresponding bool*, zend_long* or double* arguments,
|
||||
respectively. A non-zero value will be written to the zend_bool if a
|
||||
PHP NULL is passed.
|
||||
|
||||
|
||||
Note on 64bit compatibility
|
||||
---------------------------
|
||||
Please note that since version 7 PHP uses zend_long as integer type and
|
||||
zend_string with size_t as length, so make sure you pass zend_longs to "l"
|
||||
and size_t to strings length (i.e. for "s" you need to pass char * and size_t),
|
||||
not the other way round!
|
||||
|
||||
Both mistakes might cause memory corruptions and segfaults:
|
||||
1)
|
||||
char *str;
|
||||
long str_len; /* XXX THIS IS WRONG!! Use size_t instead. */
|
||||
zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len)
|
||||
|
||||
2)
|
||||
int num; /* XXX THIS IS WRONG!! Use zend_long instead. */
|
||||
zend_parse_parameters(ZEND_NUM_ARGS(), "l", &num)
|
||||
|
||||
If you're in doubt, use check_parameters.php script to the parameters
|
||||
and their types (it can be found in ./scripts/dev/ directory of PHP sources):
|
||||
|
||||
# php ./scripts/dev/check_parameters.php /path/to/your/sources/
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
/* Gets a long, a string and its length, and a zval */
|
||||
zend_long l;
|
||||
char *s;
|
||||
size_t s_len;
|
||||
zval *param;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "lsz",
|
||||
&l, &s, &s_len, ¶m) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets an object of class specified by my_ce, and an optional double. */
|
||||
zval *obj;
|
||||
double d = 0.5;
|
||||
zend_class_entry *my_ce;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|d",
|
||||
&obj, my_ce, &d) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets an object or null, and an array.
|
||||
If null is passed for object, obj will be set to NULL. */
|
||||
zval *obj;
|
||||
zval *arr;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a",
|
||||
&obj, &arr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets a separated array which can also be null. */
|
||||
zval *arr;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/!",
|
||||
&arr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get either a set of 3 longs or a string. */
|
||||
zend_long l1, l2, l3;
|
||||
char *s;
|
||||
/*
|
||||
* The function expects a pointer to a size_t in this case, not a long
|
||||
* or any other type. If you specify a type which is larger
|
||||
* than a 'size_t', the upper bits might not be initialized
|
||||
* properly, leading to random crashes on platforms like
|
||||
* Tru64 or Linux/Alpha.
|
||||
*/
|
||||
size_t length;
|
||||
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
|
||||
"lll", &l1, &l2, &l3) == SUCCESS) {
|
||||
/* manipulate longs */
|
||||
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
|
||||
"s", &s, &length) == SUCCESS) {
|
||||
/* manipulate string */
|
||||
} else {
|
||||
/* output error */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Function that accepts only varargs (0 or more) */
|
||||
|
||||
int i, num_varargs;
|
||||
zval *varargs = NULL;
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &varargs, &num_varargs) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_varargs; i++) {
|
||||
/* do something with varargs[i] */
|
||||
}
|
||||
|
||||
if (varargs) {
|
||||
efree(varargs);
|
||||
}
|
||||
|
||||
|
||||
/* Function that accepts a string, followed by varargs (1 or more) */
|
||||
|
||||
char *str;
|
||||
size_t str_len;
|
||||
int i, num_varargs;
|
||||
zval *varargs = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_varargs; i++) {
|
||||
/* do something with varargs[i] */
|
||||
}
|
||||
|
||||
/* Function that takes an array, followed by varargs, and ending with a long */
|
||||
zend_long num;
|
||||
zval *array;
|
||||
int i, num_varargs;
|
||||
zval *varargs = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_varargs; i++) {
|
||||
/* do something with varargs[i] */
|
||||
}
|
||||
|
||||
/* Function that doesn't accept any arguments */
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
+139
-236
@@ -1,23 +1,25 @@
|
||||
1. libmagic (ext/fileinfo) see ext/fileinfo/libmagic/LICENSE
|
||||
2. libmbfl (ext/mbstring) see ext/mbstring/libmbfl/LICENSE
|
||||
3. pcre2lib (ext/pcre)
|
||||
4. ext/standard crypt
|
||||
5. ext/standard crypt's blowfish implementation
|
||||
6. ext/standard/rand
|
||||
7. ext/standard/scanf
|
||||
8. ext/standard/strnatcmp.c
|
||||
9. ext/standard/uuencode
|
||||
10. main/snprintf.c
|
||||
11. main/strlcat
|
||||
12. main/strlcpy
|
||||
13. libgd (ext/gd)
|
||||
14. ext/phar portions of tar implementations
|
||||
15. ext/phar/zip.c portion extracted from libzip
|
||||
16. libbcmath (ext/bcmath) see ext/bcmath/libbcmath/LICENSE
|
||||
17. ext/mbstring/ucgendat portions based on the ucgendat.c from the OpenLDAP
|
||||
1. libmagic (ext/fileinfo) see ext/fileinfo/libmagic/LICENSE
|
||||
2. Oniguruma (ext/mbstring) see ext/mbstring/oniguruma/COPYING
|
||||
3. libmbfl (ext/mbstring) see ext/mbstring/libmbfl/LICENSE
|
||||
4. pcre2lib (ext/pcre)
|
||||
5. ext/standard crypt
|
||||
6. ext/standard crypt's blowfish implementation
|
||||
7. Sqlite/Sqlite3 ext/sqlite3 ext/sqlite
|
||||
8. ext/standard/rand
|
||||
9. ext/standard/scanf
|
||||
10. ext/standard/strnatcmp.c
|
||||
11. ext/standard/uuencode
|
||||
12. libxmlrpc ext/xmlrpc
|
||||
13. libzip ext/zip
|
||||
14. main/snprintf.c
|
||||
15. main/strlcat
|
||||
16. main/strlcpy
|
||||
17. libgd see ext/gd/libgd/COPYING
|
||||
18. ext/phar portions of tar implementations
|
||||
19. libbcmath (ext/bcmath) see ext/bcmath/libbcmath/COPYING.LIB
|
||||
|
||||
|
||||
3. pcre2lib (ext/pcre)
|
||||
4. pcre2lib (ext/pcre)
|
||||
|
||||
PCRE2 LICENCE
|
||||
-------------
|
||||
@@ -25,11 +27,11 @@ PCRE2 LICENCE
|
||||
PCRE2 is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Releases 10.00 and above of PCRE2 are distributed under the terms of the "BSD"
|
||||
licence, as specified below, with one exemption for certain binary
|
||||
redistributions. The documentation for PCRE2, supplied in the "doc" directory,
|
||||
is distributed under the same terms as the software itself. The data in the
|
||||
testdata directory is not copyrighted and is in the public domain.
|
||||
Release 10 of PCRE2 is distributed under the terms of the "BSD" licence, as
|
||||
specified below, with one exemption for certain binary redistributions. The
|
||||
documentation for PCRE2, supplied in the "doc" directory, is distributed under
|
||||
the same terms as the software itself. The data in the testdata directory is
|
||||
not copyrighted and is in the public domain.
|
||||
|
||||
The basic library functions are written in C and are freestanding. Also
|
||||
included in the distribution is a just-in-time compiler that can be used to
|
||||
@@ -47,7 +49,7 @@ Email domain: cam.ac.uk
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2019 University of Cambridge
|
||||
Copyright (c) 1997-2018 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -56,9 +58,9 @@ PCRE2 JUST-IN-TIME COMPILATION SUPPORT
|
||||
|
||||
Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Email domain: freemail.hu
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2019 Zoltan Herczeg
|
||||
Copyright(c) 2010-2018 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -67,9 +69,9 @@ STACK-LESS JUST-IN-TIME COMPILER
|
||||
|
||||
Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Email domain: freemail.hu
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2019 Zoltan Herczeg
|
||||
Copyright(c) 2009-2018 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -115,7 +117,7 @@ PCRE2 independently.
|
||||
End
|
||||
|
||||
|
||||
4. ext/standard crypt
|
||||
5. ext/standard crypt
|
||||
|
||||
FreeSec: libcrypt for NetBSD
|
||||
|
||||
@@ -126,13 +128,13 @@ Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the author nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -147,7 +149,7 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
|
||||
5. ext/standard crypt's blowfish implementation
|
||||
6. ext/standard crypt's blowfish implementation
|
||||
|
||||
The crypt_blowfish homepage is:
|
||||
|
||||
@@ -193,8 +195,16 @@ Blowfish library (I can't be sure if I would think of something if I
|
||||
hadn't seen his code).
|
||||
|
||||
|
||||
6. ext/standard/rand
|
||||
7. Sqlite/Sqlite3 ext/sqlite3 ext/sqlite
|
||||
|
||||
The author disclaims copyright to this source code. In place of
|
||||
a legal notice, here is a blessing:
|
||||
May you do good and not evil.
|
||||
May you find forgiveness for yourself and forgive others.
|
||||
May you share freely, never taking more than you give.
|
||||
|
||||
|
||||
8. ext/standard/rand
|
||||
The following php_mt_...() functions are based on a C++ class MTRand by
|
||||
Richard J. Wagner. For more information see the web page at
|
||||
http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
|
||||
@@ -224,15 +234,15 @@ modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of its contributors may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
@@ -247,8 +257,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
7. ext/standard/scanf
|
||||
|
||||
9. ext/standard/scanf
|
||||
scanf.c --
|
||||
|
||||
This file contains the base code which implements sscanf and by extension
|
||||
@@ -294,8 +303,7 @@ authors grant the U.S. Government and others acting in its behalf
|
||||
permission to use and distribute the software in accordance with the
|
||||
terms specified in this license.
|
||||
|
||||
|
||||
8. ext/standard/strnatcmp.c
|
||||
10. ext/standard/strnatcmp.c
|
||||
|
||||
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||
Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
|
||||
@@ -309,16 +317,14 @@ including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
|
||||
9. ext/standard/uuencode
|
||||
|
||||
11. ext/standard/uuencode
|
||||
Portions of this code are based on Berkeley's uuencode/uudecode
|
||||
implementation.
|
||||
|
||||
@@ -329,17 +335,17 @@ Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the University of
|
||||
California, Berkeley and its contributors.
|
||||
4. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -354,8 +360,63 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
|
||||
10. main/snprintf.c
|
||||
12. libxmlrpc ext/xmlrpc
|
||||
|
||||
Copyright 2000 Epinions, Inc.
|
||||
|
||||
Subject to the following 3 conditions, Epinions, Inc. permits you, free
|
||||
of charge, to (a) use, copy, distribute, modify, perform and display this
|
||||
software and associated documentation files (the "Software"), and (b)
|
||||
permit others to whom the Software is furnished to do so as well.
|
||||
|
||||
1) The above copyright notice and this permission notice shall be included
|
||||
without modification in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
|
||||
ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
|
||||
IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE OR NONINFRINGEMENT.
|
||||
|
||||
3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
|
||||
NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
13. libzip ext/zip
|
||||
zip.h -- exported declarations.
|
||||
Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
14. main/snprintf.c
|
||||
Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -382,26 +443,26 @@ modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. All advertising materials mentioning features or use of this
|
||||
software must display the following acknowledgment:
|
||||
"This product includes software developed by the Apache Group
|
||||
for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
software must display the following acknowledgment:
|
||||
"This product includes software developed by the Apache Group
|
||||
for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
|
||||
4. The names "Apache Server" and "Apache Group" must not be used to
|
||||
endorse or promote products derived from this software without
|
||||
prior written permission.
|
||||
endorse or promote products derived from this software without
|
||||
prior written permission.
|
||||
|
||||
5. Redistributions of any form whatsoever must retain the following
|
||||
acknowledgment:
|
||||
"This product includes software developed by the Apache Group
|
||||
for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
acknowledgment:
|
||||
"This product includes software developed by the Apache Group
|
||||
for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
|
||||
EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -428,10 +489,8 @@ This code is based on, and used with the permission of, the
|
||||
SIO stdio-replacement strx_* functions by Panos Tsirigotis
|
||||
<panos@alumni.cs.colorado.edu> for xinetd.
|
||||
|
||||
|
||||
11. main/strlcat
|
||||
12. main/strlcpy
|
||||
|
||||
15. main/strlcat
|
||||
16. main/strlcpy
|
||||
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
All rights reserved.
|
||||
|
||||
@@ -439,12 +498,12 @@ Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
@@ -457,78 +516,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
13. libgd (ext/gd)
|
||||
|
||||
* Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004 by Cold Spring Harbor Laboratory. Funded under
|
||||
Grant P41-RR02188 by the National Institutes of Health.
|
||||
|
||||
* Portions copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004 by Boutell.Com, Inc.
|
||||
|
||||
* Portions relating to GD2 format copyright 1999, 2000, 2001, 2002,
|
||||
2003, 2004 Philip Warner.
|
||||
|
||||
* Portions relating to PNG copyright 1999, 2000, 2001, 2002, 2003,
|
||||
2004 Greg Roelofs.
|
||||
|
||||
* Portions relating to gdttf.c copyright 1999, 2000, 2001, 2002,
|
||||
2003, 2004 John Ellson (ellson@graphviz.org).
|
||||
|
||||
* Portions relating to gdft.c copyright 2001, 2002, 2003, 2004 John
|
||||
Ellson (ellson@graphviz.org).
|
||||
|
||||
* Portions copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
Pierre-Alain Joye (pierre@libgd.org).
|
||||
|
||||
* Portions relating to JPEG and to color quantization copyright
|
||||
2000, 2001, 2002, 2003, 2004, Doug Becker and copyright (C) 1994,
|
||||
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Thomas
|
||||
G. Lane. This software is based in part on the work of the
|
||||
Independent JPEG Group. See the file README-JPEG.TXT for more
|
||||
information.
|
||||
|
||||
* Portions relating to GIF compression copyright 1989 by Jef
|
||||
Poskanzer and David Rowley, with modifications for thread safety
|
||||
by Thomas Boutell.
|
||||
|
||||
* Portions relating to GIF decompression copyright 1990, 1991, 1993
|
||||
by David Koblas, with modifications for thread safety by Thomas
|
||||
Boutell.
|
||||
|
||||
* Portions relating to WBMP copyright 2000, 2001, 2002, 2003, 2004
|
||||
Maurice Szmurlo and Johan Van den Brande.
|
||||
|
||||
* Portions relating to GIF animations copyright 2004 Jaakko Hyvätti
|
||||
(jaakko.hyvatti@iki.fi)
|
||||
|
||||
Permission has been granted to copy, distribute and modify gd in
|
||||
any context without fee, including a commercial application,
|
||||
provided that this notice is present in user-accessible supporting
|
||||
documentation.
|
||||
|
||||
This does not affect your ownership of the derived work itself,
|
||||
and the intent is to assure proper credit for the authors of gd,
|
||||
not to interfere with your productive use of gd. If you have
|
||||
questions, ask. "Derived works" includes all programs that utilize
|
||||
the library. Credit must be given in user-accessible
|
||||
documentation.
|
||||
|
||||
This software is provided "AS IS." The copyright holders disclaim
|
||||
all warranties, either express or implied, including but not
|
||||
limited to implied warranties of merchantability and fitness for a
|
||||
particular purpose, with respect to this code and accompanying
|
||||
documentation.
|
||||
|
||||
Although their code does not appear in the current release, the
|
||||
authors wish to thank David Koblas, David Rowley, and Hutchison
|
||||
Avenue Software Corporation for their prior contributions.
|
||||
|
||||
END OF COPYRIGHT STATEMENT
|
||||
|
||||
|
||||
14. ext/phar portions of tar implementations
|
||||
18. ext/phar portions of tar implementations
|
||||
|
||||
portions of tar implementations in ext/phar - phar_tar_octal() are based on an
|
||||
implementation by Tim Kientzle from libarchive, licensed with this license:
|
||||
@@ -555,88 +543,3 @@ implementation by Tim Kientzle from libarchive, licensed with this license:
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
15. ext/phar/zip.c portion extracted from libzip
|
||||
|
||||
zip_dirent.c -- read directory entry (local or central), clean dirent
|
||||
Copyright (C) 1999, 2003, 2004, 2005 Dieter Baron and Thomas Klausner
|
||||
|
||||
This function is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <nih@giga.or.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
16. ext/mbstring/ucgendat portions based on the ucgendat.c from the OpenLDAP
|
||||
|
||||
The OpenLDAP Public License
|
||||
Version 2.8, 17 August 2003
|
||||
|
||||
Redistribution and use of this software and associated documentation
|
||||
("Software"), with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
1. Redistributions in source form must retain copyright statements
|
||||
and notices,
|
||||
|
||||
2. Redistributions in binary form must reproduce applicable copyright
|
||||
statements and notices, this list of conditions, and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution, and
|
||||
|
||||
3. Redistributions must contain a verbatim copy of this document.
|
||||
|
||||
The OpenLDAP Foundation may revise this license from time to time.
|
||||
Each revision is distinguished by a version number. You may use
|
||||
this Software under terms of this license revision or under the
|
||||
terms of any subsequent revision of the license.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
|
||||
CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
|
||||
OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The names of the authors and copyright holders must not be used in
|
||||
advertising or otherwise to promote the sale, use or other dealing
|
||||
in this Software without specific, written prior permission. Title
|
||||
to copyright in this Software shall at all times remain with copyright
|
||||
holders.
|
||||
|
||||
OpenLDAP is a registered trademark of the OpenLDAP Foundation.
|
||||
|
||||
Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
|
||||
California, USA. All Rights Reserved. Permission to copy and
|
||||
distribute verbatim copies of this document is granted.
|
||||
@@ -0,0 +1,372 @@
|
||||
=======================
|
||||
PHP Release Process
|
||||
=======================
|
||||
|
||||
General notes and tips
|
||||
----------------------
|
||||
|
||||
1. Do not release on Fridays, Saturdays or Sundays
|
||||
because the sysadmins can not upgrade stuff then.
|
||||
|
||||
2. Package two days before a release. So if the release is to be on Thursday,
|
||||
package on Tuesday. Think about timezones as well.
|
||||
|
||||
3. Ensure that the tests on Travis CI are green.
|
||||
See: https://travis-ci.org/php/php-src/builds
|
||||
It is recommended to do so a couple of days before the packaging day, to
|
||||
have enough time to investigate failures, communicate with the authors and
|
||||
commit the fixes.
|
||||
The RM for the branch is also responsible for keeping the CI green on
|
||||
ongoing basis between the releases. Check the CI status for your branch
|
||||
periodically and resolve the failures ASAP. See more in:
|
||||
https://wiki.php.net/rfc/travis_ci
|
||||
|
||||
4. Ensure that Windows builds will work before packaging
|
||||
|
||||
5. Follow all steps to the letter. When unclear ask previous RM's (David/Julien/
|
||||
Johannes/Stas/Derick/Ilia) before proceeding. Ideally make sure that for the
|
||||
first releases one of the previous RM's is around to answer questions. For the
|
||||
steps related to the php/QA/bug websites try to have someone from the webmaster
|
||||
team (Bjori) on hand.
|
||||
|
||||
6. Verify the tags to be extra sure everything was tagged properly.
|
||||
|
||||
7. Moving extensions from/to PECL requires write access to the destination.
|
||||
Most developers should have this.
|
||||
|
||||
Moving extensions from php-src to PECL
|
||||
- Checkout the pecl directory, most likely you want a sparse-root checkout
|
||||
svn co --depth=empty https://svn.php.net/repository/pecl
|
||||
- Create a directory for the extension incl. branch and tag structure,
|
||||
no trunk at this point and commit this to svn
|
||||
cd pecl; mkdir foo foo/tags foo/branches; svn add foo; svn commit
|
||||
- Move the extension from php-src to the new location
|
||||
svn mv https://svn.php.net/repository/php/php-src/trunk/ext/foo \
|
||||
https://svn.php.net/repository/pecl/foo/trunk
|
||||
|
||||
If the extension is still usable or not dead, in cooperation with the extension
|
||||
maintainers if any:
|
||||
- create the pecl.php.net/foo package and its content, license, maintainer
|
||||
- create the package.xml, commit
|
||||
- release the package
|
||||
|
||||
For Moving extensions from PECL to php-src the svn mv has to be done the other
|
||||
way round.
|
||||
|
||||
Rolling a non stable release (alpha/beta/RC)
|
||||
--------------------------------------------
|
||||
|
||||
1. Check windows snapshot builder logs (http://windows.php.net/downloads/snaps/ the last revision)
|
||||
|
||||
2. Check the tests at https://travis-ci.org/php/php-src/builds
|
||||
|
||||
3. run the "scripts/dev/credits" script in php-src and commit the changes in the
|
||||
credits files in ext/standard.
|
||||
|
||||
4. Checkout the release branch for this release (e.g., PHP-5.4.2) from the main branch.
|
||||
|
||||
5. Bump the version numbers in ``main/php_version.h``, ``configure.ac`` and possibly ``NEWS``.
|
||||
Do not use abbreviations for alpha and beta. Do not use dashes, you should
|
||||
``#define PHP_VERSION "5.4.22RC1"`` and not ``#define PHP_VERSION "5.4.22-RC1"``
|
||||
|
||||
6. Compile and make test, with and without ZTS, using the right Bison version
|
||||
(for example, for 5.5, Bison 2.4.1 is used)
|
||||
|
||||
7. Check ./sapi/cli/php -v output for version matching.
|
||||
|
||||
8. If all is right, commit the changes to the release branch with ``git commit -a``.
|
||||
|
||||
9. Tag the repository release branch with the version, e.g.:
|
||||
``git tag -u YOURKEYID php-5.4.2RC2``
|
||||
|
||||
10. Bump the version numbers in ``main/php_version.h``, ``configure.ac`` and ``NEWS``
|
||||
in the *main* branch (PHP-5.4 for example) to prepare for the **next** version.
|
||||
F.e. if the RC is "5.4.1RC1" then the new one should be "5.4.2-dev" - regardless if we get
|
||||
a new RC or not. This is to make sure ``version_compare()`` can correctly work.
|
||||
Commit the changes to the main branch.
|
||||
|
||||
11. Push the changes to the main repo, the tag, the main branch and the release branch :
|
||||
``git push --tags origin HEAD``
|
||||
``git push origin {main branch}``
|
||||
``git push origin {release branch}``
|
||||
|
||||
12. run: ``PHPROOT=. ./makedist 5.4.2RC2``, this will export the tree, create configure
|
||||
and build three tarballs (gz, bz2 and xz).
|
||||
|
||||
13. run ``scripts/dev/gen_verify_stub <version> [identity]``, this will sign the tarballs
|
||||
and output verification information to be included in announcement email
|
||||
|
||||
14. Copy those tarballs (scp, rsync) to downloads.php.net, in your homedir there should be a
|
||||
directory "public_html/". Copy them into there, so that the system can generate
|
||||
MD5 sums. If you do not have this directory, create it.
|
||||
|
||||
15. Now the RC can be found on http://downloads.php.net/~yourname,
|
||||
f.e. http://downloads.php.net/~derick/
|
||||
|
||||
16. Once the release has been tagged, contact the release-managers@ distribution list
|
||||
so that Windows binaries can be created. Once those are made, they can be found at
|
||||
http://windows.php.net/download
|
||||
|
||||
Getting the non stable release (alpha/beta/RC) announced
|
||||
--------------------------------------------------------
|
||||
|
||||
1. Update ``qa.git/include/release-qa.php`` with the appropriate information.
|
||||
See the documentation within release-qa.php for more information, but all releases
|
||||
and RCs are configured here. Only $QA_RELEASES needs to be edited.
|
||||
|
||||
Example: When rolling an RC, set the 'rc' with appropriate information for the
|
||||
given version.
|
||||
|
||||
Note: Remember to update the MD5 and sha256 checksum information.
|
||||
|
||||
2. Update ``web/php.git/include/version.inc`` (x=major version number)
|
||||
|
||||
a. ``$PHP_x_RC`` = "5.4.0RC1" (should be set to "false" before)
|
||||
|
||||
b. ``$PHP_x_RC_DATE`` = "06 September 2007"
|
||||
|
||||
3. Add a short notice to phpweb stating that there is a new release, and
|
||||
highlight the major important things (security fixes) and when it is important
|
||||
to upgrade.
|
||||
|
||||
a. Call php bin/createNewsEntry in your local phpweb checkout
|
||||
Use category "releases" for all stable releases.
|
||||
Use category "frontpage" for X.Y.0 non-stable releases only (news only).
|
||||
|
||||
b. Add the content for the news entry. Be sure to include the text:
|
||||
"THIS IS A DEVELOPMENT PREVIEW - DO NOT USE IT IN PRODUCTION!"
|
||||
|
||||
4. Commit and push changes to qa and web
|
||||
|
||||
*Wait for web and qa sites to update with new information before sending announce*
|
||||
|
||||
5. Send **separate** emails **To** ``internals@lists.php.net`` and ``php-general@lists.php.net``
|
||||
lists pointing out "the location of the release" and "the possible release date of
|
||||
either the next RC, or the final release". Include in this information the verification
|
||||
information output by ``gen_verify_stub``.
|
||||
|
||||
6. Send **separate** emails (see example here http://news.php.net/php.pear.qa/5201) **To**
|
||||
``php-qa@lists.php.net`` and ``primary-qa-tester@lists.php.net``.
|
||||
These emails are to notify the selected projects about a new release so that they
|
||||
can make sure their projects keep working. Make sure that you have been setup
|
||||
as a moderator for ``primary-qa-tester@lists.php.net`` by having someone (Hannes, Dan,
|
||||
Derick) run the following commands for you:
|
||||
|
||||
``ssh lists.php.net``
|
||||
|
||||
``sudo -u ezmlm ezmlm-sub ~ezmlm/primary-qa-tester/mod moderator-email-address``
|
||||
|
||||
Rolling a stable release
|
||||
------------------------
|
||||
|
||||
1. Checkout your release branch, you should have created when releasing previous RC
|
||||
and bump the version numbers in ``main/php_version.h``, ``configure.ac`` and possibly ``NEWS``.
|
||||
|
||||
2. If a CVE commit needs to be merged to the release, then have it committed to
|
||||
the base branches and merged upwards as usual (f.e commit the CVE fix to 5.3,
|
||||
merge to 5.4, 5.5 etc...). Then you can cherry-pick it in your release branch.
|
||||
Don't forget to update NEWS manually in an extra commit then.
|
||||
|
||||
3. Commit those changes. Ensure the tests at https://travis-ci.org/php/php-src/builds are
|
||||
still passing.
|
||||
|
||||
4. run the "scripts/dev/credits" script in php-src and commit the changes in the
|
||||
credits files in ext/standard.
|
||||
|
||||
5. Compile and make test, with and without ZTS, using the right Bison version
|
||||
(for example, for 5.5, Bison 2.4.1 is used)
|
||||
|
||||
6. Check ./sapi/cli/php -v output for version matching.
|
||||
|
||||
7. tag the repository with the version f.e. "``git tag -u YOURKEYID -s php-5.4.1``"
|
||||
|
||||
8. Push the tag f.e. "``git push origin php-5.4.1``"
|
||||
|
||||
9. run: ``PHPROOT=. ./makedist php 5.4.1``, this will export the tag, create configure
|
||||
and build three tarballs (gz, bz2 and xz).
|
||||
Check if the pear files are updated (phar).
|
||||
On some systems the behavior of GNU tar can default to produce POSIX compliant archives
|
||||
with PAX headers. As not every application is compatible with that format, creation of
|
||||
archives with PAX headers should be avoided. When packaging on such a system, the GNU tar
|
||||
can be influenced by defining the environment variable TAR_OPTIONS='--format=gnu'.
|
||||
|
||||
10. Generate the GPG signature files for the archives.
|
||||
``gpg -u YOUREMAIL --armor --detach-sign php-X.Y.Z.tar.xxx``
|
||||
|
||||
11. Commit and push all the tarballs and signature files to web/php-distributions.git,
|
||||
then update the git submodule reference in web/php.git:
|
||||
``git submodule init;
|
||||
git submodule update;
|
||||
cd distributions;
|
||||
git fetch;
|
||||
git pull --rebase origin master;
|
||||
cd ..;
|
||||
git commit distributions;
|
||||
git push;``
|
||||
This is to fetch the last commit id from php-distributions.git and commit this
|
||||
last commit id to web/php.git, then, mirrors will now sync
|
||||
|
||||
12. Once the release has been tagged, contact release managers, windows builders, and package maintainers
|
||||
so that they can build releases. Do not send this announcement to any public lists.
|
||||
|
||||
Getting the stable release announced
|
||||
------------------------------------
|
||||
|
||||
1. Update phpweb/include/releases.inc with the old release info
|
||||
(updates the download archives)
|
||||
|
||||
a. You can run ``php bin/bumpRelease 5`` if you are making a release for the
|
||||
highest branch, otherwise you have to do this manually, see point 1.b
|
||||
|
||||
b. In case multiple PHP minor versions are in active development you have
|
||||
to manually copy the old information to include/releases.inc
|
||||
|
||||
2. Edit ``phpweb/include/version.inc`` and change (X=major release number):
|
||||
|
||||
a. ``$PHP_X_VERSION`` to the correct version
|
||||
|
||||
b. ``$PHP_X_DATE`` to the release date
|
||||
|
||||
c. ``$PHP_X_MD5`` array and update all the md5 sums
|
||||
|
||||
d. ``$PHP_X_SHA256`` array and update all the SHA256 sums
|
||||
|
||||
e. set ``$PHP_X_RC`` to false!
|
||||
|
||||
f. Make sure there are no outdated "notes" or edited "date" keys in the
|
||||
``$RELEASES[X][$PHP_X_VERSION]["source"]`` array
|
||||
|
||||
g. if the windows builds aren't ready yet prefix the "windows" key with a dot (".windows")
|
||||
|
||||
3. Create the release file (releases/x_y_z.php)
|
||||
Usually we use the same content as for point 6, but included in php template
|
||||
instead of the release xml.
|
||||
|
||||
4. Update php-qa/include/release-qa.php and add the next version as an QARELEASE
|
||||
(prepare for next RC)
|
||||
|
||||
5. Update the ChangeLog file for the given major version
|
||||
f.e. ``ChangeLog-5.php`` from the NEWS file
|
||||
|
||||
a. go over the list and put every element on one line
|
||||
|
||||
b. check for &, < and > and escape them if necessary
|
||||
|
||||
c. remove all the names at the ends of lines
|
||||
|
||||
d. for marking up, you can do the following (with VI):
|
||||
|
||||
I. ``s/^- /<li>/``
|
||||
|
||||
II. ``s/$/<\/li>/``
|
||||
|
||||
III. ``s/Fixed bug #\([0-9]\+\)/<?php bugfix(\1); ?>/``
|
||||
|
||||
IV. ``s/Fixed PECL bug #\([0-9]\+\)/<?php peclbugfix(\1); ?>/``
|
||||
|
||||
V. ``s/FR #\([0-9]\+\)/FR <?php bugl(\1); ?>/``
|
||||
|
||||
e. You may want to try php-web/bin/news2html to automate this task
|
||||
|
||||
6. Add a short notice to phpweb stating that there is a new release, and
|
||||
highlight the major important things (security fixes) and when it is important
|
||||
to upgrade.
|
||||
|
||||
a. Call php bin/createNewsEntry in your local phpweb checkout
|
||||
|
||||
b. Add the content for the news entry
|
||||
|
||||
7. **Check mirrors have been synced before announcing or pushing news**
|
||||
Try, f.e. http://www.php.net/get/php-5.5.1.tar.bz2/from/a/mirror
|
||||
Try several mirrors, mirrors may update slowly (may take an hour)
|
||||
|
||||
8. Commit all the changes to their respective git repos
|
||||
|
||||
9. Please note down the sha256 and the PGP signature (.asc). These *must* be
|
||||
included in the release mail.
|
||||
10. Wait an hour or two, then send a mail to php-announce@lists.php.net,
|
||||
php-general@lists.php.net and internals@lists.php.net with a text similar to
|
||||
http://news.php.net/php.internals/17222.
|
||||
Please make sure that the mail to php-announce@ is its own completely separate email.
|
||||
This is to make sure that replies to the announcement on php-general@ or internals@
|
||||
will not accidentally hit the php-announce@ mailinglist.
|
||||
|
||||
Re-releasing the same version (or -pl)
|
||||
--------------------------------------
|
||||
|
||||
1. Commit the new binaries to ``phpweb/distributions/``
|
||||
|
||||
2. Edit ``phpweb/include/version.inc`` and change (X=major release number):
|
||||
|
||||
a. If only releasing for one OS, make sure you edit only those variables
|
||||
|
||||
b. ``$PHP_X_VERSION`` to the correct version
|
||||
|
||||
c. ``$PHP_X_DATE`` to the release date
|
||||
|
||||
d. ``$PHP_X_MD5`` array and update all the md5 sums
|
||||
|
||||
e. ``$PHP_X_SHA256`` array and update all the SHA256 sums
|
||||
|
||||
f. Make sure there are no outdated "notes" or edited "date" keys in the
|
||||
``$RELEASES[X][$PHP_X_VERSION]["source"]`` array
|
||||
|
||||
3. Add a short notice to phpweb stating that there is a new release, and
|
||||
highlight the major important things (security fixes) and when it is important
|
||||
to upgrade.
|
||||
|
||||
a. Call php bin/createNewsEntry in your local phpweb checkout
|
||||
|
||||
b. Add the content for the news entry
|
||||
|
||||
4. Commit all the changes (``include/version.inc``, ``archive/archive.xml``,
|
||||
``archive/entries/YYYY-MM-DD-N.xml``)
|
||||
|
||||
5. Wait an hour or two, then send a mail to php-announce@lists.php.net,
|
||||
php-general@lists.php.net and internals@lists.php.net with a text similar to
|
||||
the news entry.
|
||||
Please make sure that the mail to php-announce@ is its own completely separate email.
|
||||
This is to make sure that replies to the announcement on php-general@ or internals@
|
||||
will not accidentally hit the php-announce@ mailinglist.
|
||||
|
||||
Forking a new release branch
|
||||
----------------------------
|
||||
|
||||
1. One week prior to cutting X.Y.0beta1, warn internals@ that your version's branch
|
||||
is about to be cut, and that PHP-X.Y will be moving into feature freeze.
|
||||
Try to be specific about when the branch will be cut.
|
||||
Example: http://news.php.net/php.internals/99864
|
||||
|
||||
2. Just prior to cutting X.Y.0beta1, create the new branch locally.
|
||||
Add a commit on master after the branch point clearing the NEWS file, and updating
|
||||
main/php_versions.h and Zend/zend.h to update versions.
|
||||
Example: https://github.com/php/php-src/commit/5230541ef59e0637d5522293a7d099bf18ce6af3
|
||||
Push the new branch and the commit just added to master.
|
||||
|
||||
3. Immediately notify internals@ of the branch cut and advise the new merging order:
|
||||
Example: http://news.php.net/php.internals/99903
|
||||
|
||||
4. Update php-web:git.php and wiki.php.net/vcs/gitworkflow to reflect the new branch:
|
||||
Example: https://github.com/php/web-php/commit/74bcad4c770d95f21b7fbeeedbd76d943bb83f23
|
||||
|
||||
5. Notify nlopess@ to add PHP_X_Y tag to gcov.php.net
|
||||
|
||||
New Release Manager Checklist
|
||||
-----------------------------
|
||||
|
||||
1. Email systems@ to get setup for access to downloads.php.net and to be added to the
|
||||
release-managers@ distribution list.
|
||||
|
||||
2. Create a GPG key for your @php.net address and publish it by editing `include/gpg-keys.inc`
|
||||
in the `web-php` repository, adding the output of `gpg --fingerprint "$USER@php.net"`. Let
|
||||
one or more of the previous RMs sign your key. Publish your public key to pgp.mit.edu with:
|
||||
`gpg --keyserver pgp.mit.edu --send-keys $KEYID`
|
||||
|
||||
3. Request karma to edit main/php_version.h. Possibly karma for other restricted parts of
|
||||
php-src might come in question.
|
||||
|
||||
4. Request karma for web/qa.git and web/php.git for publishing release announcements.
|
||||
|
||||
5. Request moderation access to announce@php.net and primary-qa-tester@lists.php.net lists, to
|
||||
be able to moderate your release announcements. All the announcements should be sent from
|
||||
the @php.net alias.
|
||||
@@ -0,0 +1,166 @@
|
||||
HOW TO CREATE A SELF-CONTAINED PHP EXTENSION
|
||||
|
||||
A self-contained extension can be distributed independently of
|
||||
the PHP source. To create such an extension, two things are
|
||||
required:
|
||||
|
||||
- Configuration file (config.m4)
|
||||
- Source code for your module
|
||||
|
||||
We will describe now how to create these and how to put things
|
||||
together.
|
||||
|
||||
PREPARING YOUR SYSTEM
|
||||
|
||||
While the result will run on any system, a developer's setup needs these
|
||||
tools:
|
||||
|
||||
GNU autoconf
|
||||
GNU automake
|
||||
GNU libtool
|
||||
GNU m4
|
||||
|
||||
All of these are available from
|
||||
|
||||
ftp://ftp.gnu.org/pub/gnu/
|
||||
|
||||
CONVERTING AN EXISTING EXTENSION
|
||||
|
||||
Just to show you how easy it is to create a self-contained
|
||||
extension, we will convert an embedded extension into a
|
||||
self-contained one. Install PHP and execute the following
|
||||
commands.
|
||||
|
||||
$ mkdir /tmp/newext
|
||||
$ cd /tmp/newext
|
||||
|
||||
You now have an empty directory. We will copy the files from
|
||||
the mysql extension:
|
||||
|
||||
$ cp -rp php-4.0.X/ext/mysql/* .
|
||||
|
||||
It is time to finish the module. Run:
|
||||
|
||||
$ phpize
|
||||
|
||||
You can now ship the contents of the directory - the extension
|
||||
can live completely on its own.
|
||||
|
||||
The user instructions boil down to
|
||||
|
||||
$ ./configure \
|
||||
[--with-php-config=/path/to/php-config] \
|
||||
[--with-mysql=MYSQL-DIR]
|
||||
$ make install
|
||||
|
||||
The MySQL module will either use the embedded MySQL client
|
||||
library or the MySQL installation in MYSQL-DIR.
|
||||
|
||||
|
||||
DEFINING THE NEW EXTENSION
|
||||
|
||||
Our demo extension is called "foobar".
|
||||
|
||||
It consists of two source files "foo.c" and "bar.c"
|
||||
(and any arbitrary amount of header files, but that is not
|
||||
important here).
|
||||
|
||||
The demo extension does not reference any external
|
||||
libraries (that is important, because the user does not
|
||||
need to specify anything).
|
||||
|
||||
|
||||
LTLIBRARY_SOURCES specifies the names of the sources files. You can
|
||||
name an arbitrary number of source files here.
|
||||
|
||||
CREATING THE M4 CONFIGURATION FILE
|
||||
|
||||
The m4 configuration can perform additional checks. For a
|
||||
self-contained extension, you do not need more than a few
|
||||
macro calls.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
PHP_ARG_ENABLE(foobar,whether to enable foobar,
|
||||
[ --enable-foobar Enable foobar])
|
||||
|
||||
if test "$PHP_FOOBAR" != "no"; then
|
||||
PHP_NEW_EXTENSION(foobar, foo.c bar.c, $ext_shared)
|
||||
fi
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
PHP_ARG_ENABLE will automatically set the correct variables, so
|
||||
that the extension will be enabled by PHP_NEW_EXTENSION in shared mode.
|
||||
|
||||
The first argument of PHP_NEW_EXTENSION describes the name of the
|
||||
extension. The second names the source-code files. The third passes
|
||||
$ext_shared which is set by PHP_ARG_ENABLE/WITH to PHP_NEW_EXTENSION.
|
||||
|
||||
Please use always PHP_ARG_ENABLE or PHP_ARG_WITH. Even if you do not
|
||||
plan to distribute your module with PHP, these facilities allow you
|
||||
to integrate your module easily into the main PHP module framework.
|
||||
|
||||
CREATING SOURCE FILES
|
||||
|
||||
ext_skel can be of great help when creating the common code for all modules
|
||||
in PHP for you and also writing basic function definitions and C code for
|
||||
handling arguments passed to your functions. See README.EXT_SKEL for further
|
||||
information.
|
||||
|
||||
As for the rest, you are currently alone here. There are a lot of existing
|
||||
modules, use a simple module as a starting point and add your own code.
|
||||
|
||||
|
||||
CREATING THE SELF-CONTAINED EXTENSION
|
||||
|
||||
Put config.m4 and the source files into one directory. Then, run phpize
|
||||
(this is installed during make install by PHP 4.0).
|
||||
|
||||
For example, if you configured PHP with --prefix=/php, you would run
|
||||
|
||||
$ /php/bin/phpize
|
||||
|
||||
This will automatically copy the necessary build files and create
|
||||
configure from your config.m4.
|
||||
|
||||
And that's it. You now have a self-contained extension.
|
||||
|
||||
INSTALLING A SELF-CONTAINED EXTENSION
|
||||
|
||||
An extension can be installed by running:
|
||||
|
||||
$ ./configure \
|
||||
[--with-php-config=/path/to/php-config]
|
||||
$ make install
|
||||
|
||||
ADDING SHARED MODULE SUPPORT TO A MODULE
|
||||
|
||||
In order to be useful, a self-contained extension must be loadable
|
||||
as a shared module. I will explain now how you can add shared module
|
||||
support to an existing module called foo.
|
||||
|
||||
1. In config.m4, use PHP_ARG_WITH/PHP_ARG_ENABLE. Then you will
|
||||
automatically be able to use --with-foo=shared[,..] or
|
||||
--enable-foo=shared[,..].
|
||||
|
||||
2. In config.m4, use PHP_NEW_EXTENSION(foo,.., $ext_shared) to enable
|
||||
building the extension.
|
||||
|
||||
3. Add the following lines to your C source file:
|
||||
|
||||
#ifdef COMPILE_DL_FOO
|
||||
ZEND_GET_MODULE(foo)
|
||||
#endif
|
||||
|
||||
PECL SITE CONFORMITY
|
||||
|
||||
If you plan to release an extension to the PECL website, there are several
|
||||
points to be regarded.
|
||||
|
||||
1. Add LICENSE or COPYING to the package.xml
|
||||
|
||||
2. The following should be defined in one of the extension header files
|
||||
|
||||
#define PHP_FOO_VERSION "1.2.3"
|
||||
|
||||
This macros has to be used within your foo_module_entry to indicate the
|
||||
extension version.
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
An Overview of the PHP Streams abstraction
|
||||
==========================================
|
||||
|
||||
WARNING: some prototypes in this file are out of date.
|
||||
The information contained here is being integrated into
|
||||
the PHP manual - stay tuned...
|
||||
|
||||
Please send comments to: Wez Furlong <wez@thebrainroom.com>
|
||||
|
||||
Why Streams?
|
||||
============
|
||||
You may have noticed a shed-load of issock parameters flying around the PHP
|
||||
code; we don't want them - they are ugly and cumbersome and force you to
|
||||
special case sockets and files every time you need to work with a "user-level"
|
||||
PHP file pointer.
|
||||
Streams take care of that and present the PHP extension coder with an ANSI
|
||||
stdio-alike API that looks much nicer and can be extended to support non file
|
||||
based data sources.
|
||||
|
||||
Using Streams
|
||||
=============
|
||||
Streams use a php_stream* parameter just as ANSI stdio (fread etc.) use a
|
||||
FILE* parameter.
|
||||
|
||||
The main functions are:
|
||||
|
||||
PHPAPI size_t php_stream_read(php_stream * stream, char * buf, size_t count);
|
||||
PHPAPI size_t php_stream_write(php_stream * stream, const char * buf, size_t
|
||||
count);
|
||||
PHPAPI size_t php_stream_printf(php_stream * stream,
|
||||
const char * fmt, ...);
|
||||
PHPAPI int php_stream_eof(php_stream * stream);
|
||||
PHPAPI int php_stream_getc(php_stream * stream);
|
||||
PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen);
|
||||
PHPAPI int php_stream_close(php_stream * stream);
|
||||
PHPAPI int php_stream_flush(php_stream * stream);
|
||||
PHPAPI int php_stream_seek(php_stream * stream, off_t offset, int whence);
|
||||
PHPAPI off_t php_stream_tell(php_stream * stream);
|
||||
PHPAPI int php_stream_lock(php_stream * stream, int mode);
|
||||
|
||||
These (should) behave in the same way as the ANSI stdio functions with similar
|
||||
names: fread, fwrite, fprintf, feof, fgetc, fgets, fclose, fflush, fseek, ftell, flock.
|
||||
|
||||
Opening Streams
|
||||
===============
|
||||
In most cases, you should use this API:
|
||||
|
||||
PHPAPI php_stream *php_stream_open_wrapper(const char *path, const char *mode,
|
||||
int options, char **opened_path);
|
||||
|
||||
Where:
|
||||
path is the file or resource to open.
|
||||
mode is the stdio compatible mode eg: "wb", "rb" etc.
|
||||
options is a combination of the following values:
|
||||
IGNORE_PATH (default) - don't use include path to search for the file
|
||||
USE_PATH - use include path to search for the file
|
||||
IGNORE_URL - do not use plugin wrappers
|
||||
REPORT_ERRORS - show errors in a standard format if something
|
||||
goes wrong.
|
||||
STREAM_MUST_SEEK - If you really need to be able to seek the stream
|
||||
and don't need to be able to write to the original
|
||||
file/URL, use this option to arrange for the stream
|
||||
to be copied (if needed) into a stream that can
|
||||
be seek()ed.
|
||||
|
||||
opened_path is used to return the path of the actual file opened,
|
||||
but if you used STREAM_MUST_SEEK, may not be valid. You are
|
||||
responsible for efree()ing opened_path. opened_path may be (and usually
|
||||
is) NULL.
|
||||
|
||||
If you need to open a specific stream, or convert standard resources into
|
||||
streams there are a range of functions to do this defined in php_streams.h.
|
||||
A brief list of the most commonly used functions:
|
||||
|
||||
PHPAPI php_stream *php_stream_fopen_from_file(FILE *file, const char *mode);
|
||||
Convert a FILE * into a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_fopen_tmpfile(void);
|
||||
Open a FILE * with tmpfile() and convert into a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_fopen_temporary_file(const char *dir,
|
||||
const char *pfx, char **opened_path);
|
||||
Generate a temporary file name and open it.
|
||||
|
||||
There are some network enabled relatives in php_network.h:
|
||||
|
||||
PHPAPI php_stream *php_stream_sock_open_from_socket(int socket, int persistent);
|
||||
Convert a socket into a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_sock_open_host(const char *host, unsigned short port,
|
||||
int socktype, int timeout, int persistent);
|
||||
Open a connection to a host and return a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_sock_open_unix(const char *path, int persistent,
|
||||
struct timeval *timeout);
|
||||
Open a UNIX domain socket.
|
||||
|
||||
|
||||
Stream Utilities
|
||||
================
|
||||
|
||||
If you need to copy some data from one stream to another, you will be please
|
||||
to know that the streams API provides a standard way to do this:
|
||||
|
||||
PHPAPI size_t php_stream_copy_to_stream(php_stream *src,
|
||||
php_stream *dest, size_t maxlen);
|
||||
|
||||
If you want to copy all remaining data from the src stream, pass
|
||||
PHP_STREAM_COPY_ALL as the maxlen parameter, otherwise maxlen indicates the
|
||||
number of bytes to copy.
|
||||
This function will try to use mmap where available to make the copying more
|
||||
efficient.
|
||||
|
||||
If you want to read the contents of a stream into an allocated memory buffer,
|
||||
you should use:
|
||||
|
||||
PHPAPI size_t php_stream_copy_to_mem(php_stream *src, char **buf,
|
||||
size_t maxlen, int persistent);
|
||||
|
||||
This function will set buf to the address of the buffer that it allocated,
|
||||
which will be maxlen bytes in length, or will be the entire length of the
|
||||
data remaining on the stream if you set maxlen to PHP_STREAM_COPY_ALL.
|
||||
The buffer is allocated using pemalloc(); you need to call pefree() to
|
||||
release the memory when you are done.
|
||||
As with copy_to_stream, this function will try use mmap where it can.
|
||||
|
||||
If you have an existing stream and need to be able to seek() it, you
|
||||
can use this function to copy the contents into a new stream that can
|
||||
be seek()ed:
|
||||
|
||||
PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream);
|
||||
|
||||
It returns one of the following values:
|
||||
#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */
|
||||
#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */
|
||||
#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */
|
||||
#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */
|
||||
|
||||
make_seekable will always set newstream to be the stream that is valid
|
||||
if the function succeeds.
|
||||
When you have finished, remember to close the stream.
|
||||
|
||||
NOTE: If you only need to seek forward, there is no need to call this
|
||||
function, as the php_stream_seek can emulate forward seeking when the
|
||||
whence parameter is SEEK_CUR.
|
||||
|
||||
NOTE: Writing to the stream may not affect the original source, so it
|
||||
only makes sense to use this for read-only use.
|
||||
|
||||
NOTE: If the origstream is network based, this function will block
|
||||
until the whole contents have been downloaded.
|
||||
|
||||
NOTE: Never call this function with an origstream that is referenced
|
||||
as a resource! It will close the origstream on success, and this
|
||||
can lead to a crash when the resource is later used/released.
|
||||
|
||||
NOTE: If you are opening a stream and need it to be seekable, use the
|
||||
STREAM_MUST_SEEK option to php_stream_open_wrapper();
|
||||
|
||||
PHPAPI int php_stream_supports_lock(php_stream * stream);
|
||||
|
||||
This function will return either 1 (success) or 0 (failure) indicating whether or
|
||||
not a lock can be set on this stream. Typically you can only set locks on stdio streams.
|
||||
|
||||
Casting Streams
|
||||
===============
|
||||
What if your extension needs to access the FILE* of a user level file pointer?
|
||||
You need to "cast" the stream into a FILE*, and this is how you do it:
|
||||
|
||||
FILE * fp;
|
||||
php_stream * stream; /* already opened */
|
||||
|
||||
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void*)&fp, REPORT_ERRORS) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
The prototype is:
|
||||
|
||||
PHPAPI int php_stream_cast(php_stream * stream, int castas, void ** ret, int
|
||||
show_err);
|
||||
|
||||
The show_err parameter, if non-zero, will cause the function to display an
|
||||
appropriate error message of type E_WARNING if the cast fails.
|
||||
|
||||
castas can be one of the following values:
|
||||
PHP_STREAM_AS_STDIO - a stdio FILE*
|
||||
PHP_STREAM_AS_FD - a generic file descriptor
|
||||
PHP_STREAM_AS_SOCKETD - a socket descriptor
|
||||
|
||||
If you ask a socket stream for a FILE*, the abstraction will use fdopen to
|
||||
create it for you. Be warned that doing so may cause buffered data to be lost
|
||||
if you mix ANSI stdio calls on the FILE* with php stream calls on the stream.
|
||||
|
||||
If your system has the fopencookie function, php streams can synthesize a
|
||||
FILE* on top of any stream, which is useful for SSL sockets, memory based
|
||||
streams, data base streams etc. etc.
|
||||
|
||||
In situations where this is not desirable, you should query the stream
|
||||
to see if it naturally supports FILE *. You can use this code snippet
|
||||
for this purpose:
|
||||
|
||||
if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
|
||||
/* can safely cast to FILE* with no adverse side effects */
|
||||
}
|
||||
|
||||
You can use:
|
||||
|
||||
PHPAPI int php_stream_can_cast(php_stream * stream, int castas)
|
||||
|
||||
to find out if a stream can be cast, without actually performing the cast, so
|
||||
to check if a stream is a socket you might use:
|
||||
|
||||
if (php_stream_can_cast(stream, PHP_STREAM_AS_SOCKETD) == SUCCESS) {
|
||||
/* it can be a socket */
|
||||
}
|
||||
|
||||
Please note the difference between php_stream_is and php_stream_can_cast;
|
||||
stream_is tells you if the stream is a particular type of stream, whereas
|
||||
can_cast tells you if the stream can be forced into the form you request.
|
||||
The former doesn't change anything, while the later *might* change some
|
||||
state in the stream.
|
||||
|
||||
Stream Internals
|
||||
================
|
||||
|
||||
There are two main structures associated with a stream - the php_stream
|
||||
itself, which holds some state information (and possibly a buffer) and a
|
||||
php_stream_ops structure, which holds the "virtual method table" for the
|
||||
underlying implementation.
|
||||
|
||||
The php_streams ops struct consists of pointers to methods that implement
|
||||
read, write, close, flush, seek, gets and cast operations. Of these, an
|
||||
implementation need only implement write, read, close and flush. The gets
|
||||
method is intended to be used for streams if there is an underlying method
|
||||
that can efficiently behave as fgets. The ops struct also contains a label
|
||||
for the implementation that will be used when printing error messages - the
|
||||
stdio implementation has a label of "STDIO" for example.
|
||||
|
||||
The idea is that a stream implementation defines a php_stream_ops struct, and
|
||||
associates it with a php_stream using php_stream_alloc.
|
||||
|
||||
As an example, the php_stream_fopen() function looks like this:
|
||||
|
||||
PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode)
|
||||
{
|
||||
FILE * fp = fopen(filename, mode);
|
||||
php_stream * ret;
|
||||
|
||||
if (fp) {
|
||||
ret = php_stream_alloc(&php_stream_stdio_ops, fp, 0, 0, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
php_stream_stdio_ops is a php_stream_ops structure that can be used to handle
|
||||
FILE* based streams.
|
||||
|
||||
A socket based stream would use code similar to that above to create a stream
|
||||
to be passed back to fopen_wrapper (or it's yet to be implemented successor).
|
||||
|
||||
The prototype for php_stream_alloc is this:
|
||||
|
||||
PHPAPI php_stream * php_stream_alloc(php_stream_ops * ops, void * abstract,
|
||||
size_t bufsize, int persistent, const char * mode)
|
||||
|
||||
ops is a pointer to the implementation,
|
||||
abstract holds implementation specific data that is relevant to this instance
|
||||
of the stream,
|
||||
bufsize is the size of the buffer to use - if 0, then buffering at the stream
|
||||
level will be disabled (recommended for underlying sources that implement
|
||||
their own buffering - such a FILE*),
|
||||
persistent controls how the memory is to be allocated - persistently so that
|
||||
it lasts across requests, or non-persistently so that it is freed at the end
|
||||
of a request (it uses pemalloc),
|
||||
mode is the stdio-like mode of operation - php streams places no real meaning
|
||||
in the mode parameter, except that it checks for a 'w' in the string when
|
||||
attempting to write (this may change).
|
||||
|
||||
The mode parameter is passed on to fdopen/fopencookie when the stream is cast
|
||||
into a FILE*, so it should be compatible with the mode parameter of fopen().
|
||||
|
||||
Writing your own stream implementation
|
||||
======================================
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
RULE #1: when writing your own streams: make sure you have configured PHP with
|
||||
--enable-debug.
|
||||
I've taken some great pains to hook into the Zend memory manager to help track
|
||||
down allocation problems. It will also help you spot incorrect use of the
|
||||
STREAMS_DC, STREAMS_CC and the semi-private STREAMS_REL_CC macros for function
|
||||
definitions.
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
RULE #2: Please use the stdio stream as a reference; it will help you
|
||||
understand the semantics of the stream operations, and it will always
|
||||
be more up to date than these docs :-)
|
||||
|
||||
First, you need to figure out what data you need to associate with the
|
||||
php_stream. For example, you might need a pointer to some memory for memory
|
||||
based streams, or if you were making a stream to read data from an RDBMS like
|
||||
MySQL, you might want to store the connection and rowset handles.
|
||||
|
||||
The stream has a field called abstract that you can use to hold this data.
|
||||
If you need to store more than a single field of data, define a structure to
|
||||
hold it, allocate it (use pemalloc with the persistent flag set
|
||||
appropriately), and use the abstract pointer to refer to it.
|
||||
|
||||
For structured state you might have this:
|
||||
|
||||
struct my_state {
|
||||
MYSQL conn;
|
||||
MYSQL_RES * result;
|
||||
};
|
||||
|
||||
struct my_state * state = pemalloc(sizeof(struct my_state), persistent);
|
||||
|
||||
/* initialize the connection, and run a query, using the fields in state to
|
||||
* hold the results */
|
||||
|
||||
state->result = mysql_use_result(&state->conn);
|
||||
|
||||
/* now allocate the stream itself */
|
||||
stream = php_stream_alloc(&my_ops, state, 0, persistent, "r");
|
||||
|
||||
/* now stream->abstract == state */
|
||||
|
||||
Once you have that part figured out, you can write your implementation and
|
||||
define the your own php_stream_ops struct (we called it my_ops in the above
|
||||
example).
|
||||
|
||||
For example, for reading from this weird MySQL stream:
|
||||
|
||||
static size_t php_mysqlop_read(php_stream * stream, char * buf, size_t count)
|
||||
{
|
||||
struct my_state * state = (struct my_state*)stream->abstract;
|
||||
|
||||
if (buf == NULL && count == 0) {
|
||||
/* in this special case, php_streams is asking if we have reached the
|
||||
* end of file */
|
||||
if (... at end of file ...)
|
||||
return EOF;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pull out some data from the stream and put it in buf */
|
||||
... mysql_fetch_row(state->result) ...
|
||||
/* we could do something strange, like format the data as XML here,
|
||||
and place that in the buf, but that brings in some complexities,
|
||||
such as coping with a buffer size too small to hold the data,
|
||||
so I won't even go in to how to do that here */
|
||||
}
|
||||
|
||||
Implement the other operations - remember that write, read, close and flush
|
||||
are all mandatory. The rest are optional. Declare your stream ops struct:
|
||||
|
||||
php_stream_ops my_ops = {
|
||||
php_mysqlop_write, php_mysqlop_read, php_mysqlop_close,
|
||||
php_mysqlop_flush, NULL, NULL, NULL,
|
||||
"Strange MySQL example"
|
||||
}
|
||||
|
||||
Thats it!
|
||||
|
||||
Take a look at the STDIO implementation in streams.c for more information
|
||||
about how these operations work.
|
||||
The main thing to remember is that in your close operation you need to release
|
||||
and free the resources you allocated for the abstract field. In the case of
|
||||
the example above, you need to use mysql_free_result on the rowset, close the
|
||||
connection and then use pefree to dispose of the struct you allocated.
|
||||
You may read the stream->persistent field to determine if your struct was
|
||||
allocated in persistent mode or not.
|
||||
|
||||
vim:tw=78:et
|
||||
@@ -0,0 +1,194 @@
|
||||
Submitting Enhancements and Patches to PHP
|
||||
==========================================
|
||||
|
||||
This document describes how to submit an enhancement or patch for PHP.
|
||||
It's easy!
|
||||
|
||||
You don't need any login accounts or special access to download,
|
||||
build, debug and begin submitting PHP or PECL code, tests or
|
||||
documentation. Once you've followed this README and had several
|
||||
patches accepted, commit privileges are often quickly granted.
|
||||
|
||||
An excellent article to read first is:
|
||||
http://phpadvent.org/2008/less-whining-more-coding-by-elizabeth-smith
|
||||
|
||||
|
||||
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 #winphp-dev on FreeNode.
|
||||
|
||||
|
||||
PHP Patches
|
||||
-----------
|
||||
If you are fixing broken functionality in PHP C source code first
|
||||
create a bug or identify an existing bug at http://bugs.php.net/. A
|
||||
bug can be used to track the patch progress and prevent your changes
|
||||
getting lost in the PHP mail archives.
|
||||
|
||||
If your change is large then create a Request For Comment (RFC) page
|
||||
on http://wiki.php.net/rfc, discuss it with the extension maintainer,
|
||||
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://php.net/mailing-lists.php.
|
||||
|
||||
Information on PHP internal C functions is at
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
PHP Documentation Patches
|
||||
-------------------------
|
||||
If you are fixing incorrect PHP documentation first create a bug or
|
||||
identify an existing bug at http://bugs.php.net/. A bug can be used
|
||||
to track the patch progress and prevent your changes getting lost in
|
||||
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://php.net/mailing-lists.php.
|
||||
|
||||
Information on contributing to PHP documentation is at
|
||||
http://php.net/dochowto and http://wiki.php.net/doc/howto
|
||||
|
||||
Attach the patch to the PHP bug and consider sending a notification
|
||||
email about the change to phpdoc@lists.php.net. Explain what has been
|
||||
fixed/added/changed by your patch.
|
||||
|
||||
Please make the mail subject prefix "[PATCH]". Include the bug id(s)
|
||||
which can be closed by your patch. If attaching a patch, ensure it
|
||||
has a file extension of ".txt". This is because only MIME attachments
|
||||
of type 'text/*' are accepted.
|
||||
|
||||
|
||||
PECL Extension Patches: http://pecl.php.net/
|
||||
--------------------------------------------
|
||||
If you are fixing broken functionality in a PECL extension then create
|
||||
a bug or identify an existing bug at http://bugs.php.net/. A bug
|
||||
can be used to track the patch progress and prevent your changes
|
||||
getting lost in the PHP mail archives.
|
||||
|
||||
If your change is large then create a Request For Comment (RFC) page
|
||||
on http://wiki.php.net/rfc, discuss it with the extension maintainer,
|
||||
and discuss it on the development mail list pecl-dev@lists.php.net.
|
||||
PECL mail list subscription is explained on
|
||||
http://pecl.php.net/support.php. RFC Wiki accounts can be requested
|
||||
on http://wiki.php.net/start?do=register
|
||||
|
||||
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
|
||||
printed reference is the book "Extending and Embedding PHP" by Sara
|
||||
Golemon.
|
||||
|
||||
Update any open bugs and add a link to the source of your patch. Send
|
||||
the patch or pointer to the bug to pecl-dev@lists.php.net. Also CC
|
||||
the extension maintainer. Explain what has been changed by your
|
||||
patch. Test scripts should be included.
|
||||
|
||||
Please make the mail subject prefix "[PATCH] ...". Include the patch
|
||||
as an attachment with a file extension of ".txt". This is because
|
||||
only MIME attachments of type 'text/*' are accepted.
|
||||
|
||||
|
||||
PEAR Package Patches: http://pear.php.net/
|
||||
------------------------------------------
|
||||
Information on contributing to PEAR is available at
|
||||
http://pear.php.net/manual/en/developers-newmaint.php and
|
||||
http://pear.php.net/manual/en/guide-developers.php
|
||||
|
||||
|
||||
How to create your PHP, PHP Documentation or PECL patch
|
||||
-------------------------------------------------------
|
||||
PHP and most PECL packages use Git for revision control. Some PECL
|
||||
packages use Subversion (SVN) Read http://www.php.net/git.php for help
|
||||
on using Git to get and build PHP source code. We recommend to look
|
||||
at our workflow on https://wiki.php.net/vcs/gitworkflow and our FAQ
|
||||
https://wiki.php.net/vcs/gitfaq.
|
||||
|
||||
Generally we ask that bug fix patches work on the current stable PHP
|
||||
development branches and on "master". New PHP features only need to
|
||||
work on "master".
|
||||
|
||||
Read CODING_STANDARDS before you start working.
|
||||
|
||||
After modifying the source see README.TESTING and
|
||||
http://qa.php.net/write-test.php for how to test. Submitting test
|
||||
scripts helps us to understand what functionality has changed. It is
|
||||
important for the stability and maintainability of PHP that tests are
|
||||
comprehensive.
|
||||
|
||||
After testing is finished, create a patch file using the command:
|
||||
|
||||
git diff > your_patch.txt
|
||||
|
||||
For ease of review and later troubleshooting, submit individual
|
||||
patches for each bug or feature.
|
||||
|
||||
|
||||
Checklist for submitting your PHP or PECL code patch
|
||||
----------------------------------------------------
|
||||
- Update git source just before running your final 'diff' and
|
||||
before testing.
|
||||
- Add in-line comments and/or have external documentation ready.
|
||||
Use only "/* */" style comments, not "//".
|
||||
- Create test scripts for use with "make test".
|
||||
- Run "make test" to check your patch doesn't break other features.
|
||||
- Rebuild PHP with --enable-debug (which will show some kinds of
|
||||
memory errors) and check the PHP and web server error logs after
|
||||
running your PHP tests.
|
||||
- Rebuild PHP with --enable-maintainer-zts to check your patch
|
||||
compiles on multi-threaded web servers.
|
||||
- Review the patch once more just before submitting it.
|
||||
|
||||
|
||||
What happens after submitting your PHP, PHP Documentation or PECL patch
|
||||
-----------------------------------------------------------------------
|
||||
If your patch is easy to review and obviously has no side-effects,
|
||||
it might be committed relatively quickly.
|
||||
|
||||
Because PHP is a volunteer-driven effort more complex patches will
|
||||
require patience on your side. If you do not receive feedback in a
|
||||
few days, consider resubmitting the patch. Before doing this think
|
||||
about these questions:
|
||||
|
||||
- Did I send the patch to the right mail list?
|
||||
- Did I review the mail list archives to see if these kind of
|
||||
changes had been discussed before?
|
||||
- Did I explain my patch clearly?
|
||||
- Is my patch too hard to review? Because of what factors?
|
||||
|
||||
|
||||
What happens when your PHP or PECL patch is applied
|
||||
---------------------------------------------------
|
||||
Your name will likely be included in the Git commit log. If your
|
||||
patch affects end users, a brief description and your name might be
|
||||
added to the NEWS file.
|
||||
|
||||
Thank you for patching PHP!
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
[IMPORTANT NOTICE]
|
||||
------------------
|
||||
Failed tests usually indicate a problem with your local system setup
|
||||
and not within PHP itself (at least for official PHP release versions).
|
||||
You may decide to automatically submit a test summary to our QA workflow
|
||||
at the end of a test run.
|
||||
Please do *not* submit a failed test as a bug or ask for help on why
|
||||
it failed on your system without providing substantial backup information
|
||||
on *why* the test failed on your special setup. Thank you :-)
|
||||
|
||||
|
||||
[Testing Basics]
|
||||
----------------
|
||||
The easiest way to test your PHP build is to run "make test" from the
|
||||
command line after successfully compiling. This will run the complete
|
||||
tests for all enabled functionalities and extensions using the PHP
|
||||
CLI binary.
|
||||
To execute test scripts, you must build PHP with some SAPI, then you
|
||||
type "make test" to execute all or some test scripts saved under
|
||||
"tests" directory under source root directory.
|
||||
|
||||
Usage:
|
||||
make test
|
||||
|
||||
"make test" basically executes "run-tests.php" script
|
||||
under the source root (parallel builds will not work). Therefore you
|
||||
can execute the script as follows:
|
||||
|
||||
TEST_PHP_EXECUTABLE=sapi/cli/php \
|
||||
sapi/cli/php [-c /path/to/php.ini] run-tests.php [ext/foo/tests/GLOB]
|
||||
|
||||
|
||||
[Which "php" executable "make test" look for]
|
||||
---------------------------------------------
|
||||
If you are running the run-tests.php script from the command line (as above)
|
||||
you must set the TEST_PHP_EXECUTABLE environment variable to explicitly
|
||||
select the PHP executable that is to be tested, that is, used to run the test scripts.
|
||||
|
||||
If you run the tests using make test, the PHP CLI and CGI executables are
|
||||
automatically set for you. "make test" executes "run-tests.php" script with the CLI binary. Some
|
||||
test scripts such as session must be executed by CGI SAPI. Therefore,
|
||||
you must build PHP with CGI SAPI to perform all tests.
|
||||
|
||||
NOTE: PHP binary executing "run-tests.php" and php binary used for
|
||||
executing test scripts may differ. If you use different PHP binary for
|
||||
executing "run-tests.php" script, you may get errors.
|
||||
|
||||
|
||||
[Which php.ini is used]
|
||||
-----------------------
|
||||
"make test" uses the same php.ini file as it would once installed.
|
||||
The tests have been written to be independent of that php.ini file,
|
||||
so if you find a test that is affected by a setting, please report
|
||||
this, so we can address the issue.
|
||||
|
||||
|
||||
[Which test scripts are executed]
|
||||
---------------------------------
|
||||
"run-tests.php" ("make test"), without any arguments executes all
|
||||
test scripts by extracting all directories named "tests"
|
||||
from the source root and any subdirectories below. If there are files,
|
||||
which have a "phpt" extension, "run-tests.php" looks at the sections
|
||||
in these files, determines whether it should run it, by evaluating
|
||||
the 'SKIPIF' section. If the test is eligible for execution, the 'FILE'
|
||||
section is extracted into a ".php" file (with the same name besides
|
||||
the extension) and gets executed.
|
||||
When an argument is given or TESTS environment variable is set, the
|
||||
GLOB is expanded by the shell and any file with extension "*.phpt" is
|
||||
regarded as a test file.
|
||||
|
||||
Tester can easily execute tests selectively with as follows.
|
||||
|
||||
Examples:
|
||||
./sapi/cli/php run-tests.php ext/mbstring/*
|
||||
./sapi/cli/php run-tests.php ext/mbstring/020.phpt
|
||||
|
||||
|
||||
[Test results]
|
||||
--------------
|
||||
Test results are printed to standard output. If there is a failed test,
|
||||
the "run-tests.php" script saves the result, the expected result and the
|
||||
code executed to the test script directory. For example, if
|
||||
ext/myext/tests/myext.phpt fails to pass, the following files are created:
|
||||
|
||||
ext/myext/tests/myext.php - actual test file executed
|
||||
ext/myext/tests/myext.log - log of test execution (L)
|
||||
ext/myext/tests/myext.exp - expected output (E)
|
||||
ext/myext/tests/myext.out - output from test script (O)
|
||||
ext/myext/tests/myext.diff - diff of .out and .exp (D)
|
||||
|
||||
Failed tests are always bugs. Either the test is bugged or not considering
|
||||
factors applying to the tester's environment, or there is a bug in PHP.
|
||||
If this is a known bug, we strive to provide bug numbers, in either the
|
||||
test name or the file name. You can check the status of such a bug, by
|
||||
going to: http://bugs.php.net/12345 where 12345 is the bug number.
|
||||
For clarity and automated processing, bug numbers are prefixed by a hash
|
||||
sign '#' in test names and/or test cases are named bug12345.phpt.
|
||||
|
||||
NOTE: The files generated by tests can be selected by setting the
|
||||
environment variable TEST_PHP_LOG_FORMAT. For each file you want to be
|
||||
generated use the character in brackets as shown above (default is LEOD).
|
||||
The php file will be generated always.
|
||||
|
||||
NOTE: You can set environment variable TEST_PHP_DETAILED to enable
|
||||
detailed test information.
|
||||
|
||||
[Automated Testing]
|
||||
--------------
|
||||
If you like to keep up to speed, with latest developments and quality
|
||||
assurance, setting the environment variable NO_INTERACTION to 1, will not
|
||||
prompt the tester for any user input.
|
||||
|
||||
Normally, the exit status of "make test" is zero, regardless of the results
|
||||
of independent tests. Set the environment variable REPORT_EXIT_STATUS to 1,
|
||||
and "make test" will set the exit status ("$?") to non-zero, when an
|
||||
individual test has failed.
|
||||
|
||||
Example script to be run by cron(1):
|
||||
========== qa-test.sh =============
|
||||
#!/bin/sh
|
||||
|
||||
CO_DIR=$HOME/cvs/php7
|
||||
MYMAIL=qa-test@domain.com
|
||||
TMPDIR=/var/tmp
|
||||
TODAY=`date +"%Y%m%d"`
|
||||
|
||||
# Make sure compilation environment is correct
|
||||
CONFIGURE_OPTS='--disable-all --enable-cli --with-pcre'
|
||||
export MAKE=gmake
|
||||
export CC=gcc
|
||||
|
||||
# Set test environment
|
||||
export NO_INTERACTION=1
|
||||
export REPORT_EXIT_STATUS=1
|
||||
|
||||
cd $CO_DIR
|
||||
cvs update . >>$TMPDIR/phpqatest.$TODAY
|
||||
./cvsclean ; ./buildconf ; ./configure $CONFIGURE_OPTS ; $MAKE
|
||||
$MAKE test >>$TMPDIR/phpqatest.$TODAY 2>&1
|
||||
if test $? -gt 0
|
||||
then
|
||||
cat $TMPDIR/phpqatest.$TODAY | mail -s"PHP-QA Test Failed for $TODAY" $MYMAIL
|
||||
fi
|
||||
========== end of qa-test.sh =============
|
||||
|
||||
NOTE: The exit status of run-tests.php will be 1 when
|
||||
REPORT_EXIT_STATUS is set. The result of "make test" may be higher
|
||||
than that. At present, gmake 3.79.1 returns 2, so it is
|
||||
advised to test for non-zero, rather then a specific value.
|
||||
|
||||
|
||||
[Creating new test files]
|
||||
-------------------------
|
||||
Writing test file is very easy if you are used to PHP.
|
||||
See the HOWTO at http://qa.php.net/write-test.php
|
||||
|
||||
|
||||
[How to help us]
|
||||
----------------
|
||||
If you find bug in PHP, you can submit bug report AND test script
|
||||
for us. You don't have to write complete script, just give us test
|
||||
script with following format. Please test the script and make sure
|
||||
you write the correct ACTUAL OUTPUT and EXPECTED OUTPUT before you
|
||||
submit.
|
||||
|
||||
<?php
|
||||
/*
|
||||
Bug #12345
|
||||
substr() bug. Do not return expected string.
|
||||
|
||||
ACTUAL OUTPUT
|
||||
XYXA
|
||||
|
||||
EXPECTED OUTPUT
|
||||
ABCD
|
||||
*/
|
||||
|
||||
$str = "XYZABCD";
|
||||
echo substr($str,3,7);
|
||||
|
||||
?>
|
||||
|
||||
[IMPORTANT NOTICE]
|
||||
------------------
|
||||
This is an addendum to README.TESTING with additional information
|
||||
specific to server-tests.php.
|
||||
|
||||
server-tests.php is backward compatible with tests developed for
|
||||
the original run-tests.php script. server-tests is *not* used by
|
||||
'make test'. server-tests was developed to provide support for
|
||||
testing PHP under it's primary environment, HTTP, and can run the
|
||||
PHP tests under any of the SAPI modules that are direct executables,
|
||||
or are accessible via HTTP.
|
||||
|
||||
[New features]
|
||||
----------------
|
||||
* Command line interface:
|
||||
You can run 'php server-tests.php -h' to get all the possible options.
|
||||
* Configuration file:
|
||||
the -c argument will allow you to use a configuration file. This is
|
||||
handy if you are testing multiple environments and need various options
|
||||
depending on the environment.
|
||||
see server-tests-config.php for details.
|
||||
* CGI Emulation:
|
||||
Will emulate a CGI environment when testing with the cgi sapi executable.
|
||||
* HTTP testing:
|
||||
can be configured to run test scripts through an HTTP server running
|
||||
on localhost. localhost is required since either the web server must
|
||||
alias a directory to the php source directory, or the test scripts
|
||||
must be copied to a directory under the web server
|
||||
(see config options TEST_WEB_BASE_URL, TEST_BASE_PATH, and TEST_WEB_EXT)
|
||||
* New sections supported for test files (see below)
|
||||
|
||||
When running tests over http, tests that require ini settings different that what
|
||||
the web server runs under will be skipped. Since the test harness defines a number
|
||||
of ini settings by default, the web server may require special configuration to
|
||||
make testing work.
|
||||
|
||||
[Example Usage]
|
||||
----------------
|
||||
Some (but not all!) examples of usage:
|
||||
|
||||
1. run tests from the php source directory
|
||||
php server-tests.php -p /path/to/php-cli
|
||||
|
||||
2. run tests using cgi emulation
|
||||
php server-tests.php -p /path/to/php-cgi
|
||||
|
||||
3. run tests over http, copying test files into document root
|
||||
php server-tests.php -w -u http://localhost/test -m /path/to/htdocs/test
|
||||
|
||||
4. run tests over http, php sources have been aliased in web server
|
||||
php server-tests.php -w -u http://localhost/test
|
||||
|
||||
5. run tests using configuration file
|
||||
php server-tests.php -c /path/to/server-tests-config.php
|
||||
|
||||
6. run tests using configuration file, but overriding some settings:
|
||||
(config file must be first)
|
||||
php server-tests.php -c /path/to/server-tests-config.php -w -t 3 -d /path/to/testdir
|
||||
|
||||
NOTE: configuration as described in README.TESTING still works.
|
||||
|
||||
[New Test Sections]
|
||||
----------------
|
||||
In addition to the traditional test sections
|
||||
(see http://qa.php.net/write-test.php), several new sections are available
|
||||
under server-tests.
|
||||
|
||||
--POST--
|
||||
This is not a new section, but not multipart posts are supported for testing
|
||||
file uploads, or other types of POST data.
|
||||
|
||||
--CGI--
|
||||
This section takes no value. It merely provides a simple marker for tests
|
||||
that MUST be run as CGI, even if there is no --POST-- or --GET-- sections
|
||||
in the test file.
|
||||
|
||||
--DESCRIPTION--
|
||||
Not used for anything, just a section for documenting the test
|
||||
|
||||
--ENV--
|
||||
This section get's eval()'d to help build an environment for the
|
||||
execution of the test. This can be used to change environment
|
||||
vars that are used for CGI emulation, or simply to set env vars
|
||||
for cli testing. A full example looks like:
|
||||
|
||||
--ENV--
|
||||
return <<<END
|
||||
PATH_TRANSLATED=$filename
|
||||
PATH_INFO=$scriptname
|
||||
SCRIPT_NAME=$scriptname
|
||||
END;
|
||||
|
||||
Some variables are made easily available for use in this section, they
|
||||
include:
|
||||
$filename full native path to file, will become PATH_TRANSLATED
|
||||
$filepath =dirname($filename)
|
||||
$scriptname this is what will become SCRIPT_NAME unless you override it
|
||||
$docroot the equivalent of DOCUMENT_ROOT under Apache
|
||||
$cwd the directory that the test is being initiated from
|
||||
$this->conf all server-tests configuration vars
|
||||
$this->env all environment variables that will get passed to the test
|
||||
|
||||
|
||||
--REQUEST--
|
||||
This section is also eval'd, and is similar in nature to --ENV--. However,
|
||||
this section is used to build the url used in an HTTP request. Valid values
|
||||
to set in this section would include:
|
||||
SCRIPT_NAME The initial part of the request url
|
||||
PATH_INFO The pathinfo part of a request url
|
||||
FRAGMENT The fragment section of a url (after #)
|
||||
QUERY_STRING The query part of a url (after ?)
|
||||
|
||||
--REQUEST--
|
||||
return <<<END
|
||||
PATH_INFO=/path/info
|
||||
END;
|
||||
|
||||
--HEADERS--
|
||||
This section is also eval'd. It is used to provide additional headers sent
|
||||
in an HTTP request, such as content type for multipart posts, cookies, etc.
|
||||
|
||||
--HEADERS--
|
||||
return <<<END
|
||||
Content-Type=multipart/form-data; boundary=---------------------------240723202011929
|
||||
Content-Length=100
|
||||
END;
|
||||
|
||||
--EXPECTHEADERS--
|
||||
This section can be used to define what headers are required to be
|
||||
received back from a request, and is checked in addition to the
|
||||
regular expect sections. For example:
|
||||
|
||||
--EXPECTHEADERS--
|
||||
Status: 404
|
||||
@@ -0,0 +1,123 @@
|
||||
PHP Build System V5 Overview
|
||||
|
||||
- supports Makefile.ins during transition phase
|
||||
- not-really-portable Makefile includes have been eliminated
|
||||
- supports separate build directories without VPATH by using
|
||||
explicit rules only
|
||||
- does not waste disk-space/CPU-time for building temporary libraries
|
||||
=> especially noticeable on slower systems
|
||||
- slow recursive make replaced with one global Makefile
|
||||
- eases integration of proper dependencies
|
||||
- adds PHP_DEFINE(what[, value]) which creates a single include-file
|
||||
per what. This will allow more fine-grained dependencies.
|
||||
- abandoning the "one library per directory" concept
|
||||
- improved integration of the CLI
|
||||
- several new targets
|
||||
build-modules: builds and copies dynamic modules into modules/
|
||||
install-cli: installs the CLI only, so that the install-sapi
|
||||
target does only what its name says
|
||||
- finally abandoned automake (still requires aclocal at this time)
|
||||
- changed some configure-time constructs to run at buildconf-time
|
||||
- upgraded shtool to 1.5.4
|
||||
- removed $(moduledir) (use EXTENSION_DIR)
|
||||
|
||||
The Reason For a New System
|
||||
|
||||
It became more and more apparent that there is a severe need
|
||||
for addressing the portability concerns and improving the chance
|
||||
that your build is correct (how often have you been told to
|
||||
"make clean"? When this is done, you won't need to anymore).
|
||||
|
||||
|
||||
If You Build PHP on a Unix System
|
||||
|
||||
|
||||
You, as a user of PHP, will notice no changes. Of course, the build
|
||||
system will be faster, look better and work smarter.
|
||||
|
||||
|
||||
|
||||
If You Are Developing PHP
|
||||
|
||||
|
||||
|
||||
|
||||
Extension developers:
|
||||
|
||||
Makefile.ins are abandoned. The files which are to be compiled
|
||||
are specified in the config.m4 now using the following macro:
|
||||
|
||||
PHP_NEW_EXTENSION(foo, foo.c bar.c baz.cpp, $ext_shared)
|
||||
|
||||
E.g. this enables the extension foo which consists of three source-code
|
||||
modules, two in C and one in C++. And, depending on the user's wishes,
|
||||
the extension will even be built as a dynamic module.
|
||||
|
||||
The full syntax:
|
||||
|
||||
PHP_NEW_EXTENSION(extname, sources [, shared [,sapi_class[, extra-cflags]]])
|
||||
|
||||
Please have a look at acinclude.m4 for the gory details and meanings
|
||||
of the other parameters.
|
||||
|
||||
And that's basically it for the extension side.
|
||||
|
||||
If you previously built sub-libraries for this module, add
|
||||
the source-code files here as well. If you need to specify
|
||||
separate include directories, do it this way:
|
||||
|
||||
PHP_NEW_EXTENSION(foo, foo.c mylib/bar.c mylib/gregor.c,,,-I@ext_srcdir@/lib)
|
||||
|
||||
E.g. this builds the three files which are located relative to the
|
||||
extension source directory and compiles all three files with the
|
||||
special include directive (@ext_srcdir@ is automatically replaced).
|
||||
|
||||
Now, you need to tell the build system that you want to build files
|
||||
in a directory called $ext_builddir/lib:
|
||||
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/lib)
|
||||
|
||||
Make sure to call this after PHP_NEW_EXTENSION, because $ext_builddir
|
||||
is only set by the latter.
|
||||
|
||||
If you have a complex extension, you might to need add special
|
||||
Make rules. You can do this by calling PHP_ADD_MAKEFILE_FRAGMENT
|
||||
in your config.m4 after PHP_NEW_EXTENSION.
|
||||
|
||||
This will read a file in the source-dir of your extension called
|
||||
Makefile.frag. In this file, $(builddir) and $(srcdir) will be
|
||||
replaced by the values which are correct for your extension
|
||||
and which are again determined by the PHP_NEW_EXTENSION macro.
|
||||
|
||||
Make sure to prefix *all* relative paths correctly with either
|
||||
$(builddir) or $(srcdir). Because the build system does not
|
||||
change the working directory anymore, we must use either
|
||||
absolute paths or relative ones to the top build-directory.
|
||||
Correct prefixing ensures that.
|
||||
|
||||
|
||||
SAPI developers:
|
||||
|
||||
Instead of using PHP_SAPI=foo/PHP_BUILD_XYZ, you will need to type
|
||||
|
||||
PHP_SELECT_SAPI(name, type, sources.c)
|
||||
|
||||
I.e. specify the source-code files as above and also pass the
|
||||
information regarding how PHP is supposed to be built (shared
|
||||
module, program, etc).
|
||||
|
||||
For example for APXS:
|
||||
|
||||
PHP_SELECT_SAPI(apache, shared, sapi_apache.c mod_php7.c php_apache.c)
|
||||
|
||||
|
||||
|
||||
General info
|
||||
|
||||
The foundation for the new system is the flexible handling of
|
||||
sources and their contexts. With the help of macros you
|
||||
can define special flags for each source-file, where it is
|
||||
located, in which target context it can work, etc.
|
||||
|
||||
Have a look at the well documented macros
|
||||
PHP_ADD_SOURCES(_X) in acinclude.m4.
|
||||
@@ -0,0 +1,5 @@
|
||||
The Win32 Build System.
|
||||
|
||||
See https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2
|
||||
|
||||
vim:tw=78:sw=1:ts=1:et
|
||||
@@ -0,0 +1,182 @@
|
||||
Input Filter Support in PHP 5
|
||||
-----------------------------
|
||||
|
||||
XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
|
||||
and can be quite difficult to prevent. Whenever you accept user data
|
||||
and somehow display this data back to users, you are likely vulnerable
|
||||
to XSS hacks.
|
||||
|
||||
The Input Filter support in PHP 5 is aimed at providing the framework
|
||||
through which a company-wide or site-wide security policy can be
|
||||
enforced. It is implemented as a SAPI hook and is called from the
|
||||
treat_data and post handler functions. To implement your own security
|
||||
policy you will need to write a standard PHP extension. There is also
|
||||
a powerful standard implementation in ext/filter that should suit most
|
||||
peoples' needs. However, if you want to implement your own security
|
||||
policy, read on.
|
||||
|
||||
A simple implementation might look like the following. This stores the
|
||||
original raw user data and adds a my_get_raw() function while the normal
|
||||
$_POST, $_GET and $_COOKIE arrays are only populated with stripped
|
||||
data. In this simple example all I am doing is calling strip_tags() on
|
||||
the data.
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
|
||||
zval *post_array;
|
||||
zval *get_array;
|
||||
zval *cookie_array;
|
||||
ZEND_END_MODULE_GLOBALS(my_input_filter)
|
||||
|
||||
#ifdef ZTS
|
||||
#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
|
||||
#else
|
||||
#define IF_G(v) (my_input_filter_globals.v)
|
||||
#endif
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
|
||||
|
||||
zend_function_entry my_input_filter_functions[] = {
|
||||
PHP_FE(my_get_raw, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
zend_module_entry my_input_filter_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"my_input_filter",
|
||||
my_input_filter_functions,
|
||||
PHP_MINIT(my_input_filter),
|
||||
PHP_MSHUTDOWN(my_input_filter),
|
||||
NULL,
|
||||
PHP_RSHUTDOWN(my_input_filter),
|
||||
PHP_MINFO(my_input_filter),
|
||||
"0.1",
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
PHP_MINIT_FUNCTION(my_input_filter)
|
||||
{
|
||||
ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
|
||||
|
||||
REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
sapi_register_input_filter(my_sapi_input_filter);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_RSHUTDOWN_FUNCTION(my_input_filter)
|
||||
{
|
||||
if(IF_G(get_array)) {
|
||||
zval_ptr_dtor(&IF_G(get_array));
|
||||
IF_G(get_array) = NULL;
|
||||
}
|
||||
if(IF_G(post_array)) {
|
||||
zval_ptr_dtor(&IF_G(post_array));
|
||||
IF_G(post_array) = NULL;
|
||||
}
|
||||
if(IF_G(cookie_array)) {
|
||||
zval_ptr_dtor(&IF_G(cookie_array));
|
||||
IF_G(cookie_array) = NULL;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_MINFO_FUNCTION(my_input_filter)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
|
||||
php_info_print_table_end();
|
||||
}
|
||||
|
||||
/* The filter handler. If you return 1 from it, then PHP also registers the
|
||||
* (modified) variable. Returning 0 prevents PHP from registering the variable;
|
||||
* you can use this if your filter already registers the variable under a
|
||||
* different name, or if you just don't want the variable registered at all. */
|
||||
SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
|
||||
{
|
||||
zval new_var;
|
||||
zval *array_ptr = NULL;
|
||||
char *raw_var;
|
||||
int var_len;
|
||||
|
||||
assert(*val != NULL);
|
||||
|
||||
switch(arg) {
|
||||
case PARSE_GET:
|
||||
if(!IF_G(get_array)) {
|
||||
ALLOC_ZVAL(array_ptr);
|
||||
array_init(array_ptr);
|
||||
INIT_PZVAL(array_ptr);
|
||||
}
|
||||
IF_G(get_array) = array_ptr;
|
||||
break;
|
||||
case PARSE_POST:
|
||||
if(!IF_G(post_array)) {
|
||||
ALLOC_ZVAL(array_ptr);
|
||||
array_init(array_ptr);
|
||||
INIT_PZVAL(array_ptr);
|
||||
}
|
||||
IF_G(post_array) = array_ptr;
|
||||
break;
|
||||
case PARSE_COOKIE:
|
||||
if(!IF_G(cookie_array)) {
|
||||
ALLOC_ZVAL(array_ptr);
|
||||
array_init(array_ptr);
|
||||
INIT_PZVAL(array_ptr);
|
||||
}
|
||||
IF_G(cookie_array) = array_ptr;
|
||||
break;
|
||||
}
|
||||
Z_STRLEN(new_var) = val_len;
|
||||
Z_STRVAL(new_var) = estrndup(*val, val_len);
|
||||
Z_TYPE(new_var) = IS_STRING;
|
||||
|
||||
var_len = strlen(var);
|
||||
raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
|
||||
strcpy(raw_var, "RAW_");
|
||||
strlcat(raw_var,var,var_len+5);
|
||||
|
||||
php_register_variable_ex(raw_var, &new_var, array_ptr);
|
||||
|
||||
php_strip_tags(*val, val_len, NULL, NULL, 0);
|
||||
|
||||
*new_val_len = strlen(*val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PHP_FUNCTION(my_get_raw)
|
||||
{
|
||||
long arg;
|
||||
char *var;
|
||||
int var_len;
|
||||
zval **tmp;
|
||||
zval *array_ptr = NULL;
|
||||
|
||||
if(zend_parse_parameters(2, "ls", &arg, &var, &var_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(arg) {
|
||||
case PARSE_GET:
|
||||
array_ptr = IF_G(get_array);
|
||||
break;
|
||||
case PARSE_POST:
|
||||
array_ptr = IF_G(post_array);
|
||||
break;
|
||||
case PARSE_COOKIE:
|
||||
array_ptr = IF_G(post_array);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!array_ptr) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if(zend_hash_find(HASH_OF(array_ptr), var, var_len+5, (void **)&tmp) == SUCCESS) {
|
||||
*return_value = **tmp;
|
||||
zval_copy_ctor(return_value);
|
||||
} else {
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -1,142 +1,39 @@
|
||||
<div align="center">
|
||||
<a href="https://php.net">
|
||||
<img
|
||||
alt="PHP"
|
||||
src="https://www.php.net/images/logos/new-php-logo.svg"
|
||||
width="150">
|
||||
</a>
|
||||
</div>
|
||||
The PHP Interpreter
|
||||
===================
|
||||
|
||||
# The PHP Interpreter
|
||||
This is the github mirror of the official PHP repository located at
|
||||
https://git.php.net.
|
||||
|
||||
PHP is a popular general-purpose scripting language that is especially suited to
|
||||
web development. Fast, flexible and pragmatic, PHP powers everything from your
|
||||
blog to the most popular websites in the world. PHP is distributed under the
|
||||
[PHP License v3.01](LICENSE).
|
||||
[](http://travis-ci.org/php/php-src)
|
||||
[](https://ci.appveyor.com/project/php/php-src)
|
||||
|
||||
[](https://travis-ci.org/php/php-src)
|
||||
[](https://ci.appveyor.com/project/php/php-src)
|
||||
[](https://dev.azure.com/phpazuredevops/php/_build/latest?definitionId=1&branchName=master)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:php)
|
||||
Pull Requests
|
||||
=============
|
||||
PHP accepts pull requests via github. Discussions are done on github, but
|
||||
depending on the topic can also be relayed to the official PHP developer
|
||||
mailing list internals@lists.php.net.
|
||||
|
||||
## Documentation
|
||||
New features require an RFC and must be accepted by the developers.
|
||||
See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more
|
||||
information on the process.
|
||||
|
||||
The PHP manual is available at [php.net/docs](https://php.net/docs).
|
||||
|
||||
## Installation
|
||||
|
||||
### Prebuilt packages and binaries
|
||||
|
||||
Prebuilt packages and binaries can be used to get up and running fast with PHP.
|
||||
|
||||
For Windows, the PHP binaries can be obtained from
|
||||
[windows.php.net](https://windows.php.net). After extracting the archive the
|
||||
`*.exe` files are ready to use.
|
||||
|
||||
For other systems, see the [installation chapter](https://php.net/install).
|
||||
|
||||
### Building PHP source code
|
||||
|
||||
*For Windows, see [Build your own PHP on Windows](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2).*
|
||||
|
||||
For a minimal PHP build from Git, you will need autoconf, bison, and re2c. For
|
||||
a default build, you will additionally need libxml2 and libsqlite3. On Ubuntu,
|
||||
you can install these using:
|
||||
|
||||
sudo apt install -y pkg-config build-essential autoconf bison re2c \
|
||||
libxml2-dev libsqlite3-dev
|
||||
|
||||
Generate configure:
|
||||
|
||||
./buildconf
|
||||
|
||||
Configure your build. `--enable-debug` is recommended for development, see
|
||||
`./configure --help` for a full list of options.
|
||||
|
||||
# For development
|
||||
./configure --enable-debug
|
||||
# For production
|
||||
./configure
|
||||
|
||||
Build PHP. To speed up the build, specify the maximum number of jobs using `-j`:
|
||||
|
||||
make -j4
|
||||
|
||||
The number of jobs should usually match the number of available cores, which
|
||||
can be determined using `nproc`.
|
||||
|
||||
## Testing PHP source code
|
||||
|
||||
PHP ships with an extensive test suite, the command `make test` is used after
|
||||
successful compilation of the sources to run this test suite.
|
||||
|
||||
It is possible to run tests using multiple cores by setting `-jN` in
|
||||
`TEST_PHP_ARGS`:
|
||||
|
||||
make TEST_PHP_ARGS=-j4 test
|
||||
|
||||
Shall run `make test` with a maximum of 4 concurrent jobs: Generally the maximum
|
||||
number of jobs should not exceed the number of cores available.
|
||||
|
||||
The [qa.php.net](https://qa.php.net) site provides more detailed info about
|
||||
testing and quality assurance.
|
||||
|
||||
## Installing PHP built from source
|
||||
|
||||
After a successful build (and test), PHP may be installed with:
|
||||
|
||||
make install
|
||||
|
||||
Depending on your permissions and prefix, `make install` may need super user
|
||||
permissions.
|
||||
|
||||
## PHP extensions
|
||||
|
||||
Extensions provide additional functionality on top of PHP. PHP consists of many
|
||||
essential bundled extensions. Additional extensions can be found in the PHP
|
||||
Extension Community Library - [PECL](https://pecl.php.net).
|
||||
|
||||
## Contributing
|
||||
|
||||
The PHP source code is located in the Git repository at
|
||||
[git.php.net](https://git.php.net). Contributions are most welcome by forking
|
||||
the [GitHub mirror repository](https://github.com/php/php-src) and sending a
|
||||
pull request.
|
||||
|
||||
Discussions are done on GitHub, but depending on the topic can also be relayed
|
||||
to the official PHP developer mailing list internals@lists.php.net.
|
||||
|
||||
New features require an RFC and must be accepted by the developers. See
|
||||
[Request for comments - RFC](https://wiki.php.net/rfc) and
|
||||
[Voting on PHP features](https://wiki.php.net/rfc/voting) for more information
|
||||
on the process.
|
||||
|
||||
Bug fixes **do not** require an RFC but require a bug tracker ticket. Open a
|
||||
ticket at [bugs.php.net](https://bugs.php.net) and reference the bug id using
|
||||
`#NNNNNN`.
|
||||
Bug fixes **do not** require an RFC, but require a bugtracker ticket. Always
|
||||
open a ticket at https://bugs.php.net and reference the bug id using #NNNNNN.
|
||||
|
||||
Fix #55371: get_magic_quotes_gpc() throws deprecation warning
|
||||
|
||||
After removing magic quotes, the get_magic_quotes_gpc function caused a
|
||||
deprecated warning. get_magic_quotes_gpc can be used to detect the
|
||||
magic_quotes behavior and therefore should not raise a warning at any time.
|
||||
The patch removes this warning.
|
||||
After removing magic quotes, the get_magic_quotes_gpc function caused
|
||||
a deprecate warning. get_magic_quotes_gpc can be used to detected
|
||||
the magic_quotes behavior and therefore should not raise a warning at any
|
||||
time. The patch removes this warning
|
||||
|
||||
Pull requests are not merged directly on GitHub. All PRs will be pulled and
|
||||
pushed through [git.php.net](https://git.php.net). See
|
||||
[Git workflow](https://wiki.php.net/vcs/gitworkflow) for more details.
|
||||
We do not merge pull requests directly on github. All PRs will be
|
||||
pulled and pushed through https://git.php.net.
|
||||
|
||||
### Guidelines for contributors
|
||||
|
||||
See further documents in the repository for more information on how to
|
||||
contribute:
|
||||
|
||||
- [Contributing to PHP](/CONTRIBUTING.md)
|
||||
- [PHP coding standards](/CODING_STANDARDS.md)
|
||||
- [Mailinglist rules](/docs/mailinglist-rules.md)
|
||||
- [PHP release process](/docs/release-process.md)
|
||||
|
||||
## Credits
|
||||
|
||||
For the list of people who've put work into PHP, please see the
|
||||
[PHP credits page](https://php.net/credits.php).
|
||||
Guidelines for contributors
|
||||
===========================
|
||||
- [CODING_STANDARDS](/CODING_STANDARDS)
|
||||
- [README.GIT-RULES](/README.GIT-RULES)
|
||||
- [README.MAILINGLIST_RULES](/README.MAILINGLIST_RULES)
|
||||
- [README.RELEASE_PROCESS](/README.RELEASE_PROCESS)
|
||||
@@ -0,0 +1,6 @@
|
||||
## process this file with automake to produce Makefile.am
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
noinst_LTLIBRARIES=libtsrm.la
|
||||
libtsrm_la_SOURCES = TSRM.c tsrm_strtok_r.c
|
||||
|
||||
depend:
|
||||
+256
-216
@@ -15,19 +15,16 @@
|
||||
#ifdef ZTS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if ZEND_DEBUG
|
||||
# include <assert.h>
|
||||
# define TSRM_ASSERT(c) assert(c)
|
||||
#else
|
||||
# define TSRM_ASSERT(c)
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
typedef struct _tsrm_tls_entry tsrm_tls_entry;
|
||||
|
||||
#if defined(TSRM_WIN32)
|
||||
/* TSRMLS_CACHE_DEFINE; is already done in Zend, this is being always compiled statically. */
|
||||
TSRMLS_CACHE_EXTERN();
|
||||
#endif
|
||||
|
||||
struct _tsrm_tls_entry {
|
||||
void **storage;
|
||||
@@ -41,7 +38,6 @@ typedef struct {
|
||||
size_t size;
|
||||
ts_allocate_ctor ctor;
|
||||
ts_allocate_dtor dtor;
|
||||
size_t fast_offset;
|
||||
int done;
|
||||
} tsrm_resource_type;
|
||||
|
||||
@@ -55,12 +51,8 @@ static ts_rsrc_id id_count;
|
||||
static tsrm_resource_type *resource_types_table=NULL;
|
||||
static int resource_types_table_size;
|
||||
|
||||
/* Reserved space for fast globals access */
|
||||
static size_t tsrm_reserved_pos = 0;
|
||||
static size_t tsrm_reserved_size = 0;
|
||||
|
||||
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
|
||||
static MUTEX_T tsrm_env_mutex; /* tsrm environ mutex */
|
||||
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
|
||||
|
||||
/* New thread handlers */
|
||||
static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler = NULL;
|
||||
@@ -74,7 +66,7 @@ int tsrm_error(int level, const char *format, ...);
|
||||
static int tsrm_error_level;
|
||||
static FILE *tsrm_error_file;
|
||||
|
||||
#ifdef TSRM_DEBUG
|
||||
#if TSRM_DEBUG
|
||||
#define TSRM_ERROR(args) tsrm_error args
|
||||
#define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
|
||||
{ \
|
||||
@@ -102,31 +94,52 @@ static FILE *tsrm_error_file;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
static DWORD tls_key;
|
||||
# define tsrm_tls_set(what) TlsSetValue(tls_key, (void*)(what))
|
||||
# define tsrm_tls_get() TlsGetValue(tls_key)
|
||||
#else
|
||||
#if defined(GNUPTH)
|
||||
static pth_key_t tls_key;
|
||||
# define tsrm_tls_set(what) pth_key_setdata(tls_key, (void*)(what))
|
||||
# define tsrm_tls_get() pth_key_getdata(tls_key)
|
||||
|
||||
#elif defined(PTHREADS)
|
||||
/* Thread local storage */
|
||||
static pthread_key_t tls_key;
|
||||
# define tsrm_tls_set(what) pthread_setspecific(tls_key, (void*)(what))
|
||||
# define tsrm_tls_get() pthread_getspecific(tls_key)
|
||||
|
||||
#elif defined(TSRM_ST)
|
||||
static int tls_key;
|
||||
# define tsrm_tls_set(what) st_thread_setspecific(tls_key, (void*)(what))
|
||||
# define tsrm_tls_get() st_thread_getspecific(tls_key)
|
||||
|
||||
#elif defined(TSRM_WIN32)
|
||||
static DWORD tls_key;
|
||||
# define tsrm_tls_set(what) TlsSetValue(tls_key, (void*)(what))
|
||||
# define tsrm_tls_get() TlsGetValue(tls_key)
|
||||
|
||||
#else
|
||||
# define tsrm_tls_set(what)
|
||||
# define tsrm_tls_get() NULL
|
||||
# warning tsrm_set_interpreter_context is probably broken on this platform
|
||||
#endif
|
||||
|
||||
TSRM_TLS uint8_t in_main_thread = 0;
|
||||
TSRM_TLS uint8_t is_thread_shutdown = 0;
|
||||
|
||||
/* Startup TSRM (call once for the entire process) */
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, const char *debug_filename)
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
|
||||
{/*{{{*/
|
||||
#ifdef TSRM_WIN32
|
||||
#if defined(GNUPTH)
|
||||
pth_init();
|
||||
pth_key_create(&tls_key, 0);
|
||||
#elif defined(PTHREADS)
|
||||
pthread_key_create( &tls_key, 0 );
|
||||
#elif defined(TSRM_ST)
|
||||
st_init();
|
||||
st_key_create(&tls_key, 0);
|
||||
#elif defined(TSRM_WIN32)
|
||||
tls_key = TlsAlloc();
|
||||
#else
|
||||
pthread_key_create(&tls_key, 0);
|
||||
#endif
|
||||
|
||||
/* ensure singleton */
|
||||
in_main_thread = 1;
|
||||
is_thread_shutdown = 0;
|
||||
|
||||
tsrm_error_file = stderr;
|
||||
tsrm_error_set(debug_level, debug_filename);
|
||||
@@ -135,7 +148,6 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
|
||||
tsrm_tls_table = (tsrm_tls_entry **) calloc(tsrm_tls_table_size, sizeof(tsrm_tls_entry *));
|
||||
if (!tsrm_tls_table) {
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate TLS table"));
|
||||
is_thread_shutdown = 1;
|
||||
return 0;
|
||||
}
|
||||
id_count=0;
|
||||
@@ -144,20 +156,14 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
|
||||
resource_types_table = (tsrm_resource_type *) calloc(resource_types_table_size, sizeof(tsrm_resource_type));
|
||||
if (!resource_types_table) {
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate resource types table"));
|
||||
is_thread_shutdown = 1;
|
||||
free(tsrm_tls_table);
|
||||
tsrm_tls_table = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsmm_mutex = tsrm_mutex_alloc();
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
|
||||
|
||||
tsrm_reserved_pos = 0;
|
||||
tsrm_reserved_size = 0;
|
||||
|
||||
tsrm_env_mutex = tsrm_mutex_alloc();
|
||||
|
||||
return 1;
|
||||
}/*}}}*/
|
||||
|
||||
@@ -167,53 +173,52 @@ TSRM_API void tsrm_shutdown(void)
|
||||
{/*{{{*/
|
||||
int i;
|
||||
|
||||
if (is_thread_shutdown) {
|
||||
/* shutdown must only occur once */
|
||||
return;
|
||||
}
|
||||
|
||||
is_thread_shutdown = 1;
|
||||
|
||||
if (!in_main_thread) {
|
||||
/* only the main thread may shutdown tsrm */
|
||||
/* ensure singleton */
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
|
||||
if (tsrm_tls_table) {
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
|
||||
|
||||
while (p) {
|
||||
int j;
|
||||
while (p) {
|
||||
int j;
|
||||
|
||||
next_p = p->next;
|
||||
for (j=0; j<p->count; j++) {
|
||||
if (p->storage[j]) {
|
||||
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
|
||||
resource_types_table[j].dtor(p->storage[j]);
|
||||
}
|
||||
if (!resource_types_table[j].fast_offset) {
|
||||
next_p = p->next;
|
||||
for (j=0; j<p->count; j++) {
|
||||
if (p->storage[j]) {
|
||||
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
|
||||
resource_types_table[j].dtor(p->storage[j]);
|
||||
}
|
||||
free(p->storage[j]);
|
||||
}
|
||||
}
|
||||
free(p->storage);
|
||||
free(p);
|
||||
p = next_p;
|
||||
}
|
||||
free(p->storage);
|
||||
free(p);
|
||||
p = next_p;
|
||||
}
|
||||
free(tsrm_tls_table);
|
||||
tsrm_tls_table = NULL;
|
||||
}
|
||||
if (resource_types_table) {
|
||||
free(resource_types_table);
|
||||
resource_types_table=NULL;
|
||||
}
|
||||
free(tsrm_tls_table);
|
||||
free(resource_types_table);
|
||||
tsrm_mutex_free(tsmm_mutex);
|
||||
tsrm_mutex_free(tsrm_env_mutex);
|
||||
tsmm_mutex = NULL;
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM"));
|
||||
if (tsrm_error_file!=stderr) {
|
||||
fclose(tsrm_error_file);
|
||||
}
|
||||
#ifdef TSRM_WIN32
|
||||
TlsFree(tls_key);
|
||||
#else
|
||||
#if defined(GNUPTH)
|
||||
pth_kill();
|
||||
#elif defined(PTHREADS)
|
||||
pthread_setspecific(tls_key, 0);
|
||||
pthread_key_delete(tls_key);
|
||||
#elif defined(TSRM_WIN32)
|
||||
TlsFree(tls_key);
|
||||
#endif
|
||||
if (tsrm_shutdown_handler) {
|
||||
tsrm_shutdown_handler();
|
||||
@@ -221,55 +226,14 @@ TSRM_API void tsrm_shutdown(void)
|
||||
tsrm_new_thread_begin_handler = NULL;
|
||||
tsrm_new_thread_end_handler = NULL;
|
||||
tsrm_shutdown_handler = NULL;
|
||||
|
||||
tsrm_reserved_pos = 0;
|
||||
tsrm_reserved_size = 0;
|
||||
}/*}}}*/
|
||||
|
||||
/* {{{ */
|
||||
/* environ lock api */
|
||||
TSRM_API void tsrm_env_lock(void) {
|
||||
tsrm_mutex_lock(tsrm_env_mutex);
|
||||
}
|
||||
|
||||
TSRM_API void tsrm_env_unlock(void) {
|
||||
tsrm_mutex_unlock(tsrm_env_mutex);
|
||||
} /* }}} */
|
||||
|
||||
/* enlarge the arrays for the already active threads */
|
||||
static void tsrm_update_active_threads(void)
|
||||
{/*{{{*/
|
||||
int i;
|
||||
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i];
|
||||
|
||||
while (p) {
|
||||
if (p->count < id_count) {
|
||||
int j;
|
||||
|
||||
p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
|
||||
for (j=p->count; j<id_count; j++) {
|
||||
if (resource_types_table[j].fast_offset) {
|
||||
p->storage[j] = (void *) (((char*)p) + resource_types_table[j].fast_offset);
|
||||
} else {
|
||||
p->storage[j] = (void *) malloc(resource_types_table[j].size);
|
||||
}
|
||||
if (resource_types_table[j].ctor) {
|
||||
resource_types_table[j].ctor(p->storage[j]);
|
||||
}
|
||||
}
|
||||
p->count = id_count;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
/* allocates a new thread-safe-resource id */
|
||||
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
|
||||
{/*{{{*/
|
||||
int i;
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
@@ -294,68 +258,28 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = 0;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
|
||||
|
||||
tsrm_update_active_threads();
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
/* enlarge the arrays for the already active threads */
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i];
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
|
||||
return *rsrc_id;
|
||||
}/*}}}*/
|
||||
while (p) {
|
||||
if (p->count < id_count) {
|
||||
int j;
|
||||
|
||||
|
||||
/* Reserve space for fast thread-safe-resources */
|
||||
TSRM_API void tsrm_reserve(size_t size)
|
||||
{/*{{{*/
|
||||
tsrm_reserved_pos = 0;
|
||||
tsrm_reserved_size = TSRM_ALIGNED_SIZE(size);
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
/* allocates a new fast thread-safe-resource id */
|
||||
TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
|
||||
{/*{{{*/
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new fast resource id, %d bytes", size));
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
|
||||
/* obtain a resource id */
|
||||
*rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
|
||||
|
||||
size = TSRM_ALIGNED_SIZE(size);
|
||||
if (tsrm_reserved_size - tsrm_reserved_pos < size) {
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate space for fast resource"));
|
||||
*rsrc_id = 0;
|
||||
*offset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*offset = TSRM_ALIGNED_SIZE(sizeof(tsrm_tls_entry)) + tsrm_reserved_pos;
|
||||
tsrm_reserved_pos += size;
|
||||
|
||||
/* store the new resource type in the resource sizes table */
|
||||
if (resource_types_table_size < id_count) {
|
||||
tsrm_resource_type *_tmp;
|
||||
_tmp = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);
|
||||
if (!_tmp) {
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
|
||||
*rsrc_id = 0;
|
||||
return 0;
|
||||
p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
|
||||
for (j=p->count; j<id_count; j++) {
|
||||
p->storage[j] = (void *) malloc(resource_types_table[j].size);
|
||||
if (resource_types_table[j].ctor) {
|
||||
resource_types_table[j].ctor(p->storage[j]);
|
||||
}
|
||||
}
|
||||
p->count = id_count;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
resource_types_table = _tmp;
|
||||
resource_types_table_size = id_count;
|
||||
}
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = *offset;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
|
||||
|
||||
tsrm_update_active_threads();
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
|
||||
@@ -368,7 +292,7 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
|
||||
int i;
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Creating data structures for thread %x", thread_id));
|
||||
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(TSRM_ALIGNED_SIZE(sizeof(tsrm_tls_entry)) + tsrm_reserved_size);
|
||||
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
|
||||
(*thread_resources_ptr)->storage = NULL;
|
||||
if (id_count > 0) {
|
||||
(*thread_resources_ptr)->storage = (void **) malloc(sizeof(void *)*id_count);
|
||||
@@ -379,7 +303,6 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
|
||||
|
||||
/* Set thread local storage to this new thread resources structure */
|
||||
tsrm_tls_set(*thread_resources_ptr);
|
||||
TSRMLS_CACHE = *thread_resources_ptr;
|
||||
|
||||
if (tsrm_new_thread_begin_handler) {
|
||||
tsrm_new_thread_begin_handler(thread_id);
|
||||
@@ -387,12 +310,9 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
|
||||
for (i=0; i<id_count; i++) {
|
||||
if (resource_types_table[i].done) {
|
||||
(*thread_resources_ptr)->storage[i] = NULL;
|
||||
} else {
|
||||
if (resource_types_table[i].fast_offset) {
|
||||
(*thread_resources_ptr)->storage[i] = (void *) (((char*)(*thread_resources_ptr)) + resource_types_table[i].fast_offset);
|
||||
} else {
|
||||
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
|
||||
}
|
||||
} else
|
||||
{
|
||||
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
|
||||
if (resource_types_table[i].ctor) {
|
||||
resource_types_table[i].ctor((*thread_resources_ptr)->storage[i]);
|
||||
}
|
||||
@@ -469,6 +389,65 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
|
||||
TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
|
||||
}/*}}}*/
|
||||
|
||||
/* frees an interpreter context. You are responsible for making sure that
|
||||
* it is not linked into the TSRM hash, and not marked as the current interpreter */
|
||||
void tsrm_free_interpreter_context(void *context)
|
||||
{/*{{{*/
|
||||
tsrm_tls_entry *next, *thread_resources = (tsrm_tls_entry*)context;
|
||||
int i;
|
||||
|
||||
while (thread_resources) {
|
||||
next = thread_resources->next;
|
||||
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
if (resource_types_table[i].dtor) {
|
||||
resource_types_table[i].dtor(thread_resources->storage[i]);
|
||||
}
|
||||
}
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
free(thread_resources->storage[i]);
|
||||
}
|
||||
free(thread_resources->storage);
|
||||
free(thread_resources);
|
||||
thread_resources = next;
|
||||
}
|
||||
}/*}}}*/
|
||||
|
||||
void *tsrm_set_interpreter_context(void *new_ctx)
|
||||
{/*{{{*/
|
||||
tsrm_tls_entry *current;
|
||||
|
||||
current = tsrm_tls_get();
|
||||
|
||||
/* TODO: unlink current from the global linked list, and replace it
|
||||
* it with the new context, protected by mutex where/if appropriate */
|
||||
|
||||
/* Set thread local storage to this new thread resources structure */
|
||||
tsrm_tls_set(new_ctx);
|
||||
|
||||
/* return old context, so caller can restore it when they're done */
|
||||
return current;
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
/* allocates a new interpreter context */
|
||||
void *tsrm_new_interpreter_context(void)
|
||||
{/*{{{*/
|
||||
tsrm_tls_entry *new_ctx, *current;
|
||||
THREAD_T thread_id;
|
||||
|
||||
thread_id = tsrm_thread_id();
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
|
||||
current = tsrm_tls_get();
|
||||
|
||||
allocate_new_resource(&new_ctx, thread_id);
|
||||
|
||||
/* switch back to the context that was in use prior to our creation
|
||||
* of the new one */
|
||||
return tsrm_set_interpreter_context(current);
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
/* frees all resources allocated for the current thread */
|
||||
void ts_free_thread(void)
|
||||
@@ -479,8 +458,6 @@ void ts_free_thread(void)
|
||||
int hash_value;
|
||||
tsrm_tls_entry *last=NULL;
|
||||
|
||||
TSRM_ASSERT(!in_main_thread);
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
|
||||
thread_resources = tsrm_tls_table[hash_value];
|
||||
@@ -493,9 +470,7 @@ void ts_free_thread(void)
|
||||
}
|
||||
}
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
if (!resource_types_table[i].fast_offset) {
|
||||
free(thread_resources->storage[i]);
|
||||
}
|
||||
free(thread_resources->storage[i]);
|
||||
}
|
||||
free(thread_resources->storage);
|
||||
if (last) {
|
||||
@@ -515,6 +490,53 @@ void ts_free_thread(void)
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
/* frees all resources allocated for all threads except current */
|
||||
void ts_free_worker_threads(void)
|
||||
{/*{{{*/
|
||||
tsrm_tls_entry *thread_resources;
|
||||
int i;
|
||||
THREAD_T thread_id = tsrm_thread_id();
|
||||
int hash_value;
|
||||
tsrm_tls_entry *last=NULL;
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
|
||||
thread_resources = tsrm_tls_table[hash_value];
|
||||
|
||||
while (thread_resources) {
|
||||
if (thread_resources->thread_id != thread_id) {
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
if (resource_types_table[i].dtor) {
|
||||
resource_types_table[i].dtor(thread_resources->storage[i]);
|
||||
}
|
||||
}
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
free(thread_resources->storage[i]);
|
||||
}
|
||||
free(thread_resources->storage);
|
||||
if (last) {
|
||||
last->next = thread_resources->next;
|
||||
} else {
|
||||
tsrm_tls_table[hash_value] = thread_resources->next;
|
||||
}
|
||||
free(thread_resources);
|
||||
if (last) {
|
||||
thread_resources = last->next;
|
||||
} else {
|
||||
thread_resources = tsrm_tls_table[hash_value];
|
||||
}
|
||||
} else {
|
||||
if (thread_resources->next) {
|
||||
last = thread_resources;
|
||||
}
|
||||
thread_resources = thread_resources->next;
|
||||
}
|
||||
}
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
/* deallocates all occurrences of a given id */
|
||||
void ts_free_id(ts_rsrc_id id)
|
||||
{/*{{{*/
|
||||
@@ -534,9 +556,7 @@ void ts_free_id(ts_rsrc_id id)
|
||||
if (resource_types_table && resource_types_table[j].dtor) {
|
||||
resource_types_table[j].dtor(p->storage[j]);
|
||||
}
|
||||
if (!resource_types_table[j].fast_offset) {
|
||||
free(p->storage[j]);
|
||||
}
|
||||
free(p->storage[j]);
|
||||
p->storage[j] = NULL;
|
||||
}
|
||||
p = p->next;
|
||||
@@ -551,6 +571,8 @@ void ts_free_id(ts_rsrc_id id)
|
||||
}/*}}}*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Utility Functions
|
||||
*/
|
||||
@@ -560,8 +582,12 @@ TSRM_API THREAD_T tsrm_thread_id(void)
|
||||
{/*{{{*/
|
||||
#ifdef TSRM_WIN32
|
||||
return GetCurrentThreadId();
|
||||
#else
|
||||
#elif defined(GNUPTH)
|
||||
return pth_self();
|
||||
#elif defined(PTHREADS)
|
||||
return pthread_self();
|
||||
#elif defined(TSRM_ST)
|
||||
return st_thread_self();
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
@@ -573,9 +599,14 @@ TSRM_API MUTEX_T tsrm_mutex_alloc(void)
|
||||
#ifdef TSRM_WIN32
|
||||
mutexp = malloc(sizeof(CRITICAL_SECTION));
|
||||
InitializeCriticalSection(mutexp);
|
||||
#else
|
||||
#elif defined(GNUPTH)
|
||||
mutexp = (MUTEX_T) malloc(sizeof(*mutexp));
|
||||
pth_mutex_init(mutexp);
|
||||
#elif defined(PTHREADS)
|
||||
mutexp = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
|
||||
pthread_mutex_init(mutexp,NULL);
|
||||
#elif defined(TSRM_ST)
|
||||
mutexp = st_mutex_new();
|
||||
#endif
|
||||
#ifdef THR_DEBUG
|
||||
printf("Mutex created thread: %d\n",mythreadid());
|
||||
@@ -591,9 +622,13 @@ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
|
||||
#ifdef TSRM_WIN32
|
||||
DeleteCriticalSection(mutexp);
|
||||
free(mutexp);
|
||||
#else
|
||||
#elif defined(GNUPTH)
|
||||
free(mutexp);
|
||||
#elif defined(PTHREADS)
|
||||
pthread_mutex_destroy(mutexp);
|
||||
free(mutexp);
|
||||
#elif defined(TSRM_ST)
|
||||
st_mutex_destroy(mutexp);
|
||||
#endif
|
||||
}
|
||||
#ifdef THR_DEBUG
|
||||
@@ -612,8 +647,15 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
|
||||
#ifdef TSRM_WIN32
|
||||
EnterCriticalSection(mutexp);
|
||||
return 0;
|
||||
#else
|
||||
#elif defined(GNUPTH)
|
||||
if (pth_mutex_acquire(mutexp, 0, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#elif defined(PTHREADS)
|
||||
return pthread_mutex_lock(mutexp);
|
||||
#elif defined(TSRM_ST)
|
||||
return st_mutex_lock(mutexp);
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
@@ -628,8 +670,15 @@ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
|
||||
#ifdef TSRM_WIN32
|
||||
LeaveCriticalSection(mutexp);
|
||||
return 0;
|
||||
#else
|
||||
#elif defined(GNUPTH)
|
||||
if (pth_mutex_release(mutexp)) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#elif defined(PTHREADS)
|
||||
return pthread_mutex_unlock(mutexp);
|
||||
#elif defined(TSRM_ST)
|
||||
return st_mutex_unlock(mutexp);
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
@@ -640,8 +689,12 @@ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
|
||||
TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset)
|
||||
{/*{{{*/
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Changed sigmask in thread: %ld", tsrm_thread_id()));
|
||||
|
||||
return pthread_sigmask(how, set, oldset);
|
||||
/* TODO: add support for other APIs */
|
||||
#ifdef PTHREADS
|
||||
return pthread_sigmask(how, set, oldset);
|
||||
#else
|
||||
return sigprocmask(how, set, oldset);
|
||||
#endif
|
||||
}/*}}}*/
|
||||
#endif
|
||||
|
||||
@@ -677,7 +730,7 @@ TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler)
|
||||
* Debug support
|
||||
*/
|
||||
|
||||
#ifdef TSRM_DEBUG
|
||||
#if TSRM_DEBUG
|
||||
int tsrm_error(int level, const char *format, ...)
|
||||
{/*{{{*/
|
||||
if (level<=tsrm_error_level) {
|
||||
@@ -698,11 +751,11 @@ int tsrm_error(int level, const char *format, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void tsrm_error_set(int level, const char *debug_filename)
|
||||
void tsrm_error_set(int level, char *debug_filename)
|
||||
{/*{{{*/
|
||||
tsrm_error_level = level;
|
||||
|
||||
#ifdef TSRM_DEBUG
|
||||
#if TSRM_DEBUG
|
||||
if (tsrm_error_file!=stderr) { /* close files opened earlier */
|
||||
fclose(tsrm_error_file);
|
||||
}
|
||||
@@ -723,46 +776,33 @@ TSRM_API void *tsrm_get_ls_cache(void)
|
||||
return tsrm_tls_get();
|
||||
}/*}}}*/
|
||||
|
||||
/* Returns offset of tsrm_ls_cache slot from Thread Control Block address */
|
||||
TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void)
|
||||
{/*{{{*/
|
||||
#if defined(__APPLE__) && defined(__x86_64__)
|
||||
// TODO: Implement support for fast JIT ZTS code ???
|
||||
return 0;
|
||||
#elif defined(__x86_64__) && defined(__GNUC__) && !defined(__FreeBSD__)
|
||||
size_t ret;
|
||||
|
||||
asm ("movq _tsrm_ls_cache@gottpoff(%%rip),%0"
|
||||
: "=r" (ret));
|
||||
return ret;
|
||||
#elif defined(__i386__) && defined(__GNUC__) && !defined(__FreeBSD__)
|
||||
size_t ret;
|
||||
|
||||
asm ("leal _tsrm_ls_cache@ntpoff,%0"
|
||||
: "=r" (ret));
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API uint8_t tsrm_is_main_thread(void)
|
||||
{/*{{{*/
|
||||
return in_main_thread;
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API uint8_t tsrm_is_shutdown(void)
|
||||
{/*{{{*/
|
||||
return is_thread_shutdown;
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API const char *tsrm_api_name(void)
|
||||
{/*{{{*/
|
||||
#ifdef TSRM_WIN32
|
||||
#if defined(GNUPTH)
|
||||
return "GNU Pth";
|
||||
#elif defined(PTHREADS)
|
||||
return "POSIX Threads";
|
||||
#elif defined(TSRM_ST)
|
||||
return "State Threads";
|
||||
#elif defined(TSRM_WIN32)
|
||||
return "Windows Threads";
|
||||
#else
|
||||
return "POSIX Threads";
|
||||
return "Unknown";
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
#endif /* ZTS */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
+74
-47
@@ -15,9 +15,9 @@
|
||||
|
||||
#if !defined(__CYGWIN__) && defined(WIN32)
|
||||
# define TSRM_WIN32
|
||||
# include "Zend/zend_config.w32.h"
|
||||
# include "tsrm_config.w32.h"
|
||||
#else
|
||||
# include "main/php_config.h"
|
||||
# include <tsrm_config.h>
|
||||
#endif
|
||||
|
||||
#include "main/php_stdint.h"
|
||||
@@ -44,16 +44,17 @@ typedef uintptr_t tsrm_uintptr_t;
|
||||
# ifndef TSRM_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
#else
|
||||
# include <windows.h>
|
||||
# include <shellapi.h>
|
||||
#elif defined(GNUPTH)
|
||||
# include <pth.h>
|
||||
#elif defined(PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if SIZEOF_SIZE_T == 4
|
||||
# define TSRM_ALIGNED_SIZE(size) \
|
||||
(((size) + INT32_C(15)) & ~INT32_C(15))
|
||||
#else
|
||||
# define TSRM_ALIGNED_SIZE(size) \
|
||||
(((size) + INT64_C(15)) & ~INT64_C(15))
|
||||
#elif defined(TSRM_ST)
|
||||
# include <st.h>
|
||||
#elif defined(BETHREADS)
|
||||
#include <kernel/OS.h>
|
||||
#include <TLS.h>
|
||||
#endif
|
||||
|
||||
typedef int ts_rsrc_id;
|
||||
@@ -62,12 +63,20 @@ typedef int ts_rsrc_id;
|
||||
#ifdef TSRM_WIN32
|
||||
# define THREAD_T DWORD
|
||||
# define MUTEX_T CRITICAL_SECTION *
|
||||
#else
|
||||
#elif defined(GNUPTH)
|
||||
# define THREAD_T pth_t
|
||||
# define MUTEX_T pth_mutex_t *
|
||||
#elif defined(PTHREADS)
|
||||
# define THREAD_T pthread_t
|
||||
# define MUTEX_T pthread_mutex_t *
|
||||
#elif defined(TSRM_ST)
|
||||
# define THREAD_T st_thread_t
|
||||
# define MUTEX_T st_mutex_t
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
typedef void (*ts_allocate_ctor)(void *);
|
||||
typedef void (*ts_allocate_dtor)(void *);
|
||||
@@ -79,20 +88,12 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* startup/shutdown */
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, const char *debug_filename);
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename);
|
||||
TSRM_API void tsrm_shutdown(void);
|
||||
|
||||
/* environ lock API */
|
||||
TSRM_API void tsrm_env_lock(void);
|
||||
TSRM_API void tsrm_env_unlock(void);
|
||||
|
||||
/* allocates a new thread-safe-resource id */
|
||||
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
|
||||
|
||||
/* Fast resource in reserved (pre-allocated) space */
|
||||
TSRM_API void tsrm_reserve(size_t size);
|
||||
TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
|
||||
|
||||
/* fetches the requested resource for the current thread */
|
||||
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
|
||||
#define ts_resource(id) ts_resource_ex(id, NULL)
|
||||
@@ -100,6 +101,9 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
|
||||
/* frees all resources allocated for the current thread */
|
||||
TSRM_API void ts_free_thread(void);
|
||||
|
||||
/* frees all resources allocated for all threads except current */
|
||||
void ts_free_worker_threads(void);
|
||||
|
||||
/* deallocates all occurrences of a given id */
|
||||
TSRM_API void ts_free_id(ts_rsrc_id id);
|
||||
|
||||
@@ -115,7 +119,7 @@ typedef void (*tsrm_shutdown_func_t)(void);
|
||||
|
||||
|
||||
TSRM_API int tsrm_error(int level, const char *format, ...);
|
||||
TSRM_API void tsrm_error_set(int level, const char *debug_filename);
|
||||
TSRM_API void tsrm_error_set(int level, char *debug_filename);
|
||||
|
||||
/* utility functions */
|
||||
TSRM_API THREAD_T tsrm_thread_id(void);
|
||||
@@ -131,55 +135,63 @@ TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_th
|
||||
TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler);
|
||||
TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler);
|
||||
|
||||
/* these 3 APIs should only be used by people that fully understand the threading model
|
||||
* used by PHP/Zend and the selected SAPI. */
|
||||
TSRM_API void *tsrm_new_interpreter_context(void);
|
||||
TSRM_API void *tsrm_set_interpreter_context(void *new_ctx);
|
||||
TSRM_API void tsrm_free_interpreter_context(void *context);
|
||||
|
||||
TSRM_API void *tsrm_get_ls_cache(void);
|
||||
TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void);
|
||||
TSRM_API uint8_t tsrm_is_main_thread(void);
|
||||
TSRM_API uint8_t tsrm_is_shutdown(void);
|
||||
TSRM_API const char *tsrm_api_name(void);
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
# define TSRM_TLS __declspec(thread)
|
||||
#if defined(__cplusplus) && __cplusplus > 199711L
|
||||
# define TSRM_TLS thread_local
|
||||
#else
|
||||
# define TSRM_TLS __thread
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#if !__has_attribute(tls_model) || defined(__FreeBSD__)
|
||||
# define TSRM_TLS_MODEL_ATTR
|
||||
#elif __PIC__
|
||||
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec")))
|
||||
#else
|
||||
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("local-exec")))
|
||||
# ifdef TSRM_WIN32
|
||||
# define TSRM_TLS __declspec(thread)
|
||||
# else
|
||||
# define TSRM_TLS __thread
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
|
||||
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
|
||||
|
||||
#define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
|
||||
#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_get_ls_cache()
|
||||
#define TSRMG(id, type, element) (TSRMG_BULK(id, type)->element)
|
||||
#define TSRMG_BULK(id, type) ((type) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(id)])
|
||||
#define TSRMG_FAST(offset, type, element) (TSRMG_FAST_BULK(offset, type)->element)
|
||||
#define TSRMG_FAST_BULK(offset, type) ((type) (((char*) tsrm_get_ls_cache())+(offset)))
|
||||
|
||||
#define TSRMG_STATIC(id, type, element) (TSRMG_BULK_STATIC(id, type)->element)
|
||||
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
|
||||
#define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element)
|
||||
#define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset)))
|
||||
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR;
|
||||
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
|
||||
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
|
||||
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
|
||||
#if ZEND_DEBUG
|
||||
#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
|
||||
#define TSRMLS_CACHE_RESET()
|
||||
#else
|
||||
#define TSRMLS_CACHE_UPDATE() if (!TSRMLS_CACHE) TSRMLS_CACHE = tsrm_get_ls_cache()
|
||||
#define TSRMLS_CACHE_RESET() TSRMLS_CACHE = NULL
|
||||
#endif
|
||||
#define TSRMLS_CACHE _tsrm_ls_cache
|
||||
|
||||
/* BC only */
|
||||
#define TSRMLS_D void
|
||||
#define TSRMLS_DC
|
||||
#define TSRMLS_C
|
||||
#define TSRMLS_CC
|
||||
#define TSRMLS_FETCH()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* non ZTS */
|
||||
|
||||
#define tsrm_env_lock()
|
||||
#define tsrm_env_unlock()
|
||||
#define TSRMLS_FETCH()
|
||||
#define TSRMLS_FETCH_FROM_CTX(ctx)
|
||||
#define TSRMLS_SET_CTX(ctx)
|
||||
|
||||
#define TSRMG_STATIC(id, type, element)
|
||||
#define TSRMLS_CACHE_EXTERN()
|
||||
@@ -189,6 +201,21 @@ TSRM_API const char *tsrm_api_name(void);
|
||||
|
||||
#define TSRM_TLS
|
||||
|
||||
/* BC only */
|
||||
#define TSRMLS_D void
|
||||
#define TSRMLS_DC
|
||||
#define TSRMLS_C
|
||||
#define TSRMLS_CC
|
||||
|
||||
#endif /* ZTS */
|
||||
|
||||
#endif /* TSRM_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -0,0 +1,3 @@
|
||||
AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[
|
||||
LIBTOOL='$(SHELL) $(top_builddir)/libtool $1'
|
||||
])
|
||||
@@ -0,0 +1,40 @@
|
||||
# Makefile to generate build tools
|
||||
#
|
||||
# Standard usage:
|
||||
# make -f build.mk
|
||||
#
|
||||
# Written by Sascha Schumann
|
||||
|
||||
LT_TARGETS = ltmain.sh ltconfig
|
||||
|
||||
config_h_in = tsrm_config.h.in
|
||||
|
||||
makefile_am_files = Makefile.am
|
||||
makefile_in_files = $(makefile_am_files:.am=.in)
|
||||
makefile_files = $(makefile_am_files:e.am=e)
|
||||
|
||||
targets = $(makefile_in_files) $(LT_TARGETS) configure $(config_h_in)
|
||||
|
||||
all: $(targets)
|
||||
|
||||
clean:
|
||||
rm -f $(targets)
|
||||
|
||||
$(LT_TARGETS):
|
||||
rm -f $(LT_TARGETS)
|
||||
libtoolize --automake $(AMFLAGS) -f
|
||||
|
||||
$(makefile_in_files): $(makefile_am_files)
|
||||
automake -a -i $(AMFLAGS) $(makefile_files)
|
||||
|
||||
aclocal.m4: configure.ac acinclude.m4
|
||||
aclocal
|
||||
|
||||
$(config_h_in): configure.ac
|
||||
# explicitly remove target since autoheader does not seem to work
|
||||
# correctly otherwise (timestamps are not updated)
|
||||
@rm -f $@
|
||||
autoheader
|
||||
|
||||
configure: aclocal.m4 configure.ac
|
||||
autoconf
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
--copy)
|
||||
automake_flags=--copy
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
libtoolize --force --automake $automake_flags
|
||||
|
||||
mv aclocal.m4 aclocal.m4.old 2>/dev/null
|
||||
aclocal
|
||||
if cmp aclocal.m4.old aclocal.m4 > /dev/null 2>&1; then
|
||||
echo "buildconf: keeping ${1}aclocal.m4"
|
||||
mv aclocal.m4.old aclocal.m4
|
||||
else
|
||||
echo "buildconf: created or modified ${1}aclocal.m4"
|
||||
fi
|
||||
|
||||
autoheader
|
||||
|
||||
automake --add-missing --include-deps $automake_flags
|
||||
|
||||
mv configure configure.old 2>/dev/null
|
||||
autoconf
|
||||
if cmp configure.old configure > /dev/null 2>&1; then
|
||||
echo "buildconf: keeping ${1}configure"
|
||||
mv configure.old configure
|
||||
else
|
||||
echo "buildconf: created or modified ${1}configure"
|
||||
fi
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// vim:ft=javascript
|
||||
|
||||
ADD_SOURCES("TSRM", "TSRM.c tsrm_win32.c");
|
||||
ADD_SOURCES("TSRM", "TSRM.c tsrm_strtok_r.c tsrm_win32.c");
|
||||
ADD_FLAG("CFLAGS_BD_TSRM", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
@@ -0,0 +1,35 @@
|
||||
dnl
|
||||
dnl Minimalistic configure.ac for TSRM.
|
||||
dnl
|
||||
|
||||
AC_INIT(TSRM.c)
|
||||
AM_INIT_AUTOMAKE(TSRM, 1.0, nodefine)
|
||||
AM_CONFIG_HEADER(tsrm_config.h)
|
||||
|
||||
AH_TOP([
|
||||
#undef PTHREADS
|
||||
])
|
||||
|
||||
sinclude(tsrm.m4)
|
||||
|
||||
TSRM_BASIC_CHECKS
|
||||
TSRM_THREADS_CHECKS
|
||||
|
||||
AM_PROG_LIBTOOL
|
||||
if test "$enable_debug" != "yes"; then
|
||||
AM_SET_LIBTOOL_VARIABLE([--silent])
|
||||
fi
|
||||
|
||||
dnl TSRM_PTHREAD
|
||||
|
||||
AC_CHECK_HEADERS(
|
||||
utime.h \
|
||||
dirent.h \
|
||||
stdarg.h \
|
||||
alloca.h \
|
||||
unistd.h \
|
||||
limits.h
|
||||
)
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
/* Keep this header for compatibility with external code, it's currently not
|
||||
used anywhere in the core and there are no implementations in TSRM. */
|
||||
#include "win32/readdir.h"
|
||||
+34
-9
@@ -28,7 +28,7 @@ dnl OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
dnl
|
||||
dnl PTHREADS_FLAGS
|
||||
dnl
|
||||
dnl Set some magic defines to achieve POSIX threads conformance.
|
||||
dnl Set some magic defines to achieve POSIX threads conformance
|
||||
dnl
|
||||
AC_DEFUN([PTHREADS_FLAGS],[
|
||||
if test -z "$host_alias" && test -n "$host"; then
|
||||
@@ -52,17 +52,18 @@ AC_DEFUN([PTHREADS_FLAGS],[
|
||||
PTHREAD_FLAGS=-D_REENTRANT;;
|
||||
*sco*)
|
||||
PTHREAD_FLAGS=-D_REENTRANT;;
|
||||
dnl Solves sigwait() problem, creates problems with u_long etc.
|
||||
dnl PTHREAD_FLAGS="-D_REENTRANT -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506 -D_XOPEN_SOURCE_EXTENDED=1";;
|
||||
esac
|
||||
|
||||
if test -n "$PTHREAD_FLAGS"; then
|
||||
CPPFLAGS="$CPPFLAGS $PTHREAD_FLAGS"
|
||||
fi
|
||||
])
|
||||
|
||||
])dnl
|
||||
dnl
|
||||
dnl PTHREADS_CHECK_COMPILE
|
||||
dnl
|
||||
dnl Check whether the current setup can use POSIX threads calls.
|
||||
dnl Check whether the current setup can use POSIX threads calls
|
||||
dnl
|
||||
AC_DEFUN([PTHREADS_CHECK_COMPILE], [
|
||||
AC_LINK_IFELSE([ AC_LANG_SOURCE([
|
||||
@@ -84,12 +85,11 @@ int main() {
|
||||
], [
|
||||
pthreads_checked=no
|
||||
]
|
||||
) ] )
|
||||
|
||||
) ] )dnl
|
||||
dnl
|
||||
dnl PTHREADS_CHECK
|
||||
dnl PTHREADS_CHECK()
|
||||
dnl
|
||||
dnl Try to find a way to enable POSIX threads.
|
||||
dnl Try to find a way to enable POSIX threads
|
||||
dnl
|
||||
dnl Magic flags
|
||||
dnl -kthread gcc (FreeBSD)
|
||||
@@ -102,6 +102,14 @@ dnl -qthreaded AIX cc V5
|
||||
dnl -threads gcc (HP-UX)
|
||||
dnl
|
||||
AC_DEFUN([PTHREADS_CHECK],[
|
||||
|
||||
save_CFLAGS=$CFLAGS
|
||||
save_LIBS=$LIBS
|
||||
PTHREADS_ASSIGN_VARS
|
||||
PTHREADS_CHECK_COMPILE
|
||||
LIBS=$save_LIBS
|
||||
CFLAGS=$save_CFLAGS
|
||||
|
||||
AC_CACHE_CHECK(for pthreads_cflags,ac_cv_pthreads_cflags,[
|
||||
ac_cv_pthreads_cflags=
|
||||
if test "$pthreads_working" != "yes"; then
|
||||
@@ -137,4 +145,21 @@ fi
|
||||
if test "x$ac_cv_pthreads_cflags" != "x" -o "x$ac_cv_pthreads_lib" != "x"; then
|
||||
pthreads_working="yes"
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$pthreads_working" = "yes"; then
|
||||
threads_result="POSIX-Threads found"
|
||||
else
|
||||
threads_result="POSIX-Threads not found"
|
||||
fi
|
||||
])dnl
|
||||
dnl
|
||||
dnl
|
||||
AC_DEFUN([PTHREADS_ASSIGN_VARS],[
|
||||
if test -n "$ac_cv_pthreads_lib"; then
|
||||
LIBS="$LIBS -l$ac_cv_pthreads_lib"
|
||||
fi
|
||||
|
||||
if test -n "$ac_cv_pthreads_cflags"; then
|
||||
CFLAGS="$CFLAGS $ac_cv_pthreads_cflags"
|
||||
fi
|
||||
])dnl
|
||||
+93
-4
@@ -1,9 +1,59 @@
|
||||
dnl This file contains TSRM specific autoconf macros.
|
||||
m4_include([TSRM/m4/ax_func_which_gethostbyname_r.m4])
|
||||
|
||||
AC_DEFUN([TSRM_BASIC_CHECKS],[
|
||||
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
dnl AC_REQUIRE([AM_PROG_CC_STDC])dnl
|
||||
AC_REQUIRE([AC_PROG_CC_C_O])dnl
|
||||
AC_REQUIRE([AC_PROG_RANLIB])dnl
|
||||
|
||||
AC_CHECK_HEADERS(stdarg.h)
|
||||
|
||||
AC_CHECK_FUNCS(sigprocmask)
|
||||
|
||||
AX_FUNC_WHICH_GETHOSTBYNAME_R()
|
||||
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TSRM_CHECK_PTH],[
|
||||
|
||||
AC_MSG_CHECKING(for GNU Pth)
|
||||
PTH_PREFIX="`$1 --prefix`"
|
||||
if test -z "$PTH_PREFIX"; then
|
||||
AC_MSG_RESULT(Please check your Pth installation)
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS `$1 --cflags`"
|
||||
LDFLAGS="$LDFLAGS `$1 --ldflags`"
|
||||
LIBS="$LIBS `$1 --libs`"
|
||||
|
||||
AC_DEFINE(GNUPTH, 1, [Whether you use GNU Pth])
|
||||
AC_MSG_RESULT(yes - installed in $PTH_PREFIX)
|
||||
|
||||
])
|
||||
|
||||
AC_DEFUN([TSRM_CHECK_ST],[
|
||||
if test -r "$1/include/st.h"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$1/include"
|
||||
LDFLAGS="$LDFLAGS -L$1/lib"
|
||||
elif test -r "$1/st.h"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$1"
|
||||
LDFLAGS="$LDFLAGS -L$1"
|
||||
fi
|
||||
AC_CHECK_HEADERS(st.h,[],[
|
||||
AC_MSG_ERROR([Sorry[,] I was unable to locate the State Threads header file. Please specify the prefix using --with-tsrm-st=/prefix])
|
||||
])
|
||||
LIBS="$LIBS -lst"
|
||||
AC_MSG_CHECKING(for SGI's State Threads)
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(TSRM_ST, 1, [ ])
|
||||
])
|
||||
|
||||
sinclude(threads.m4)
|
||||
|
||||
dnl
|
||||
dnl TSRM_CHECK_PTHREADS
|
||||
dnl
|
||||
AC_DEFUN([TSRM_CHECK_PTHREADS],[
|
||||
|
||||
PTHREADS_CHECK
|
||||
|
||||
if test "$pthreads_working" != "yes"; then
|
||||
@@ -15,3 +65,42 @@ AC_DEFINE(PTHREADS, 1, Whether to use Pthreads)
|
||||
AC_MSG_CHECKING(for POSIX threads)
|
||||
AC_MSG_RESULT(yes)
|
||||
])
|
||||
|
||||
AC_DEFUN([TSRM_THREADS_CHECKS],[
|
||||
|
||||
dnl For the thread implementations, we always use --with-*
|
||||
dnl to maintain consistency
|
||||
|
||||
AC_ARG_WITH(tsrm-pth,
|
||||
[ --with-tsrm-pth[=pth-config]
|
||||
Use GNU Pth],[
|
||||
TSRM_PTH=$withval
|
||||
],[
|
||||
TSRM_PTH=no
|
||||
])
|
||||
|
||||
AC_ARG_WITH(tsrm-st,
|
||||
[ --with-tsrm-st Use SGI's State Threads],[
|
||||
TSRM_ST=$withval
|
||||
],[
|
||||
TSRM_ST=no
|
||||
])
|
||||
|
||||
AC_ARG_WITH(tsrm-pthreads,
|
||||
[ --with-tsrm-pthreads Use POSIX threads (default)],[
|
||||
TSRM_PTHREADS=$withval
|
||||
],[
|
||||
TSRM_PTHREADS=yes
|
||||
])
|
||||
|
||||
test "$TSRM_PTH" = "yes" && TSRM_PTH=pth-config
|
||||
|
||||
if test "$TSRM_PTH" != "no"; then
|
||||
TSRM_CHECK_PTH($TSRM_PTH)
|
||||
elif test "$TSRM_ST" != "no"; then
|
||||
TSRM_CHECK_ST($TSRM_ST)
|
||||
elif test "$TSRM_PTHREADS" != "no"; then
|
||||
TSRM_CHECK_PTHREADS
|
||||
fi
|
||||
|
||||
])
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef TSRM_CONFIG_W32_H
|
||||
#define TSRM_CONFIG_W32_H
|
||||
|
||||
#include <../main/config.w32.h>
|
||||
#include "Zend/zend_config.w32.h"
|
||||
|
||||
#define HAVE_UTIME 1
|
||||
#define HAVE_ALLOCA 1
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifndef TSRM_CONFIG_COMMON_H
|
||||
#define TSRM_CONFIG_COMMON_H
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
# ifdef _WIN32
|
||||
# define TSRM_WIN32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
# include "tsrm_config.w32.h"
|
||||
#else
|
||||
# include <tsrm_config.h>
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_ALLOCA_H && !defined(_ALLOCA_H)
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#ifndef __GNUC__
|
||||
# ifndef HAVE_ALLOCA_H
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
# if _WIN32
|
||||
# include "win32/ioutil.h"
|
||||
# define MAXPATHLEN PHP_WIN32_IOUTIL_MAXPATHLEN
|
||||
# elif PATH_MAX
|
||||
# define MAXPATHLEN PATH_MAX
|
||||
# elif defined(MAX_PATH)
|
||||
# define MAXPATHLEN MAX_PATH
|
||||
# else
|
||||
# define MAXPATHLEN 256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2))
|
||||
# define TSRM_ALLOCA_MAX_SIZE 4096
|
||||
# define TSRM_ALLOCA_FLAG(name) \
|
||||
int name;
|
||||
# define tsrm_do_alloca_ex(size, limit, use_heap) \
|
||||
((use_heap = ((size) > (limit))) ? malloc(size) : alloca(size))
|
||||
# define tsrm_do_alloca(size, use_heap) \
|
||||
tsrm_do_alloca_ex(size, TSRM_ALLOCA_MAX_SIZE, use_heap)
|
||||
# define tsrm_free_alloca(p, use_heap) \
|
||||
do { if (use_heap) free(p); } while (0)
|
||||
#else
|
||||
# define TSRM_ALLOCA_FLAG(name)
|
||||
# define tsrm_do_alloca(p, use_heap) malloc(p)
|
||||
# define tsrm_free_alloca(p, use_heap) free(p)
|
||||
#endif
|
||||
|
||||
#endif /* TSRM_CONFIG_COMMON_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tsrm_config_common.h"
|
||||
#include "tsrm_strtok_r.h"
|
||||
|
||||
static inline int in_character_class(char ch, const char *delim)
|
||||
{/*{{{*/
|
||||
while (*delim) {
|
||||
if (*delim == ch) {
|
||||
return 1;
|
||||
}
|
||||
delim++;
|
||||
}
|
||||
return 0;
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API char *tsrm_strtok_r(char *s, const char *delim, char **last)
|
||||
{/*{{{*/
|
||||
char *token;
|
||||
|
||||
if (s == NULL) {
|
||||
s = *last;
|
||||
}
|
||||
|
||||
while (*s && in_character_class(*s, delim)) {
|
||||
s++;
|
||||
}
|
||||
if (!*s) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = s;
|
||||
|
||||
while (*s && !in_character_class(*s, delim)) {
|
||||
s++;
|
||||
}
|
||||
if (!*s) {
|
||||
*last = s;
|
||||
} else {
|
||||
*s = '\0';
|
||||
*last = s + 1;
|
||||
}
|
||||
return token;
|
||||
}/*}}}*/
|
||||
|
||||
#if 0
|
||||
|
||||
main()
|
||||
{
|
||||
char foo[] = "/foo/bar//\\barbara";
|
||||
char *last;
|
||||
char *token;
|
||||
|
||||
token = tsrm_strtok_r(foo, "/\\", &last);
|
||||
while (token) {
|
||||
printf ("Token = '%s'\n", token);
|
||||
token = tsrm_strtok_r(NULL, "/\\", &last);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef TSRM_STRTOK_R
|
||||
#define TSRM_STRTOK_R
|
||||
|
||||
#include "TSRM.h"
|
||||
|
||||
TSRM_API char *tsrm_strtok_r(char *s, const char *delim, char **last);
|
||||
|
||||
#endif
|
||||
+35
-29
@@ -1,6 +1,8 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2018 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
@@ -103,7 +105,7 @@ TSRM_API void tsrm_win32_shutdown(void)
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
const char * tsrm_win32_get_path_sid_key(const char *pathname, size_t pathname_len, size_t *key_len)
|
||||
char * tsrm_win32_get_path_sid_key(const char *pathname, size_t pathname_len, size_t *key_len)
|
||||
{/*{{{*/
|
||||
PSID pSid = TWG(impersonation_token_sid);
|
||||
char *ptcSid = NULL;
|
||||
@@ -443,7 +445,7 @@ TSRM_API FILE *popen(const char *command, const char *type)
|
||||
return popen_ex(command, type, NULL, NULL);
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, const char *env)
|
||||
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
|
||||
{/*{{{*/
|
||||
FILE *stream = NULL;
|
||||
int fno, type_len, read, mode;
|
||||
@@ -456,6 +458,7 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd,
|
||||
process_pair *proc;
|
||||
char *cmd = NULL;
|
||||
wchar_t *cmdw = NULL, *cwdw = NULL, *envw = NULL;
|
||||
int i;
|
||||
char *ptype = (char *)type;
|
||||
HANDLE thread_token = NULL;
|
||||
HANDLE token_user = NULL;
|
||||
@@ -465,25 +468,25 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*The following two checks can be removed once we drop XP support */
|
||||
type_len = (int)strlen(type);
|
||||
if (type_len < 1 || type_len > 2) {
|
||||
if (type_len <1 || type_len > 2) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ptype[0] != 'r' && ptype[0] != 'w') {
|
||||
return NULL;
|
||||
for (i=0; i < type_len; i++) {
|
||||
if (!(*ptype == 'r' || *ptype == 'w' || *ptype == 'b' || *ptype == 't')) {
|
||||
return NULL;
|
||||
}
|
||||
ptype++;
|
||||
}
|
||||
|
||||
if (type_len > 1 && (ptype[1] != 'b' && ptype[1] != 't')) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /s /c ")+2);
|
||||
cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")+2);
|
||||
if (!cmd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(cmd, "%s /s /c \"%s\"", TWG(comspec), command);
|
||||
sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
|
||||
cmdw = php_win32_cp_any_to_w(cmd);
|
||||
if (!cmdw) {
|
||||
free(cmd);
|
||||
@@ -613,16 +616,14 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
|
||||
{/*{{{*/
|
||||
shm_pair *shm;
|
||||
char shm_segment[26], shm_info[29];
|
||||
HANDLE shm_handle = NULL, info_handle = NULL;
|
||||
HANDLE shm_handle, info_handle;
|
||||
BOOL created = FALSE;
|
||||
|
||||
if (key != IPC_PRIVATE) {
|
||||
snprintf(shm_segment, sizeof(shm_segment), "TSRM_SHM_SEGMENT:%d", key);
|
||||
snprintf(shm_info, sizeof(shm_info), "TSRM_SHM_DESCRIPTOR:%d", key);
|
||||
snprintf(shm_segment, sizeof(shm_segment), "TSRM_SHM_SEGMENT:%d", key);
|
||||
snprintf(shm_info, sizeof(shm_info), "TSRM_SHM_DESCRIPTOR:%d", key);
|
||||
|
||||
shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
|
||||
info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
|
||||
}
|
||||
shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
|
||||
info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
|
||||
|
||||
if (!shm_handle && !info_handle) {
|
||||
if (flags & IPC_CREAT) {
|
||||
@@ -633,8 +634,8 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
|
||||
DWORD high = 0;
|
||||
DWORD low = size;
|
||||
#endif
|
||||
shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, high, low, key == IPC_PRIVATE ? NULL : shm_segment);
|
||||
info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), key == IPC_PRIVATE ? NULL : shm_info);
|
||||
shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, high, low, shm_segment);
|
||||
info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
|
||||
created = TRUE;
|
||||
}
|
||||
if (!shm_handle || !info_handle) {
|
||||
@@ -720,7 +721,6 @@ TSRM_API void *shmat(int key, const void *shmaddr, int flags)
|
||||
TSRM_API int shmdt(const void *shmaddr)
|
||||
{/*{{{*/
|
||||
shm_pair *shm = shm_get(0, (void*)shmaddr);
|
||||
int ret;
|
||||
|
||||
if (!shm->segment) {
|
||||
return -1;
|
||||
@@ -730,12 +730,7 @@ TSRM_API int shmdt(const void *shmaddr)
|
||||
shm->descriptor->shm_lpid = getpid();
|
||||
shm->descriptor->shm_nattch--;
|
||||
|
||||
ret = UnmapViewOfFile(shm->addr) ? 0 : -1;
|
||||
if (!ret && shm->descriptor->shm_nattch <= 0) {
|
||||
ret = UnmapViewOfFile(shm->descriptor) ? 0 : -1;
|
||||
shm->descriptor = NULL;
|
||||
}
|
||||
return ret;
|
||||
return UnmapViewOfFile(shm->addr) ? 0 : -1;
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf)
|
||||
@@ -769,12 +764,13 @@ TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf)
|
||||
}
|
||||
}/*}}}*/
|
||||
|
||||
#if HAVE_UTIME
|
||||
static zend_always_inline void UnixTimeToFileTime(time_t t, LPFILETIME pft) /* {{{ */
|
||||
{
|
||||
// Note that LONGLONG is a 64-bit value
|
||||
LONGLONG ll;
|
||||
|
||||
ll = t * 10000000LL + 116444736000000000LL;
|
||||
ll = Int32x32To64(t, 10000000) + 116444736000000000;
|
||||
pft->dwLowDateTime = (DWORD)ll;
|
||||
pft->dwHighDateTime = ll >> 32;
|
||||
}
|
||||
@@ -823,3 +819,13 @@ TSRM_API int win32_utime(const char *filename, struct utimbuf *buf) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
+17
-4
@@ -1,6 +1,8 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2018 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
@@ -19,7 +21,9 @@
|
||||
|
||||
#include "TSRM.h"
|
||||
#include <windows.h>
|
||||
#include <sys/utime.h>
|
||||
#if HAVE_UTIME
|
||||
# include <sys/utime.h>
|
||||
#endif
|
||||
#include "win32/ipc.h"
|
||||
|
||||
struct ipc_perm {
|
||||
@@ -89,12 +93,12 @@ TSRMLS_CACHE_EXTERN()
|
||||
#define SHM_RND FILE_MAP_WRITE
|
||||
#define SHM_REMAP FILE_MAP_COPY
|
||||
|
||||
const char * tsrm_win32_get_path_sid_key(const char *pathname, size_t pathname_len, size_t *key_len);
|
||||
char * tsrm_win32_get_path_sid_key(const char *pathname, size_t pathname_len, size_t *key_len);
|
||||
|
||||
TSRM_API void tsrm_win32_startup(void);
|
||||
TSRM_API void tsrm_win32_shutdown(void);
|
||||
|
||||
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, const char *env);
|
||||
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env);
|
||||
TSRM_API FILE *popen(const char *command, const char *type);
|
||||
TSRM_API int pclose(FILE *stream);
|
||||
TSRM_API int tsrm_win32_access(const char *pathname, int mode);
|
||||
@@ -105,3 +109,12 @@ TSRM_API void *shmat(int key, const void *shmaddr, int flags);
|
||||
TSRM_API int shmdt(const void *shmaddr);
|
||||
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
+156
-409
@@ -1,35 +1,39 @@
|
||||
PHP 8.0 INTERNALS UPGRADE NOTES
|
||||
PHP 7.3 INTERNALS UPGRADE NOTES
|
||||
|
||||
1. Internal API changes
|
||||
a. Object Handlers API
|
||||
b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler
|
||||
c. TSRM changes
|
||||
d. get() and set() object handlers
|
||||
e. zend_parse_parameters 'L' specifier
|
||||
f. Arginfo argument types
|
||||
g. zend_free_op type and should_free argument of zend_get_zval_ptr()
|
||||
h. zend_value_error()
|
||||
i. get_closure() object handler
|
||||
j. compare_objects() and compare() object handlers
|
||||
k. The 'I' length modifier
|
||||
l. Some VM instructions switched to IS_TMP_VAR result instead of IS_VAR
|
||||
m. All internal functions must have arginfo
|
||||
n. zend_hash_sort compare function and zend_hash_sort signature change
|
||||
o. cast_object() object handler is now required
|
||||
p. ARG_COUNT() macro removed
|
||||
q. GC_COLLECTABLE flag
|
||||
r. Cannot implement Traversable only
|
||||
s. zend_fcall_info no_separation flag removed
|
||||
t. Signature changes
|
||||
u. Error Notification callbacks to replace zend_error_cb overwrite use-cases
|
||||
v. Removed Zend APIs
|
||||
w. Renamed Zend APIs
|
||||
x. ZEND_EXT_NOP no longer emitted
|
||||
a. array_init() and array_init_size()
|
||||
b. Run-time constant operand addressing
|
||||
c. Array/Object recursion protection
|
||||
d. HASH_FLAG_PERSISTENT
|
||||
e. AST and IS_CONSTANT
|
||||
f. GC_REFCOUNT()
|
||||
g. zend_get_parameters()
|
||||
h. zend_register_persistent_resource()
|
||||
i. RAND_RANGE()
|
||||
j. cast_object() with _IS_NUMBER
|
||||
k. zend_fcall_info_cache.initialized
|
||||
l. php_hrtime_current()
|
||||
m. zend_cpu_supports()
|
||||
n. IS_TYPE_COPYABLE
|
||||
o. IS_UNUSED
|
||||
p. VM instruction operands (FETCH_CLASS, FETCH_CONSTANT, CATCH)
|
||||
q. sapi_cli_single_write()
|
||||
r. php_url
|
||||
s. zend_function.reserved[]
|
||||
t. zif_handler
|
||||
u. GC_G
|
||||
v. php_add[c]slashes
|
||||
w. zend_class_entry.iterator_funcs
|
||||
x. Class declaration opcodes (DECLARE_INHERITED_CLASS ...)
|
||||
y. zend_constant
|
||||
z. HAVE_ST_BLKSIZE and HAVE_ST_RDEV
|
||||
aa. RETSIGTYPE
|
||||
bb. php_setcookie
|
||||
|
||||
2. Build system changes
|
||||
a. Abstract
|
||||
b. Unix build system changes
|
||||
c. Windows build system changes
|
||||
a. Unix build system changes
|
||||
b. Windows build system changes
|
||||
|
||||
|
||||
3. Module changes
|
||||
|
||||
@@ -37,425 +41,168 @@ PHP 8.0 INTERNALS UPGRADE NOTES
|
||||
1. Internal API changes
|
||||
========================
|
||||
|
||||
a. The Object Handlers API was changed to receive zend_object* instead of
|
||||
zval* and zend_string* instead of zval* for property names. See also
|
||||
section t for other similar changes.
|
||||
a. array_init() and array_init_size() are not functions anymore.
|
||||
They don't return any values.
|
||||
|
||||
b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler
|
||||
were removed. ZEND_INTERNAL_FUNCTION with ZEND_ACC_CALL_VIA_HANDLER and
|
||||
defined "handler" callback should be used instead. This "handler" callback
|
||||
should also take care about function cleanup. See ext/zend_test/test.c
|
||||
for example.
|
||||
b. In 64-bit builds PHP-7.2 and below used relative run-time constant operand
|
||||
addressing. E.g. opline->op1.constant kept an offset from start of literals
|
||||
table - op_array->literals. To speedup access op_array->literals was cached
|
||||
in execute_data->literals. So the resulting address calculated as
|
||||
EX(literals) + opline->op1.constant.
|
||||
|
||||
c. The following things have been removed from TSRM:
|
||||
- TSRMLS_DC
|
||||
- TSRMLS_D
|
||||
- TSRMLS_CC
|
||||
- TSRMLS_C
|
||||
- TSRMLS_FETCH
|
||||
- TSRMLS_FETCH_FROM_CTX
|
||||
- TSRMLS_SET_CTX
|
||||
- tsrm_new_interpreter_context
|
||||
- tsrm_set_interpreter_context
|
||||
- tsrm_free_interpreter_context
|
||||
- support for GNUPTH, SGI ST, and BETHREADS
|
||||
Now at run-time literals allocated close to opcodes, and addressed
|
||||
relatively from current opline. This eliminates load of EX(literals) on
|
||||
each constant access as well as EX(literals) initialization on each call.
|
||||
|
||||
d. The get() and set() object handlers have been removed. The get() handler
|
||||
can generally be replaced with cast_object(). Some uses of set() may be
|
||||
replaced by do_operation(). If set() was used to overload direct
|
||||
assignments using "=", then this is no longer supported and the
|
||||
functionality should be provided in some other way (for example, as
|
||||
modification of an object property).
|
||||
As result some related macros were removed (ZEND_EX_USE_LITERALS,
|
||||
EX_LOAD_LITERALS, EX_LITERALS, RT_CONSTANT_EX, EX_CONSTANT) or changed
|
||||
(RT_CONSTANT, ZEND_PASS_TWO_UPDATE_CONSTANT, ZEND_PASS_TWO_UNDO_CONSTANT).
|
||||
This change may affect only some "system" extensions. EX_LITERALS,
|
||||
RT_CONSTANT_EX, EX_CONSTANT should be substituted by RT_CONSTANT, and now
|
||||
use "opline" (instead of "op_array") as first argument.
|
||||
|
||||
e. The zend_parse_parameters 'L' specifier and the Z_PARAM_STRICT_LONG()
|
||||
family of macros have been removed. Use 'l' and Z_PARAM_LONG() instead,
|
||||
which, despite the confusing name, actually have stricter input validation.
|
||||
c. Protection from recursion during processing circular data structures was
|
||||
refactored. HashTable.nApplyCount and IS_OBJ_APPLY_COUNT are replaced by
|
||||
single flag GC_PROTECTED. Corresponding macros Z_OBJ_APPLY_COUNT,
|
||||
Z_OBJ_INC_APPLY_COUNT, Z_OBJ_DEC_APPLY_COUNT, ZEND_HASH_GET_APPLY_COUNT,
|
||||
ZEND_HASH_INC_APPLY_COUNT, ZEND_HASH_DEC_APPLY_COUNT are replaced with
|
||||
GC_IS_RECURSIVE, GC_PROTECT_RECURSION, GC_UNPROTECT_RECURSION,
|
||||
Z_IS_RECURSIVE, Z_PROTECT_RECURSION, Z_UNPROTECT_RECURSION.
|
||||
|
||||
f. Arginfo argument types for internal functions are no longer checked.
|
||||
Instead type checks should be performed using the zend_parse_parameters()
|
||||
or ZEND_PARSE_PARAMETERS_*() APIs.
|
||||
HASH_FLAG_APPLY_PROTECTION flag and ZEND_HASH_APPLY_PROTECTION() macro
|
||||
are removed. All mutable arrays should use recursion protection.
|
||||
Corresponding checks should be replaced by Z_REFCOUNTED() or
|
||||
!(GC_FLAGS(p) & GC_IMMUTABLE).
|
||||
|
||||
g. The zend_free_op type and the "should_free" and "type" arguments of
|
||||
zend_get_zval_ptr() were removed. It's possible to get the old
|
||||
"should_free" value using the following code:
|
||||
d. HASH_FLAG_PERSISTENT renamed into IS_ARRAY_PERSISTENT and moved into
|
||||
GC_FLAGS (to be consistent with IS_STR_PERSISTENT).
|
||||
|
||||
zval *ret = zend_get_zval_ptr(
|
||||
opline, opline->op1_type, &opline->op1, execute_data);
|
||||
zval *should_free = (op_type & (IS_TMP_VAR|IS_VAR)) ? ret : NULL;
|
||||
e. zend_ast_ref structure is changed to use only one allocation.
|
||||
zend_ast_copy() now returns zend_ast_ref (instead of zend_asr).
|
||||
zend_ast_destroy_and_free() is removed. ZVAL_NEW_AST() is replaced
|
||||
by ZVAL_AST().
|
||||
|
||||
h. Added the zend_value_error() function, which is intended to be used
|
||||
to raise ValueError when inappropriate argument values are passed
|
||||
to functions.
|
||||
IS_CONSTANT type and Z_CONST_FLAGS() are removed. Now constants are always
|
||||
represented using IS_CONSTANT_AST (ZEND_AST_CONSTANT kind). AST node
|
||||
attributes are used instead of constant flags. IS_TYPE_CONSTANT flag is
|
||||
removed, but Z_CONSTANT() macro is kept for compatibility.
|
||||
|
||||
i. get_closure() object handlers now accept an additional zend_bool parameter
|
||||
`check_only`. If it is true, the handler is called to check whether the
|
||||
object is callable; in this case the handler should not throw an exception.
|
||||
f. GC_REFCOUNT() is turned into inline function and can't be modified direcly.
|
||||
All reference-counting operations should be done through corresponding
|
||||
macros GC_SET_REFCOUNT(), GC_ADDREF() and GC_DELREF().
|
||||
|
||||
j. compare_objects() handler was removed. Extensions should use compare() object
|
||||
handler instead and check if both arguments are objects and have the same
|
||||
compare handler, using ZEND_COMPARE_OBJECTS_FALLBACK() macro.
|
||||
GC_REFCOUNT(p)++ should be changed into GC_ADDREF(p),
|
||||
GC_REFCOUNT(p)-- into GC_DELREF(p),
|
||||
GC_REFCOUNT(p) = 1 into GC_SET_REFCOUNT(p, 1).
|
||||
|
||||
k. The 'I' length modifier, used to denote 32 and 64bit integer from the custom
|
||||
snprintf and spprintf implementations has been removed.
|
||||
Use the ZEND_LONG_FMT, ZEND_ULONG_FMT and ZEND_XLONG_FMT macros defined in
|
||||
php-src/Zend/zend_long.h
|
||||
g. The zend_get_parameters() and zend_get_parameters_ex() functions were
|
||||
removed. Instead zend_parse_parameters() should be used.
|
||||
|
||||
The 'v' format from the custom snprintf and spprintf implementations has
|
||||
been removed. Use the standard 's' format instead.
|
||||
h. New functions zend_register_persistent_resource() or
|
||||
zend_register_persistent_resource_ex() should beused to register
|
||||
persistent resources, instead of manual insertion into EG(persistent_list).
|
||||
|
||||
l. Some VM instructions switched to IS_TMP_VAR result instead of IS_VAR.
|
||||
Actually, all assignments (ZEND_ASSIGN, ZEND_ASSIGN_DIM, ZEND_ASSIGN_OBJ,
|
||||
ZEND_ASSIGN_STATIC_PROP), all compound assignments (ZEND_ASSIGN_OP,
|
||||
ZEND_ASSIGN_DIM_OP, ZEND_ASSIGN_OBJ_OP, ZEND_ASSIGN_STATIC_PROP_OP) and all
|
||||
pre increments/decrements (ZEND_PRE_INC, ZEND_PRE_DEC, ZEND_PRE_INC_OBJ
|
||||
ZEND_PRE_DEC_OBJ, ZEND_PRE_INC_STATIC_PROP ZEND_PRE_DEC_STATIC_PROP).
|
||||
i. The RAND_RANGE() macro has been removed. php_mt_rand_range() should be
|
||||
used instead.
|
||||
|
||||
m. All internal functions and methods are now required to specify arginfo
|
||||
information, otherwise warnings will be thrown on startup.
|
||||
j. The cast_object() object handler now also accepts the _IS_NUMBER type. The
|
||||
handler should return either an integer or float value in this case,
|
||||
whichever is more appropriate.
|
||||
|
||||
n. The zend_hash_sort and zend_hash_minmax APIs now accept a comparison
|
||||
function with the following signature:
|
||||
k. zend_fcall_info_cache.initialized is removed. zend_fcall_info_cache is
|
||||
initialized if zend_fcall_info_cache.function_handler is set.
|
||||
|
||||
typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b);
|
||||
l. php_hrtime_current() delivers the number of nanoseconds since an uncertain
|
||||
point in the past.
|
||||
|
||||
Previously compare_func_t was used, which accepted void pointers.
|
||||
Furthermore, the return type of zend_hash_sort and zend_ts_hash_sort has
|
||||
been changed from int to void; these functions always succeed.
|
||||
m. zend_cpu_supports() determines if a feature is supported by current cpu.
|
||||
Also serial inline zend_cpu_supports_xxx() are added, which is designed for
|
||||
ifunc resolver function, as resolver function should not depend on any
|
||||
external function.
|
||||
|
||||
o. The cast_object() handler is now required, i.e. must be non-null. You can
|
||||
indicate that casting is not supported by always returning FAILURE.
|
||||
n. IS_TYPE_COPYABLE flag is removed. IS_STRING zvals didn't need to be
|
||||
duplication by zval_copy_ctor(), ZVAL_DUP() and SEPARATE_ZVAL*() macros.
|
||||
Interned strings didn't set IS_TYPE_COPYABLE, so they aren't affected at
|
||||
all. Now instead of checking for IS_TYPE_COPYABLE, engine checks for
|
||||
IS_ARRAY type (it may be IS_TYPE_REFCOUNTED or not). All the related
|
||||
macros: Z_COPYABLE..., Z_IMMUTABLE... are kept for compatibility.
|
||||
|
||||
p. The ARG_COUNT() macro has been removed use ZEND_NUM_ARGS() instead.
|
||||
o. IS_UNUSED became zero and can't be used as a bitmask (there were no such
|
||||
usages in PHP sources).
|
||||
|
||||
q. GC_COLLECTABLE flag was inverted into GC_NOT_COLLECTABLE.
|
||||
Assignments to GC_TYPE_INFO() might need to be changed to properly
|
||||
set the value of the GC_NOT_COLLECTABLE flag.
|
||||
p. Operands of few VM instructions were changed
|
||||
- FETCH_CLASS op1<fetch-flags>, op2<name>, result<var>
|
||||
- FETCH_CONSTANT op1<fetch-flags>, op2<name>, result<tmp>
|
||||
- CATCH ext<last-flag>, op1<name>, op2<jump_addr>, result<cv>
|
||||
|
||||
r. Just for for userland classes, it is no longer allowed to implement only
|
||||
the Traversable interface. Instead, it is necessary to implement either
|
||||
Iterator or IteratorAggregate. You can do the latter by implementing
|
||||
zend_ce_aggregate and providing the following method implementation:
|
||||
q. sapi_cli_single_write() now returns ssize_t instead of size_t.
|
||||
|
||||
ZEND_METHOD(MyClass, getIterator) {
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
zend_create_internal_iterator_zval(return_value, ZEND_THIS);
|
||||
}
|
||||
r. fields of php_url struct change from char * to zend_string *
|
||||
|
||||
s. The zend_fcall_info no_separation flag has been removed, and separation is
|
||||
never allowed. If you wish to pass (or allow passing) arguments by
|
||||
reference, explicitly create those arguments as references using
|
||||
ZEND_MAKE_REF. This removal also affects call_user_function_ex(), which
|
||||
should be replaced by call_user_function().
|
||||
s. Special purpose zend_functions marked by ZEND_ACC_CALL_VIA_TRAMPOLINE or
|
||||
ZEND_ACC_FAKE_CLOSURE flags use reserved[0] for internal purpose.
|
||||
Third party extensions must not modify reserved[] fields of these functions.
|
||||
|
||||
t. The following ZEND_API function have changed signature:
|
||||
1. Void in Zend Engine 4.0:
|
||||
- add_assoc_*()
|
||||
- add_index_*()
|
||||
- add_property_*()
|
||||
- object_init()
|
||||
- zend_declare_class_constant*()
|
||||
- zend_declare_property*()
|
||||
- zend_startup_modules()
|
||||
- zend_wrong_parameters_none_error()
|
||||
- zend_fcall_info_argp()
|
||||
- zend_fcall_info_argv()
|
||||
- zend_fcall_info_argn()
|
||||
- zend_startup()
|
||||
- zend_set_memory_limit()
|
||||
- pass_two()
|
||||
- zend_startup_constants()
|
||||
- zend_shutdown_constants()
|
||||
- zend_startup_extensions_mechanism()
|
||||
- zend_startup_extensions()
|
||||
- zend_register_extension()
|
||||
- highlight_string()
|
||||
- zend_ini_startup()
|
||||
- zend_ini_shutdown()
|
||||
- zend_ini_global_shutdown()
|
||||
- zend_ini_deactivate()
|
||||
- zend_copy_ini_directives()
|
||||
- zend_prepare_string_for_scanning()
|
||||
- zend_init_rsrc_list()
|
||||
- zend_list_close()
|
||||
- zend_signal()
|
||||
- zend_sigaction()
|
||||
- zend_stack_init()
|
||||
- zend_stack_del_top()
|
||||
- zend_stack_destroy()
|
||||
2. Argument int to uint32_t in Zend Engine 4.0:
|
||||
- _zend_get_parameters_array_ex()
|
||||
- zend_copy_parameters_array()
|
||||
- zend_fcall_info_args_save()
|
||||
- zend_fcall_info_args_restore()
|
||||
- zend_fcall_info_argp()
|
||||
- zend_fcall_info_argv()
|
||||
- zend_fcall_info_argn()
|
||||
- zend_wrong_parameter*()
|
||||
- zend_wrong_callback_error()
|
||||
- zend_parse_arg_class()
|
||||
3. Argument int to bool in Zend Engine 4.0:
|
||||
- add_next_index_bool()
|
||||
- zend_register_class_alias_ex()
|
||||
- add_assoc_bool_ex()
|
||||
- add_index_bool()
|
||||
- zend_fcall_info_args_clear()
|
||||
- zend_set_local_var()
|
||||
- zend_set_local_var_str()
|
||||
- zend_parse_arg_*()
|
||||
- shutdown_memory_manager()
|
||||
- zend_memory_usage()
|
||||
- zend_memory_peak_usage()
|
||||
- zend_mm_shutdown()
|
||||
- zend_eval_string*()
|
||||
- zend_set_timeout()
|
||||
- _zend_hash_append_ex()
|
||||
- _zend_hash_append_ptr_ex()
|
||||
- zend_alter_ini_entry_ex()
|
||||
- (*zend_encoding_list_parser) typedef
|
||||
- zend_multibyte_parse_encoding_list()
|
||||
- zend_safe_address()
|
||||
- zend_string_tolower_ex()
|
||||
- zend_string_alloc()
|
||||
- zend_string_safe_alloc()
|
||||
- zend_string_init()
|
||||
- zend_string_dup()
|
||||
- zend_string_realloc()
|
||||
- zend_string_extend()
|
||||
- zend_string_truncate()
|
||||
- zend_string_safe_realloc()
|
||||
- zend_string_release_ex()
|
||||
- zend_ts_hash_merge()
|
||||
- zend_ts_hash_sort()
|
||||
4. Argument int to size_t in Zend Engine 4.0:
|
||||
- zend_set_hash_symbol()
|
||||
5. Argument zval* to zend_object* in Zend Engine 4.0:
|
||||
- zend_read_property()
|
||||
- zend_update_property()
|
||||
- zend_unset_property()
|
||||
- zend_call_method()
|
||||
- zend_objects_clone_obj()
|
||||
- zend_get_closure_method_def()
|
||||
- zend_throw_exception_hook()
|
||||
- zend_throw_exception_internal()
|
||||
- zend_get_exception_base()
|
||||
6. Argument zval* to zend_long in Zend Engine 4.0:
|
||||
- _php_math_longtobase()
|
||||
7. Return type from int to zend_result in Zend Engine 4.0:
|
||||
- (*stream_open_function) in _zend_utility_functions
|
||||
- (*zend_post_startup_cb)
|
||||
- (*zend_preload_autoload)
|
||||
- zend_execute_scripts()
|
||||
- zend_post_startup()
|
||||
- _zend_get_parameters_array_ex()
|
||||
- zend_copy_parameters_array()
|
||||
- zend_parse_parameters()
|
||||
- zend_parse_parameters_ex()
|
||||
- zend_parse_method_parameters()
|
||||
- zend_parse_method_parameters_ex()
|
||||
- zend_parse_method_parameters()
|
||||
- zend_register_functions()
|
||||
- zend_startup_module()
|
||||
- zend_startup_module_ex()
|
||||
- zend_register_class_alias_ex()
|
||||
- zend_disable_function()
|
||||
- zend_disable_class()
|
||||
- zend_update_class_constants()
|
||||
- zend_update_static_property*()
|
||||
- object_init_ex()
|
||||
- object_and_properties_init()
|
||||
- add_index_zval()
|
||||
- add_next_index_long_*()
|
||||
- array_set_zval_key()
|
||||
- _call_user_function_impl()
|
||||
- zend_fcall_info_*()
|
||||
- zend_call_function()
|
||||
- zend_set_hash_symbol()
|
||||
- zend_delete_global_variable()
|
||||
- zend_set_local_var()
|
||||
- zend_set_local_var_str()
|
||||
- zend_forbid_dynamic_call()
|
||||
- zend_get_default_from_internal_arg_info()
|
||||
- zend_try_assign_typed_ref*()
|
||||
- zend_ast_evaluate()
|
||||
- zend_startup_builtin_functions()
|
||||
- do_bind_function()
|
||||
- do_bind_class()
|
||||
- zend_unmangle_property_name_ex()
|
||||
- zend_register_auto_global()
|
||||
- zend_register_constant()
|
||||
- zend_exception_error()
|
||||
- zend_eval_string*()
|
||||
- zend_undefined_offset_write()
|
||||
- zend_undefined_index_write()
|
||||
- zval_update_constant(_ex)()
|
||||
- zend_load_extension()
|
||||
- zend_load_extension_handle()
|
||||
- zend_hash_del(_ind)()
|
||||
- zend_hash_str_del(_ind)()
|
||||
- zend_hash_index_del()
|
||||
- zend_hash_move_forward_ex()
|
||||
- zend_hash_move_backward_ex()
|
||||
- zend_hash_get_current_key_ex()
|
||||
- zend_hash_get_current_key_type_ex()
|
||||
- zend_symtable_del(_ind)()
|
||||
- zend_symtable_str_del(_ind)()
|
||||
- highlight_file()
|
||||
- zend_do_link_class()
|
||||
- zend_alter_ini_entry*()
|
||||
- zend_restore_ini_entry()
|
||||
- zend_ini_register_displayer()
|
||||
- zend_ini_open_file_for_scanning()
|
||||
- zend_ini_prepare_string_for_scanning()
|
||||
- zend_user_it_valid()
|
||||
- zend_create_internal_iterator_zval()
|
||||
- zend_multibyte_set_filter()
|
||||
- zend_lex_tstring()
|
||||
- _zend_module_entry module_startup_func, module_shutdown_func,
|
||||
request_startup_func, request_shutdown_func, and post_deactivate_func function pointers
|
||||
- (*zend_encoding_list_parser) typedef
|
||||
- (*zend_encoding_internal_encoding_setter) typedef
|
||||
- zend_multibyte_set_functions()
|
||||
- zend_multibyte_set_script_encoding_by_string()
|
||||
- add_function()
|
||||
- sub_function()
|
||||
- mul_function()
|
||||
- pow_function()
|
||||
- div_function()
|
||||
- mod_function()
|
||||
- boolean_xor_function()
|
||||
- boolean_not_function()
|
||||
- bitwise_not_function()
|
||||
- bitwise_or_function()
|
||||
- bitwise_and_function()
|
||||
- bitwise_xor_function()
|
||||
- shift_left_function()
|
||||
- shift_right_function()
|
||||
- concat_function()
|
||||
- is_equal_function(
|
||||
- is_identical_function()
|
||||
- is_not_identical_function()
|
||||
- is_not_equal_function()
|
||||
- is_smaller_function()
|
||||
- is_smaller_or_equal_function(zv
|
||||
- increment_function()
|
||||
- decrement_function()
|
||||
- zend_stream_open()
|
||||
- zend_stream_fixup()
|
||||
- zend_ts_hash_del()
|
||||
- zend_ts_hash_index_del()
|
||||
8. Return type from int to bool in Zend Engine 4.0:
|
||||
- zend_make_printable_zval()
|
||||
- zend_parse_arg_*()
|
||||
- is_zend_mm()
|
||||
- is_zend_ptr()
|
||||
- zend_mm_is_custom_heap()
|
||||
- (*zend_mm_chunk_truncate_t)
|
||||
- (*zend_mm_chunk_extend_t)
|
||||
- zend_bitset_empty()
|
||||
- zend_is_smart_branch()
|
||||
- zend_check_arg_send_type()
|
||||
- zend_verify_const_access()
|
||||
- zend_gdb_register_code()
|
||||
- zend_gdb_present()
|
||||
- _zend_handle_numeric_str(_ex)()
|
||||
- zend_hash_exists_ind()
|
||||
- zend_hash_str_exists_ind()
|
||||
- zend_symtable_exists(_ind)()
|
||||
- zend_symtable_str_exists()
|
||||
- (*zend_encoding_lexer_compatibility_checker)
|
||||
- zend_object_is_true()
|
||||
- i_zend_is_true()
|
||||
- zendi_smart_streq()
|
||||
- zend_stack_is_empty()
|
||||
- zend_ts_hash_exists()
|
||||
- zend_ts_hash_index_exists()
|
||||
9. Argument void to const char* in Zend Engine 4.0:
|
||||
- zend_get_op_array_extension_handle()
|
||||
10. Argument zend_extension to const char* in Zend Engine 4.0:
|
||||
- zend_get_resource_handle()
|
||||
11. Argument const char * to HMODULE in Zend Engine 4.0:
|
||||
- php_win32_image_compatible()
|
||||
12. const char * argument dropped in Zend Engine 4.0:
|
||||
- php_win32_crt_compatible()
|
||||
t. For internal functions the typedef zif_handler has been introduced. It is
|
||||
recommended to use this from now on, instead of defining own handler types.
|
||||
|
||||
u. Instead of overwriting zend_error_cb extensions with debugging, monitoring
|
||||
use-cases catching Errors/Exceptions are strongly encouraged to use
|
||||
the new error observer API instead.
|
||||
u. The GC globals (GC_G) are now private. Use the new zend_gc_get_status() to
|
||||
retrieve status information of the GC.
|
||||
|
||||
Error observering callbacks are guaranteed to be called regardless of
|
||||
the users error_reporting setting or userland error handler return values.
|
||||
v. The should_free argument of the php_add[c]slashes functions has been
|
||||
removed. It is now always the caller's responsibility to free the passed
|
||||
string.
|
||||
|
||||
Register observer callbacks during MINIT of an extension:
|
||||
w. zend_class_entry.iterator_funcs have been replaced by iterator_funcs_ptr.
|
||||
You don't have to set its value, setting parent.funcs in the get_iterator
|
||||
function is enough.
|
||||
|
||||
void my_error_observer_cb(int type,
|
||||
const char *error_filename,
|
||||
uint32_t error_lineno,
|
||||
zend_string *message) {
|
||||
}
|
||||
zend_observer_error_register(my_error_observer_cb);
|
||||
x. Class declaration opcode formats were changed
|
||||
- DECLARE_INHERITED_CLASS and DECLARE_ANON_INHERITED_CLASS now encode parent
|
||||
class name in second operand directly (as IS_CONST operand). Previously,
|
||||
parent class was fetched by the prior FETCH_CLASS opcode.
|
||||
- ADD_INTERFACE and ADD_TRAIT don't use run-time cache to keep interface or
|
||||
trait. These instructions are executed once, and caching is useless.
|
||||
|
||||
v. The following APIs have been removed from the Zend Engine:
|
||||
- zend_ts_hash_init_ex(), drop the last argument and use zend_ts_hash_init() instead
|
||||
- zend_hash_init_ex(), drop the last argument and use zend_hash_init() instead
|
||||
- zval_internal_dtor(), use zval_internal_ptr_dtor() instead
|
||||
- zval_dtor_func(), use rc_dtor_func() instead
|
||||
- zval_ptr_dtor_wrapper(), use zval_ptr_dtor() instead
|
||||
- zval_internal_ptr_dtor_wrapper(), use zval_internal_ptr_dtor() instead
|
||||
y. zend_constant.flags and zend_constant.module_number are packed into
|
||||
reserved space inside zend_constant.value. They should be accessed using
|
||||
ZEND_CONSTANT_FLAGS(), ZEND_CONSTANT_MODULE_NUMBER() and
|
||||
ZEND_CONSTANT_SET_FLAGS() macros.
|
||||
|
||||
w. The following APIs have been renamed:
|
||||
- _zend_ts_hash_init() to zend_ts_hash_init()
|
||||
z. HAVE_ST_BLKSIZE must be replaced with HAVE_STRUCT_STAT_ST_BLKSIZE and
|
||||
HAVE_ST_RDEV must be replaced with HAVE_STRUCT_STAT_ST_RDEV.
|
||||
|
||||
x. In COMPILE_EXTENDED_STMT mode, a ZEND_EXT_NOP opcode will no longer be
|
||||
generated at the start of a function. Use the new observer APIs or hook
|
||||
into zend_execute_ex instead.
|
||||
aa. RETSIGTYPE has been removed from the generated php_config.h and should be
|
||||
replaced with void.
|
||||
|
||||
bb. php_setcookie() now expects an additional samesite argument, and the
|
||||
url_encode parameter has been moved to the end. The signature is now:
|
||||
int php_setcookie(zend_string *name, zend_string *value, time_t expires,
|
||||
zend_string *path, zend_string *domain, int secure,
|
||||
int httponly, zend_string *samesite, int url_encode);
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
||||
a. Abstract
|
||||
1. Symbol HAVE_HASH_EXT is removed and is no longer defined. It should be
|
||||
considered to have hash extension always available since PHP 7.4.
|
||||
a. Unix build system changes
|
||||
- PHP_PROG_LEX, TSRM_CHECK_GCC_ARG, and LIBZEND_CPLUSPLUS_CHECKS Autoconf
|
||||
macros have been removed.
|
||||
- Minimum Autoconf version is 2.68+ for generating the configure script.
|
||||
|
||||
2. Symbol HAVE_PCRE is removed and is no longer defined. It should be
|
||||
considered to have pcre extension always available since PHP 7.4.
|
||||
|
||||
3. Symbol HAVE_LOCALE_H has been removed and is no longer defined.
|
||||
|
||||
4. --disable-inline-optimization (which actually disabled all compiler
|
||||
optimizations) has been removed. If you wish to build PHP on a host
|
||||
with extremely constrained memory, and compilation fails with an "out
|
||||
of memory" message, add "-O0" to CFLAGS.
|
||||
|
||||
5. build system and provider are displayed in phpinfo from environment:
|
||||
- PHP_BUILD_SYSTEM (default is same as PHP_UNAME)
|
||||
- PHP_BUILD_PROVIDER (no default)
|
||||
|
||||
b. Unix build system changes
|
||||
|
||||
1. --enable-maintainer-zts is renamed --enable-zts for parity with Windows
|
||||
and as recognition that ZTS is not a "maintainer" or experimental
|
||||
feature.
|
||||
|
||||
2. The PHP_CHECK_GCC_ARG() m4 macro has been removed in favor of
|
||||
AX_CHECK_COMPILE_FLAG().
|
||||
|
||||
3. The 6th argument of PHP_ADD_SOURCES_X has been removed.
|
||||
|
||||
4. The 'special-flags' (3rd) argument of PHP_ADD_SOURCES_X are
|
||||
now appended instead of prepended to previous compiler flags.
|
||||
This means compiler flags passed to PHP_NEW_EXTENSION and PHP_ADD_SOURCES
|
||||
are now appended, this allows to disable compiler flags set by Zend/Zend.m4
|
||||
(e.g. disable certain compiler flags enabled by -Wextra)
|
||||
|
||||
c. Windows build system changes
|
||||
|
||||
- The configuration option --enable-crt-debug has been removed. The VC
|
||||
debug heap can now be enabled for debug builds by setting the environment
|
||||
variable PHP_WIN32_DEBUG_HEAP to a non-negative number before PHP process
|
||||
startup.
|
||||
b. Windows build system changes
|
||||
- ZEND_WIN32_FORCE_INLINE doesn't affect C++ anymore. zend_always_inline is
|
||||
still usable in C++, but anything else inlining related is up to
|
||||
compiler.
|
||||
- ZEND_WIN32_KEEP_INLINE was removed, it was only needed for C++
|
||||
convenience and is now default behavior with C++.
|
||||
- New configure option --enable-native-intrinsics accepts a list of the
|
||||
intrinsic optimizations to enable. It affects both the code generation
|
||||
and the explicit optimizations guarded by preprocessor macros.
|
||||
- The configure option --with-codegen-arch accepts only ia32 as a value.
|
||||
Use it, to produce builds suitable for older processors without SSE2 or
|
||||
even SSE support.
|
||||
|
||||
========================
|
||||
3. Module changes
|
||||
========================
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
## Process this file with automake to produce Makefile.in -*- makefile -*-
|
||||
|
||||
#CLEANFILES = zend_language_parser.c zend_language_parser.h zend_language_scanner.c zend_language_parser.output zend_ini_parser.c zend_ini_parser.h zend_ini_scanner.c zend_ini_parser.output
|
||||
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
noinst_LTLIBRARIES=libZend.la
|
||||
|
||||
libZend_la_SOURCES=\
|
||||
zend_language_parser.y zend_language_scanner.l \
|
||||
zend_ini_parser.y zend_ini_scanner.l \
|
||||
zend_alloc.c zend_compile.c zend_constants.c \
|
||||
zend_execute.c zend_execute_API.c zend_highlight.c zend_llist.c \
|
||||
zend_vm_opcodes.c zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
|
||||
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
|
||||
zend_list.c zend_builtin_functions.c zend_sprintf.c \
|
||||
zend_ini.c zend_sort.c zend_objects.c zend_object_handlers.c \
|
||||
zend_objects_API.c zend_ts_hash.c zend_stream.c \
|
||||
zend_default_classes.c \
|
||||
zend_iterators.c zend_interfaces.c zend_exceptions.c \
|
||||
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
|
||||
zend_generators.c zend_virtual_cwd.c zend_ast.c zend_smart_str.c zend_cpuinfo.c
|
||||
|
||||
libZend_la_CFLAGS = -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1
|
||||
libZend_la_LDFLAGS =
|
||||
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
|
||||
|
||||
# automake isn't too clever about "non-standard" use of lex and yacc
|
||||
|
||||
$(libZend_la_OBJECTS): zend_language_parser.h
|
||||
|
||||
zend_ini_scanner.lo: zend_ini_parser.h
|
||||
|
||||
# Language parser/scanner rules
|
||||
|
||||
zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
|
||||
$(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt $(srcdir)/zend_language_scanner_defs.h -o$@ $(srcdir)/zend_language_scanner.l
|
||||
|
||||
zend_language_parser.h: zend_language_parser.c
|
||||
zend_language_parser.c: $(srcdir)/zend_language_parser.y
|
||||
$(YACC) -p zend -v -d $(srcdir)/zend_language_parser.y -o zend_language_parser.c
|
||||
|
||||
# INI parser/scanner rules
|
||||
|
||||
zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
|
||||
$(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o zend_ini_parser.c
|
||||
|
||||
zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
|
||||
$(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt $(srcdir)/zend_ini_scanner_defs.h -o$@ $(srcdir)/zend_ini_scanner.l
|
||||
|
||||
zend_ini_parser.h: zend_ini_parser.c
|
||||
|
||||
depend:
|
||||
|
||||
zend_execute.lo: $(srcdir)/zend_execute.c
|
||||
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(INLINE_CFLAGS) -c $(srcdir)/zend_execute.c
|
||||
Regular → Executable
-36
@@ -1,37 +1 @@
|
||||
#
|
||||
# Zend
|
||||
#
|
||||
|
||||
$(builddir)/zend_language_scanner.lo: $(srcdir)/zend_language_parser.h
|
||||
$(builddir)/zend_ini_scanner.lo: $(srcdir)/zend_ini_parser.h
|
||||
|
||||
$(srcdir)/zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
|
||||
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l)
|
||||
|
||||
$(srcdir)/zend_language_parser.h: $(srcdir)/zend_language_parser.c
|
||||
$(srcdir)/zend_language_parser.c: $(srcdir)/zend_language_parser.y
|
||||
# Tweak zendparse to be exported through ZEND_API. This has to be revisited once
|
||||
# bison supports foreign skeletons and that bison version is used. Read
|
||||
# https://git.savannah.gnu.org/cgit/bison.git/tree/data/README.md for more.
|
||||
@$(YACC) $(YFLAGS) -v -d $(srcdir)/zend_language_parser.y -o $@
|
||||
@$(SED) -e 's,^int zendparse\(.*\),ZEND_API int zendparse\1,g' < $@ \
|
||||
> $@.tmp && \
|
||||
mv $@.tmp $@
|
||||
@$(SED) -e 's,^int zendparse\(.*\),ZEND_API int zendparse\1,g' < $(srcdir)/zend_language_parser.h \
|
||||
> $(srcdir)/zend_language_parser.h.tmp && \
|
||||
mv $(srcdir)/zend_language_parser.h.tmp $(srcdir)/zend_language_parser.h
|
||||
@nlinit=`echo 'nl="'; echo '"'`; eval "$$nlinit"; \
|
||||
$(SED) -e "s/^#ifndef YYTOKENTYPE/#include \"zend.h\"\\$${nl}#ifndef YYTOKENTYPE/" < $(srcdir)/zend_language_parser.h \
|
||||
> $(srcdir)/zend_language_parser.h.tmp && \
|
||||
mv $(srcdir)/zend_language_parser.h.tmp $(srcdir)/zend_language_parser.h
|
||||
|
||||
$(srcdir)/zend_ini_parser.h: $(srcdir)/zend_ini_parser.c
|
||||
$(srcdir)/zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
|
||||
$(YACC) $(YFLAGS) -v -d $(srcdir)/zend_ini_parser.y -o $@
|
||||
|
||||
$(srcdir)/zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
|
||||
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
|
||||
|
||||
$(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(srcdir)/zend_language_parser.h
|
||||
|
||||
Zend/zend_execute.lo: $(srcdir)/zend_vm_execute.h $(srcdir)/zend_vm_opcodes.h
|
||||
@@ -0,0 +1,43 @@
|
||||
Zend Memory Manager
|
||||
===================
|
||||
|
||||
General:
|
||||
--------
|
||||
|
||||
The goal of the new memory manager (available since PHP 5.2) is to reduce memory
|
||||
allocation overhead and speedup memory management.
|
||||
|
||||
The new manager's "configure" has no "--disable-zend-memory-manager" option,
|
||||
but it has "--enable-malloc-mm" instead. It is enabled by default in DEBUG
|
||||
build and disabled by default in RELEASE build. When enabled it allows selecting
|
||||
between malloc and emalloc at runtime so you can use internal and external memory
|
||||
debuggers without recompilation.
|
||||
|
||||
Debugging:
|
||||
----------
|
||||
|
||||
Normal:
|
||||
|
||||
$ sapi/cli/php -r 'leak();'
|
||||
|
||||
Zend MM disabled:
|
||||
|
||||
$ USE_ZEND_ALLOC=0 valgrind --leak-check=full sapi/cli/php -r 'leak();'
|
||||
|
||||
Shared extensions:
|
||||
------------------
|
||||
|
||||
Since PHP 5.3.11 it is possible to prevent shared extensions from unloading so
|
||||
that valgrind can correctly track the memory leaks in shared extensions. For
|
||||
this there is the ZEND_DONT_UNLOAD_MODULES environment variable. If set, then
|
||||
DL_UNLOAD() is skipped during the shutdown of shared extensions.
|
||||
|
||||
|
||||
Tweaking:
|
||||
---------
|
||||
|
||||
The Zend MM can be tweaked using ZEND_MM_MEM_TYPE and ZEND_MM_SEG_SIZE environment
|
||||
variables. Default values are "malloc" and "256K". Dependent on target system you
|
||||
can also use "mmap_anon", "mmap_zero" and "win32" storage managers.
|
||||
|
||||
$ ZEND_MM_MEM_TYPE=mmap_anon ZEND_MM_SEG_SIZE=1M sapi/cli/php ..etc.
|
||||
@@ -0,0 +1,102 @@
|
||||
ZEND_VM
|
||||
=======
|
||||
|
||||
ZEND_VM architecture allows specializing opcode handlers according to op_type
|
||||
fields and using different execution methods (call threading, switch threading
|
||||
and direct threading). As a result ZE2 got more than 20% speedup on raw PHP
|
||||
code execution (with specialized executor and direct threading execution
|
||||
method). As in most PHP applications raw execution speed isn't the limiting
|
||||
factor but system calls and database calls are, your mileage with this patch
|
||||
will vary.
|
||||
|
||||
Most parts of the old zend_execute.c go into zend_vm_def.h. Here you can
|
||||
find opcode handlers and helpers. The typical opcode handler template looks
|
||||
like this:
|
||||
|
||||
ZEND_VM_HANDLER(<OPCODE-NUMBER>, <OPCODE>, <OP1_TYPES>, <OP2_TYPES>)
|
||||
{
|
||||
<HANDLER'S CODE>
|
||||
}
|
||||
|
||||
<OPCODE-NUMBER> is a opcode number (0, 1, ...)
|
||||
<OPCODE> is an opcode name (ZEN_NOP, ZEND_ADD, :)
|
||||
<OP1_TYPES> & <OP2_TYPES> are masks for allowed operand op_types. Specializer
|
||||
will generate code only for defined combination of types. You can use any
|
||||
combination of the following op_types UNUSED, CONST, VAR, TMP and CV also
|
||||
you can use ANY mask to disable specialization according operand's op_type.
|
||||
<HANDLER'S CODE> is a handler's code itself. For most handlers it stills the
|
||||
same as in old zend_execute.c, but now it uses macros to access opcode operands
|
||||
and some internal executor data.
|
||||
|
||||
You can see the conformity of new macros to old code in the following list:
|
||||
|
||||
EXECUTE_DATA
|
||||
execute_data
|
||||
ZEND_VM_DISPATCH_TO_HANDLER(<OP>)
|
||||
return <OP>_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
|
||||
ZEND_VM_DISPATCH_TO_HELPER(<NAME>)
|
||||
return <NAME>(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(<NAME>,<PARAM>,<VAL>)
|
||||
return <NAME>(<VAL>, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
|
||||
ZEND_VM_CONTINUE()
|
||||
return 0
|
||||
ZEND_VM_NEXT_OPCODE()
|
||||
NEXT_OPCODE()
|
||||
ZEND_VM_SET_OPCODE(<TARGET>
|
||||
SET_OPCODE(<TARGET>
|
||||
ZEND_VM_INC_OPCODE()
|
||||
INC_OPCOD()
|
||||
ZEND_VM_RETURN_FROM_EXECUTE_LOOP()
|
||||
RETURN_FROM_EXECUTE_LOOP()
|
||||
ZEND_VM_C_LABEL(<LABEL>):
|
||||
<LABEL>:
|
||||
ZEND_VM_C_GOTO(<LABEL>)
|
||||
goto <LABEL>
|
||||
OP<X>_TYPE
|
||||
opline->op<X>.op_type
|
||||
GET_OP<X>_ZVAL_PTR(<TYPE>)
|
||||
get_zval_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
GET_OP<X>_ZVAL_PTR_PTR(<TYPE>)
|
||||
get_zval_ptr_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
GET_OP<X>_OBJ_ZVAL_PTR(<TYPE>)
|
||||
get_obj_zval_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
GET_OP<X>_OBJ_ZVAL_PTR_PTR(<TYPE>)
|
||||
get_obj_zval_ptr_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
IS_OP<X>_TMP_FREE()
|
||||
IS_TMP_FREE(free_op<X>)
|
||||
FREE_OP<X>()
|
||||
FREE_OP(free_op<X>)
|
||||
FREE_OP<X>_IF_VAR()
|
||||
FREE_VAR(free_op<X>)
|
||||
FREE_OP<X>_VAR_PTR()
|
||||
FREE_VAR_PTR(free_op<X>)
|
||||
|
||||
|
||||
Executor's helpers can be defined without parameters or with one parameter.
|
||||
This is done with the following constructs:
|
||||
|
||||
ZEND_VM_HELPER(<HELPER-NAME>, <OP1_TYPES>, <OP2_TYPES>)
|
||||
{
|
||||
<HELPER'S CODE>
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(<HELPER-NAME>, <OP1_TYPES>, <OP2_TYPES>, <PARAM_SPEC>)
|
||||
{
|
||||
<HELPER'S CODE>
|
||||
}
|
||||
|
||||
Executor's code is generated by PHP script zend_vm_gen.php it uses zend_vm_def.h
|
||||
and zend_vm_execute.skl as input and produces zend_vm_opcodes.h and
|
||||
zend_vm_execute.h. The first file is a list of opcode definitions. It is
|
||||
included from zend_compile.h. The second one is an executor code itself. It is
|
||||
included from zend_execute.c.
|
||||
|
||||
zend_vm_gen.php can produce different kind of executors. You can select
|
||||
different opcode threading model using --with-vm-kind=CALL|SWITCH|GOTO. You can
|
||||
disable opcode specialization using --without-specializer. You can include or
|
||||
exclude old executor together with specialized one using --without-old-executor.
|
||||
At last you can debug executor using original zend_vm_def.h or generated file
|
||||
zend_vm_execute.h. Debugging with original file requires --with-lines
|
||||
option. By default ZE2 uses the following command to generate executor:
|
||||
|
||||
$ php zend_vm_gen.php --with-vm-kind=CALL
|
||||
-139
@@ -1,139 +0,0 @@
|
||||
# Zend Engine
|
||||
|
||||
## Zend memory manager
|
||||
|
||||
### General
|
||||
|
||||
The goal of the new memory manager (available since PHP 5.2) is to reduce memory
|
||||
allocation overhead and speedup memory management.
|
||||
|
||||
### Debugging
|
||||
|
||||
Normal:
|
||||
|
||||
```bash
|
||||
sapi/cli/php -r 'leak();'
|
||||
```
|
||||
|
||||
Zend MM disabled:
|
||||
|
||||
```bash
|
||||
USE_ZEND_ALLOC=0 valgrind --leak-check=full sapi/cli/php -r 'leak();'
|
||||
```
|
||||
|
||||
### Shared extensions
|
||||
|
||||
Since PHP 5.3.11 it is possible to prevent shared extensions from unloading so
|
||||
that valgrind can correctly track the memory leaks in shared extensions. For
|
||||
this there is the `ZEND_DONT_UNLOAD_MODULES` environment variable. If set, then
|
||||
`DL_UNLOAD()` is skipped during the shutdown of shared extensions.
|
||||
|
||||
## ZEND_VM
|
||||
|
||||
`ZEND_VM` architecture allows specializing opcode handlers according to
|
||||
`op_type` fields and using different execution methods (call threading, switch
|
||||
threading and direct threading). As a result ZE2 got more than 20% speedup on
|
||||
raw PHP code execution (with specialized executor and direct threading execution
|
||||
method). As in most PHP applications raw execution speed isn't the limiting
|
||||
factor but system calls and database calls are, your mileage with this patch
|
||||
will vary.
|
||||
|
||||
Most parts of the old zend_execute.c go into `zend_vm_def.h`. Here you can find
|
||||
opcode handlers and helpers. The typical opcode handler template looks like
|
||||
this:
|
||||
|
||||
```c
|
||||
ZEND_VM_HANDLER(<OPCODE-NUMBER>, <OPCODE>, <OP1_TYPES>, <OP2_TYPES>)
|
||||
{
|
||||
<HANDLER'S CODE>
|
||||
}
|
||||
```
|
||||
|
||||
`<OPCODE-NUMBER>` is a opcode number (0, 1, ...)
|
||||
`<OPCODE>` is an opcode name (ZEN_NOP, ZEND_ADD, :)
|
||||
`<OP1_TYPES>` and `<OP2_TYPES>` are masks for allowed operand op_types.
|
||||
Specializer will generate code only for defined combination of types. You can
|
||||
use any combination of the following op_types UNUSED, CONST, VAR, TMP and CV
|
||||
also you can use ANY mask to disable specialization according operand's op_type.
|
||||
`<HANDLER'S CODE>` is a handler's code itself. For most handlers it stills the
|
||||
same as in old `zend_execute.c`, but now it uses macros to access opcode
|
||||
operands and some internal executor data.
|
||||
|
||||
You can see the conformity of new macros to old code in the following list:
|
||||
|
||||
```c
|
||||
EXECUTE_DATA
|
||||
execute_data
|
||||
ZEND_VM_DISPATCH_TO_HANDLER(<OP>)
|
||||
return <OP>_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
|
||||
ZEND_VM_DISPATCH_TO_HELPER(<NAME>)
|
||||
return <NAME>(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(<NAME>,<PARAM>,<VAL>)
|
||||
return <NAME>(<VAL>, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
|
||||
ZEND_VM_CONTINUE()
|
||||
return 0
|
||||
ZEND_VM_NEXT_OPCODE()
|
||||
NEXT_OPCODE()
|
||||
ZEND_VM_SET_OPCODE(<TARGET>
|
||||
SET_OPCODE(<TARGET>
|
||||
ZEND_VM_INC_OPCODE()
|
||||
INC_OPCOD()
|
||||
ZEND_VM_RETURN_FROM_EXECUTE_LOOP()
|
||||
RETURN_FROM_EXECUTE_LOOP()
|
||||
ZEND_VM_C_LABEL(<LABEL>):
|
||||
<LABEL>:
|
||||
ZEND_VM_C_GOTO(<LABEL>)
|
||||
goto <LABEL>
|
||||
OP<X>_TYPE
|
||||
opline->op<X>.op_type
|
||||
GET_OP<X>_ZVAL_PTR(<TYPE>)
|
||||
get_zval_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
GET_OP<X>_ZVAL_PTR_PTR(<TYPE>)
|
||||
get_zval_ptr_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
GET_OP<X>_OBJ_ZVAL_PTR(<TYPE>)
|
||||
get_obj_zval_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
GET_OP<X>_OBJ_ZVAL_PTR_PTR(<TYPE>)
|
||||
get_obj_zval_ptr_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
|
||||
IS_OP<X>_TMP_FREE()
|
||||
IS_TMP_FREE(free_op<X>)
|
||||
FREE_OP<X>()
|
||||
FREE_OP(free_op<X>)
|
||||
FREE_OP<X>_IF_VAR()
|
||||
FREE_VAR(free_op<X>)
|
||||
FREE_OP<X>_VAR_PTR()
|
||||
FREE_VAR_PTR(free_op<X>)
|
||||
```
|
||||
|
||||
Executor's helpers can be defined without parameters or with one parameter. This
|
||||
is done with the following constructs:
|
||||
|
||||
```c
|
||||
ZEND_VM_HELPER(<HELPER-NAME>, <OP1_TYPES>, <OP2_TYPES>)
|
||||
{
|
||||
<HELPER'S CODE>
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(<HELPER-NAME>, <OP1_TYPES>, <OP2_TYPES>, <PARAM_SPEC>)
|
||||
{
|
||||
<HELPER'S CODE>
|
||||
}
|
||||
```
|
||||
|
||||
Executor's code is generated by PHP script zend_vm_gen.php it uses
|
||||
`zend_vm_def.h` and `zend_vm_execute.skl` as input and produces
|
||||
`zend_vm_opcodes.h` and `zend_vm_execute.h`. The first file is a list of opcode
|
||||
definitions. It is included from `zend_compile.h`. The second one is an executor
|
||||
code itself. It is included from `zend_execute.c`.
|
||||
|
||||
`zend_vm_gen.php` can produce different kind of executors. You can select
|
||||
different opcode threading model using `--with-vm-kind=CALL|SWITCH|GOTO`. You
|
||||
can disable opcode specialization using `--without-specializer`. You can include
|
||||
or exclude old executor together with specialized one using
|
||||
`--without-old-executor`. At last you can debug executor using original
|
||||
`zend_vm_def.h` or generated file `zend_vm_execute.h`. Debugging with original
|
||||
file requires `--with-lines` option. By default ZE2 uses the following command
|
||||
to generate executor:
|
||||
|
||||
```bash
|
||||
php zend_vm_gen.php --with-vm-kind=CALL
|
||||
```
|
||||
+396
-160
@@ -1,139 +1,77 @@
|
||||
dnl This file contains Zend specific autoconf macros.
|
||||
|
||||
dnl
|
||||
dnl ZEND_CHECK_FLOAT_PRECISION
|
||||
dnl This file contains Zend specific autoconf functions.
|
||||
dnl
|
||||
dnl x87 floating point internal precision control checks
|
||||
dnl See: http://wiki.php.net/rfc/rounding
|
||||
dnl
|
||||
AC_DEFUN([ZEND_CHECK_FLOAT_PRECISION],[
|
||||
AC_MSG_CHECKING([for usable _FPU_SETCW])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <fpu_control.h>
|
||||
]],[[
|
||||
fpu_control_t fpu_oldcw, fpu_cw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
_FPU_GETCW(fpu_oldcw);
|
||||
fpu_cw = (fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE;
|
||||
_FPU_SETCW(fpu_cw);
|
||||
result = a / b;
|
||||
_FPU_SETCW(fpu_oldcw);
|
||||
]])],[ac_cfp_have__fpu_setcw=yes],[ac_cfp_have__fpu_setcw=no])
|
||||
if test "$ac_cfp_have__fpu_setcw" = "yes" ; then
|
||||
AC_DEFINE(HAVE__FPU_SETCW, 1, [whether _FPU_SETCW is present and usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for usable fpsetprec])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <machine/ieeefp.h>
|
||||
]],[[
|
||||
fp_prec_t fpu_oldprec;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
fpu_oldprec = fpgetprec();
|
||||
fpsetprec(FP_PD);
|
||||
result = a / b;
|
||||
fpsetprec(fpu_oldprec);
|
||||
]])], [ac_cfp_have_fpsetprec=yes], [ac_cfp_have_fpsetprec=no])
|
||||
if test "$ac_cfp_have_fpsetprec" = "yes" ; then
|
||||
AC_DEFINE(HAVE_FPSETPREC, 1, [whether fpsetprec is present and usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for usable _controlfp])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <float.h>
|
||||
]],[[
|
||||
unsigned int fpu_oldcw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
fpu_oldcw = _controlfp(0, 0);
|
||||
_controlfp(_PC_53, _MCW_PC);
|
||||
result = a / b;
|
||||
_controlfp(fpu_oldcw, _MCW_PC);
|
||||
]])], [ac_cfp_have__controlfp=yes], [ac_cfp_have__controlfp=no])
|
||||
if test "$ac_cfp_have__controlfp" = "yes" ; then
|
||||
AC_DEFINE(HAVE__CONTROLFP, 1, [whether _controlfp is present usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for usable _controlfp_s])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <float.h>
|
||||
]],[[
|
||||
unsigned int fpu_oldcw, fpu_cw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
_controlfp_s(&fpu_cw, 0, 0);
|
||||
fpu_oldcw = fpu_cw;
|
||||
_controlfp_s(&fpu_cw, _PC_53, _MCW_PC);
|
||||
result = a / b;
|
||||
_controlfp_s(&fpu_cw, fpu_oldcw, _MCW_PC);
|
||||
]])], [ac_cfp_have__controlfp_s=yes], [ac_cfp_have__controlfp_s=no])
|
||||
if test "$ac_cfp_have__controlfp_s" = "yes" ; then
|
||||
AC_DEFINE(HAVE__CONTROLFP_S, 1, [whether _controlfp_s is present and usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether FPU control word can be manipulated by inline assembler])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
/* nothing */
|
||||
]],[[
|
||||
unsigned int oldcw, cw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
__asm__ __volatile__ ("fnstcw %0" : "=m" (*&oldcw));
|
||||
cw = (oldcw & ~0x0 & ~0x300) | 0x200;
|
||||
__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
|
||||
|
||||
result = a / b;
|
||||
|
||||
__asm__ __volatile__ ("fldcw %0" : : "m" (*&oldcw));
|
||||
]])], [ac_cfp_have_fpu_inline_asm_x86=yes], [ac_cfp_have_fpu_inline_asm_x86=no])
|
||||
if test "$ac_cfp_have_fpu_inline_asm_x86" = "yes" ; then
|
||||
AC_DEFINE(HAVE_FPU_INLINE_ASM_X86, 1, [whether FPU control word can be manipulated by inline assembler])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_DEFUN([LIBZEND_CHECK_INT_TYPE],[
|
||||
AC_MSG_CHECKING(for $1)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#elif HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif]],
|
||||
[[if (($1 *) 0)
|
||||
return 0;
|
||||
if (sizeof ($1))
|
||||
return 0;
|
||||
]])],[
|
||||
AC_DEFINE_UNQUOTED([HAVE_]translit($1,a-z_-,A-Z__), 1,[Define if $1 type is present. ])
|
||||
AC_MSG_RESULT(yes)
|
||||
], [AC_MSG_RESULT(no)
|
||||
])dnl
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl LIBZEND_BASIC_CHECKS
|
||||
dnl
|
||||
dnl Basic checks specific for the Zend engine library.
|
||||
dnl
|
||||
AC_DEFUN([LIBZEND_BASIC_CHECKS],[
|
||||
|
||||
AC_REQUIRE([AC_PROG_YACC])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_CC_C_O])
|
||||
AC_REQUIRE([AC_HEADER_STDC])
|
||||
|
||||
AC_CHECK_HEADERS([cpuid.h])
|
||||
LIBZEND_BISON_CHECK
|
||||
|
||||
dnl
|
||||
dnl LIBZEND_DLSYM_CHECK
|
||||
dnl Ugly hack to get around a problem with gcc on AIX.
|
||||
if test "$CC" = "gcc" -a "$ac_cv_prog_cc_g" = "yes" -a \
|
||||
"`uname -sv`" = "AIX 4"; then
|
||||
CFLAGS=`echo $CFLAGS | sed -e 's/-g//'`
|
||||
fi
|
||||
|
||||
dnl Hack to work around a Mac OS X cpp problem
|
||||
dnl Known versions needing this workaround are 5.3 and 5.4
|
||||
if test "$ac_cv_prog_gcc" = "yes" -a "`uname -s`" = "Rhapsody"; then
|
||||
CPPFLAGS="$CPPFLAGS -traditional-cpp"
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(
|
||||
inttypes.h \
|
||||
stdint.h \
|
||||
limits.h \
|
||||
malloc.h \
|
||||
string.h \
|
||||
unistd.h \
|
||||
stdarg.h \
|
||||
sys/types.h \
|
||||
sys/time.h \
|
||||
signal.h \
|
||||
unix.h \
|
||||
stdlib.h \
|
||||
cpuid.h \
|
||||
dlfcn.h)
|
||||
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
AC_DEFUN([LIBZEND_LIBDL_CHECKS],[
|
||||
AC_CHECK_LIB(dl, dlopen, [LIBS="-ldl $LIBS"])
|
||||
AC_CHECK_FUNC(dlopen,[AC_DEFINE(HAVE_LIBDL, 1,[ ])])
|
||||
])
|
||||
|
||||
AC_DEFUN([LIBZEND_DLSYM_CHECK],[
|
||||
dnl
|
||||
dnl Ugly hack to check if dlsym() requires a leading underscore in symbol name.
|
||||
dnl
|
||||
AC_DEFUN([LIBZEND_DLSYM_CHECK],[
|
||||
AC_MSG_CHECKING([whether dlsym() requires a leading underscore in symbol names])
|
||||
_LT_AC_TRY_DLOPEN_SELF([
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -145,17 +83,32 @@ _LT_AC_TRY_DLOPEN_SELF([
|
||||
], [])
|
||||
])
|
||||
|
||||
dnl This is required for QNX and may be some BSD derived systems
|
||||
AC_CHECK_TYPE( uint, unsigned int )
|
||||
AC_CHECK_TYPE( ulong, unsigned long )
|
||||
|
||||
dnl Check if int32_t and uint32_t are defined
|
||||
LIBZEND_CHECK_INT_TYPE(int32_t)
|
||||
LIBZEND_CHECK_INT_TYPE(uint32_t)
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(getpid kill sigsetjmp)
|
||||
AC_FUNC_VPRINTF
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_FUNCS(memcpy strdup getpid kill strtod strtol finite fpclass sigsetjmp)
|
||||
AC_ZEND_BROKEN_SPRINTF
|
||||
|
||||
AC_CHECK_DECLS([isfinite, isnan, isinf], [], [], [[#include <math.h>]])
|
||||
|
||||
ZEND_FP_EXCEPT
|
||||
|
||||
ZEND_CHECK_FLOAT_PRECISION
|
||||
|
||||
dnl Test whether double cast to long preserves least significant bits.
|
||||
dnl test whether double cast to long preserves least significant bits
|
||||
AC_MSG_CHECKING(whether double cast to long preserves least significant bits)
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -163,16 +116,16 @@ int main()
|
||||
double d = (double) LONG_MIN * LONG_MIN + 2e9;
|
||||
|
||||
if ((long) d == 2e9 && (long) -d == -2e9) {
|
||||
return 0;
|
||||
exit(0);
|
||||
}
|
||||
} else if (sizeof(long) == 8) {
|
||||
double correct = 18e18 - ((double) LONG_MIN * -2); /* Subtract ULONG_MAX + 1 */
|
||||
|
||||
if ((long) 18e18 == correct) { /* On 64-bit, only check between LONG_MAX and ULONG_MAX */
|
||||
return 0;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
]])], [
|
||||
AC_DEFINE([ZEND_DVAL_TO_LVAL_CAST_OK], 1, [Define if double cast to long preserves least significant bits])
|
||||
@@ -185,13 +138,39 @@ int main()
|
||||
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl LIBZEND_OTHER_CHECKS
|
||||
dnl
|
||||
AC_DEFUN([LIBZEND_ENABLE_DEBUG],[
|
||||
|
||||
AC_ARG_ENABLE(debug,
|
||||
[ --enable-debug Compile with debugging symbols],[
|
||||
ZEND_DEBUG=$enableval
|
||||
],[
|
||||
ZEND_DEBUG=no
|
||||
])
|
||||
|
||||
])
|
||||
|
||||
AC_DEFUN([LIBZEND_OTHER_CHECKS],[
|
||||
|
||||
AC_ARG_ENABLE(maintainer-zts,
|
||||
[ --enable-maintainer-zts Enable thread safety - for code maintainers only!!],[
|
||||
ZEND_MAINTAINER_ZTS=$enableval
|
||||
],[
|
||||
ZEND_MAINTAINER_ZTS=no
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE(inline-optimization,
|
||||
[ --disable-inline-optimization
|
||||
If building zend_execute.lo fails, try this switch],[
|
||||
ZEND_INLINE_OPTIMIZATION=$enableval
|
||||
],[
|
||||
ZEND_INLINE_OPTIMIZATION=yes
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(whether to enable thread-safety)
|
||||
AC_MSG_RESULT($ZEND_ZTS)
|
||||
AC_MSG_RESULT($ZEND_MAINTAINER_ZTS)
|
||||
|
||||
AC_MSG_CHECKING(whether to enable inline optimization for GCC)
|
||||
AC_MSG_RESULT($ZEND_INLINE_OPTIMIZATION)
|
||||
|
||||
AC_MSG_CHECKING(whether to enable Zend debugging)
|
||||
AC_MSG_RESULT($ZEND_DEBUG)
|
||||
@@ -202,23 +181,32 @@ if test "$ZEND_DEBUG" = "yes"; then
|
||||
if test "$CFLAGS" = "-g -O2"; then
|
||||
CFLAGS=-g
|
||||
fi
|
||||
test -n "$GCC" && DEBUG_CFLAGS="$DEBUG_CFLAGS -Wall"
|
||||
test -n "$GCC" && test "$USE_MAINTAINER_MODE" = "yes" && \
|
||||
DEBUG_CFLAGS="$DEBUG_CFLAGS -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations"
|
||||
else
|
||||
AC_DEFINE(ZEND_DEBUG,0,[ ])
|
||||
fi
|
||||
|
||||
test -n "$GCC" && CFLAGS="-Wall -Wextra -Wno-strict-aliasing -Wno-implicit-fallthrough -Wno-unused-parameter -Wno-sign-compare $CFLAGS"
|
||||
dnl Check if compiler supports -Wno-clobbered (only GCC)
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-clobbered], CFLAGS="-Wno-clobbered $CFLAGS", , [-Werror])
|
||||
|
||||
test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS"
|
||||
|
||||
if test "$ZEND_ZTS" = "yes"; then
|
||||
if test "$ZEND_MAINTAINER_ZTS" = "yes"; then
|
||||
AC_DEFINE(ZTS,1,[ ])
|
||||
CFLAGS="$CFLAGS -DZTS"
|
||||
fi
|
||||
|
||||
changequote({,})
|
||||
if test -n "$GCC" && test "$ZEND_INLINE_OPTIMIZATION" != "yes"; then
|
||||
INLINE_CFLAGS=`echo $ac_n "$CFLAGS $ac_c" | sed s/-O[0-9s]*//`
|
||||
else
|
||||
INLINE_CFLAGS="$CFLAGS"
|
||||
fi
|
||||
changequote([,])
|
||||
|
||||
AC_C_INLINE
|
||||
|
||||
AC_SUBST(INLINE_CFLAGS)
|
||||
|
||||
AC_MSG_CHECKING(target system is Darwin)
|
||||
if echo "$target" | grep "darwin" > /dev/null; then
|
||||
AC_DEFINE([DARWIN], 1, [Define if the target system is darwin])
|
||||
@@ -227,13 +215,12 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl Test and set the alignment define for ZEND_MM. This also does the
|
||||
dnl logarithmic test for ZEND_MM.
|
||||
dnl test and set the alignment define for ZEND_MM
|
||||
dnl this also does the logarithmic test for ZEND_MM.
|
||||
AC_MSG_CHECKING(for MM alignment and log values)
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef union _mm_align_test {
|
||||
void *ptr;
|
||||
@@ -262,7 +249,7 @@ int main()
|
||||
fprintf(fp, "%d %d\n", ZEND_MM_ALIGNMENT, zeros);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
exit(0);
|
||||
}
|
||||
]])], [
|
||||
LIBZEND_MM_ALIGN=`cat conftest.zend | cut -d ' ' -f 1`
|
||||
@@ -270,22 +257,126 @@ int main()
|
||||
AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT, $LIBZEND_MM_ALIGN, [ ])
|
||||
AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT_LOG2, $LIBZEND_MM_ALIGN_LOG2, [ ])
|
||||
], [], [
|
||||
dnl Cross compilation needs something here.
|
||||
dnl cross-compile needs something here
|
||||
LIBZEND_MM_ALIGN=8
|
||||
])
|
||||
|
||||
AC_MSG_RESULT(done)
|
||||
|
||||
dnl test for memory allocation using mmap(MAP_ANON)
|
||||
AC_MSG_CHECKING(for memory allocation using mmap(MAP_ANON))
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifndef MAP_ANON
|
||||
# ifdef MAP_ANONYMOUS
|
||||
# define MAP_ANON MAP_ANONYMOUS
|
||||
# endif
|
||||
#endif
|
||||
#ifndef MREMAP_MAYMOVE
|
||||
# define MREMAP_MAYMOVE 0
|
||||
#endif
|
||||
#ifndef MAP_FAILED
|
||||
# define MAP_FAILED ((void*)-1)
|
||||
#endif
|
||||
|
||||
#define SEG_SIZE (256*1024)
|
||||
|
||||
int main()
|
||||
{
|
||||
void *seg = mmap(NULL, SEG_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (seg == MAP_FAILED) {
|
||||
return 1;
|
||||
}
|
||||
if (munmap(seg, SEG_SIZE) != 0) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
]])], [
|
||||
AC_DEFINE([HAVE_MEM_MMAP_ANON], 1, [Define if the target system has support for memory allocation using mmap(MAP_ANON)])
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
], [
|
||||
dnl cross-compile needs something here
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
dnl test for memory allocation using mmap("/dev/zero")
|
||||
AC_MSG_CHECKING(for memory allocation using mmap("/dev/zero"))
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifndef MAP_ANON
|
||||
# ifdef MAP_ANONYMOUS
|
||||
# define MAP_ANON MAP_ANONYMOUS
|
||||
# endif
|
||||
#endif
|
||||
#ifndef MREMAP_MAYMOVE
|
||||
# define MREMAP_MAYMOVE 0
|
||||
#endif
|
||||
#ifndef MAP_FAILED
|
||||
# define MAP_FAILED ((void*)-1)
|
||||
#endif
|
||||
|
||||
#define SEG_SIZE (256*1024)
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd;
|
||||
void *seg;
|
||||
|
||||
fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
return 1;
|
||||
}
|
||||
seg = mmap(NULL, SEG_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
if (seg == MAP_FAILED) {
|
||||
return 2;
|
||||
}
|
||||
if (munmap(seg, SEG_SIZE) != 0) {
|
||||
return 3;
|
||||
}
|
||||
if (close(fd) != 0) {
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
]])], [
|
||||
AC_DEFINE([HAVE_MEM_MMAP_ZERO], 1, [Define if the target system has support for memory allocation using mmap("/dev/zero")])
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
], [
|
||||
dnl cross-compile needs something here
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
AC_CHECK_FUNCS(mremap)
|
||||
|
||||
AC_ARG_ENABLE([zend-signals],
|
||||
[AS_HELP_STRING([--disable-zend-signals],
|
||||
[whether to enable zend signal handling])],
|
||||
[ZEND_SIGNALS=$enableval],
|
||||
[ZEND_SIGNALS=yes])
|
||||
|
||||
AC_CHECK_FUNCS([sigaction], [], [
|
||||
ZEND_SIGNALS=no
|
||||
AC_ARG_ENABLE(zend-signals,
|
||||
[ --disable-zend-signals whether to enable zend signal handling],[
|
||||
ZEND_SIGNALS=$enableval
|
||||
],[
|
||||
ZEND_SIGNALS=yes
|
||||
])
|
||||
|
||||
AC_CHECK_FUNC(sigaction, [
|
||||
AC_DEFINE(HAVE_SIGACTION, 1, [Whether sigaction() is available])
|
||||
], [
|
||||
ZEND_SIGNALS=no
|
||||
])
|
||||
if test "$ZEND_SIGNALS" = "yes"; then
|
||||
AC_DEFINE(ZEND_SIGNALS, 1, [Use zend signal handling])
|
||||
@@ -305,12 +396,21 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([gcc-global-regs],
|
||||
[AS_HELP_STRING([--disable-gcc-global-regs],
|
||||
[whether to enable GCC global register variables])],
|
||||
[ZEND_GCC_GLOBAL_REGS=$enableval],
|
||||
[ZEND_GCC_GLOBAL_REGS=yes])
|
||||
AC_MSG_CHECKING(whether /dev/arandom exists)
|
||||
if test -r "/dev/arandom" && test -c "/dev/arandom"; then
|
||||
AC_DEFINE([HAVE_DEV_ARANDOM], 1, [Define if the target system has /dev/arandom device])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(gcc-global-regs,
|
||||
[ --disable-gcc-global-regs
|
||||
whether to enable GCC global register variables],[
|
||||
ZEND_GCC_GLOBAL_REGS=$enableval
|
||||
],[
|
||||
ZEND_GCC_GLOBAL_REGS=yes
|
||||
])
|
||||
AC_MSG_CHECKING(for global register variables support)
|
||||
if test "$ZEND_GCC_GLOBAL_REGS" != "no"; then
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
@@ -331,9 +431,6 @@ if test "$ZEND_GCC_GLOBAL_REGS" != "no"; then
|
||||
#elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
|
||||
# define ZEND_VM_FP_GLOBAL_REG "r28"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "r29"
|
||||
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__aarch64__)
|
||||
# define ZEND_VM_FP_GLOBAL_REG "x27"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "x28"
|
||||
#else
|
||||
# error "global register variables are not supported"
|
||||
#endif
|
||||
@@ -363,7 +460,146 @@ else
|
||||
fi
|
||||
AC_MSG_RESULT($ZEND_GCC_GLOBAL_REGS)
|
||||
|
||||
dnl Check whether __cpuid_count is available.
|
||||
dnl
|
||||
dnl Check if atof() accepts NAN
|
||||
dnl
|
||||
AC_CACHE_CHECK(whether atof() accepts NAN, ac_cv_atof_accept_nan,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISNAN
|
||||
#define zend_isnan(a) isnan(a)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
|
||||
#else
|
||||
#define zend_isnan(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return zend_isnan(atof("NAN")) ? 0 : 1;
|
||||
}
|
||||
]])],[
|
||||
ac_cv_atof_accept_nan=yes
|
||||
],[
|
||||
ac_cv_atof_accept_nan=no
|
||||
],[
|
||||
ac_cv_atof_accept_nan=no
|
||||
])])
|
||||
if test "$ac_cv_atof_accept_nan" = "yes"; then
|
||||
AC_DEFINE([HAVE_ATOF_ACCEPTS_NAN], 1, [whether atof() accepts NAN])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Check if atof() accepts INF
|
||||
dnl
|
||||
AC_CACHE_CHECK(whether atof() accepts INF, ac_cv_atof_accept_inf,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISINF
|
||||
#define zend_isinf(a) isinf(a)
|
||||
#elif defined(INFINITY)
|
||||
/* Might not work, but is required by ISO C99 */
|
||||
#define zend_isinf(a) (((a)==INFINITY)?1:0)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
|
||||
#else
|
||||
#define zend_isinf(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return zend_isinf(atof("INF")) && zend_isinf(atof("-INF")) ? 0 : 1;
|
||||
}
|
||||
]])],[
|
||||
ac_cv_atof_accept_inf=yes
|
||||
],[
|
||||
ac_cv_atof_accept_inf=no
|
||||
],[
|
||||
ac_cv_atof_accept_inf=no
|
||||
])])
|
||||
if test "$ac_cv_atof_accept_inf" = "yes"; then
|
||||
AC_DEFINE([HAVE_ATOF_ACCEPTS_INF], 1, [whether atof() accepts INF])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Check if HUGE_VAL == INF
|
||||
dnl
|
||||
AC_CACHE_CHECK(whether HUGE_VAL == INF, ac_cv_huge_val_inf,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISINF
|
||||
#define zend_isinf(a) isinf(a)
|
||||
#elif defined(INFINITY)
|
||||
/* Might not work, but is required by ISO C99 */
|
||||
#define zend_isinf(a) (((a)==INFINITY)?1:0)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
|
||||
#else
|
||||
#define zend_isinf(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return zend_isinf(HUGE_VAL) ? 0 : 1;
|
||||
}
|
||||
]])],[
|
||||
ac_cv_huge_val_inf=yes
|
||||
],[
|
||||
ac_cv_huge_val_inf=no
|
||||
],[
|
||||
ac_cv_huge_val_inf=yes
|
||||
])])
|
||||
dnl This is the most probable fallback so we assume yes in case of cross compile.
|
||||
if test "$ac_cv_huge_val_inf" = "yes"; then
|
||||
AC_DEFINE([HAVE_HUGE_VAL_INF], 1, [whether HUGE_VAL == INF])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Check if HUGE_VAL + -HUGEVAL == NAN
|
||||
dnl
|
||||
AC_CACHE_CHECK(whether HUGE_VAL + -HUGEVAL == NAN, ac_cv_huge_val_nan,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISNAN
|
||||
#define zend_isnan(a) isnan(a)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
|
||||
#else
|
||||
#define zend_isnan(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#if defined(__sparc__) && !(__GNUC__ >= 3)
|
||||
/* prevent bug #27830 */
|
||||
return 1;
|
||||
#else
|
||||
return zend_isnan(HUGE_VAL + -HUGE_VAL) ? 0 : 1;
|
||||
#endif
|
||||
}
|
||||
]])],[
|
||||
ac_cv_huge_val_nan=yes
|
||||
],[
|
||||
ac_cv_huge_val_nan=no
|
||||
],[
|
||||
ac_cv_huge_val_nan=yes
|
||||
])])
|
||||
dnl This is the most probable fallback so we assume yes in case of cross compile.
|
||||
if test "$ac_cv_huge_val_nan" = "yes"; then
|
||||
AC_DEFINE([HAVE_HUGE_VAL_NAN], 1, [whether HUGE_VAL + -HUGEVAL == NAN])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Check whether __cpuid_count is available
|
||||
dnl
|
||||
AC_CACHE_CHECK(whether __cpuid_count is available, ac_cv_cpuid_count_available, [
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <cpuid.h>
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
dnl This file contains local autoconf functions.
|
||||
|
||||
AC_DEFUN([LIBZEND_BISON_CHECK],[
|
||||
# we only support certain bison versions;
|
||||
# min: 2.4 (i.e. 204, major * 100 + minor for easier comparison)
|
||||
bison_version_min="204"
|
||||
# non-working versions, e.g. "3.0 3.2";
|
||||
# remove "none" when introducing the first incompatible bison version an
|
||||
# separate any following additions by spaces
|
||||
bison_version_exclude=""
|
||||
|
||||
# for standalone build of Zend Engine
|
||||
test -z "$SED" && SED=sed
|
||||
|
||||
bison_version=none
|
||||
if test "$YACC"; then
|
||||
AC_CACHE_CHECK([for bison version], php_cv_bison_version, [
|
||||
bison_version_vars=`$YACC --version 2> /dev/null | grep 'GNU Bison' | cut -d ' ' -f 4 | $SED -e 's/\./ /g' | tr -d a-z`
|
||||
php_cv_bison_version=invalid
|
||||
if test -n "$bison_version_vars"; then
|
||||
set $bison_version_vars
|
||||
bison_version="${1}.${2}"
|
||||
bison_version_num="`expr ${1} \* 100 + ${2}`"
|
||||
if test $bison_version_num -ge $bison_version_min; then
|
||||
php_cv_bison_version="$bison_version (ok)"
|
||||
for bison_check_version in $bison_version_exclude; do
|
||||
if test "$bison_version" = "$bison_check_version"; then
|
||||
php_cv_bison_version=invalid
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
])
|
||||
fi
|
||||
case $php_cv_bison_version in
|
||||
""|invalid[)]
|
||||
bison_msg="This bison version is not supported for regeneration of the Zend/PHP parsers (found: $bison_version, min: $bison_version_min, excluded: $bison_version_exclude)."
|
||||
AC_MSG_WARN([$bison_msg])
|
||||
YACC="exit 0;"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
AC_DEFUN([ZEND_FP_EXCEPT],[
|
||||
AC_CACHE_CHECK(whether fp_except is defined, ac_cv_type_fp_except,[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <floatingpoint.h>
|
||||
]],[[
|
||||
fp_except x = (fp_except) 0;
|
||||
]])],[
|
||||
ac_cv_type_fp_except=yes
|
||||
],[
|
||||
ac_cv_type_fp_except=no
|
||||
])])
|
||||
if test "$ac_cv_type_fp_except" = "yes"; then
|
||||
AC_DEFINE(HAVE_FP_EXCEPT, 1, [whether floatingpoint.h defines fp_except])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check for broken sprintf()
|
||||
dnl
|
||||
AC_DEFUN([AC_ZEND_BROKEN_SPRINTF],[
|
||||
AC_CACHE_CHECK(whether sprintf is broken, ac_cv_broken_sprintf,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[main() {char buf[20];exit(sprintf(buf,"testing 123")!=11); }]])],[
|
||||
ac_cv_broken_sprintf=no
|
||||
],[
|
||||
ac_cv_broken_sprintf=yes
|
||||
],[
|
||||
ac_cv_broken_sprintf=no
|
||||
])
|
||||
])
|
||||
if test "$ac_cv_broken_sprintf" = "yes"; then
|
||||
ac_result=1
|
||||
else
|
||||
ac_result=0
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(ZEND_BROKEN_SPRINTF, $ac_result, [Whether sprintf is broken])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl AC_ZEND_C_BIGENDIAN
|
||||
dnl Replacement macro for AC_C_BIGENDIAN
|
||||
dnl
|
||||
AC_DEFUN([AC_ZEND_C_BIGENDIAN],
|
||||
[AC_CACHE_CHECK([whether byte ordering is bigendian], ac_cv_c_bigendian_php,
|
||||
[
|
||||
ac_cv_c_bigendian_php=unknown
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
int main(void)
|
||||
{
|
||||
short one = 1;
|
||||
char *cp = (char *)&one;
|
||||
|
||||
if (*cp == 0) {
|
||||
return(0);
|
||||
} else {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
]])], [ac_cv_c_bigendian_php=yes], [ac_cv_c_bigendian_php=no], [ac_cv_c_bigendian_php=unknown])
|
||||
])
|
||||
if test $ac_cv_c_bigendian_php = yes; then
|
||||
AC_DEFINE(WORDS_BIGENDIAN, 1, [Define if processor uses big-endian word])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[
|
||||
LIBTOOL='$(SHELL) $(top_builddir)/libtool $1'
|
||||
])
|
||||
|
||||
dnl x87 floating point internal precision control checks
|
||||
dnl See: http://wiki.php.net/rfc/rounding
|
||||
AC_DEFUN([ZEND_CHECK_FLOAT_PRECISION],[
|
||||
AC_MSG_CHECKING([for usable _FPU_SETCW])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <fpu_control.h>
|
||||
]],[[
|
||||
fpu_control_t fpu_oldcw, fpu_cw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
_FPU_GETCW(fpu_oldcw);
|
||||
fpu_cw = (fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE;
|
||||
_FPU_SETCW(fpu_cw);
|
||||
result = a / b;
|
||||
_FPU_SETCW(fpu_oldcw);
|
||||
]])],[ac_cfp_have__fpu_setcw=yes],[ac_cfp_have__fpu_setcw=no])
|
||||
if test "$ac_cfp_have__fpu_setcw" = "yes" ; then
|
||||
AC_DEFINE(HAVE__FPU_SETCW, 1, [whether _FPU_SETCW is present and usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for usable fpsetprec])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <machine/ieeefp.h>
|
||||
]],[[
|
||||
fp_prec_t fpu_oldprec;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
fpu_oldprec = fpgetprec();
|
||||
fpsetprec(FP_PD);
|
||||
result = a / b;
|
||||
fpsetprec(fpu_oldprec);
|
||||
]])], [ac_cfp_have_fpsetprec=yes], [ac_cfp_have_fpsetprec=no])
|
||||
if test "$ac_cfp_have_fpsetprec" = "yes" ; then
|
||||
AC_DEFINE(HAVE_FPSETPREC, 1, [whether fpsetprec is present and usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for usable _controlfp])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <float.h>
|
||||
]],[[
|
||||
unsigned int fpu_oldcw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
fpu_oldcw = _controlfp(0, 0);
|
||||
_controlfp(_PC_53, _MCW_PC);
|
||||
result = a / b;
|
||||
_controlfp(fpu_oldcw, _MCW_PC);
|
||||
]])], [ac_cfp_have__controlfp=yes], [ac_cfp_have__controlfp=no])
|
||||
if test "$ac_cfp_have__controlfp" = "yes" ; then
|
||||
AC_DEFINE(HAVE__CONTROLFP, 1, [whether _controlfp is present usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for usable _controlfp_s])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <float.h>
|
||||
]],[[
|
||||
unsigned int fpu_oldcw, fpu_cw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
_controlfp_s(&fpu_cw, 0, 0);
|
||||
fpu_oldcw = fpu_cw;
|
||||
_controlfp_s(&fpu_cw, _PC_53, _MCW_PC);
|
||||
result = a / b;
|
||||
_controlfp_s(&fpu_cw, fpu_oldcw, _MCW_PC);
|
||||
]])], [ac_cfp_have__controlfp_s=yes], [ac_cfp_have__controlfp_s=no])
|
||||
if test "$ac_cfp_have__controlfp_s" = "yes" ; then
|
||||
AC_DEFINE(HAVE__CONTROLFP_S, 1, [whether _controlfp_s is present and usable])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether FPU control word can be manipulated by inline assembler])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
/* nothing */
|
||||
]],[[
|
||||
unsigned int oldcw, cw;
|
||||
volatile double result;
|
||||
double a = 2877.0;
|
||||
volatile double b = 1000000.0;
|
||||
|
||||
__asm__ __volatile__ ("fnstcw %0" : "=m" (*&oldcw));
|
||||
cw = (oldcw & ~0x0 & ~0x300) | 0x200;
|
||||
__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
|
||||
|
||||
result = a / b;
|
||||
|
||||
__asm__ __volatile__ ("fldcw %0" : : "m" (*&oldcw));
|
||||
]])], [ac_cfp_have_fpu_inline_asm_x86=yes], [ac_cfp_have_fpu_inline_asm_x86=no])
|
||||
if test "$ac_cfp_have_fpu_inline_asm_x86" = "yes" ; then
|
||||
AC_DEFINE(HAVE_FPU_INLINE_ASM_X86, 1, [whether FPU control word can be manipulated by inline assembler])
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
])
|
||||
+37
-37
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
if (function_exists("date_default_timezone_set")) {
|
||||
date_default_timezone_set("UTC");
|
||||
date_default_timezone_set("UTC");
|
||||
}
|
||||
|
||||
function simple() {
|
||||
@@ -220,30 +220,30 @@ function heapsort_r($n, &$ra) {
|
||||
$ir = $n;
|
||||
|
||||
while (1) {
|
||||
if ($l > 1) {
|
||||
$rra = $ra[--$l];
|
||||
} else {
|
||||
$rra = $ra[$ir];
|
||||
$ra[$ir] = $ra[1];
|
||||
if (--$ir == 1) {
|
||||
$ra[1] = $rra;
|
||||
return;
|
||||
}
|
||||
}
|
||||
$i = $l;
|
||||
$j = $l << 1;
|
||||
while ($j <= $ir) {
|
||||
if (($j < $ir) && ($ra[$j] < $ra[$j+1])) {
|
||||
$j++;
|
||||
}
|
||||
if ($rra < $ra[$j]) {
|
||||
$ra[$i] = $ra[$j];
|
||||
$j += ($i = $j);
|
||||
} else {
|
||||
$j = $ir + 1;
|
||||
}
|
||||
}
|
||||
$ra[$i] = $rra;
|
||||
if ($l > 1) {
|
||||
$rra = $ra[--$l];
|
||||
} else {
|
||||
$rra = $ra[$ir];
|
||||
$ra[$ir] = $ra[1];
|
||||
if (--$ir == 1) {
|
||||
$ra[1] = $rra;
|
||||
return;
|
||||
}
|
||||
}
|
||||
$i = $l;
|
||||
$j = $l << 1;
|
||||
while ($j <= $ir) {
|
||||
if (($j < $ir) && ($ra[$j] < $ra[$j+1])) {
|
||||
$j++;
|
||||
}
|
||||
if ($rra < $ra[$j]) {
|
||||
$ra[$i] = $ra[$j];
|
||||
$j += ($i = $j);
|
||||
} else {
|
||||
$j = $ir + 1;
|
||||
}
|
||||
}
|
||||
$ra[$i] = $rra;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@ function mkmatrix ($rows, $cols) {
|
||||
$count = 1;
|
||||
$mx = array();
|
||||
for ($i=0; $i<$rows; $i++) {
|
||||
for ($j=0; $j<$cols; $j++) {
|
||||
$mx[$i][$j] = $count++;
|
||||
}
|
||||
for ($j=0; $j<$cols; $j++) {
|
||||
$mx[$i][$j] = $count++;
|
||||
}
|
||||
}
|
||||
return($mx);
|
||||
}
|
||||
@@ -278,13 +278,13 @@ function mkmatrix ($rows, $cols) {
|
||||
function mmult ($rows, $cols, $m1, $m2) {
|
||||
$m3 = array();
|
||||
for ($i=0; $i<$rows; $i++) {
|
||||
for ($j=0; $j<$cols; $j++) {
|
||||
$x = 0;
|
||||
for ($k=0; $k<$cols; $k++) {
|
||||
$x += $m1[$i][$k] * $m2[$k][$j];
|
||||
}
|
||||
$m3[$i][$j] = $x;
|
||||
}
|
||||
for ($j=0; $j<$cols; $j++) {
|
||||
$x = 0;
|
||||
for ($k=0; $k<$cols; $k++) {
|
||||
$x += $m1[$i][$k] * $m2[$k][$j];
|
||||
}
|
||||
$m3[$i][$j] = $x;
|
||||
}
|
||||
}
|
||||
return($m3);
|
||||
}
|
||||
@@ -353,7 +353,7 @@ function gethrtime()
|
||||
|
||||
function start_test()
|
||||
{
|
||||
ob_start();
|
||||
ob_start();
|
||||
return gethrtime();
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ function end_test($start, $name)
|
||||
$pad = str_repeat(" ", 24-strlen($name)-strlen($num));
|
||||
|
||||
echo $name.$pad.$num."\n";
|
||||
ob_start();
|
||||
ob_start();
|
||||
return gethrtime();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Makefile to generate build tools
|
||||
#
|
||||
# Standard usage:
|
||||
# make -f build.mk
|
||||
#
|
||||
# Written by Sascha Schumann
|
||||
|
||||
|
||||
LT_TARGETS = ltmain.sh ltconfig
|
||||
|
||||
config_h_in = zend_config.h.in
|
||||
|
||||
makefile_am_files = Makefile.am
|
||||
makefile_in_files = $(makefile_am_files:.am=.in)
|
||||
makefile_files = $(makefile_am_files:e.am=e)
|
||||
|
||||
targets = $(makefile_in_files) $(LT_TARGETS) configure $(config_h_in)
|
||||
|
||||
all: $(targets)
|
||||
|
||||
clean:
|
||||
rm -f $(targets)
|
||||
|
||||
$(LT_TARGETS):
|
||||
rm -f $(LT_TARGETS)
|
||||
libtoolize --automake $(AMFLAGS) -f
|
||||
|
||||
$(makefile_in_files): $(makefile_am_files)
|
||||
automake -a -i $(AMFLAGS) $(makefile_files)
|
||||
|
||||
aclocal.m4: configure.ac acinclude.m4
|
||||
aclocal
|
||||
|
||||
$(config_h_in): configure.ac
|
||||
# explicitly remove target since autoheader does not seem to work
|
||||
# correctly otherwise (timestamps are not updated)
|
||||
@rm -f $@
|
||||
autoheader
|
||||
|
||||
configure: aclocal.m4 configure.ac
|
||||
autoconf
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
--copy)
|
||||
automake_flags=--copy
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
libtoolize --force --automake $automake_flags
|
||||
|
||||
mv aclocal.m4 aclocal.m4.old 2>/dev/null
|
||||
aclocal
|
||||
if cmp aclocal.m4.old aclocal.m4 > /dev/null 2>&1; then
|
||||
echo "buildconf: keeping ${1}aclocal.m4"
|
||||
mv aclocal.m4.old aclocal.m4
|
||||
else
|
||||
echo "buildconf: created or modified ${1}aclocal.m4"
|
||||
fi
|
||||
|
||||
autoheader
|
||||
|
||||
automake --add-missing --include-deps $automake_flags
|
||||
|
||||
mv configure configure.old 2>/dev/null
|
||||
autoconf
|
||||
if cmp configure.old configure > /dev/null 2>&1; then
|
||||
echo "buildconf: keeping ${1}configure"
|
||||
mv configure.old configure
|
||||
else
|
||||
echo "buildconf: created or modified ${1}configure"
|
||||
fi
|
||||
@@ -0,0 +1,133 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(zend.c)
|
||||
AM_INIT_AUTOMAKE(zend, 0.80A, nodefine)
|
||||
AM_CONFIG_HEADER(zend_config.h)
|
||||
AM_SANITY_CHECK
|
||||
AM_MAINTAINER_MODE
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_STDC
|
||||
ZEND_VERSION=$VERSION
|
||||
AC_ZEND_C_BIGENDIAN
|
||||
|
||||
AH_TOP([
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define ZEND_API __attribute__ ((visibility("default")))
|
||||
# define ZEND_DLEXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
# define ZEND_API
|
||||
# define ZEND_DLEXPORT
|
||||
#endif
|
||||
|
||||
#define ZEND_DLIMPORT
|
||||
|
||||
#undef uint
|
||||
#undef ulong
|
||||
])
|
||||
|
||||
AH_BOTTOM([
|
||||
#ifndef ZEND_ACCONFIG_H_NO_C_PROTOS
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IEEEFP_H
|
||||
# include <ieeefp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#if ZEND_BROKEN_SPRINTF
|
||||
int zend_sprintf(char *buffer, const char *format, ...);
|
||||
#else
|
||||
# define zend_sprintf sprintf
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef zend_isnan
|
||||
#if HAVE_DECL_ISNAN && (!defined(__cplusplus) || __cplusplus < 201103L)
|
||||
#define zend_isnan(a) isnan(a)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
|
||||
#else
|
||||
#define zend_isnan(a) ((a) != (a))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_ISINF && (!defined(__cplusplus) || __cplusplus < 201103L)
|
||||
#define zend_isinf(a) isinf(a)
|
||||
#elif defined(INFINITY)
|
||||
/* Might not work, but is required by ISO C99 */
|
||||
#define zend_isinf(a) (((a)==INFINITY || (a)==-INFINITY)?1:0)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
|
||||
#else
|
||||
#define zend_isinf(a) 0
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_ISFINITE && (!defined(__cplusplus) || __cplusplus < 201103L)
|
||||
#define zend_finite(a) isfinite(a)
|
||||
#elif defined(HAVE_FINITE)
|
||||
#define zend_finite(a) finite(a)
|
||||
#elif defined(fpclassify)
|
||||
#define zend_finite(a) ((fpclassify((a))!=FP_INFINITE&&fpclassify((a))!=FP_NAN)?1:0)
|
||||
#else
|
||||
#define zend_finite(a) (zend_isnan(a) ? 0 : zend_isinf(a) ? 0 : 1)
|
||||
#endif
|
||||
|
||||
#endif /* ifndef ZEND_ACCONFIG_H_NO_C_PROTOS */
|
||||
|
||||
])
|
||||
|
||||
dnl We want this one before the checks, so the checks can modify CFLAGS.
|
||||
test -z "$CFLAGS" && auto_cflags=1
|
||||
|
||||
AC_CHECK_SIZEOF(long, 8)
|
||||
AC_CHECK_SIZEOF(int, 4)
|
||||
|
||||
sinclude(Zend.m4)
|
||||
|
||||
LIBZEND_BASIC_CHECKS
|
||||
LIBZEND_LIBDL_CHECKS
|
||||
LIBZEND_DLSYM_CHECK
|
||||
|
||||
AM_PROG_LIBTOOL
|
||||
if test "$enable_debug" != "yes"; then
|
||||
AM_SET_LIBTOOL_VARIABLE([--silent])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Check for /usr/pkg/{lib,include} which is where NetBSD puts binary
|
||||
dnl and source packages. This should be harmless on other OSs.
|
||||
dnl
|
||||
if test -d /usr/pkg/include -a -d /usr/pkg/lib ; then
|
||||
CFLAGS="$CFLAGS -I/usr/pkg/include"
|
||||
LDFLAGS="$LDFLAGS -L/usr/pkg/lib"
|
||||
fi
|
||||
|
||||
LIBZEND_ENABLE_DEBUG
|
||||
LIBZEND_OTHER_CHECKS
|
||||
|
||||
ZEND_EXTRA_LIBS="$LIBS"
|
||||
LIBS=""
|
||||
AC_SUBST(ZEND_EXTRA_LIBS)
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 4
|
||||
# End:
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2010 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: |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
+141
-141
@@ -22,220 +22,220 @@ function simpleicall($n) {
|
||||
}
|
||||
|
||||
class Foo {
|
||||
static $a = 0;
|
||||
public $b = 0;
|
||||
const TEST = 0;
|
||||
static $a = 0;
|
||||
public $b = 0;
|
||||
const TEST = 0;
|
||||
|
||||
static function read_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = self::$a;
|
||||
}
|
||||
}
|
||||
static function read_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = self::$a;
|
||||
}
|
||||
}
|
||||
|
||||
static function write_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
self::$a = 0;
|
||||
}
|
||||
}
|
||||
static function write_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
self::$a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static function isset_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = isset(self::$a);
|
||||
}
|
||||
}
|
||||
static function isset_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = isset(self::$a);
|
||||
}
|
||||
}
|
||||
|
||||
static function empty_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = empty(self::$a);
|
||||
}
|
||||
}
|
||||
static function empty_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = empty(self::$a);
|
||||
}
|
||||
}
|
||||
|
||||
static function f() {
|
||||
}
|
||||
static function f() {
|
||||
}
|
||||
|
||||
static function call_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
self::f();
|
||||
}
|
||||
}
|
||||
static function call_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
self::f();
|
||||
}
|
||||
}
|
||||
|
||||
function read_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $this->b;
|
||||
}
|
||||
}
|
||||
function read_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $this->b;
|
||||
}
|
||||
}
|
||||
|
||||
function write_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b = 0;
|
||||
}
|
||||
}
|
||||
function write_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function assign_add_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b += 2;
|
||||
}
|
||||
}
|
||||
function assign_add_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b += 2;
|
||||
}
|
||||
}
|
||||
|
||||
function pre_inc_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
++$this->b;
|
||||
}
|
||||
}
|
||||
function pre_inc_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
++$this->b;
|
||||
}
|
||||
}
|
||||
|
||||
function pre_dec_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
--$this->b;
|
||||
}
|
||||
}
|
||||
function pre_dec_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
--$this->b;
|
||||
}
|
||||
}
|
||||
|
||||
function post_inc_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b++;
|
||||
}
|
||||
}
|
||||
function post_inc_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b++;
|
||||
}
|
||||
}
|
||||
|
||||
function post_dec_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b--;
|
||||
}
|
||||
}
|
||||
function post_dec_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->b--;
|
||||
}
|
||||
}
|
||||
|
||||
function isset_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = isset($this->b);
|
||||
}
|
||||
}
|
||||
function isset_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = isset($this->b);
|
||||
}
|
||||
}
|
||||
|
||||
function empty_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = empty($this->b);
|
||||
}
|
||||
}
|
||||
function empty_prop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = empty($this->b);
|
||||
}
|
||||
}
|
||||
|
||||
function g() {
|
||||
}
|
||||
function g() {
|
||||
}
|
||||
|
||||
function call($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->g();
|
||||
}
|
||||
}
|
||||
function call($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$this->g();
|
||||
}
|
||||
}
|
||||
|
||||
function read_const($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $this::TEST;
|
||||
}
|
||||
}
|
||||
function read_const($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $this::TEST;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function read_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = Foo::$a;
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = Foo::$a;
|
||||
}
|
||||
}
|
||||
|
||||
function write_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
Foo::$a = 0;
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
Foo::$a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function isset_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = isset(Foo::$a);
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = isset(Foo::$a);
|
||||
}
|
||||
}
|
||||
|
||||
function empty_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = empty(Foo::$a);
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = empty(Foo::$a);
|
||||
}
|
||||
}
|
||||
|
||||
function call_static($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
Foo::f();
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
Foo::f();
|
||||
}
|
||||
}
|
||||
|
||||
function create_object($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = new Foo();
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = new Foo();
|
||||
}
|
||||
}
|
||||
|
||||
define('TEST', null);
|
||||
|
||||
function read_const($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = TEST;
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = TEST;
|
||||
}
|
||||
}
|
||||
|
||||
function read_auto_global($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $_GET;
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $_GET;
|
||||
}
|
||||
}
|
||||
|
||||
$g_var = 0;
|
||||
|
||||
function read_global_var($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $GLOBALS['g_var'];
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $GLOBALS['g_var'];
|
||||
}
|
||||
}
|
||||
|
||||
function read_hash($n) {
|
||||
$hash = array('test' => 0);
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $hash['test'];
|
||||
}
|
||||
$hash = array('test' => 0);
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $hash['test'];
|
||||
}
|
||||
}
|
||||
|
||||
function read_str_offset($n) {
|
||||
$str = "test";
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $str[1];
|
||||
}
|
||||
$str = "test";
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $str[1];
|
||||
}
|
||||
}
|
||||
|
||||
function issetor($n) {
|
||||
$val = array(0,1,2,3,4,5,6,7,8,9);
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $val ?: null;
|
||||
}
|
||||
$val = array(0,1,2,3,4,5,6,7,8,9);
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $val ?: null;
|
||||
}
|
||||
}
|
||||
|
||||
function issetor2($n) {
|
||||
$f = false; $j = 0;
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $f ?: $j + 1;
|
||||
}
|
||||
$f = false; $j = 0;
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $f ?: $j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
function ternary($n) {
|
||||
$val = array(0,1,2,3,4,5,6,7,8,9);
|
||||
$f = false;
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $f ? null : $val;
|
||||
}
|
||||
$val = array(0,1,2,3,4,5,6,7,8,9);
|
||||
$f = false;
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $f ? null : $val;
|
||||
}
|
||||
}
|
||||
|
||||
function ternary2($n) {
|
||||
$f = false; $j = 0;
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $f ? $f : $j + 1;
|
||||
}
|
||||
$f = false; $j = 0;
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$x = $f ? $f : $j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****/
|
||||
|
||||
function empty_loop($n) {
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
}
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
}
|
||||
}
|
||||
|
||||
function gethrtime()
|
||||
|
||||
+16
-19
@@ -4,59 +4,56 @@ func_num_args() tests
|
||||
<?php
|
||||
|
||||
function test1() {
|
||||
var_dump(func_num_args());
|
||||
var_dump(func_num_args());
|
||||
}
|
||||
|
||||
function test2($a) {
|
||||
var_dump(func_num_args());
|
||||
var_dump(func_num_args());
|
||||
}
|
||||
|
||||
function test3($a, $b) {
|
||||
var_dump(func_num_args());
|
||||
var_dump(func_num_args());
|
||||
}
|
||||
|
||||
test1();
|
||||
test2(1);
|
||||
try {
|
||||
test2();
|
||||
test2();
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
test3(1,2);
|
||||
|
||||
call_user_func("test1");
|
||||
try {
|
||||
call_user_func("test3", 1);
|
||||
call_user_func("test3", 1);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
call_user_func("test3", 1, 2);
|
||||
|
||||
class test {
|
||||
static function test1($a) {
|
||||
var_dump(func_num_args());
|
||||
}
|
||||
static function test1($a) {
|
||||
var_dump(func_num_args());
|
||||
}
|
||||
}
|
||||
|
||||
test::test1(1);
|
||||
|
||||
try {
|
||||
func_num_args();
|
||||
} catch (Error $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
var_dump(func_num_args());
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(0)
|
||||
int(1)
|
||||
Exception: Too few arguments to function test2(), 0 passed in %s on line %d and exactly 1 expected
|
||||
Exception: Too few arguments to function test2(), 0 passed in %s001.php on line 18 and exactly 1 expected
|
||||
int(2)
|
||||
int(0)
|
||||
Exception: Too few arguments to function test3(), 1 passed in %s on line %d and exactly 2 expected
|
||||
Exception: Too few arguments to function test3(), 1 passed in %s001.php on line 27 and exactly 2 expected
|
||||
int(2)
|
||||
int(1)
|
||||
func_num_args() must be called from a function context
|
||||
|
||||
Warning: func_num_args(): Called from the global scope - no function context in %s on line %d
|
||||
int(-1)
|
||||
Done
|
||||
+56
-76
@@ -4,118 +4,98 @@ func_get_arg() tests
|
||||
<?php
|
||||
|
||||
function test1() {
|
||||
try {
|
||||
var_dump(func_get_arg(-10));
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(func_get_arg(0));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(func_get_arg(1));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(func_get_arg(-10));
|
||||
var_dump(func_get_arg(0));
|
||||
var_dump(func_get_arg(1));
|
||||
}
|
||||
|
||||
function test2($a) {
|
||||
try {
|
||||
var_dump(func_get_arg(0));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(func_get_arg(1));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(func_get_arg(0));
|
||||
var_dump(func_get_arg(1));
|
||||
}
|
||||
|
||||
function test3($a, $b) {
|
||||
try {
|
||||
var_dump(func_get_arg(0));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(func_get_arg(1));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(func_get_arg(2));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(func_get_arg(0));
|
||||
var_dump(func_get_arg(1));
|
||||
var_dump(func_get_arg(2));
|
||||
}
|
||||
|
||||
test1();
|
||||
test1(10);
|
||||
test2(1);
|
||||
try {
|
||||
test2();
|
||||
test2();
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
test3(1,2);
|
||||
|
||||
call_user_func("test1");
|
||||
try {
|
||||
call_user_func("test3", 1);
|
||||
call_user_func("test3", 1);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
call_user_func("test3", 1, 2);
|
||||
|
||||
class test {
|
||||
static function test1($a) {
|
||||
try {
|
||||
var_dump(func_get_arg(0));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(func_get_arg(1));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
}
|
||||
static function test1($a) {
|
||||
var_dump(func_get_arg(0));
|
||||
var_dump(func_get_arg(1));
|
||||
}
|
||||
}
|
||||
|
||||
test::test1(1);
|
||||
try {
|
||||
var_dump(func_get_arg(1));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(func_get_arg(1));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
func_get_arg(): Argument #1 ($position) must be greater than or equal to 0
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
func_get_arg(): Argument #1 ($position) must be greater than or equal to 0
|
||||
Warning: func_get_arg(): The argument number should be >= 0 in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): Argument 0 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): The argument number should be >= 0 in %s on line %d
|
||||
bool(false)
|
||||
int(10)
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
int(1)
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
Exception: Too few arguments to function test2(), 0 passed in %s002.php on line %d and exactly 1 expected
|
||||
int(1)
|
||||
int(2)
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
func_get_arg(): Argument #1 ($position) must be greater than or equal to 0
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
Exception: Too few arguments to function test3(), 1 passed in %s on line %d and exactly 2 expected
|
||||
|
||||
Warning: func_get_arg(): Argument 2 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): The argument number should be >= 0 in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): Argument 0 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
Exception: Too few arguments to function test3(), 1 passed in %s002.php on line %d and exactly 2 expected
|
||||
int(1)
|
||||
int(2)
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
|
||||
Warning: func_get_arg(): Argument 2 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
int(1)
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
func_get_arg() cannot be called from the global scope
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg(): Called from the global scope - no function context in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
+16
-17
@@ -4,49 +4,45 @@ func_get_args() tests
|
||||
<?php
|
||||
|
||||
function test1() {
|
||||
var_dump(func_get_args());
|
||||
var_dump(func_get_args());
|
||||
}
|
||||
|
||||
function test2($a) {
|
||||
var_dump(func_get_args());
|
||||
var_dump(func_get_args());
|
||||
}
|
||||
|
||||
function test3($a, $b) {
|
||||
var_dump(func_get_args());
|
||||
var_dump(func_get_args());
|
||||
}
|
||||
|
||||
test1();
|
||||
test1(10);
|
||||
test2(1);
|
||||
try {
|
||||
test2();
|
||||
test2();
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
test3(1,2);
|
||||
|
||||
call_user_func("test1");
|
||||
try {
|
||||
call_user_func("test3", 1);
|
||||
call_user_func("test3", 1);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
call_user_func("test3", 1, 2);
|
||||
|
||||
class test {
|
||||
static function test1($a) {
|
||||
var_dump(func_get_args());
|
||||
}
|
||||
static function test1($a) {
|
||||
var_dump(func_get_args());
|
||||
}
|
||||
}
|
||||
|
||||
test::test1(1);
|
||||
var_dump(func_get_args());
|
||||
|
||||
try {
|
||||
var_dump(func_get_args());
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(0) {
|
||||
@@ -79,4 +75,7 @@ array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
}
|
||||
func_get_args() cannot be called from the global scope
|
||||
|
||||
Warning: func_get_args(): Called from the global scope - no function context in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
+10
-7
@@ -3,20 +3,23 @@ strncmp() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(strncmp("", ""));
|
||||
var_dump(strncmp("", "", 100));
|
||||
try {
|
||||
var_dump(strncmp("aef", "dfsgbdf", -1));
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(strncmp("aef", "dfsgbdf", -1));
|
||||
var_dump(strncmp("fghjkl", "qwer", 0));
|
||||
var_dump(strncmp("qwerty", "qwerty123", 6));
|
||||
var_dump(strncmp("qwerty", "qwerty123", 7));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Warning: strncmp() expects exactly 3 parameters, 2 given in %s on line %d
|
||||
NULL
|
||||
int(0)
|
||||
strncmp(): Argument #3 ($length) must be greater than or equal to 0
|
||||
|
||||
Warning: Length must be greater than or equal to 0 in %s on line %d
|
||||
bool(false)
|
||||
int(0)
|
||||
int(0)
|
||||
int(-1)
|
||||
Done
|
||||
+4
-1
@@ -3,6 +3,7 @@ strcasecmp() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(strcasecmp(""));
|
||||
var_dump(strcasecmp("", ""));
|
||||
var_dump(strcasecmp("aef", "dfsgbdf"));
|
||||
var_dump(strcasecmp("qwe", "qwer"));
|
||||
@@ -13,7 +14,9 @@ var_dump(strcasecmp("01", "01"));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Warning: strcasecmp() expects exactly 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
int(0)
|
||||
int(-3)
|
||||
int(-1)
|
||||
|
||||
+10
-8
@@ -3,12 +3,8 @@ strncasecmp() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(strncasecmp("", "", -1));
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
|
||||
var_dump(strncasecmp(""));
|
||||
var_dump(strncasecmp("", "", -1));
|
||||
var_dump(strncasecmp("aef", "dfsgbdf", 0));
|
||||
var_dump(strncasecmp("aef", "dfsgbdf", 10));
|
||||
var_dump(strncasecmp("qwe", "qwer", 3));
|
||||
@@ -17,9 +13,14 @@ var_dump(strncasecmp("qwErtY", "qwer", 7));
|
||||
var_dump(strncasecmp("q123", "Q123", 3));
|
||||
var_dump(strncasecmp("01", "01", 1000));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
strncasecmp(): Argument #3 ($length) must be greater than or equal to 0
|
||||
--EXPECTF--
|
||||
Warning: strncasecmp() expects exactly 3 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Length must be greater than or equal to 0 in %s on line %d
|
||||
bool(false)
|
||||
int(0)
|
||||
int(-3)
|
||||
int(0)
|
||||
@@ -27,3 +28,4 @@ int(0)
|
||||
int(2)
|
||||
int(0)
|
||||
int(0)
|
||||
Done
|
||||
@@ -0,0 +1,65 @@
|
||||
--TEST--
|
||||
each() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(each());
|
||||
$var = 1;
|
||||
var_dump(each($var));
|
||||
$var = "string";
|
||||
var_dump(each($var));
|
||||
$var = array(1,2,3);
|
||||
var_dump(each($var));
|
||||
$var = array("a"=>1,"b"=>2,"c"=>3);
|
||||
var_dump(each($var));
|
||||
|
||||
$a = array(1);
|
||||
$a [] =&$a[0];
|
||||
|
||||
var_dump(each($a));
|
||||
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: each() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d
|
||||
|
||||
Warning: Variable passed to each() is not an array or object in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Variable passed to each() is not an array or object in %s on line %d
|
||||
NULL
|
||||
array(4) {
|
||||
[1]=>
|
||||
int(1)
|
||||
["value"]=>
|
||||
int(1)
|
||||
[0]=>
|
||||
int(0)
|
||||
["key"]=>
|
||||
int(0)
|
||||
}
|
||||
array(4) {
|
||||
[1]=>
|
||||
int(1)
|
||||
["value"]=>
|
||||
int(1)
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
["key"]=>
|
||||
string(1) "a"
|
||||
}
|
||||
array(4) {
|
||||
[1]=>
|
||||
int(1)
|
||||
["value"]=>
|
||||
int(1)
|
||||
[0]=>
|
||||
int(0)
|
||||
["key"]=>
|
||||
int(0)
|
||||
}
|
||||
Done
|
||||
+20
-16
@@ -3,25 +3,19 @@ define() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(define(array(1,2,3,4,5), 1));
|
||||
} catch (TypeError $e) {
|
||||
echo "TypeError: ", $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
var_dump(define());
|
||||
var_dump(define("TRUE"));
|
||||
var_dump(define("TRUE", 1));
|
||||
var_dump(define("TRUE", 1, array(1)));
|
||||
|
||||
var_dump(define(array(1,2,3,4,5), 1));
|
||||
var_dump(define(" ", 1));
|
||||
var_dump(define("[[[", 2));
|
||||
var_dump(define("test const", 3));
|
||||
var_dump(define("test const", 3));
|
||||
var_dump(define("test", array(1)));
|
||||
var_dump(define("test1", fopen(__FILE__, 'r')));
|
||||
|
||||
try {
|
||||
var_dump(define("test2", new stdclass));
|
||||
} catch (TypeError $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
|
||||
var_dump(constant(" "));
|
||||
var_dump(constant("[[["));
|
||||
@@ -30,19 +24,29 @@ var_dump(constant("test const"));
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
TypeError: define(): Argument #1 ($constant_name) must be of type string, array given
|
||||
Warning: define() expects at least 2 parameters, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Constant TRUE already defined in %s on line %d
|
||||
bool(false)
|
||||
Warning: define() expects at least 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
bool(true)
|
||||
|
||||
Warning: define() expects parameter 3 to be bool, array given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: define() expects parameter 1 to be string, array given in %s on line %d
|
||||
NULL
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Constant test const already defined in %s on line %d
|
||||
Notice: Constant test const already defined in %s on line %d
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
define(): Argument #2 ($value) cannot be an object, stdClass given
|
||||
|
||||
Warning: Constants may only evaluate to scalar values, arrays or resources in %s on line %d
|
||||
bool(false)
|
||||
int(1)
|
||||
int(2)
|
||||
int(3)
|
||||
|
||||
+24
-22
@@ -4,38 +4,29 @@ get_class() tests
|
||||
<?php
|
||||
|
||||
class foo {
|
||||
function bar () {
|
||||
var_dump(get_class());
|
||||
}
|
||||
function bar () {
|
||||
var_dump(get_class());
|
||||
}
|
||||
function testNull ()
|
||||
{
|
||||
try {
|
||||
var_dump(get_class(null));
|
||||
} catch (TypeError $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump(get_class(null));
|
||||
}
|
||||
}
|
||||
|
||||
class foo2 extends foo {
|
||||
}
|
||||
|
||||
foo::bar();
|
||||
foo2::bar();
|
||||
|
||||
$f1 = new foo;
|
||||
$f2 = new foo2;
|
||||
|
||||
$f1->bar();
|
||||
$f2->bar();
|
||||
|
||||
try {
|
||||
var_dump(get_class());
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
var_dump(get_class("qwerty"));
|
||||
} catch (TypeError $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump(get_class());
|
||||
var_dump(get_class("qwerty"));
|
||||
|
||||
var_dump(get_class($f1));
|
||||
var_dump(get_class($f2));
|
||||
@@ -44,12 +35,23 @@ $f1->testNull();
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Deprecated: Non-static method foo::bar() should not be called statically in %s on line %d
|
||||
string(3) "foo"
|
||||
|
||||
Deprecated: Non-static method foo::bar() should not be called statically in %s on line %d
|
||||
string(3) "foo"
|
||||
string(3) "foo"
|
||||
get_class() without arguments must be called from within a class
|
||||
get_class(): Argument #1 ($object) must be of type object, string given
|
||||
string(3) "foo"
|
||||
|
||||
Warning: get_class() called without object from outside a class in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: get_class() expects parameter 1 to be object, string given in %s on line %d
|
||||
bool(false)
|
||||
string(3) "foo"
|
||||
string(4) "foo2"
|
||||
get_class(): Argument #1 ($object) must be of type object, null given
|
||||
|
||||
Warning: get_class() expects parameter 1 to be object, null given in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
+17
-42
@@ -4,19 +4,19 @@ get_parent_class() tests
|
||||
<?php
|
||||
|
||||
interface i {
|
||||
function test();
|
||||
function test();
|
||||
}
|
||||
|
||||
class foo implements i {
|
||||
function test() {
|
||||
var_dump(get_parent_class());
|
||||
}
|
||||
function test() {
|
||||
var_dump(get_parent_class());
|
||||
}
|
||||
}
|
||||
|
||||
class bar extends foo {
|
||||
function test_bar() {
|
||||
var_dump(get_parent_class());
|
||||
}
|
||||
function test_bar() {
|
||||
var_dump(get_parent_class());
|
||||
}
|
||||
}
|
||||
|
||||
$bar = new bar;
|
||||
@@ -32,37 +32,12 @@ var_dump(get_parent_class("bar"));
|
||||
var_dump(get_parent_class("foo"));
|
||||
var_dump(get_parent_class("i"));
|
||||
|
||||
try {
|
||||
get_parent_class("");
|
||||
} catch (TypeError $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
get_parent_class("[[[[");
|
||||
} catch (TypeError $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
get_parent_class(" ");
|
||||
} catch (TypeError $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
|
||||
var_dump(get_parent_class(""));
|
||||
var_dump(get_parent_class("[[[["));
|
||||
var_dump(get_parent_class(" "));
|
||||
var_dump(get_parent_class(new stdclass));
|
||||
|
||||
try {
|
||||
get_parent_class(array());
|
||||
} catch (TypeError $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
get_parent_class(1);
|
||||
} catch (TypeError $exception) {
|
||||
echo $exception->getMessage() . "\n";
|
||||
}
|
||||
var_dump(get_parent_class(array()));
|
||||
var_dump(get_parent_class(1));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
@@ -75,10 +50,10 @@ bool(false)
|
||||
string(3) "foo"
|
||||
bool(false)
|
||||
bool(false)
|
||||
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
|
||||
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
|
||||
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
|
||||
bool(false)
|
||||
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given
|
||||
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, int given
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
Done
|
||||
+35
-45
@@ -4,25 +4,27 @@ property_exists() tests
|
||||
<?php
|
||||
|
||||
class foo {
|
||||
public $pp1 = 1;
|
||||
private $pp2 = 2;
|
||||
protected $pp3 = 3;
|
||||
public $pp1 = 1;
|
||||
private $pp2 = 2;
|
||||
protected $pp3 = 3;
|
||||
|
||||
function bar() {
|
||||
var_dump(property_exists("foo","pp1"));
|
||||
var_dump(property_exists("foo","pp2"));
|
||||
var_dump(property_exists("foo","pp3"));
|
||||
}
|
||||
function bar() {
|
||||
var_dump(property_exists("foo","pp1"));
|
||||
var_dump(property_exists("foo","pp2"));
|
||||
var_dump(property_exists("foo","pp3"));
|
||||
}
|
||||
}
|
||||
|
||||
class bar extends foo {
|
||||
function test() {
|
||||
var_dump(property_exists("foo","pp1"));
|
||||
var_dump(property_exists("foo","pp2"));
|
||||
var_dump(property_exists("foo","pp3"));
|
||||
}
|
||||
function test() {
|
||||
var_dump(property_exists("foo","pp1"));
|
||||
var_dump(property_exists("foo","pp2"));
|
||||
var_dump(property_exists("foo","pp3"));
|
||||
}
|
||||
}
|
||||
|
||||
var_dump(property_exists());
|
||||
var_dump(property_exists(""));
|
||||
var_dump(property_exists("foo","pp1"));
|
||||
var_dump(property_exists("foo","pp2"));
|
||||
var_dump(property_exists("foo","pp3"));
|
||||
@@ -39,40 +41,23 @@ var_dump(property_exists($foo,"pp2"));
|
||||
var_dump(property_exists($foo,"pp3"));
|
||||
var_dump(property_exists($foo,"nonexistent"));
|
||||
var_dump(property_exists($foo,""));
|
||||
|
||||
try {
|
||||
var_dump(property_exists(array(), "test"));
|
||||
} catch (\TypeError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(property_exists(1, "test"));
|
||||
} catch (\TypeError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(property_exists(3.14, "test"));
|
||||
} catch (\TypeError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(property_exists(true, "test"));
|
||||
} catch (\TypeError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(property_exists(null, "test"));
|
||||
} catch (\TypeError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(property_exists(array(),"test"));
|
||||
var_dump(property_exists(1,"test"));
|
||||
var_dump(property_exists(true,"test"));
|
||||
|
||||
$foo->bar();
|
||||
|
||||
$bar = new bar;
|
||||
$bar->test();
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Warning: property_exists() expects exactly 2 parameters, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: property_exists() expects exactly 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
@@ -86,14 +71,19 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
property_exists(): Argument #1 ($object_or_class) must be of type object|string, array given
|
||||
property_exists(): Argument #1 ($object_or_class) must be of type object|string, int given
|
||||
property_exists(): Argument #1 ($object_or_class) must be of type object|string, float given
|
||||
property_exists(): Argument #1 ($object_or_class) must be of type object|string, bool given
|
||||
property_exists(): Argument #1 ($object_or_class) must be of type object|string, null given
|
||||
|
||||
Warning: First parameter must either be an object or the name of an existing class in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: First parameter must either be an object or the name of an existing class in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: First parameter must either be an object or the name of an existing class in %s on line %d
|
||||
NULL
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
Done
|
||||
+8
-1
@@ -6,8 +6,10 @@ class_exists() tests
|
||||
class foo {
|
||||
}
|
||||
|
||||
var_dump(class_exists());
|
||||
var_dump(class_exists("qwerty"));
|
||||
var_dump(class_exists(""));
|
||||
var_dump(class_exists(array()));
|
||||
var_dump(class_exists("test", false));
|
||||
var_dump(class_exists("foo", false));
|
||||
var_dump(class_exists("foo"));
|
||||
@@ -16,9 +18,14 @@ var_dump(class_exists("stdClass"));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Warning: class_exists() expects at least 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
|
||||
Warning: class_exists() expects parameter 1 to be string, array given in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
+8
-1
@@ -6,8 +6,10 @@ interface_exists() tests
|
||||
interface foo {
|
||||
}
|
||||
|
||||
var_dump(interface_exists());
|
||||
var_dump(interface_exists("qwerty"));
|
||||
var_dump(interface_exists(""));
|
||||
var_dump(interface_exists(array()));
|
||||
var_dump(interface_exists("test", false));
|
||||
var_dump(interface_exists("foo", false));
|
||||
var_dump(interface_exists("foo"));
|
||||
@@ -16,9 +18,14 @@ var_dump(interface_exists("stdClass"));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Warning: interface_exists() expects at least 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
|
||||
Warning: interface_exists() expects parameter 1 to be string, array given in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
+13
-3
@@ -5,13 +5,17 @@ get_included_files() tests
|
||||
|
||||
var_dump(get_included_files());
|
||||
|
||||
include(__DIR__."/014.inc");
|
||||
include(dirname(__FILE__)."/014.inc");
|
||||
var_dump(get_included_files());
|
||||
|
||||
include_once(__DIR__."/014.inc");
|
||||
var_dump(get_included_files(1,1));
|
||||
|
||||
include_once(dirname(__FILE__)."/014.inc");
|
||||
var_dump(get_included_files());
|
||||
|
||||
include(__DIR__."/014.inc");
|
||||
var_dump(get_included_files(1));
|
||||
|
||||
include(dirname(__FILE__)."/014.inc");
|
||||
var_dump(get_included_files());
|
||||
|
||||
echo "Done\n";
|
||||
@@ -27,12 +31,18 @@ array(2) {
|
||||
[1]=>
|
||||
string(%d) "%s"
|
||||
}
|
||||
|
||||
Warning: get_included_files() expects exactly 0 parameters, 2 given in %s on line %d
|
||||
NULL
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(%d) "%s"
|
||||
[1]=>
|
||||
string(%d) "%s"
|
||||
}
|
||||
|
||||
Warning: get_included_files() expects exactly 0 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(%d) "%s"
|
||||
|
||||
+18
-14
@@ -3,31 +3,35 @@ trigger_error() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(trigger_error());
|
||||
var_dump(trigger_error("error"));
|
||||
|
||||
try {
|
||||
var_dump(trigger_error("error", -1));
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
try {
|
||||
var_dump(trigger_error("error", 0));
|
||||
} catch (\ValueError $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
|
||||
var_dump(trigger_error(array()));
|
||||
var_dump(trigger_error("error", -1));
|
||||
var_dump(trigger_error("error", 0));
|
||||
var_dump(trigger_error("error", E_USER_WARNING));
|
||||
var_dump(trigger_error("error", E_USER_DEPRECATED));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: trigger_error() expects at least 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Notice: error in %s on line %d
|
||||
bool(true)
|
||||
trigger_error(): Argument #2 ($error_level) must be one of E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, or E_USER_DEPRECATED
|
||||
trigger_error(): Argument #2 ($error_level) must be one of E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, or E_USER_DEPRECATED
|
||||
|
||||
Warning: trigger_error() expects parameter 1 to be string, array given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Invalid error type specified in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Invalid error type specified in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: error in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Deprecated: error in %s on line %d
|
||||
bool(true)
|
||||
Done
|
||||
@@ -3,6 +3,8 @@ builtin functions tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(get_resource_type());
|
||||
var_dump(get_resource_type(""));
|
||||
$fp = fopen(__FILE__, "r");
|
||||
var_dump(get_resource_type($fp));
|
||||
fclose($fp);
|
||||
@@ -12,9 +14,11 @@ var_dump(gettype(get_loaded_extensions()));
|
||||
var_dump(count(get_loaded_extensions()));
|
||||
var_dump(gettype(get_loaded_extensions(true)));
|
||||
var_dump(count(get_loaded_extensions(true)));
|
||||
var_dump(get_loaded_extensions(true, true));
|
||||
|
||||
define("USER_CONSTANT", "test");
|
||||
|
||||
var_dump(get_defined_constants(true, true));
|
||||
var_dump(gettype(get_defined_constants(true)));
|
||||
var_dump(gettype(get_defined_constants()));
|
||||
var_dump(count(get_defined_constants()));
|
||||
@@ -25,9 +29,11 @@ function test () {
|
||||
var_dump(gettype(get_defined_functions()));
|
||||
var_dump(count(get_defined_functions()));
|
||||
|
||||
var_dump(get_declared_interfaces(true));
|
||||
var_dump(gettype(get_declared_interfaces()));
|
||||
var_dump(count(get_declared_interfaces()));
|
||||
|
||||
var_dump(get_extension_funcs());
|
||||
var_dump(get_extension_funcs(true));
|
||||
var_dump(gettype(get_extension_funcs("standard")));
|
||||
var_dump(count(get_extension_funcs("standard")));
|
||||
@@ -38,19 +44,36 @@ var_dump(count(get_extension_funcs("zend")));
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: get_resource_type() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: get_resource_type() expects parameter 1 to be resource, string given in %s on line %d
|
||||
NULL
|
||||
string(6) "stream"
|
||||
string(7) "Unknown"
|
||||
string(5) "array"
|
||||
int(%d)
|
||||
string(5) "array"
|
||||
int(%d)
|
||||
|
||||
Warning: get_loaded_extensions() expects at most 1 parameter, 2 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: get_defined_constants() expects at most 1 parameter, 2 given in %s on line %d
|
||||
NULL
|
||||
string(5) "array"
|
||||
string(5) "array"
|
||||
int(%d)
|
||||
string(5) "array"
|
||||
int(%d)
|
||||
|
||||
Warning: get_declared_interfaces() expects exactly 0 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
string(5) "array"
|
||||
int(%d)
|
||||
|
||||
Warning: get_extension_funcs() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
string(5) "array"
|
||||
int(%d)
|
||||
|
||||
+17
-7
@@ -3,11 +3,11 @@ constant() tests
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(constant(""));
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump(constant());
|
||||
var_dump(constant("", ""));
|
||||
var_dump(constant(""));
|
||||
|
||||
var_dump(constant(array()));
|
||||
|
||||
define("TEST_CONST", 1);
|
||||
var_dump(constant("TEST_CONST"));
|
||||
@@ -17,8 +17,18 @@ var_dump(constant("TEST_CONST2"));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
Undefined constant ""
|
||||
--EXPECTF--
|
||||
Warning: constant() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: constant() expects exactly 1 parameter, 2 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: constant(): Couldn't find constant in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: constant() expects parameter 1 to be string, array given in %s on line %d
|
||||
NULL
|
||||
int(1)
|
||||
string(4) "test"
|
||||
Done
|
||||
+124
-112
@@ -2,6 +2,16 @@
|
||||
Test unset(), empty() and isset() functions
|
||||
--FILE--
|
||||
<?php
|
||||
/* Prototype: void unset ( mixed $var [, mixed $var [, mixed $...]] );
|
||||
Description: unset() destroys the specified variables
|
||||
|
||||
Prototype: bool empty( mixed $var );
|
||||
Description: Determine whether a variable is considered to be empty
|
||||
|
||||
Prototype: bool isset ( mixed $var [, mixed $var [, $...]] );
|
||||
Description: Returns TRUE if var exists; FALSE otherwise
|
||||
*/
|
||||
|
||||
echo "*** Testing unset(), empty() & isset() with scalar variables ***\n";
|
||||
|
||||
// testing scalar variables
|
||||
@@ -139,9 +149,9 @@ foreach ($array_variables as $array_var) {
|
||||
var_dump( empty($array_var) ); // expected: bool(true)
|
||||
}
|
||||
|
||||
echo "\n*** Testing unset(), empty() & isset() with resource variables ***\n";
|
||||
echo "\n*** Testing unset(), emtpy() & isset() with resource variables ***\n";
|
||||
$fp = fopen(__FILE__, "r");
|
||||
$dfp = opendir( __DIR__ );
|
||||
$dfp = opendir( dirname(__FILE__) );
|
||||
$resources = array (
|
||||
$fp,
|
||||
$dfp
|
||||
@@ -233,7 +243,7 @@ var_dump( empty($point1->x) ); // expected: bool(true)
|
||||
// unset all members and check
|
||||
unset($point1->y);
|
||||
unset($point1->lable);
|
||||
// dump the object to check that all variables are unset
|
||||
// dump the objec to check that all variables are unset
|
||||
var_dump($point1);
|
||||
var_dump( isset($point1) ); // expected: bool(ture)
|
||||
var_dump( empty($point1) ); // expected: bool(false)
|
||||
@@ -350,6 +360,7 @@ var_dump($global_var);
|
||||
//Note: No error conditions relating to passing arguments can be tested
|
||||
// because these are not functions but statements, it will result in syntax error.
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
*** Testing unset(), empty() & isset() with scalar variables ***
|
||||
-- Iteration 1 --
|
||||
@@ -357,7 +368,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -369,7 +380,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -381,7 +392,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -393,7 +404,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -405,7 +416,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -417,7 +428,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -429,7 +440,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -441,7 +452,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -453,7 +464,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -465,7 +476,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -477,7 +488,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -489,7 +500,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -501,7 +512,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -513,7 +524,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -525,7 +536,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -537,7 +548,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -549,7 +560,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -561,7 +572,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -573,7 +584,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -585,7 +596,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -597,7 +608,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -609,7 +620,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -621,7 +632,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -633,7 +644,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -645,7 +656,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -657,7 +668,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -669,7 +680,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $scalar_var in %s on line %d
|
||||
Notice: Undefined variable: scalar_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -686,7 +697,7 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -702,18 +713,18 @@ bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -729,18 +740,18 @@ bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -756,18 +767,18 @@ bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -783,18 +794,18 @@ bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -816,13 +827,13 @@ array(3) {
|
||||
int(4)
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(3) {
|
||||
[1]=>
|
||||
@@ -840,13 +851,13 @@ array(2) {
|
||||
int(4)
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(2) {
|
||||
[2]=>
|
||||
@@ -860,13 +871,13 @@ array(1) {
|
||||
int(4)
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(1) {
|
||||
[3]=>
|
||||
@@ -876,18 +887,18 @@ array(1) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -907,13 +918,13 @@ array(2) {
|
||||
float(5.6)
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(2) {
|
||||
[1]=>
|
||||
@@ -927,13 +938,13 @@ array(1) {
|
||||
float(5.6)
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(1) {
|
||||
[2]=>
|
||||
@@ -943,18 +954,18 @@ array(1) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -972,13 +983,13 @@ array(1) {
|
||||
string(3) "two"
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(1) {
|
||||
[2]=>
|
||||
@@ -988,18 +999,18 @@ array(1) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -1017,13 +1028,13 @@ array(1) {
|
||||
string(2) "30"
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(1) {
|
||||
["Age"]=>
|
||||
@@ -1033,18 +1044,18 @@ array(1) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
@@ -1068,13 +1079,13 @@ array(4) {
|
||||
string(0) ""
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(4) {
|
||||
[1]=>
|
||||
@@ -1096,13 +1107,13 @@ array(3) {
|
||||
string(0) ""
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(3) {
|
||||
["One"]=>
|
||||
@@ -1120,13 +1131,13 @@ array(2) {
|
||||
string(0) ""
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(2) {
|
||||
[2]=>
|
||||
@@ -1140,13 +1151,13 @@ array(1) {
|
||||
string(0) ""
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(1) {
|
||||
[""]=>
|
||||
@@ -1156,24 +1167,24 @@ array(1) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $key_val in %s on line %d
|
||||
Notice: Undefined variable: key_val in %s on line %d
|
||||
bool(true)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Undefined variable $array_var in %s on line %d
|
||||
Notice: Undefined variable: array_var in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(true)
|
||||
|
||||
*** Testing unset(), empty() & isset() with resource variables ***
|
||||
*** Testing unset(), emtpy() & isset() with resource variables ***
|
||||
-- Iteration 1 --
|
||||
resource(%d) of type (stream)
|
||||
bool(true)
|
||||
@@ -1185,7 +1196,7 @@ bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $resource in %s on line %d
|
||||
Notice: Undefined variable: resource in %s on line %d
|
||||
NULL
|
||||
-- Iteration 2 --
|
||||
resource(%d) of type (stream)
|
||||
@@ -1198,10 +1209,10 @@ bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $resource in %s on line %d
|
||||
Notice: Undefined variable: resource in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Undefined variable $resources in %s on line %d
|
||||
Notice: Undefined variable: resources in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(true)
|
||||
@@ -1218,16 +1229,16 @@ object(Point)#%d (3) {
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $lable in %s on line %d
|
||||
Notice: Undefined variable: lable in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $lable in %s on line %d
|
||||
Notice: Undefined variable: lable in %s on line %d
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $lable in %s on line %d
|
||||
Notice: Undefined variable: lable in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $lable in %s on line %d
|
||||
Notice: Undefined variable: lable in %s on line %d
|
||||
bool(true)
|
||||
object(Point)#%d (3) {
|
||||
["x"]=>
|
||||
@@ -1252,7 +1263,7 @@ bool(false)
|
||||
bool(false)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined variable $point1 in %s on line %d
|
||||
Notice: Undefined variable: point1 in %s on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(true)
|
||||
@@ -1282,7 +1293,7 @@ value of static_var before unset: 1
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $static_var in %s on line %d
|
||||
Notice: Undefined variable: static_var in %s on line %d
|
||||
value of static_var after unset:
|
||||
bool(false)
|
||||
bool(true)
|
||||
@@ -1291,7 +1302,7 @@ value of static_var before unset: 2
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $static_var in %s on line %d
|
||||
Notice: Undefined variable: static_var in %s on line %d
|
||||
value of static_var after unset:
|
||||
bool(false)
|
||||
bool(true)
|
||||
@@ -1300,7 +1311,7 @@ value of static_var before unset: 3
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
||||
Warning: Undefined variable $static_var in %s on line %d
|
||||
Notice: Undefined variable: static_var in %s on line %d
|
||||
value of static_var after unset:
|
||||
bool(false)
|
||||
bool(true)
|
||||
@@ -1319,3 +1330,4 @@ bool(false)
|
||||
bool(false)
|
||||
bool(true)
|
||||
int(10)
|
||||
===DONE===
|
||||
+20
-15
@@ -3,27 +3,32 @@ func_get_arg() invalid usage
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(func_get_arg(1));
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
var_dump(func_get_arg(1,2,3));
|
||||
var_dump(func_get_arg(1));
|
||||
var_dump(func_get_arg());
|
||||
|
||||
function bar() {
|
||||
var_dump(func_get_arg(1));
|
||||
var_dump(func_get_arg(1));
|
||||
}
|
||||
|
||||
function foo() {
|
||||
bar(func_get_arg(1));
|
||||
bar(func_get_arg(1));
|
||||
}
|
||||
|
||||
try {
|
||||
foo(1,2);
|
||||
} catch (\Error $e) {
|
||||
echo $e->getMessage() . \PHP_EOL;
|
||||
}
|
||||
foo(1,2);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
func_get_arg() cannot be called from the global scope
|
||||
func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function
|
||||
--EXPECTF--
|
||||
Warning: func_get_arg() expects exactly 1 parameter, 3 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: func_get_arg(): Called from the global scope - no function context in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: func_get_arg() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
+6
-7
@@ -1,25 +1,24 @@
|
||||
--TEST--
|
||||
Implementing abstracting methods and optional parameters
|
||||
Implementating abstracting methods and optional parameters
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
abstract class Base
|
||||
{
|
||||
abstract function someMethod($param);
|
||||
abstract function someMethod($param);
|
||||
}
|
||||
|
||||
class Ext extends Base
|
||||
{
|
||||
function someMethod($param = "default")
|
||||
{
|
||||
echo $param, "\n";
|
||||
}
|
||||
function someMethod($param = "default")
|
||||
{
|
||||
echo $param, "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$a = new Ext();
|
||||
$a->someMethod("foo");
|
||||
$a->someMethod();
|
||||
?>
|
||||
--EXPECT--
|
||||
foo
|
||||
default
|
||||
+8
-8
@@ -10,20 +10,20 @@ print "\n";
|
||||
|
||||
|
||||
class bar {
|
||||
public function a() {
|
||||
return "bar!";
|
||||
}
|
||||
public function a() {
|
||||
return "bar!";
|
||||
}
|
||||
}
|
||||
|
||||
class foo {
|
||||
public function test() {
|
||||
print "foo!\n";
|
||||
return new bar;
|
||||
}
|
||||
public function test() {
|
||||
print "foo!\n";
|
||||
return new bar;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
return new foo;
|
||||
return new foo;
|
||||
}
|
||||
|
||||
$a = 'test';
|
||||
|
||||
+13
-19
@@ -15,43 +15,37 @@ var_dump($a->$b->{$c[1]});
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Undefined variable $a in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Notice: Undefined variable: a in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Undefined variable $a in %s on line %d
|
||||
Notice: Undefined variable: %s in %s on line %d
|
||||
|
||||
Warning: Undefined variable $c in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Notice: Undefined variable: %s in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Undefined variable $a in %s on line %d
|
||||
Notice: Undefined variable: a in %s on line %d
|
||||
int(1)
|
||||
|
||||
Warning: Undefined variable $a in %s on line %d
|
||||
Notice: Undefined variable: %s in %s on line %d
|
||||
|
||||
Warning: Undefined variable $b in %s on line %d
|
||||
Notice: Undefined variable: %s in %s on line %d
|
||||
int(0)
|
||||
|
||||
Warning: Undefined variable $a in %s on line %d
|
||||
Notice: Undefined variable: a in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Undefined variable $b in %s on line %d
|
||||
Notice: Undefined variable: b in %s on line %d
|
||||
int(1)
|
||||
|
||||
Warning: Attempt to read property "1" on int in %s on line %d
|
||||
Notice: Trying to get property '1' of non-object in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Attempt to read property "1" on int in %s on line %d
|
||||
Notice: Trying to get property '1' of non-object in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: Undefined variable $c in %s on line %d
|
||||
Notice: Undefined variable: c in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Notice: Trying to get property '1' of non-object in %s on line %d
|
||||
|
||||
Warning: Attempt to read property "1" on int in %s on line %d
|
||||
|
||||
Warning: Attempt to read property "" on null in %s on line %d
|
||||
Notice: Trying to get property '' of non-object in %s on line %d
|
||||
NULL
|
||||
+3
-3
@@ -4,9 +4,9 @@ Testing dynamic calls
|
||||
<?php
|
||||
|
||||
class foo {
|
||||
static public function a() {
|
||||
print "ok\n";
|
||||
}
|
||||
static public function a() {
|
||||
print "ok\n";
|
||||
}
|
||||
}
|
||||
|
||||
$a = 'a';
|
||||
|
||||
+6
-9
@@ -4,8 +4,8 @@ Trying assign value to property when an object is not returned in a function
|
||||
<?php
|
||||
|
||||
class foo {
|
||||
public function a() {
|
||||
}
|
||||
public function a() {
|
||||
}
|
||||
}
|
||||
|
||||
$test = new foo;
|
||||
@@ -13,16 +13,13 @@ $test = new foo;
|
||||
$test->a()->a;
|
||||
print "ok\n";
|
||||
|
||||
try {
|
||||
$test->a()->a = 1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
$test->a()->a = 1;
|
||||
print "ok\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Attempt to read property "a" on null in %s on line %d
|
||||
Notice: Trying to get property 'a' of non-object in %s on line %d
|
||||
ok
|
||||
Attempt to assign property "a" on null
|
||||
|
||||
Warning: Creating default object from empty value in %s on line %d
|
||||
ok
|
||||
+2
-2
@@ -18,9 +18,9 @@ bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: Undefined array key 2 in %s on line %d
|
||||
Notice: Undefined offset: 2 in %s on line %d
|
||||
|
||||
Fatal error: Uncaught Error: Value of type null is not callable in %s:%d
|
||||
Fatal error: Uncaught Error: Function name must be a string in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
+17
-17
@@ -4,26 +4,26 @@ Overriding $this in catch and checking the object properties later.
|
||||
<?php
|
||||
|
||||
class foo {
|
||||
public $test = 0;
|
||||
private $test_2 = 1;
|
||||
protected $test_3 = 2;
|
||||
public $test = 0;
|
||||
private $test_2 = 1;
|
||||
protected $test_3 = 2;
|
||||
|
||||
public function bar() {
|
||||
try {
|
||||
throw new Exception('foo');
|
||||
} catch (Exception $this) {
|
||||
var_dump($this);
|
||||
}
|
||||
public function bar() {
|
||||
try {
|
||||
throw new Exception('foo');
|
||||
} catch (Exception $this) {
|
||||
var_dump($this);
|
||||
}
|
||||
|
||||
$this->baz();
|
||||
}
|
||||
$this->baz();
|
||||
}
|
||||
|
||||
public function baz() {
|
||||
foreach ($this as $k => $v) {
|
||||
printf("'%s' => '%s'\n", $k, $v);
|
||||
}
|
||||
print "ok\n";
|
||||
}
|
||||
public function baz() {
|
||||
foreach ($this as $k => $v) {
|
||||
printf("'%s' => '%s'\n", $k, $v);
|
||||
}
|
||||
print "ok\n";
|
||||
}
|
||||
}
|
||||
|
||||
$test = new foo;
|
||||
|
||||
+8
-44
@@ -9,58 +9,22 @@ echo $arr[1][2][3][4][5];
|
||||
|
||||
$arr[1][2][3][4][5]->foo;
|
||||
|
||||
try {
|
||||
$arr[1][2][3][4][5]->foo = 1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
$arr[1][2][3][4][5]->foo = 1;
|
||||
|
||||
$arr[][] = 2;
|
||||
|
||||
try {
|
||||
$arr[][]->bar = 2;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
$arr[][]->bar = 2;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Undefined variable $arr in %s on line %d
|
||||
Notice: Undefined variable: arr in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Notice: Undefined variable: arr in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Notice: Undefined variable: arr in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Notice: Trying to get property 'foo' of non-object in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
Warning: Creating default object from empty value in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Undefined variable $arr in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Undefined variable $arr in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Trying to access array offset on value of type null in %s on line %d
|
||||
|
||||
Warning: Attempt to read property "foo" on null in %s on line %d
|
||||
Attempt to assign property "foo" on null
|
||||
Attempt to assign property "bar" on null
|
||||
Warning: Creating default object from empty value in %s on line %d
|
||||
+15
-15
@@ -4,21 +4,21 @@ Testing multiples 'default:' in switch
|
||||
<?php
|
||||
|
||||
switch (1) {
|
||||
case 2:
|
||||
print 'foo';
|
||||
break;
|
||||
case 3:
|
||||
print 'bar';
|
||||
break;
|
||||
default:
|
||||
print 1;
|
||||
break;
|
||||
default:
|
||||
print 2;
|
||||
break;
|
||||
default:
|
||||
print 3;
|
||||
break;
|
||||
case 2:
|
||||
print 'foo';
|
||||
break;
|
||||
case 3:
|
||||
print 'bar';
|
||||
break;
|
||||
default:
|
||||
print 1;
|
||||
break;
|
||||
default:
|
||||
print 2;
|
||||
break;
|
||||
default:
|
||||
print 3;
|
||||
break;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
+6
-7
@@ -3,12 +3,11 @@ Trying to use lambda in array offset
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
$test[function(){}] = 1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
$test[function(){}] = 1;
|
||||
$a{function() { }} = 1;
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Illegal offset type
|
||||
--EXPECTF--
|
||||
Warning: Illegal offset type in %s on line %d
|
||||
|
||||
Warning: Illegal offset type in %s on line %d
|
||||
+1
-1
@@ -16,7 +16,7 @@ var_dump($x::$x);
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
|
||||
Fatal error: Uncaught Error: Access to undeclared static property Closure::$x in %s:%d
|
||||
Fatal error: Uncaught Error: Access to undeclared static property: Closure::$x in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
+5
-7
@@ -3,12 +3,10 @@ Trying to use lambda as array key
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(array(function() { } => 1));
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
var_dump(array(function() { } => 1));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Illegal offset type
|
||||
--EXPECTF--
|
||||
Warning: Illegal offset type in %s on line %d
|
||||
array(0) {
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
--TEST--
|
||||
Bug #67468 (Segfault in highlight_file()/highlight_string())
|
||||
--SKIPIF--
|
||||
<?php if(!function_exists("leak")) print "skip only for debug builds"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
highlight_string("<?php __CLASS__;", true);
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
--TEST--
|
||||
Test default value handling of ErrorException::__construct()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$e = new ErrorException();
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
$e = new ErrorException("Second", 0, E_ERROR, null);
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
$e = new ErrorException("Third", 0, E_ERROR, null, null);
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
$e = new ErrorException("Forth", 0, E_ERROR, null, 123);
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
$e = new ErrorException("Fifth", 0, E_ERROR, "abc.php");
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
$e = new ErrorException("Sixth", 0, E_ERROR, "abc.php", null);
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
$e = new ErrorException("Seventh", 0, E_ERROR, "abc.php", 123);
|
||||
var_dump($e->getMessage());
|
||||
var_dump($e->getFile());
|
||||
var_dump($e->getLine());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(0) ""
|
||||
string(%d) "%sErrorException_construct.php"
|
||||
int(3)
|
||||
string(6) "Second"
|
||||
string(%d) "%sErrorException_construct.php"
|
||||
int(8)
|
||||
string(5) "Third"
|
||||
string(%d) "%sErrorException_construct.php"
|
||||
int(13)
|
||||
string(5) "Forth"
|
||||
string(%d) "%sErrorException_construct.php"
|
||||
int(123)
|
||||
string(5) "Fifth"
|
||||
string(7) "abc.php"
|
||||
int(0)
|
||||
string(5) "Sixth"
|
||||
string(7) "abc.php"
|
||||
int(0)
|
||||
string(7) "Seventh"
|
||||
string(7) "abc.php"
|
||||
int(123)
|
||||
@@ -4,8 +4,8 @@ using multiple access modifiers (methods)
|
||||
<?php
|
||||
|
||||
class test {
|
||||
static public public static final public final function foo() {
|
||||
}
|
||||
static public public static final public final function foo() {
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
@@ -4,7 +4,7 @@ using multiple access modifiers (attributes)
|
||||
<?php
|
||||
|
||||
class test {
|
||||
static public public static final public final $var;
|
||||
static public public static final public final $var;
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
Loaded 100 of 18034 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user