Compare commits

..
22360 changed files with 1604220 additions and 2803783 deletions

No files matched your search

-60
View File
@@ -1,60 +0,0 @@
version: "{branch}.build.{build}"
image: Visual Studio 2019
branches:
except:
- PHP-5.6
- PHP-7.0
clone_depth: 64
skip_commits:
files:
- docs/*
- NEWS
- UPGRADING
- UPGRADING.INTERNALS
cache:
- c:\build-cache
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
# ext and env setup for tests
#MYSQL_TEST_PASSWD: Password12!
#MYSQL_TEST_USER: root
#PDO_MYSQL_TEST_DSN: "pgsql:host=127.0.0.1 port=5432 dbname=test user=root password=Password12!"
#PDO_MYSQL_TEST_USER: root
#PDO_MYSQL_TEST_PASS: Password12!
#PGSQL_TEST_CONNSTR: "host=127.0.0.1 dbname=test port=5432 user=postgres password=Password12!"
#PDO_PGSQL_TEST_DSN: "pgsql:host=127.0.0.1 port=5432 dbname=test user=postgres password=Password12!"
#build permutations
matrix:
- THREAD_SAFE: 0
OPCACHE: 0
PARALLEL: -j2
- THREAD_SAFE: 1
OPCACHE: 1
PARALLEL: -j2
INTRINSICS: AVX
services:
# the setup scripts have to be touched, once some other db version is used
- mysql
- postgresql101
- mssql2017
platform:
- x64
# - x86
build_script:
- appveyor\build.bat
test_script:
- appveyor\test.bat
-34
View File
@@ -1,34 +0,0 @@
# https://editorconfig.org/
root = true
[*]
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
charset = utf-8
tab_width = 4
[{*.{awk,bat,c,cpp,d,h,l,re,skl,w32,y},Makefile*}]
indent_size = 4
indent_style = tab
[*.{dtd,html,inc,php,phpt,rng,wsdl,xml,xsd,xsl}]
indent_size = 4
indent_style = space
[*.{ac,m4,sh,yml}]
indent_size = 2
indent_style = space
[*.md]
indent_style = space
max_line_length = 80
[COMMIT_EDITMSG]
indent_size = 4
indent_style = space
max_line_length = 80
[*.patch]
trim_trailing_whitespace = false
+393 -433
View File
File diff suppressed because it is too large. Load diff
-19
View File
@@ -1,19 +0,0 @@
# 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
-285
View File
@@ -1,285 +0,0 @@
# 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
*~
# 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
*.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`
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
# ------------------------------------------------------------------------------
config.h
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
php
# ------------------------------------------------------------------------------
# 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
# ------------------------------------------------------------------------------
# Generated by `/buildconf.bat`
/configure.bat
/configure.js
# Generated by `/configure.(bat|js)` (architecture dependent)
/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/**/*.diff
**/tests/**/*.out*
**/tests/**/*.php
**/tests/**/*.exp
**/tests/**/*.log
**/tests/**/*.sh
# Generated by some test cases
**/tests/**/*.db
# 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
-98
View File
@@ -1,98 +0,0 @@
git:
quiet: true
dist: bionic
language: c
os: linux
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
- libxpm-dev
- libxslt1-dev
- libzip-dev
services:
- mysql
- postgresql
notifications:
email:
on_failure: change
irc:
template:
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} - Change view : %{compare_url} - Build details : %{build_url}"
channels:
- "irc.efnet.org#php.pecl"
on_success: change
on_failure: always
cache:
apt: true
ccache: true
env:
global:
- MYSQL_TEST_HOST=127.0.0.1
- MYSQL_TEST_USER=travis
- PDO_MYSQL_TEST_DSN="mysql:host=127.0.0.1;dbname=test"
- 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
before_script:
- ccache --version
- ccache --zero-stats
- export USE_CCACHE=1
# Enable IPv6
- sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'
# Compile PHP
- travis_wait ./travis/compile.sh
# Setup Extensions
- ./travis/setup-mysql.sh
- ./travis/setup-pgsql.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");'
after_success:
- ccache --show-stats
+277
View File
@@ -0,0 +1,277 @@
========================
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 (yet) fully
follow it, but it's going in that general direction. Since we are now
well into the version 4 releases, 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 a 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 "<svn username here>_0". For example, #if FOO_0, where FOO is your
svn 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.
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:
'mcrypt_enc_self_test'
'mysql_list_fields'
Ok:
'mcrypt_module_get_algo_supported_key_sizes'
(could be 'mcrypt_mod_get_algo_sup_key_sizes'?)
'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. Classes should be given descriptive names. Avoid using abbreviations where
possible. Each word in the class name should start with a capital letter,
without underscore delimiters (CampelCaps starting with a capital letter).
The class name should be prefixed with the name of the 'parent set' (e.g.
the name of the extension)::
Good:
'Curl'
'FooBar'
Bad:
'foobar'
'foo_bar'
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 SVN comments.
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
/phpdoc/README for more information on documentation.
-320
View File
@@ -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.
-425
View File
@@ -1,425 +0,0 @@
# 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)
## Pull requests
PHP welcomes pull requests to [add tests](#writing-tests), fix bugs and to
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/).
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.
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).
## Filing bugs
Bugs can be filed on the [PHP bug tracker](https://bugs.php.net/). If this is
the first time you've filed a bug, we suggest reading the
[guide to reporting a bug](https://bugs.php.net/how-to-report.php).
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
[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
[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.
## Writing tests
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.
## Writing documentation
There are two ways to contribute to the PHP manual. You can edit the manual and
send patches anonymously via [the online editor](https://edit.php.net/), or you
can check the XML source out from Subversion and edit that and build it
[per the instructions on the documentation site](http://doc.php.net/tutorial/).
Patches created that way should be sent to the
[documentation mailing list](mailto:phpdoc@lists.php.net).
## Getting help
If you are having trouble contributing to PHP, or just want to talk to a human
about what you're working on, you can contact us via the
[internals mailing list](mailto:internals@lists.php.net), or the
[documentation mailing list](mailto:phpdoc@lists.php.net) for documentation
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!
+2
View File
@@ -0,0 +1,2 @@
For the list of people who've put work into PHP, please see
http://www.php.net/credits.php
+157791
View File
File diff suppressed because it is too large. Load diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+190 -166
View File
@@ -3,6 +3,7 @@
Maintenance legend
------------------
Supported: Someone is actually paid to look after this.
Maintained: Someone actually looks after it.
Odd Fixes: It has a maintainer but they don't have time to do
much other than throw the odd patch in. See below.
@@ -25,32 +26,56 @@ Status legend
== Server APIs ==
-------------------------------------------------------------------------------
EXTENSION: aolserver
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: apache
PRIMARY MAINTAINER: Rasmus Lerdorf <rasmus@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: apache_hooks
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: apache2filter
PRIMARY MAINTAINER: Aaron Bannert <aaron@php.net>
MAINTENANCE: Maintained
STATUS: Experimental
-------------------------------------------------------------------------------
EXTENSION: apache2handler
PRIMARY MAINTAINER: Aaron Bannert <aaron@php.net>, Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: caudium
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: cgi
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 Boerger <helly@php.net>, Edin Kadribasic <edink@php.net>
STATUS: Working
SINCE: 4.3.0
-------------------------------------------------------------------------------
EXTENSION: continuity
PRIMARY MAINTAINER: Alex Leigh <aleigh@php.net>
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: embed
PRIMARY MAINTAINER: Edin Kadribasic <edink@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: fpm
PRIMARY MAINTAINER: Jakub Zelenka <bukka@php.net>
MAINTENANCE: Maintained
EXTENSION: isapi
MAINTENANCE: Unknown
STATUS: Working
SINCE: 5.3.3
-------------------------------------------------------------------------------
EXTENSION: litespeed
PRIMARY MAINTAINER: George Wang <gwang@php.net>
@@ -58,10 +83,40 @@ MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: phpdbg
PRIMARY MAINTAINER: Joe Watkins <krakjoe@php.net>, Bob Weinand <bwoebi@php.net>
EXTENSION: milter
MAINTENANCE: Unknown
STATUS: 5.6
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: nsapi
PRIMARY MAINTAINER: Uwe Schindler <thetaphi@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: phttpd
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: pi3web
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: roxen
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: thttpd
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx>
MAINTENANCE: Odd fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: tux
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: webjames
PRIMARY MAINTAINER: Alex Waugh <alex@alexwaugh.com>
MAINTENANCE: Maintained
STATUS: Experimental
-------------------------------------------------------------------------------
@@ -69,66 +124,70 @@ STATUS: 5.6
-------------------------------------------------------------------------------
EXTENSION: dba
PRIMARY MAINTAINER: Marcus Börger <helly@php.net> (2002 - 2007)
Christopher Jones <sixd@php.net> (2008 - 2013)
Pierre-Alain Joye <pajoye@php.net> (2011 - 2011)
PRIMARY MAINTAINER: Marcus Börger <helly@php.net>,Christopher Jones <sixd@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
COMMENT: DBM abstraction for db2, db3, db4, dbm, ndbm, gdbm, ini
-------------------------------------------------------------------------------
EXTENSION: interbase
PRIMARY MAINTAINER: Ard Biesheuvel <ard@ard.nu>, Jouni Ahto <jouni.ahto@exdec.fi>
MAINTENANCE: Odd fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: mssql
PRIMARY MAINTAINER: Frank M. Kromann <fmk@swwwing.com>
MAINTENANCE: Maintained
STATUS: Working
COMMENT: Tested on phpts and isapi versions
-------------------------------------------------------------------------------
EXTENSION: mysql
PRIMARY MAINTAINER: Zak Greant <zak@mysql.com>, Georg Richter <georg@php.net>, Johannes Schlüter <johannes@php.net>, Ulf Wendel <uw@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: mysqli
PRIMARY MAINTAINER: Georg Richter <georg@php.net> (2003 - 2006)
Andrey Hristov <andrey@php.net> (2003 - 2016)
Johannes Schlüter <johannes@php.net> (2008 - 2014)
Ulf Wendel <uw@php.net> (2007 - 2013)
PRIMARY MAINTAINER: Georg Richter <georg@php.net>, Andrey Hristov <andrey@php.net>, Johannes Schlüter <johannes@php.net>, Ulf Wendel <uw@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: mysqlnd
PRIMARY MAINTAINER: Andrey Hristov <andrey@php.net> (2007 - 2017)
Johannes Schlüter <johannes@php.net> (2008 - 2018)
Ulf Wendel <uw@php.net> (2009 - 2011)
PRIMARY MAINTAINER: Georg Richter <georg@php.net>, Andrey Hristov <andrey@php.net>, Johannes Schlüter <johannes@php.net>, Ulf Wendel <uw@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: oci8
PRIMARY MAINTAINER: Christopher Jones <sixd@php.net> (2007 - 2017)
Antony Dovgal <tony2001@php.net> (2003 - 2009)
PRIMARY MAINTAINER: Christopher Jones <sixd@php.net>, Antony Dovgal <tony2001@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: odbc
PRIMARY MAINTAINER: Daniel R. Kalowsky <kalowsky@php.net> (2000 - 2004)
PRIMARY MAINTAINER: Daniel R. Kalowsky <kalowsky@php.net>
MAINTENANCE: Maintained
STATUS: Working
COMMENT: Working
COMMENT: Working
-------------------------------------------------------------------------------
EXTENSION: pdo
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net> (2004 - 2011)
Wez Furlong <wez@php.net> (2004 - 2006)
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_dblib
PRIMARY MAINTAINER: Adam Baratz <adambaratz@php.net> (2016 - 2017)
MAINTENANCE: Maintained
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_firebird
PRIMARY MAINTAINER: Lars Westermann <lwe@php.net> (2007 - 2007)
PRIMARY MAINTAINER: Lars Westermann <lwe@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_mysql
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net> (2004 - 2010)
Johannes Schlüter <johannes@php.net> (2008 - 2014)
Andrey Hristov <andrey@php.net> (2005 - 2015)
Ulf Wendel <uw@php.net> (2008 - 2012)
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net>, Johannes Schlüter <johannes@php.net>, Andrey Hristov <andrey@php.net>, Ulf Wendel <uw@php.net>
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
@@ -140,89 +199,102 @@ STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_oci
PRIMARY MAINTAINER: Christopher Jones <sixd@php.net> (2007 - 2017)
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_pgsql
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net> (2004 - 2011)
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_sqlite
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net> (2005 - 2011)
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pgsql
PRIMARY MAINTAINER: Marcus Börger <helly@php.net> (2002 - 2007)
Yasuo Ohgaki <yohgaki@php.net> (2001 - 2015)
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Yasuo Ohgaki <yohgaki@php.net>
MAINTENANCE: Maintained
STATUS: Working
COMMENT: Use PostgreSQL 7.0.x or later. PostgreSQL 6.5.3 or less have fatal bug.
-------------------------------------------------------------------------------
EXTENSION: sqlite
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Wez Furlong <wez@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0 (Since 4.3.2 in PECL)
COMMENT: Integrates SQLite 2 embeddable SQL database engine.
-------------------------------------------------------------------------------
EXTENSION: sqlite3
PRIMARY MAINTAINER: Scott MacVicar <scottmac@php.net> (2008 - 2011)
Christoph M. Becker <cmb@php.net> (2016 - 2020)
PRIMARY MAINTAINER: Scott MacVicar <scottmac@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
COMMENT: Integrates SQLite 3 embeddable SQL database engine.
-------------------------------------------------------------------------------
EXTENSION: sybase_ct
PRIMARY MAINTAINER: Timm Friebe <thekid@thekid.de>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
== XML extensions ==
-------------------------------------------------------------------------------
EXTENSION: dom
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net> (2003 - 2011)
Rob Richards <rrichards@php.net> (2003 - 2012)
Marcus Börger <helly@php.net> (2003 - 2006)
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net>, Rob Richards <rrichards@php.net>, Marcus Boerger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: simplexml
PRIMARY MAINTAINER: Marcus Börger <helly@php.net> (2003 - 2008)
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: soap
PRIMARY MAINTAINER: Dmitry Stogov <dmitry@php.net> (2004 - 2018)
PRIMARY MAINTAINER: Dmitry Stogov <dmitry@zend.com>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: wddx
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net>
MAINTENANCE: Orphaned
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: xml
PRIMARY MAINTAINER: Thies C. Arntzen <thies@thieso.net> (1999 - 2002)
Rob Richards <rrichards@php.net> (2003 - 2013)
PRIMARY MAINTAINER: Thies C. Arntzen <thies@thieso.net>, Rob Richards <rrichards@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: libxml
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net> (2003 - 2009)
Christian Stocker <chregu@php.net> (2004 - 2011)
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net>, Christian Stocker <chregu@php.net>
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: Dan Libby
MAINTENANCE: Orphaned
STATUS: Experimental
-------------------------------------------------------------------------------
EXTENSION: xmlwriter
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net> (2004 - 2010)
Pierre-Alain Joye <pajoye@php.net> (2005-2009)
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: xsl
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net> (2003 - 2011)
Rob Richards <rrichards@php.net> (2003 - 2010)
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net>, Rob Richards <rrichards@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
@@ -233,284 +305,236 @@ SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: bcmath
PRIMARY MAINTAINER: Andi Gutmans <andi@php.net> (2000 - 2004)
MAINTENANCE: Unknown
MAINTENANCE: Andi Gutmans <andi@zend.com>
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: bz2
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net> (2004 - 2004)
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
MAINTENANCE: Odd Fixes
STATUS: Working
SINCE: 4.0.3
-------------------------------------------------------------------------------
EXTENSION: calendar
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net> (2000 - 2004)
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
MAINTENANCE: Odd Fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: com_dotnet
PRIMARY MAINTAINER: Wez Furlong <wez@php.net> (2003 - 2005)
Christoph M. Becker <cmb@php.net> (2018 - 2020)
PRIMARY MAINTAINER: Wez Furlong <wez@php.net>
MAINTENANCE: Maintained
STATUS: Windows
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: ctype
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net> (2000 - 2004)
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: curl
PRIMARY MAINTAINER: Sterling Hughes <sterling@php.net> (2000 - 2004)
Ilia Alshanetsky <iliaa@php.net> (2002 - 2011)
Pierrick Charron <pierrick@php.net> (2010 - 2016)
PRIMARY MAINTAINER: Sterling Hughes <sterling@php.net>,Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.2
-------------------------------------------------------------------------------
EXTENSION: date
PRIMARY MAINTAINER: Derick Rethans <derick@php.net> (2005 - 2018)
PRIMARY MAINTAINER: Derick Rethans <derick@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: enchant
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: exif
PRIMARY MAINTAINER: Kalle Sommer Nielsen <kalle@php.net> (2010 - 2018)
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>
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)
PRIMARY MAINTAINER: Derick Rethans <derick@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: filter
PRIMARY MAINTAINER: Derick Rethans <derick@php.net> (2006 - 2006)
Pierre-Alain Joye <pajoye@php.net> (2006 - 2011)
Ilia Alshanetsky <iliaa@php.net> (2006 - 2011)
PRIMARY MAINTAINER: Derick Rethans <derick@php.net>, Pierre-Alain Joye <pajoye@php.net>, Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.2
-------------------------------------------------------------------------------
EXTENSION: ftp
PRIMARY MAINTAINER: Unknown
PRIMARY MAINTAINER: Stefan Esser <sesser@php.net>
MAINTENANCE: Odd fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: gd
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net> (2002 - 2016)
Christoph M. Becker <cmb@php.net> (2015 - 2020)
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: gettext
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: gmp
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net> (2000 - 2019)
Antony Dovgal <tony2001@php.net> (2005 - 2010)
Nikita Popov <nikic@php.net> (2013 - 2020)
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net>, Antony Dovgal <tony2001@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.4
-------------------------------------------------------------------------------
EXTENSION: hash
PRIMARY MAINTAINER: Sara Golemon <pollita@php.net> (2005 - 2017)
Mike Wallner <mike@php.net> (2005 - 2013)
Anatol Belski <ab@php.net> (2014 - 2018)
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.1.2
-------------------------------------------------------------------------------
EXTENSION: iconv
PRIMARY MAINTAINER: Moriyoshi Koizumi <moriyoshi@php.net> (2002 - 2010)
PRIMARY MAINTAINER: Moriyoshi Koizumi <moriyoshi@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: intl
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net> (2008 - 2019)
Anatol Belski <ab@php.net> (2017 - 2018)
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
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)
PRIMARY MAINTAINER: Chuck Hagenbuch <chuck@horde.org>, Ilia Alshanetsky <iliaa@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: json
PRIMARY MAINTAINER: Jakub Zelenka <bukka@php.net> (2014 - 2018)
MAINTENANCE: Maintained
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.2
-------------------------------------------------------------------------------
EXTENSION: ldap
PRIMARY MAINTAINER: Stig Venaas <venaas@php.net> (2000 - 2002)
Douglas Goldstein <cardoe@php.net> (2007 - 2007)
Pierre-Alain Joye <pajoye@php.net> (2008 - 2010)
Côme Bernigaud <mcmic@php.net> (2015 - 2017)
PRIMARY MAINTAINER: Stig Venaas <venaas@php.net>, Douglas Goldstein <cardoe@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: mbstring
PRIMARY MAINTAINER: Rui Hirokawa <hirokawa@php.net> (2001 - 2013)
Nikita Popov <nikic@php.net> (2017 - 2020)
PRIMARY MAINTAINER: Rui Hirokawa <hirokawa@php.net>
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)
EXTENSION: mcrypt
PRIMARY MAINTAINER: Derick Rethans <derick@derickrethans.nl>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.5.0
-------------------------------------------------------------------------------
EXTENSION: mhash
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx>, Scott MacVicar <scottmac@php.net>
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: mime_magic
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Deprecated
STATUS: Experimental
COMMENT: Use the fileinfo extension instead
-------------------------------------------------------------------------------
EXTENSION: ming
PRIMARY MAINTAINER: Frank M. Kromann
MAINTENANCE: Unknown
STATUS: Experimental
-------------------------------------------------------------------------------
EXTENSION: openssl
PRIMARY MAINTAINER: Wez Furlong <wez@php.net> (2001 - 2006)
Pierre-Alain Joye <pajoye@php.net> (2006 - 2011)
Jakub Zelenka <bukka@php.net> (2015 - 2019)
PRIMARY MAINTAINER: Wez Furlong <wez@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.4
-------------------------------------------------------------------------------
EXTENSION: pcntl
PRIMARY MAINTAINER: Arnaud Le Blanc <lbarnaud@php.net> (2008 - 2010)
PRIMARY MAINTAINER: Arnaud Le Blanc <lbarnaud@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: pcre
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net> (1999 - 2006)
Nuno Lopes <nlopess@php.net> (2006 - 2009)
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net>, Nuno Lopes <nlopess@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
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)
PRIMARY MAINTAINER: Greg Beaver <cellog@php.net>, Marcus Börger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: posix
PRIMARY MAINTAINER: Kristian Köhntopp <kris@koehntopp.de> (2000 - 2000)
PRIMARY MAINTAINER: Kristian Köhntopp <kris@koehntopp.de>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: pspell
PRIMARY MAINTAINER: Vlad Krupin <phpdevel@echospace.com> (2000 - 2004)
PRIMARY MAINTAINER: Vlad Krupin <phpdevel@echospace.com>
MAINTENANCE: Unknown
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>
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)
PRIMARY MAINTAINER: Marcus Börger <helly@php.net>, Johannes Schlüter <johannes@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: session
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx> (1999 - 2004)
Ilia Alshanetsky <iliaa@php.net> (2002 - 2012)
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx>, Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: shmop
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net> (2002 - 2008)
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.3
-------------------------------------------------------------------------------
EXTENSION: snmp
PRIMARY MAINTAINER: Boris Lytochkin <lytboris@php.net> (2011 - 2013)
Rasmus Lerdorf <rasmus@php.net> (1999 - 2002)
Pierre-Alain Joye <pajoye@php.net> (2010 - 2011)
MAINTENANCE: Maintained
PRIMARY MAINTAINER: Rasmus Lerdorf <rasmus@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Odd Fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: sockets
PRIMARY MAINTAINER: Chris Vandomelen <chrisv@b0rked.dhs.org> (2000 - 2000)
PRIMARY MAINTAINER: Chris Vandomelen <chrisv@b0rked.dhs.org>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.2
-------------------------------------------------------------------------------
EXTENSION: sodium
PRIMARY MAINTAINER: Frank Denis <jedisct1@php.net> (2017 - 2017)
MAINTENANCE: Maintained
STATUS: Working
SINCE: 7.2.0
-------------------------------------------------------------------------------
EXTENSION: spl
PRIMARY MAINTAINER: Marcus Börger <helly@php.net> (2003 - 2009)
Etienne Kneuss <colder@php.net> (2008 - 2014)
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Etienne Kneuss <colder@php.net>
MAINTENANCE: Maintained
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
-------------------------------------------------------------------------------
EXTENSION: tidy
PRIMARY MAINTAINER: John Coggeshall <john@php.net> (2003 - 2006)
Ilia Alshanetsky <iliaa@php.net> (2003 - 2009)
Nuno Lopes <nlopess@php.net> (2006 - 2012)
PRIMARY MAINTAINER: John Coggeshall <john@php.net>, Ilia Alshanetsky <iliaa@php.net>, Nuno Lopes <nlopess@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: tokenizer
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net> (2002 - 2002)
Nikita Popov <nikic@php.net> (2013 - 2020)
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: unicode
MAINTENANCE: Andrei Zmievski <andrei@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: zip
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net> (2006 - 2011)
Remi Collet <remi@php.net> (2013-2020)
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: zlib
PRIMARY MAINTAINER: Stefan Roehrich <sr@linux.de> (1999 - 2003)
PRIMARY MAINTAINER: Stefan Roehrich <sr@linux.de>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
+1538
View File
File diff suppressed because it is too large. Load diff
+14 -14
View File
@@ -1,7 +1,7 @@
--------------------------------------------------------------------
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2021 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Copyright (c) 1999 - 2009 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
@@ -9,22 +9,22 @@ 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 name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
@@ -41,27 +41,27 @@ are met:
"This product includes PHP software, freely available from
<http://www.php.net/software/>".
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
DEVELOPMENT TEAM OR ITS CONTRIBUTORS 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.
--------------------------------------------------------------------
--------------------------------------------------------------------
This software consists of voluntary contributions made by many
individuals on behalf of the PHP Group.
The PHP Group can be contacted via Email at group@php.net.
For more information on the PHP Group and the PHP project,
For more information on the PHP Group and the PHP project,
please see <http://www.php.net>.
PHP includes the Zend Engine, freely available at
+23
View File
@@ -0,0 +1,23 @@
#
# 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) --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) --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
$(builddir)/zend_indent.lo $(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(srcdir)/zend_language_parser.h
+79
View File
@@ -0,0 +1,79 @@
#
# LCOV
#
lcov: lcov-html
lcov-test: all
@echo "Running test suite"
@find . -name \*.gcda -o -name \*.da -o -name \*.bbg? | xargs rm -f
-@if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \
NO_INTERACTION=1 \
TEST_PHP_EXECUTABLE=$(PHP_EXECUTABLE) \
TEST_PHP_SRCDIR=$(top_srcdir) \
CC="$(CC)" \
$(PHP_EXECUTABLE) -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' $(top_srcdir)/run-tests.php -d 'extension_dir=modules/' -d `( . $(PHP_MODULES) ; echo extension=$$dlname)` tests/; \
elif test ! -z "$(SAPI_CLI_PATH)" && test -x "$(SAPI_CLI_PATH)"; then \
NO_INTERACTION=1 \
TEST_PHP_EXECUTABLE=$(top_builddir)/$(SAPI_CLI_PATH) \
TEST_PHP_SRCDIR=$(top_srcdir) \
CC="$(CC)" \
$(top_builddir)/$(SAPI_CLI_PATH) -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' $(top_srcdir)/run-tests.php $(TESTS); \
else \
echo "ERROR: Cannot run tests without CLI sapi."; \
fi
php_lcov.info: lcov-test
@echo "Generating data for $@"
@rm -rf lcov_data/
@$(mkinstalldirs) lcov_data/
@echo
-@find . -name \*.gcda -o -name \*.gcno -o -name \*.da -o -name \*.h | sed -e 's/^\.\///' | sed -e 's/\.gcda//g' -e 's/\.gcno//g' -e 's/\.da//g' | uniq | while read x; 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; \
test -f "$$x.gcno" && cp $$x.gcno lcov_data/$$y.gcno ; \
test -f "$$x.gcda" && cp $$x.gcda lcov_data/$$y.gcda ; \
test -f "$$x.da" && cp $$x.da lcov_data/$$y.da ; \
test -f "$$x.bb" && cp $$x.bb lcov_data/$$y.bb ; \
test -f "$$x.bbg" && cp $$x.bbg lcov_data/$$y.bbg ; \
done
for dir in ext/bcmath/libbcmath ext/fileinfo/libmagic ext/gd/libgd ext/mbstring/libmbfl ext/mbstring/oniguruma ext/pcre/pcrelib ext/pdo_sqlite/libsqlite ext/sqlite/libsqlite ext/sqlite3/libsqlite ext/xmlrpc/libxmlrpc ext/zip/lib; do \
test -d lcov_data/$$dir && rm -rf lcov_data/$$dir ; \
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/
+118
View File
@@ -0,0 +1,118 @@
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)
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-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 = '^(define_syslog_variables|register_(globals|long_arrays)?|safe_mode|safe_mode_(gid|include_dir|exec_dir|allowed_env_vars|protected_env_vars)?|highlight_bg|enable_dl|detect_unicode|allow_call_time_pass_reference|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); \
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) $(OVERALL_TARGET) modules/* libs/*
distclean: clean
rm -f Makefile config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h stamp-h sapi/apache/libphp$(PHP_MAJOR_VERSION).module buildmk.stamp
$(EGREP) define'.*include/php' $(top_srcdir)/configure | $(SED) 's/.*>//'|xargs rm -f
.PHONY: all clean install distclean test
.NOEXPORT:
+48 -769
View File
@@ -1,771 +1,50 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
03 Jun 2021, PHP 8.0.7
- Core:
. Fixed bug #80960 (opendir() warning wrong info when failed on Windows).
(cmb)
. Fixed bug #67792 (HTTP Authorization schemes are treated as case-sensitive).
(cmb)
. Fixed bug #80972 (Memory exhaustion on invalid string offset). (girgias)
- FPM:
. Fixed bug #65800 (Events port mechanism). (psumbera)
- FTP:
. Fixed bug #80901 (Info leak in ftp extension). (cmb)
. Fixed bug #79100 (Wrong FTP error messages). (cmb)
- GD:
. Fixed bug #81032 (GD install is affected by external libgd installation).
(Flavio Heleno, cmb)
- Intl:
. Fixed bug #81019 (Unable to clone NumberFormatter after failed parse()).
(Nikita)
- MBString:
. Fixed bug #81011 (mb_convert_encoding removes references from arrays). (cmb)
- ODBC:
. Fixed bug #80460 (ODBC doesn't account for SQL_NO_TOTAL indicator). (cmb)
- Opcache:
. Fixed bug #81007 (JIT "not supported" on 32-bit x86 -- build problem?).
(Nikita)
. Fixed bug #81015 (Opcache optimization assumes wrong part of ternary
operator in if-condition). (Nikita)
. Fixed bug #81046 (Literal compaction merges non-equal related literals).
(Nikita)
- PDO_MySQL:
. Fixed bug #81037 (PDO discards error message text from prepared
statement). (Kamil Tekiela)
- PDO_ODBC:
. Fixed bug #44643 (bound parameters ignore explicit type definitions). (cmb)
- pgsql:
. Fixed php_pgsql_fd_cast() wrt. php_stream_can_cast(). (cmb)
- SPL:
. Fixed bug #80933 (SplFileObject::DROP_NEW_LINE is broken for NUL and CR).
(cmb, Nikita)
- XMLReader:
. Fixed bug #73246 (XMLReader: encoding length not checked). (cmb)
- Zip:
. Fixed bug #80863 (ZipArchive::extractTo() ignores references). (cmb)
06 May 2021, PHP 8.0.6
- PDO_pgsql:
. Revert "Fixed bug #80892 (PDO::PARAM_INT is treated the same as PDO::PARAM_STR)"
from PHP 8.0.5.
29 Apr 2021, PHP 8.0.5
- Core:
. Changed PowerPC CPU registers used by Zend VM to work around GCC bug.
Old registers (r28/r29) might be clobbered by _restgpr routine used for
return from C function compiled with -Os. (Dmitry)
- DOM:
. Fixed bug #66783 (UAF when appending DOMDocument to element). (cmb)
- FFI:
. Fixed bug #80847 (CData structs with fields of type struct can't be passed
as C function argument). (Nickolas Daniel da Silva, Dmitry)
- FPM:
. Fixed bug #80024 (Duplication of info about inherited socket after pool
removing). (Jakub Zelenka)
- FTP:
. Fixed bug #80880 (SSL_read on shutdown, ftp/proc_open). (cmb, Jakub
Zelenka)
- Imap:
. Fixed bug #80710 (imap_mail_compose() header injection). (cmb, Stas)
- LibXML:
. Fixed bug #73533 (Invalid memory access in php_libxml_xmlCheckUTF8). (cmb)
- Opcache:
. Fixed bug #80839 (PHP problem with JIT). (Dmitry)
. Fixed bug #80861 (erronous array key overflow in 2D array with JIT).
(Dmitry)
- Pcntl:
. Fixed bug #79812 (Potential integer overflow in pcntl_exec()). (cmb)
- PDO_ODBC:
. Fixed bug #80783 (PDO ODBC truncates BLOB records at every 256th byte).
(cmb)
- PDO_pgsql:
. Fixed bug #80892 (PDO::PARAM_INT is treated the same as PDO::PARAM_STR).
(Matteo)
- Session:
. Fixed bug #80889 (Cannot set save handler when save_handler is invalid).
(cmb)
- SOAP:
. Fixed bug #69668 (SOAP special XML characters in namespace URIs not
encoded). (cmb)
- Standard:
. Fixed bug #80915 (Taking a reference to $_SERVER hides its values from
phpinfo()). (Rowan Tommins)
. Fixed bug #80914 ('getdir' accidentally defined as an alias of 'dir').
(Rowan Tommins)
01 Apr 2021, PHP 8.0.4
- Core:
. Fixed bug #75776 (Flushing streams with compression filter is broken). (cmb)
. Fixed bug #80811 (Function exec without $output but with $restult_code
parameter crashes). (Nikita)
. Fixed bug #80814 (threaded mod_php won't load on FreeBSD: No space
available for static Thread Local Storage). (Dmitry)
- Dba:
. Fixed bug #80817 (dba_popen() may cause segfault during RSHUTDOWN). (cmb)
- IMAP:
. Fixed bug #80800 (imap_open() fails when the flags parameter includes
CL_EXPUNGE). (girgias)
- Intl:
. Fixed bug #80763 (msgfmt_format() does not accept DateTime references).
(cmb)
- Libxml:
. Fixed bug #51903 (simplexml_load_file() doesn't use HTTP headers). (cmb)
- MySQLnd:
. Fixed bug #80837 (Calling stmt_store_result after fetch doesn't throw an
error). (Kamil Tekiela)
- Opcache:
. Fixed bug #80786 (PHP crash using JIT). (Nikita)
. Fixed bug #80782 (DASM_S_RANGE_VREG on PHP_INT_MIN-1). (Dmitry)
- PCRE:
. Fixed bug #80866 (preg_split ignores limit flag when pattern with \K has
0-width fullstring match). (Kamil Tekiela)
- Session:
. Fixed bug #80774 (session_name() problem with backslash). (cmb)
- Standard:
. Fixed bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI). (cmb)
. Fixed bug #78719 (http wrapper silently ignores long Location headers).
(cmb)
. Fixed bug #80838 (HTTP wrapper waits for HTTP 1 response after HTTP 101).
(manuelm)
- Zip:
. Fixed bug #80825 (ZipArchive::isCompressionMethodSupported does not exist).
(cmb)
18 Feb 2021, PHP 8.0.3
- Core:
. Fixed #80706 (mail(): Headers after Bcc headers may be ignored). (cmb)
- DOM:
. Fixed bug #80600 (DOMChildNode::remove() doesn't work on CharacterData
nodes). (beberlei)
- Gettext:
. Fixed bug #53251 (bindtextdomain with null dir doesn't return old value).
(cmb)
- MySQLnd:
. Fixed bug #78680 (mysqlnd's mysql_clear_password does not transmit
null-terminated password). (Daniel Black)
. Fixed bug #80713 (SegFault when disabling ATTR_EMULATE_PREPARES and
MySQL 8.0). (Nikita)
- MySQLi:
. Fixed bug #74779 (x() and y() truncating floats to integers). (cmb)
- Opcache:
. Fixed bug #80634 (write_property handler of internal classes is skipped on
preloaded JITted code). (Dmitry)
. Fixed bug #80682 (opcache doesn't honour pcre.jit option). (Remi)
. Fixed bug #80742 (Opcache JIT makes some boolean logic unexpectedly be
true). (Dmitry)
. Fixed bug #80745 (JIT produces Assert failure and UNKNOWN:0 var_dumps in
code involving bitshifts). (Dmitry)
- OpenSSL:
. Fixed bug #80747 (Providing RSA key size < 512 generates key that crash
PHP). (Nikita)
- Phar:
. Fixed bug #75850 (Unclear error message wrt. __halt_compiler() w/o
semicolon) (cmb)
. Fixed bug #70091 (Phar does not mark UTF-8 filenames in ZIP archives). (cmb)
. Fixed bug #53467 (Phar cannot compress large archives). (cmb, lserni)
- Socket:
. Fixed bug #80723 (Different sockets compare as equal (regression in 8.0)).
(Nikita)
- SPL:
. Fixed bug#80719 (Iterating after failed ArrayObject::setIteratorClass()
causes Segmentation fault). (Nikita)
- Standard:
. Fixed bug #80654 (file_get_contents() maxlen fails above (2**31)-1 bytes).
(cmb)
. Fixed bug #80718 (ext/standard/dl.c fallback code path with syntax error).
(Nikita)
21 Jan 2021, PHP 8.0.2
- Core:
. Fixed bug #80523 (bogus parse error on >4GB source code). (Nikita)
. Fixed bug #80384 (filter buffers entire read until file closed). (Adam
Seitz, cmb)
. Fixed bug #80596 (Invalid union type TypeError in anonymous classes).
(Daniil Gentili)
. Fixed bug #80617 (GCC throws warning about type narrowing in
ZEND_TYPE_INIT_CODE). (Nikita)
- BCMath:
. Fixed bug #80545 (bcadd('a', 'a') doesn't throw an exception).
(Jens de Nies)
- Curl:
. Fixed bug #80595 (Resetting POSTFIELDS to empty array breaks request). (cmb)
- Date:
. Fixed bug #80376 (last day of the month causes runway cpu usage). (Derick)
- DOM:
. Fixed bug #80537 (Wrong parameter type in DOMElement::removeAttributeNode
stub). (Nikita)
- Filter:
. Fixed bug #80584 (0x and 0X are considered valid hex numbers by
filter_var()). (girgias)
- GMP:
. Fixed bug #80560 (Strings containing only a base prefix return 0 object).
(girgias)
- Intl:
. Fixed bug #80644 (Missing resource causes subsequent get() calls to fail).
(Nikita)
- MySQLi:
. Fixed bug #67983 (mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to
interpret bit columns). (Nikita)
. Fixed bug #64638 (Fetching resultsets from stored procedure with cursor
fails). (Nikita)
. Fixed bug #72862 (segfault using prepared statements on stored procedures
that use a cursor). (Nikita)
. Fixed bug #77935 (Crash in mysqlnd_fetch_stmt_row_cursor when calling an SP
with a cursor). (Nikita)
- ODBC:
. Fixed bug #80592 (all floats are the same in ODBC parameters). (cmb)
- Opcache:
. Fixed bug #80422 (php_opcache.dll crashes when using Apache 2.4 with JIT).
(Dmitry)
- PDO_Firebird:
. Fixed bug #80521 (Parameters with underscores no longer recognized). (cmb,
Simonov Denis)
- Phar:
. Fixed bug #76929 (zip-based phar does not respect phar.require_hash).
(david at bamsoftware, cmb)
. Fixed bug #77565 (Incorrect locator detection in ZIP-based phars). (cmb)
. Fixed bug #69279 (Compressed ZIP Phar extractTo() creates garbage files).
(cmb)
- Phpdbg:
. Reverted fix for bug #76813 (Access violation near NULL on source operand).
(cmb)
07 Jan 2021, PHP 8.0.1
- Core:
. Fixed bug #80345 (PHPIZE configuration has outdated PHP_RELEASE_VERSION).
(cmb)
. Fixed bug #72964 (White space not unfolded for CC/Bcc headers). (cmb)
. Fixed bug #80391 (Iterable not covariant to mixed). (Nikita)
. Fixed bug #80393 (Build of PHP extension fails due to configuration gap
with libtool). (kir dot morozov at gmail dot com)
. Fixed bug #77069 (stream filter loses final block of data). (cmb)
- Fileinfo:
. Fixed bug #77961 (finfo_open crafted magic parsing SIGABRT). (cmb)
- FPM:
. Fixed bug #69625 (FPM returns 200 status on request without
SCRIPT_FILENAME env). (Jakub Zelenka)
- IMAP
. Fixed bug #80438 (imap_msgno() incorrectly warns and return false on valid UIDs in PHP 8.0.0). (girgias)
. Fix a regression with valid UIDs in imap_savebody() (girgias)
. Make warnings for invalid message numbers/UIDs between functions consistent (girgias)
- Intl:
. Fixed bug #80425 (MessageFormatAdapter::getArgTypeList redefined). (Nikita)
- OCI8
. Create Windows DLLs for Oracle Client 19c. (cmb)
- Opcache:
. Fixed bug #80404 (Incorrect range inference result when division results
in float). (Nikita)
. Fixed bug #80377 (Opcache misses executor_globals). (Nikita)
. Fixed bug #80433 (Unable to disable the use of the AVX command when using
JIT). (Nikita)
. Fixed bug #80447 (Strange out of memory error when running with JIT).
(Dmitry)
. Fixed bug #80480 (Segmentation fault with JIT enabled). (Dmitry)
. Fixed bug #80506 (Immediate SIGSEGV upon ini_set("opcache.jit_debug", 1)).
(Dmitry)
- OpenSSL:
. Fixed bug #80368 (OpenSSL extension fails to build against LibreSSL due to
lack of OCB support). (Nikita)
- PDO MySQL:
. Fixed bug #80458 (PDOStatement::fetchAll() throws for upsert queries).
(Kamil Tekiela)
. Fixed bug #63185 (nextRowset() ignores MySQL errors with native prepared
statements). (Nikita)
. Fixed bug #78152 (PDO::exec() - Bad error handling with multiple commands).
(Nikita)
. Fixed bug #66878 (Multiple rowsets not returned unless PDO statement object
is unset()). (Nikita)
. Fixed bug #70066 (Unexpected "Cannot execute queries while other unbuffered
queries"). (Nikita)
. Fixed bug #71145 (Multiple statements in init command triggers unbuffered
query error). (Nikita)
. Fixed bug #76815 (PDOStatement cannot be GCed/closeCursor-ed when a
PROCEDURE resultset SIGNAL). (Nikita)
. Fixed bug #79872 (Can't execute query with pending result sets). (Nikita)
. Fixed bug #79131 (PDO does not throw an exception when parameter values are
missing). (Nikita)
. Fixed bug #72368 (PdoStatement->execute() fails but does not throw an
exception). (Nikita)
. Fixed bug #62889 (LOAD DATA INFILE broken). (Nikita)
. Fixed bug #67004 (Executing PDOStatement::fetch() more than once prevents
releasing resultset). (Nikita)
. Fixed bug #79132 (PDO re-uses parameter values from earlier calls to
execute()). (Nikita)
- Phar:
. Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)
. Fixed bug #75102 (`PharData` says invalid checksum for valid tar). (cmb)
. Fixed bug #77322 (PharData::addEmptyDir('/') Possible integer overflow).
(cmb)
- Phpdbg:
. Fixed bug #76813 (Access violation near NULL on source operand). (cmb)
- SPL:
. Fixed #62004 (SplFileObject: fgets after seek returns wrong line). (cmb)
- Standard:
. Fixed bug #77423 (FILTER_VALIDATE_URL accepts URLs with invalid userinfo).
(CVE-2020-7071) (cmb)
. Fixed bug #80366 (Return Value of zend_fstat() not Checked). (sagpant, cmb)
- Tidy:
. Fixed bug #77594 (ob_tidyhandler is never reset). (cmb)
- Tokenizer:
. Fixed bug #80462 (Nullsafe operator tokenize with TOKEN_PARSE flag fails).
(Nikita)
- XML:
. XmlParser opaque object renamed to XMLParser for consistency with other XML objects. (girgias)
- Zlib:
. Fixed #48725 (Support for flushing in zlib stream). (cmb)
26 Nov 2020, PHP 8.0.0
- BZ2:
. Fixed bug #71263 (fread() does not report bzip2.decompress errors). (cmb)
- CLI:
. Allow debug server binding to an ephemeral port via `-S localhost:0`. (Sara)
- COM:
. Fixed bug #55847 (DOTNET .NET 4.0 GAC new location). (cmb)
. Fixed bug #62474 (com_event_sink crashes on certain arguments). (cmb)
- Calendar:
. Fixed bug #80007 (Potential type confusion in unixtojd() parameter parsing).
(Andy Postnikov)
- Core:
. Fixed bug #36365 (scandir duplicates file name at every 65535th file).
(cmb)
. Fixed bug #49555 (Fatal error "Function must be a string" message should be
renamed). (Nikita)
. Fixed bug #62294 (register_shutdown_function() does not correctly handle
exit code). (Nikita)
. Fixed bug #62609 (Allow implementing Traversable on abstract classes).
(Nikita)
. Fixed bug #65274 (Enhance undefined class constant error with class name).
(Nikita)
. Fixed bug #65275 (Calling exit() in a shutdown function does not change the
exit value in CLI). (Nikita)
. Fixed bug #69084 (Unclear error message when not implementing a renamed
abstract trait function). (Nikita)
. Fixed bug #70839 (Converting optional argument to variadic forbidden by LSP
checks). (Nikita)
. Fixed bug #74558 (Can't rebind closure returned by Closure::fromCallable()).
(cmb)
. Fixed bug #77561 (Shebang line not stripped for non-primary script).
(Nikita)
. Fixed bug #77619 (Wrong reflection on MultipleIterator::__construct).
(Fabien Villepinte)
. Fixed bug #77966 (Cannot alias a method named "namespace"). (Nikita)
. Fixed bug #78236 (convert error on receiving variables when duplicate [).
(cmb)
. Fixed bug #78770 (Incorrect callability check inside internal methods).
(Nikita)
. Fixed bug #79108 (Referencing argument in a function makes it a reference
in the stack trace). (Nikita)
. Fixed bug #79368 ("Unexpected end of file" is not an acceptable error
message). (Alex Dowad)
. Fixed bug #79462 (method_exists and property_exists incoherent behavior).
(cmb)
. Fixed bug #79467 (data:// wrappers are writable). (cmb)
. Fixed bug #79521 (Check __set_state structure). (carusogabriel)
. Fixed bug #79790 ("Illegal offset type" exception during AST evaluation
not handled properly). (Nikita)
. Fixed bug #79791 (Assertion failure when unsetting variable during binary
op). (Nikita)
. Fixed bug #79828 (Segfault when trying to access non-existing variable).
(Nikita)
. Fixed bug #79841 (Syntax error in configure / unescaped "[]" in php.m4).
(Nikita)
. Fixed bug #79852 (count(DOMNodeList) doesn't match
count(IteratorIterator(DOMNodeList))). (Nikita)
. Fixed bug #79867 (Promoted untyped properties should get null default
value). (Nikita)
. Fixed bug #79897 (Promoted constructor params with attribs cause crash).
(Deus Kane)
. Fixed bug #79927 (Generator doesn't throw exception after multiple yield
from iterable). (Nikita)
. Fixed bug #79946 (Build fails due to undeclared UINT32_C). (Nikita)
. Fixed bug #79948 (Exit in auto-prepended file does not abort PHP execution).
(Nikita)
. Fixed bug #80045 (memleak after two set_exception_handler calls with
__call). (Nikita)
. Fixed bug #80096 (Segmentation fault with named arguments in nested call).
(Nikita)
. Fixed bug #80109 (Cannot skip arguments when extended debug is enabled).
(Nikita)
. Fixed bug #80225 (broken namespace usage in eval code). (Nikita)
. Fixed bug #80258 (Windows Deduplication Enabled, randon permission errors).
(cmb)
. Fixed bug #80280 (ADD_EXTENSION_DEP() fails for ext/standard and ext/date).
(cmb)
. Fixed bug #80334 (assert() vs named parameters - confusing error). (Nikita)
. Fixed bug #80055 (Abstract trait methods returning "self" cannot be
fulfilled by traits). (Nikita)
. Fixed faulty generator cleanup with yield from. (Bob)
. Implement #[Attr] Attribute syntax as per final vote in RFC
https://wiki.php.net/rfc/shorter_attribute_syntax_change
. Implemented FR #47074 (phpinfo() reports "On" as 1 for the some
extensions). (cmb)
. Implemented FR #72089 (require() throws fatal error instead of exception).
(Nikita)
. Removed the pdo_odbc.db2_instance_name php.ini directive. (Kalle)
. Use SSE2 instructions do locale independent strtolower. (Laruence)
- Curl:
. Bumped required libcurl version to 7.29.0. (cmb)
. Fixed bug #80121 (Null pointer deref if CurlHandle directly instantiated).
(Nikita)
- DOM:
. Add property DOMXPath::$registerNodeNamespaces and constructor argument
that allow global flag to configure query() or evaluate() calls.
. Fixed bug #79968 (DOMChildNode API crash on unattached nodes). (Benjamin)
. Fixed bug #80268 (loadHTML() truncates at NUL bytes). (cmb)
- Date:
. Fixed bug #60302 (DateTime::createFromFormat should new static(), not new
self()). (Derick)
. Fixed bug #65547 (Default value for sunrise/sunset zenith still wrong).
(cmb)
. Fixed bug #69044 (discrepancy between time and microtime). (krakjoe)
. Fixed bug #80057 (DateTimeImmutable::createFromFormat() does not populate
time). (Derick)
. Implemented FR #79903 (datetime: new format "p", same as "P" but returning
"Z" for UTC). (gharlan)
- Enchant:
. Add LIBENCHANT_VERSION macro.
. Add enchant_dict_add and enchant_dict_is_added functions.
. Deprecate enchant_broker_set_dict_path, enchant_broker_get_dict_path,
enchant_dict_add_to_personal and enchant_dict_is_in_session.
. Use libenchant-2 when available.
- FFI:
. Added FFI\CType::getName() method. (chopins)
. Fixed bug #79177 (FFI doesn't handle well PHP exceptions within callback).
(cmb, Dmitry, Nikita)
. Fixed bug #79749 (Converting FFI instances to bool fails). (cmb)
- FPM:
. Add pm.status_listen option. (Jakub Zelenka)
- Fileinfo:
. Upgrade to libmagic 5.39. (Anatol)
- GD:
. Added imagegetinterpolation(). (cmb)
. Fixed bug #55005 (imagepolygon num_points requirement). (cmb)
. Made the $num_points parameter of php_imagepolygon optional. (cmb)
. Removed deprecated image2wbmp(). (cmb)
. Removed deprecated png2wbmp() and jpeg2wbmp(). (cmb)
. Replaced gd resources with objects. (Mark Randall)
- IMAP:
. Fixed bug #64076 (imap_sort() does not return FALSE on failure). (cmb)
. Fixed bug #76618 (segfault on imap_reopen). (girgias)
. Fixed bug #80213 (imap_mail_compose() segfaults on certain $bodies). (cmb)
. Fixed bug #80215 (imap_mail_compose() may modify by-val parameters). (cmb)
. Fixed bug #80216 (imap_mail_compose() does not validate types/encodings).
(cmb)
. Fixed bug #80220 (imap_mail_compose() may leak memory). (cmb)
. Fixed bug #80223 (imap_mail_compose() leaks envelope on malformed bodies).
(cmb)
. Fixed bug #80226 (imap_sort() leaks sortpgm memory). (cmb)
. Fixed bug #80239 (imap_rfc822_write_address() leaks memory). (cmb)
. Fixed bug #80242 (imap_mail_compose() segfaults for multipart with rfc822).
(cmb)
. Fixed minor regression caused by fixing bug #80220. (cmb)
- Iconv:
. Dropped support for iconv without proper errno setting. (cmb)
- Intl:
. Removed deprecated INTL_IDNA_VARIANT_2003. (cmb)
- JIT:
. Fixed bug #77857 (Wrong result if executed with JIT). (Laruence)
. Fixed bug #79255 (PHP cannot be compiled with enable JIT).
(Laruence, Dmitry)
. Fixed bug #79582 (Crash seen when opcache.jit=1235 and
opcache.jit_debug=2). (Laruence)
. Fixed bug #79743 (Fatal error when assigning to array property
with JIT enabled). (Laruence)
. Fixed bug #79864 (JIT segfault in Symfony OptionsResolver). (Dmitry)
. Fixed bug #79888 (Incorrect execution with JIT enabled). (Dmitry)
- JSON:
. The JSON extension is now an integral part of PHP and cannot be disabled
as per RFC: https://wiki.php.net/rfc/always_enable_json (tandre)
- LDAP:
. Fixed memory leaks. (ptomulik)
. Removed deprecated ldap_sort. (mcmic)
- MBString:
. Fixed bug #76999 (mb_regex_set_options() return current options). (cmb)
. Removed the unused $is_hex parameter from mb_decode_numericentity(). (cmb)
- MySQLi:
. Fixed bug #76809 (SSL settings aren't respected when persistent connections
are used). (fabiomsouto)
- Mysqlnd:
. Fixed #60594 (mysqlnd exposes 160 lines of stats in phpinfo). (PeeHaa)
- OCI8:
. Deprecated old OCI8 function aliases. (Jens de Nies)
. Modernized oci_register_taf_callback() callable argument parsing
implementation. (girgias)
. Removed obsolete no-op function oci_internal_debug(). (Jens de Nies)
- ODBC:
. Fixed bug #22986 (odbc_connect() may reuse persistent connection). (cmb)
. Fixed bug #44618 (Fetching may rely on uninitialized data). (cmb)
- Opcache:
. Fixed bug #76535 (Opcache does not replay compile-time warnings). (Nikita)
. Fixed bug #78654 (Incorrectly computed opcache checksum on files with
non-ascii characters). (mhagstrand)
. Fixed bug #79665 (ini_get() and opcache_get_configuration() inconsistency).
(cmb)
. Fixed bug #80030 (Optimizer segfault with isset on static property with
undef dynamic class name). (Nikita)
. Fixed bug #80175 (PHP8 RC1 - JIT Buffer not working). (cmb)
. Fixed bug #80184 (Complex expression in while / if statements resolves to
false incorrectly). (Nikita)
. Fixed bug #80255 (Opcache bug (bad condition result) in 8.0.0rc1). (Nikita)
. Fixed run-time binding of preloaded dynamically declared function. (Dmitry)
- OpenSSL:
. Added Cryptographic Message Syntax (CMS) support. (Eliot Lear)
- PCRE:
. Don't ignore invalid escape sequences. (sjon)
. Updated to PCRE2 10.35. (cmb)
- PDO:
. Changed default PDO error mode to exceptions. (AllenJB)
. Fixed bug #77849 (Disable cloning of PDO handle/connection objects).
(camporter)
- PDO_Firebird:
. Fixed bug #64937 (Firebird PDO preprocessing sql). (Simonov Denis)
- PDO_OCI:
. Added support for setting and getting the oracle OCI 18c call timeout.
(camporter)
- PDO_PGSQL:
. Bumped required libpq version to 9.1. (cmb)
- PGSQL:
. Bumped required libpq version to 9.1. (cmb)
- Phpdbg:
. Fixed bug #76596 (phpdbg support for display_errors=stderr). (kabel)
. Fixed bug #76801 (too many open files). (alekitto)
. Fixed bug #77800 (phpdbg segfaults on listing some conditional breakpoints).
(krakjoe)
. Fixed bug #77805 (phpdbg build fails when readline is shared). (krakjoe)
- Reflection:
. Fixed bug #64592 (ReflectionClass::getMethods() returns methods out of
scope). (Nikita)
. Fixed bug #69180 (Reflection does not honor trait conflict resolution /
method aliasing). (Nikita)
. Fixed bug #74939 (Nested traits' aliased methods are lowercased). (Nikita)
. Fixed bug #77325 (ReflectionClassConstant::$class returns wrong class when
extending). (Nikita)
. Fixed bug #78697 (ReflectionClass::implementsInterface - inaccurate error
message with traits). (villfa)
. Fixed bug #80190 (ReflectionMethod::getReturnType() does not handle static
as part of union type). (Nikita)
. Fixed bug #80299 (ReflectionFunction->invokeArgs confused in arguments).
(Nikita)
. Fixed bug #80370 (getAttributes segfault on dynamic properties). (Benjamin
Eberlei)
. Implement #79628 (Add $filter parameter for ReflectionClass::getConstants
and ReflectionClass::getReflectionConstants) (carusogabriel)
. Implement ReflectionProperty::hasDefaultValue and
Reflection::getDefaultValue (beberlei)
- SNMP:
. Fixed bug #70461 (disable md5 code when it is not supported in net-snmp).
(Alexander Bergmann, cmb)
- SPL:
. Fixed bug #65006 (spl_autoload_register fails with multiple callables using
self, same method). (Nikita)
. Fixed bug #65387 (Circular references in SPL iterators are not garbage
collected). (Nikita)
. Fixed bug #71236 (Second call of spl_autoload_register() does nothing if it
has no arguments). (Nikita)
. Fixed bug #79987 (Memory leak in SplFileInfo because of missing
zend_restore_error_handling()). (Dmitry)
. SplFixedArray is now IteratorAggregate rather than Iterator. (alexdowad)
- SQLite3:
. Added SQLite3::setAuthorizer() and respective class constants. (bohwaz)
- Session:
. Fixed bug #73529 (session_decode() silently fails on wrong input). (cmb)
. Fixed bug #78624 (session_gc return value for user defined session
handlers). (bshaffer)
- Shmop:
. Converted shmop resources to objects. (cmb)
- SimpleXML:
. Fixed bug #63575 (Root elements are not properly cloned). (cmb)
. Fixed bug #75245 (Don't set content of elements with only whitespaces).
(eriklundin)
- Sodium:
. Fixed bug #77646 (sign_detached() strings not terminated). (Frank)
- Standard:
. Don't force rebuild of symbol table, when populating $http_response_header
variable by the HTTP stream wrapper. (Dmitry)
. Fixed bug #47983 (mixed LF and CRLF line endings in mail()). (cmb)
. Fixed bug #64060 (lstat_stat_variation7.phpt fails on certain file systems).
(M. Voelker, cmb)
. Fixed bug #75902 (str_replace should warn when misused with nested arrays).
(Nikita)
. Fixed bug #76859 (stream_get_line skips data if used with data-generating
filter). (kkopachev)
. Fixed bug #77204 (getimagesize(): Read error! should mention file path).
(peter279k)
. Fixed bug #78385 (parse_url() does not include 'query' when question mark
is the last char). (Islam Israfilov)
. Fixed bug #79868 (Sorting with array_unique gives unwanted result). (Nikita)
. Fixed bug #80256 (file_get_contents strip first line with chunked encoding
redirect). (Nikita)
. Fixed bug #80266 (parse_url silently drops port number 0). (cmb, Nikita)
. Fixed bug #80290 (Double free when ASSERT_CALLBACK is used with a dynamic
message). (Nikita)
. Implemented FR #78638 (__PHP_Incomplete_Class should be final). (Laruence)
. Made quoting of cmd execution functions consistent. (cmb)
- Tidy:
. Removed the unused $use_include_path parameter from tidy_repair_string().
(cmb)
- Tokenizer:
. Fixed bug #80328 (PhpToken::getAll() confusing name). (Nikita)
- XML:
. Fixed bug #76874 (xml_parser_free() should never leak memory). (Nikita)
- XMLWriter:
. Changed functions to accept/return XMLWriter objects instead of resources.
(cmb)
. Implemented FR #79344 (xmlwriter_write_attribute_ns: $prefix should be
nullable). (cmb)
. Removed return types from XMLWriter stubs. (cmb)
- Zip:
. Add "flags" options to ZipArchive::addGlob and addPattern methods
keeping previous behavior having FL_OVERWRITE by default. (Remi)
. Add ZipArchive::EM_UNKNOWN and ZipArchive::EM_TRAD_PKWARE constants. (Remi)
. Add ZipArchive::isCompressionMethodSupported() and
ZipArchive::isEncryptionMethodSupported() method (libzip 1.7.0). (Remi)
. Add ZipArchive::replaceFile() method. (Remi)
. Add ZipArchive::setCancelCallback method (since libzip 1.6.0). (Remi)
. Add ZipArchive::setMtimeName and ZipArchive::setMtimeIndex methods. (Remi)
. Add ZipArchive::setProgressCallback method (since libzip 1.3.0). (Remi)
. Add lastId property to ZipArchive. (Remi)
. Add optional "flags" parameter to ZipArchive::addEmptyDir, addFile and
addFromString methods. (Remi)
. Fixed bug #50678 (files extracted by ZipArchive class lost their
original modified time). (Remi)
. Fixed bug #72374 (remove_path strips first char of filename). (tyage, Remi)
. Implemented FR #77960 (add compression / encryption options for
ZipArchive::addGlob and ZipArchive::addPattern). (Remi)
. ZipArchive::status and ZipArchive::statusSys properties and
ZipArchive::getStatusString() method stay valid after the archive
is closed. (Remi)
- Zlib:
. Fixed bug #71417 (fread() does not report zlib.inflate errors). (cmb)
. Fixed bug #78792 (zlib.output_compression disabled by Content-Type: image/).
(cmb)
?? ??? 20??, PHP 6.0
- Unicode support. (Andrei, Dmitry, et al)
- Changed "allow_url_fopen" and "allow_url_include" php.ini directives to allow
per-wrapper enable/disable and runtime tightening. (Sara)
- Changed --with-config-file-scan-dir / PHP_INI_SCAN_DIR to allow multiple
paths. (Mikko)
- Removed undocumented and incomplete support for strings in list() operator.
(Dmitry)
- Removed old legacy:
. "register_globals" support. (Pierre)
. "register_long_arrays" ini option. (Dmitry)
. "safe_mode" support. (Ilia, Andi)
. "allow_call_time_pass_reference", added E_STRICT error message. (Dmitry)
. session_register(), session_unregister() and session_is_registered()
(needed only with "register_globals=On").
. "magic_quotes_gpc", "magic_quotes_runtime" and "magic_quotes_sybase" ini
options. (Pierre)
. Changed get_magic_quotes_gpc(), get_magic_quotes_runtime to always return
false and set_magic_quotes_runtime() to raise an E_CORE_ERROR.
. "define_syslog_variables" ini option and define_syslog_variables()
(Kalle)
- Removed support for "continue" and "break" operators with non-constant
operands. (Dmitry)
- Removed Freetype 1.x and GD 1.x support from GD extension. (Pierre)
- Improved ext/zlib: re-implemented non-file related functionality. (Mike)
- Improved output layer. See README.NEW-OUTPUT-API for internals. (Mike)
- Improved ext/mhash: (Mike)
. Added keygen constants.
. Added new functions: mhash_keygen_count, mhash_get_keygen_name,
mhash_keygen_uses_hash, mhash_keygen_uses_salt, mhash_get_keygen_salt_size,
mhash_keygen.
- Improved ext/dba:
. Added support for Tokyo Cabinet. (Michael)
- Added DTrace support. (David Soria Parra)
- Added runtime JIT auto-globals fetching and caching. (Dmitry, Sara)
- Added E_STRICT to E_ALL. (Dmitry)
- Added "context" and "binary_pipes" params in "other_options" for proc_open().
(Sara)
- Added stream_resolve_include_path() function which checks which file fopen()
with a relative path will open. (Sara)
- Fixed bug #46647 (SplFileObject::fgetcsv segfaults). (Etienne)
- Fixed bug #40325 (Vary: header missing in gzip output handlers). (Mike)
- Fixed bug #48774 (SIGSEGVs when using curl_copy_handle()). (Sriram Natarajan)
+39
View File
@@ -0,0 +1,39 @@
Between PHP 4.0.6 and 4.1.0, the Zend module struct changed in a way
that broke both source and binary compatibility. If you are
maintaining a third party extension, here's how to update it:
If this was your old module entry:
zend_module_entry foo_module_entry = {
"foo", /* extension name */
foo_functions, /* extension function list */
NULL, /* extension-wide startup function */
NULL, /* extension-wide shutdown function */
PHP_RINIT(foo), /* per-request startup function */
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
PHP_MINFO(foo), /* information function */
STANDARD_MODULE_PROPERTIES
};
Here's how it should look if you want your code to build with PHP
4.1.0 and up:
zend_module_entry foo_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"foo", /* extension name */
foo_functions, /* extension function list */
NULL, /* extension-wide startup function */
NULL, /* extension-wide shutdown function */
PHP_RINIT(foo), /* per-request startup function */
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
PHP_MINFO(foo), /* information function */
#if ZEND_MODULE_API_NO >= 20010901
FOO_VERSION, /* extension version number (string) */
#endif
STANDARD_MODULE_PROPERTIES
};
If you don't care about source compatibility with earlier PHP releases
than 4.1.0, you can drop the #if/#endif lines.
+194
View File
@@ -0,0 +1,194 @@
(NOTE: you may also want to take a look at the pear package
PECL_Gen, a PHP-only alternative for this script that
supports way more extension writing tasks and is
supposed to replace ext_skel completely in the long run ...)
WHAT IT IS
It's a tool for automatically creating the basic framework for a PHP module
and writing C code handling arguments passed to your functions from a simple
configuration file. See an example at the end of this file.
HOW TO USE IT
Very simple. First, change to the ext/ directory of the PHP 4 sources. If
you just need the basic framework and will be writing all the code in your
functions yourself, you can now do
./ext_skel --extname=module_name
and everything you need is placed in directory module_name.
[ Note that GNU awk is likely required for this script to work. Debian
systems seem to default to using mawk, so you may need to change the
#! line in skeleton/create_stubs and the cat $proto | awk line in
ext_skel to use gawk explicitly. ]
If you don't need to test the existence of any external header files,
libraries or functions in them, the module is already almost ready to be
compiled in PHP. Just remove 3 comments in your_module_name/config.m4,
change back up to PHP sources top directory, and do
./buildconf; ./configure --enable-module_name; make
But if you already have planned the overall scheme of your module, what
functions it will contain, their return types and the arguments they take
(a very good idea) and don't want to bother yourself with creating function
definitions and handling arguments passed yourself, it's time to create a
function definitions file, which you will give as an argument to ext_skel
with option
--proto=filename.
FORMAT OF FUNCTION DEFINITIONS FILE
All the definitions must be on one line. In it's simplest form, it's just
the function name, e.g.
my_function
but then you'll be left with an almost empty function body without any
argument handling.
Arguments are given in parenthesis after the function name, and are of
the form 'argument_type argument_name'. Arguments are separated from each
other with a comma and optional space. Argument_type can be one of int,
bool, double, float, string, array, object or mixed.
An optional argument is separated from the previous by an optional space,
then '[' and of course comma and optional space, like all the other
arguments. You should close a row of optional arguments with same amount of
']'s as there where '['s. Currently, it does not harm if you forget to do it
or there is a wrong amount of ']'s, but this may change in the future.
An additional short description may be added after the parameters.
If present it will be filled into the 'proto' header comments in the stubs
code and the <refpurpose> tag in the XML documentation.
An example:
my_function(int arg1, int arg2 [, int arg3 [, int arg4]]) this is my 1st
Arguments arg3 and arg4 are optional.
If possible, the function definition should also contain it's return type
in front of the definition. It's not actually used for any C code generating
purposes but PHP in-source documentation instead, and as such, very useful.
It can be any of int, double, string, bool, array, object, resource, mixed
or void.
The file must contain nothing else but function definitions, no comments or
empty lines.
OTHER OPTIONS
--no-help
By default, ext_skel creates both comments in the source code and a test
function to help first time module writers to get started and testing
configuring and compiling their module. This option turns off all such things
which may just annoy experienced PHP module coders. Especially useful with
--stubs=file
which will leave out also all module specific stuff and write just function
stubs with function value declarations and passed argument handling, and
function entries and definitions at the end of the file, for copying and
pasting into an already existing module.
--assign-params
--string-lens
By default, function proto 'void foo(string bar)' creates the following:
...
zval **bar;
... (zend_get_parameters_ex() called in the middle...)
convert_to_string_ex(bar);
Specifying both of these options changes the generated code to:
...
zval **bar_arg;
int bar_len;
char *bar = NULL;
... (zend_get_parameters_ex() called in the middle...)
convert_to_string_ex(bar_arg);
bar = Z_STRVAL_PP(bar_arg);
bar_len = Z_STRLEN_PP(bar_arg);
You shouldn't have to ask what happens if you leave --string-lens out. If you
have to, it's questionable whether you should be reading this document.
--with-xml[=file]
Creates the basics for phpdoc .xml file.
--full-xml
Not implemented yet. When or if there will ever be created a framework for
self-contained extensions to use phpdoc system for their documentation, this
option enables it on the created xml file.
CURRENT LIMITATIONS, BUGS AND OTHER ODDITIES
Only arguments of types int, bool, double, float, string and array are
handled. For other types you must write the code yourself. And for type
mixed, it wouldn't even be possible to write anything, because only you
know what to expect.
It can't handle correctly, and probably never will, variable list of
of arguments. (void foo(int bar [, ...])
Don't trust the generated code too much. It tries to be useful in most of
the situations you might encounter, but automatic code generation will never
beat a programmer who knows the real situation at hand. ext_skel is generally
best suited for quickly generating a wrapper for c-library functions you
might want to have available in PHP too.
This program doesn't have a --help option. It has --no-help instead.
EXAMPLE
The following _one_ line
bool my_drawtext(resource image, string text, resource font, int x, int y [, int color])
will create this function definition for you (note that there are a few
question marks to be replaced by you, and you must of course add your own
value definitions too):
/* {{{ proto bool my_drawtext(resource image, string text, resource font, int x, int y[, int color])
*/
PHP_FUNCTION(my_drawtext)
{
zval **image, **text, **font, **x, **y, **color;
int argc;
int image_id = -1;
int font_id = -1;
argc = ZEND_NUM_ARGS();
if (argc < 5 || argc > 6 || zend_get_parameters_ex(argc, &image, &text, &font, &x, &y, &color) == FAILURE) {
WRONG_PARAM_COUNT;
}
ZEND_FETCH_RESOURCE(???, ???, image, image_id, "???", ???_rsrc_id);
ZEND_FETCH_RESOURCE(???, ???, font, font_id, "???", ???_rsrc_id);
switch (argc) {
case 6:
convert_to_long_ex(color);
/* Fall-through. */
case 5:
convert_to_long_ex(y);
convert_to_long_ex(x);
/* font: fetching resources already handled. */
convert_to_string_ex(text);
/* image: fetching resources already handled. */
break;
default:
WRONG_PARAM_COUNT;
}
php_error(E_WARNING, "my_drawtext: not yet implemented");
}
/* }}} */
+79
View File
@@ -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
+142
View File
@@ -0,0 +1,142 @@
$Id$
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(TSRMLS_C);
Starting the default output handler:
// php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
php_output_start_default(TSRMLS_C);
Starting an user handler by zval:
// php_start_ob_buffer(zhandler, chunk_size, erase TSRMLS_CC);
php_output_start_user(zhandler, chunk_size, flags TSRMLS_CC);
Starting an internal handler whithout context:
// php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase TSRMLS_CC);
php_output_start_internal(handler_name_zval, my_php_output_handler_func_t, chunk_size, flags TSRMLS_CC);
Starting an internal handler with context:
// not possible with old API
php_output_handler *h;
h = php_output_handler_create_internal(handler_name_zval, my_php_output_handler_context_func_t, chunk_size, flags TSRMLS_CC);
php_output_handler_set_context(h, my_context, my_context_dtor);
php_output_handler_start(h TSRMLS_CC);
Testing whether a certain output handler has already been started:
// php_ob_handler_used("output handler name" TSRMLS_CC);
php_output_handler_started(handler_name_zval TSRMLS_CC);
Flushing one output buffer:
// php_ob_end_buffer(1, 1 TSRMLS_CC);
php_output_flush(TSRMLS_C);
Flushing all output buffers:
// not possible with old API
php_output_flush_all(TSRMLS_C);
Cleaning one output buffer:
// php_ob_end_buffer(0, 1 TSRMLS_CC);
php_output_clean(TSRMLS_C);
Cleaning all output buffers:
// not possible with old API
php_output_clean_all(TSRMLS_C);
Discarding one output buffer:
// php_ob_end_buffer(0, 0 TSRMLS_CC);
php_output_discard(TSRMLS_C);
Discarding all output buffers:
// php_ob_end_buffers(0 TSRMLS_CC);
php_output_discard_all(TSRMLS_C);
Stopping (and dropping) one output buffer:
// php_ob_end_buffer(1, 0 TSRMLS_CC)
php_output_end(TSRMLS_C);
Stopping (and dropping) all output buffers:
// php_ob_end_buffers(1, 0 TSRMLS_CC);
php_output_end_all(TSRMLS_C);
Retrieving output buffers contents:
// php_ob_get_buffer(zstring TSRMLS_CC);
php_output_get_contents(zstring TSRMLS_CC);
Retrieving output buffers length:
// php_ob_get_length(zlength TSRMLS_CC);
php_output_get_length(zlength TSRMLS_CC);
Retrieving output buffering level:
// OG(nesting_level);
php_output_get_level(TSRMLS_C);
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" TSRMLS_CC);
php_output_handler_conflict(new_handler_name_zval, set_handler_name_zval TSRMLS_CC);
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_zval, my_php_output_handler_conflict_check_t TSRMLS_CC);
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_zval, my_php_output_handler_conflict_check_t TSRMLS_CC);
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 TSRMLS_CC);
Disabling of the output handler by itself:
//not possible with old API
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL TSRMLS_CC);
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 TSRMLS_CC);
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
+281
View File
@@ -0,0 +1,281 @@
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 TSRMLS_DC, char *type_spec, ...);
int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, 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.
Type specifiers
---------------
The following list shows the type specifier, its meaning and the parameter
types that need to be passed by address. All passed paramaters 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 (long)
L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (long)
o - object of any type (zval*)
O - object of specific type given by class entry (zval*, zend_class_entry)
r - resource (zval*)
s - string (with possible null bytes) and its length (char*, int)
S - binary string, does not allow conversion from Unicode strings
t - text (zstr (string union), int (length), zend_uchar (IS_STRING/..))
accepts either Unicode or binary string
T - text (zstr (string union), int (length), zend_uchar (IS_STRING/..))
coalesces all T parameters to common type (Unicode or binary)
u - unicode (UChar*, int)
U - Unicode string, does not allow conversion from binary strings
x - Unicode or binary string depending on UG(unicode). In unicode this
behaves like 'u' and in nonunicode mode it behaves like 's'.
z - the actual zval (zval*)
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 (applies
to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the
results pointer is set to NULL as well.
& - alternate format (currently used for 's' only to specify a converter to
use when converting from Unicode strings)
^ - returns original string type before conversion (only for 's' and 'u'
specifiers)
Note on 64bit compatibility
---------------------------
Please do not forget that int and long are two different things on 64bit
OSes (int is 4 bytes and long is 8 bytes), so make sure you pass longs to "l"
and ints to strings length (i.e. for "s" you need to pass char * and int),
not the other way round!
Remember: "l" is the only case when you need to pass long (and that's why
it's "l", not "i" btw).
Both mistakes cause memory corruptions and segfaults on 64bit OSes:
1)
char *str;
long str_len; /* XXX THIS IS WRONG!! Use int instead. */
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)
2)
int num; /* XXX THIS IS WRONG!! Use long instead. */
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "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 */
long l;
char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
&l, &s, &s_len, &param) == 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() TSRMLS_CC, "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() TSRMLS_CC, "o!a",
&obj, &arr) == FAILURE) {
return;
}
/* Gets a separated array which can also be null. */
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
&arr) == FAILURE) {
return;
}
/* Gets a binary string in UTF-8 */
char *str;
int str_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &str, &str_len, UG(utf8_conv)) == FAILURE) {
return;
}
/* Gets a Unicode string */
UChar *str;
int len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &len) == FAILURE) {
return;
}
/* Gets a Unicode or binary string */
zstr str;
int len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &str, &len, &type) == FAILURE) {
return;
}
if (type == IS_UNICODE) {
/* process str.u as Unicode string */
} else {
/* process str.s binary string */
}
/* Gets two string parameters, both of which will be guaranteed to be of the same type */
zstr str1, str2;
int len1, len2;
zend_uchar type1, type2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "TT", &str1, &len1,
&type1, &str2, &len2, &type2) == FAILURE) {
return;
}
if (type1 == IS_UNICODE) {
/* process as Unicode, str2 is guaranteed to be Unicode as well */
} else {
/* process as binary string, str2 is guaranteed to be the same */
}
/* Get either a set of 3 longs or a string. */
long l1, l2, l3;
char *s;
/*
* The function expects a pointer to a integer in this case, not a long
* or any other type. If you specify a type which is larger
* than a 'int', the upper bits might not be initialized
* properly, leading to random crashes on platforms like
* Tru64 or Linux/Alpha.
*/
int length;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"lll", &l1, &l2, &l3) == SUCCESS) {
/* manipulate longs */
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"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() TSRMLS_CC, "*", &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;
int str_len;
int i, num_varargs;
zval ***varargs = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
return;
}
for (i = 0; i < num_varargs; i++) {
/* do something with varargs[i] */
}
if (varargs) {
efree(varargs);
}
/* Function that takes an array, followed by varargs, and ending with a long */
long num;
zval *array;
int i, num_varargs;
zval ***varargs = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
return;
}
for (i = 0; i < num_varargs; i++) {
/* do something with varargs[i] */
}
if (varargs) {
efree(varargs);
}
+11
View File
@@ -0,0 +1,11 @@
To install the PEAR installer, please use go-pear.
On linux:
$ lynx -source http://pear.php.net/go-pear | php
or save the setup script under go-pear.php and run:
php go-pear.php
For more informations see the PEAR manual:
http://pear.php.net/manual/en/installation.getting.php
+155
View File
@@ -0,0 +1,155 @@
1. strrpos() and strripos() now use the entire string as a needle. Be aware
that the existing scripts may no longer work as you expect.
EX :
<?php
var_dump(strrpos("ABCDEF","DEF"));
var_dump(strrpos("ABCDEF","DAF"));
?>
Will give you different results. The former returns 3 while the latter
returns false rather than the position of the last occurrence of 'D'.
The same applies to strripos().
2. Illegal use of string offsets causes E_ERROR instead of E_WARNING.
EX :
<?php
$a = "foo";
unset($a[0][1][2]);
?>
Fatal error: Cannot use string offset as an array in ... on line 1
3. array_merge() was changed to accept only arrays. If a non-array variable is
passed, a E_WARNING will be thrown for every such parameter. Be careful
because your code may start emitting E_WARNING out of the blue.
4. Be careful when porting from ext/mysql to ext/mysqli. The following
functions return NULL when no more data is available in the result set
(ext/mysql's functions return FALSE).
- mysqli_fetch_row()
- mysqli_fetch_array()
- mysqli_fetch_assoc()
5. PATH_TRANSLATED server variable is no longer set implicitly under
Apache2 SAPI in contrast to the situation in PHP 4, where it is set to the
same value as the SCRIPT_FILENAME server variable when it is not populated
by Apache. This change was made to comply with the CGI specification.
Please refer to bug #23610 for further information.
6. Starting PHP 5.0.0 the T_ML_CONSTANT constant is no longer defined by the
ext/tokenizer extension. If error_reporting is set to E_ALL notices will
be produced. Instead of T_ML_CONSTANT for /* */ the T_COMMENT constant
is used, thus both // and /* */ are resolved as the T_COMMENT constant.
However the PHPDoc style comments /** */ ,which starting PHP 5 are parsed
by PHP, are recongnized as T_DOC_COMMENT.
7. $_SERVER should be populated with argc and argv if variables_order
includes "S". If you have specifically configured your system to not
create $_SERVER, then of course it shouldn't be there. The change was to
always make argc and argv available in the CLI version regardless of the
variables_order setting. As in, the CLI version will now always populate
the global $argc and $argv variables.
8. In some cases classes must be declared before used. It only happens only
if some of the new features of PHP 5 are used. Otherwise the behaviour is
the old.
Example 1 (works with no errors):
<?php
$a = new a();
class a {
}
?>
Example 2 (throws an error):
<?php
$a = new a();
interface b{
}
class a implements b {
}
?>
Output (example 2) :
Fatal error: Class 'a' not found in /tmp/cl.php on line 2
9. get_class() starting PHP 5 returns the name of the class as it was
declared which may lead to problems in older scripts that rely on
the previous behaviour - the class name is lowercased. Expect the
same behaviour from get_parent_class() when applicable.
Example :
<?php
class FooBar {
}
class ExtFooBar extends FooBar{}
$a = new FooBar();
var_dump(get_class($a), get_parent_class($a));
?>
Output (PHP 4):
string(6) "foobar"
string(9) "extfoobar"
Output (PHP 5):
string(6) "FooBar"
string(9) "ExtFooBar"
----------------------------------------------------------------------
Example code that will break :
//....
function someMethod($p) {
if (get_class($p) != 'helpingclass') {
return FALSE;
}
//...
}
//...
Possible solution is to search for get_class() and get_parent_class() in
all your scripts and use strtolower().
10. get_class_methods() returns the names of the methods of a class as they
declared. In PHP4 the names are all lowercased.
Example code :
<?php
class Foo{
function doFoo(){}
function hasFoo(){}
}
var_dump(get_class_methods("Foo"));
?>
Output (PHP4):
array(2) {
[0]=>
string(5) "dofoo"
[1]=>
string(6) "hasfoo"
}
Output (PHP5):
array(2) {
[0]=>
string(5) "doFoo"
[1]=>
string(6) "hasFoo"
}
11. Assignment $this is impossible. Starting PHP 5.0.0 $this has special
meaning in class methods and is recognized by the PHP parser. The latter
will generate a parse error when assignment to $this is found
Example code :
<?php
class Foo {
function assignNew($obj) {
$this = $obj;
}
}
$a = new Foo();
$b = new Foo();
$a->assignNew($b);
echo "I was executed\n";
?>
Output (PHP 4):
I was executed
Output (PHP 5):
PHP Fatal error: Cannot re-assign $this in /tmp/this_ex.php on line 4
+57
View File
@@ -0,0 +1,57 @@
QNX4 Installation Notes
-----------------------
NOTE: General installation instructions are in the INSTALL file
1. To compile and test PHP3 you have to grab, compile and install:
- GNU dbm library or another db library;
- GNU bison (1.25 or later; 1.25 tested);
- GNU flex (any version supporting -o and -P options; 2.5.4 tested);
- GNU diffutils (any version supporting -w option; 2.7 tested);
2. To use CVS version you may need also:
- GNU CVS (1.9 tested);
- GNU autoconf (2.12 tested);
- GNU m4 (1.3 or later preferable; 1.4 tested);
3. To run configure define -lunix in command line:
LDFLAGS=-lunix ./configure
4. To use Sybase SQL Anywhere define ODBC_QNX and CUSTOM_ODBC_LIBS in
command line and run configure with --with-custom-odbc:
CFLAGS=-DODBC_QNX LDFLAGS=-lunix CUSTOM_ODBC_LIBS="-ldblib -lodbc" ./configure --with-custom-odbc=/usr/lib/sqlany50
If you have SQL Anywhere version 5.5.00, then you have to add
CFLAGS=-DSQLANY_BUG
to workaround its SQLFreeEnv() bug. Other versions has not been tested,
so try without this flag first.
5. To build the Apache module, you may have to hardcode an include path for
alloc.h in your Apache base directory:
- APACHE_DIRECTORY/src/httpd.h:
change #include "alloc.h"
to #include "APACHE_DIRECTORY/src/alloc.h"
Unless you want to use system regex library, you have to hardcode also
a path to regex.h:
- APACHE_DIRECTORY/src/conf.h:
change #include <regex.h>
to #include "APACHE_DIRECTORY/src/regex/regex.h"
I don't know so far why this required for QNX, may be it is Watcom
compiler problem.
If you building Apache module with SQL Anywhere support, you'll get
symbol conflict with BOOL. It is defined in Apache (httpd.h) and in
SQL Anywhere (odbc.h). This has nothing to do with PHP, so you have to
fix it yourself someway.
6. With above precautions, it should compile as is and pass regression
tests completely:
make
make check
make install
Don't bother me unless you really sure you made that all but it
still doesn't work.
June 28, 1998
Igor Kovalenko -- owl@infomarket.ru
+160 -373
View File
@@ -1,121 +1,23 @@
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. pcrelib (ext/pcre) see ext/pcre/pcrelib/LICENCE
5. ext/standard crypt
6. ext/standard crypt's blowfish implementation
7. Sqlite/Sqlite3 ext/sqlite3 ext/sqlite
8. ext/json/json_parser
9. ext/standard/rand
10. ext/standard/scanf
11. ext/standard/strnatcmp.c
12. ext/standard/uuencode
13. libxmlrpc ext/xmlrpc
14. libzip ext/zip
15. main/snprintf.c
16. main/strlcat
17. main/strlcpy
18. libgd see ext/gd/libgd/COPYING
3. pcre2lib (ext/pcre)
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.
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
optimize pattern matching. This is an optional feature that can be omitted when
the library is built.
THE BASIC LIBRARY FUNCTIONS
---------------------------
Written by: Philip Hazel
Email local part: ph10
Email domain: cam.ac.uk
University of Cambridge Computing Service,
Cambridge, England.
Copyright (c) 1997-2019 University of Cambridge
All rights reserved.
PCRE2 JUST-IN-TIME COMPILATION SUPPORT
--------------------------------------
Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright(c) 2010-2019 Zoltan Herczeg
All rights reserved.
STACK-LESS JUST-IN-TIME COMPILER
--------------------------------
Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright(c) 2009-2019 Zoltan Herczeg
All rights reserved.
THE "BSD" LICENCE
-----------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notices,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notices, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of any
contributors may be used to endorse or promote 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 LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES
------------------------------------------
The second condition in the BSD licence (covering binary redistributions) does
not apply all the way down a chain of software. If binary package A includes
PCRE2, it must respect the condition, but if package B is software that
includes package A, the condition is not imposed on package B unless it uses
PCRE2 independently.
End
4. ext/standard crypt
5. ext/standard crypt
FreeSec: libcrypt for NetBSD
@@ -126,13 +28,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
@@ -145,44 +47,31 @@ 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.
5. ext/standard crypt's blowfish implementation
The crypt_blowfish homepage is:
http://www.openwall.com/crypt/
6. ext/standard crypt's blowfish implementation
This code comes from John the Ripper password cracker, with reentrant
and crypt(3) interfaces added, but optimizations specific to password
cracking removed.
Written by Solar Designer <solar at openwall.com> in 1998-2011.
No copyright is claimed, and the software is hereby placed in the public
domain. In case this attempt to disclaim copyright and place the software
in the public domain is deemed null and void, then the software is
Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
general public under the following terms:
Written by Solar Designer <solar at openwall.com> in 1998-2002 and
placed in the public domain.
Redistribution and use in source and binary forms, with or without
modification, are permitted.
There's ABSOLUTELY NO WARRANTY, express or implied.
There's absolutely no warranty.
It is my intent that you should be able to use this on your system,
as part of a software package, or anywhere else to improve security,
as a part of a software package, or anywhere else to improve security,
ensure compatibility, or for any other purpose. I would appreciate
it if you give credit where it is due and keep your modifications in
the public domain as well, but I don't require that in order to let
you place this code and any modifications you make under a license
of your choice.
This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix
"$2a$") by Niels Provos <provos at citi.umich.edu>, and uses some of his
This implementation is compatible with OpenBSD bcrypt.c (version 2a)
by Niels Provos <provos at citi.umich.edu>, and uses some of his
ideas. The password hashing algorithm was designed by David Mazieres
<dm at lcs.mit.edu>. For more information on the level of compatibility,
please refer to the comments in BF_set_key() and to the crypt(3) man page
included in the crypt_blowfish tarball.
<dm at lcs.mit.edu>.
There's a paper on the algorithm that explains its design decisions:
@@ -191,10 +80,42 @@ http://www.usenix.org/events/usenix99/provos.html
Some of the tricks in BF_ROUND might be inspired by Eric Young's
Blowfish library (I can't be sure if I would think of something if I
hadn't seen his code).
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.
6. ext/standard/rand
8. ext/json/json_parser
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
9. 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
@@ -217,22 +138,22 @@ Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
Copyright (C) 2000 - 2003, Richard J. Wagner
All rights reserved.
All rights reserved.
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 names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
3. The names of its contributors may not be used to endorse or promote
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 +168,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
10. ext/standard/scanf
scanf.c --
This file contains the base code which implements sscanf and by extension
@@ -294,8 +214,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
11. 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 +228,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
12. ext/standard/uuencode
Portions of this code are based on Berkeley's uuencode/uudecode
implementation.
@@ -329,17 +246,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 +271,63 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
10. main/snprintf.c
13. 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.
14. 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.
15. 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 +354,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 +400,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
16. main/strlcat
17. main/strlcpy
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
All rights reserved.
@@ -439,12 +409,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,186 +427,3 @@ 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
portions of tar implementations in ext/phar - phar_tar_octal() are based on an
implementation by Tim Kientzle from libarchive, licensed with this license:
Copyright (c) 2003-2007 Tim Kientzle
All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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.
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.
+286
View File
@@ -0,0 +1,286 @@
=======================
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 the day before a release. So if the release is to be on Thursday,
package on Wednesday.
3. Ensure that Windows builds will work before packaging
4. Follow all steps to the letter. When unclear ask previous RM's (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.
5. Verify the tags to be extra sure everything was tagged properly.
6. Moving extensions from/to PECL requires root level access to the CVS server.
Contact systems@php.net to get this taken care of.
Moving extensions from php-src to PECL
- Filesystem: cp -r php-src/ext/foo pecl/foo
- cvs rm php-src/ext/foo
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
Moving extensions from PECL to php-src
- Filesystem: cp -r pecl/foo php-src/ext/foo
OR depending on the wishes from the PECL extension maintainer.
- Filesystem: ln -s pecl/foo php-src/ext/foo
Rolling a non stable release (alpha/beta/RC)
--------------------------------------------
1. Check windows snapshot builder logs (http://snaps.php.net/win32/snapshot-STABLE.log f.e.)
2. Bump the version numbers in ``main/php_version.h``, ``configure.in`` and possibly ``NEWS``.
Do not use abbreviations for alpha and beta.
3. Commit those changes
4. run the "scripts/dev/credits" script in php-src and commit the changes in the
credits files in ext/standard.
5. tag the repository with the version f.e. "``cvs tag php_4_4_1RC1``"
(of course, you need to change that to the version you're rolling an RC for).
6. Bump up the version numbers in ``main/php_version.h``, ``configure.in``
and possibly ``NEWS`` again, to the **next** version. F.e. if the release
candidate was "4.4.1RC1" then the new one should be "4.4.1RC2-dev" - regardless
if we get a new RC or not. This is to make sure ``version_compare()`` can
correctly work.
7. Commit those changes
8. Log in onto the snaps box and go into the correct tree (f.e. the PHP_4_4
branch if you're rolling 4.4.x releases).
9. You do not have to update the tree, but of course you can with "``cvs up -dP``".
10. run: ``./makedist php 4.4.1RC1``, this will export the tree, create configure
and build two tarballs (one gz and one bz2).
11. Copy those two tarballs to www.php.net, in your homedir there should be a
directory "downloads/". Copy them into there, so that the system can generate
MD5 sums. If you do not have this directory, talk to Derick.
12. Now the RC can be found on http://downloads.php.net/yourname,
f.e. http://downloads.php.net/derick/
13. Once the release has been tagged, contact the PHP Windows development team
(internals-win@lists.php.net) so that Windows binaries can be created. Once
those are made, they should be placed into the same directory as the source snapshots.
Getting the non stable release (alpha/beta/RC) announced
--------------------------------------------------------
1. Send an email (see example here: http://news.php.net/php.internals/19486)
**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".
2. Send an email (see example here http://news.php.net/php.pear.qa/5201) **To**
``php-qa@lists.php.net`` and ``primary-qa-tests@lists.php.net``.
This email is 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-tests@lists.php.net`` by having someone (Wez,
Derick) run the following commands for you:
``ssh lists.php.net``
``sudo -u ezmlm ezmlm-sub ~ezmlm/primary-qa-tester/mod moderator-email-address``
3. Update the MD5 sums in ``web/qa/trunk/include/rc-md5sums.txt`` (no empty lines).
4. Update in ``web/qa/trunk/include/release-qa.php`` constants with the new RC and
commit this.
a. ``$BUILD_TEST_RELEASES`` = array("4.4.7RC1", "5.2.2RC1")
b. ``$CURRENT_QA_RELEASE_4`` = "4.4.7RC1" (``$CURRENT_QA_RELEASE_5`` for PHP5)
c. ``$RELEASE_PROCESS`` = array(4 => true, 5 => true)
1. Update in ``php-bugs/trunk/include/functions.inc`` the ``show_version_option``
function to include the new RC and commit.
2. Update ``phpweb/include/version.inc`` (x=major version number)
a. ``$PHP_x_RC`` = "5.3.0RC1"
b. ``$PHP_x_RC_DATE`` = "06 September 2007"
3. Commit those changes:
a. ``cvs commit include/version.inc include/releases.inc``
4. For the first RC, write the doc team (phpdoc@lists.php.net) about updating the
INSTALL and win32/install.txt files which are generated from the PHP manual sources.
Rolling a stable release
------------------------
1. Check windows snapshot builder logs (http://snaps.php.net/win32/snapshot-STABLE.log f.e.)
2. Bump the version numbers in ``main/php_version.h``, ``configure.in`` and possibly ``NEWS``.
3. **Merge** all related sections in NEWS (f.e. merge the 4.4.1RC1 and 4.4.0 sections)
4. Commit those changes
5. run the "scripts/dev/credits" script in php-src and commit the changes in the
credits files in ext/standard.
6. tag the repository with the version f.e. "``cvs tag php_4_4_1``"
(of course, you need to change that to the version you're rolling an RC for).
When making 5.X release, you need to tag the Zend directory separately!!
7. Bump up the version numbers in ``main/php_version.h``, ``configure.in`` and
possibly ``NEWS`` again, to the **next** version. F.e. if the release candidate
was "4.4.1RC1" then the new one should be "4.4.1RC2-dev" - regardless if we get
a new RC or not. This is to make sure ``version_compare()`` can correctly work.
8. Commit those changes
9. Log in onto the snaps box and go into the correct tree (f.e. the PHP_4_4
branch if you're rolling 4.4.x releases).
10. You do not have to update the tree, but of course you can with "``cvs up -dP``".
11. run: ``./makedist php 4.4.1``, this will export the tree, create configure
and build two tarballs (one gz and one bz2).
12. Commit those two tarballs to CVS (phpweb/distributions)
13. Once the release has been tagged, contact the PHP Windows development team
(internals-win@lists.php.net) so that Windows binaries can be created. Once
those are made, they should be committed to CVS too.
14. Check if the pear files are updated (phar for 5.1+ or run pear/make-pear-bundle.php with 4.4)
15. When making a final release, also remind the PHP Windows development team
(internals-win@lists.php.net) to prepare the installer packages for Win32.
Getting the stable release announced
------------------------------------
1. Run the bumpRelease script for phpweb on your local checkout
a. ``php bin/bumpRelease 5`` (or ``php bin/bumpRelease 4`` for PHP4)
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. set ``$PHP_X_RC`` to false!
e. Make sure there are no outdated "notes" or edited "date" keys in the
``$RELEASES[X][$PHP_X_VERSION]["source"]`` array
f. if the windows builds aren't ready yet prefix the "windows" key with a dot (".windows")
3. Update the ChangeLog file for the given major version
f.e. ``ChangeLog-4.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); ?>/``
4. ``cp releases/4_4_0.php releases/4_4_1.php``
5. ``cvs add releases/4_4_1.php``
6. Update the ``releases/*.php`` file with relevant data. The release
announcement file should list in detail:
a. security fixes,
b. changes in behavior (whether due to a bug fix or not)
7. 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
8. Commit all the changes.
9. 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.
10. Update ``php-bugs-web/include/functions.php`` to include the new version
number, and remove the RC from there.
11. Update ``qaweb/include/release-qa.php``
a. Update the $BUILD_TEST_RELEASES array with the release name
b. Update $RELEASE_PROCESS array (set to false)
I. For PHP4: Set $CURRENT_QA_RELEASE_4 to false
II. For PHP5: Set $CURRENT_QA_RELEASE_5 to false
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. 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.
+155
View File
@@ -0,0 +1,155 @@
$Id$
=============================================================================
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
+379
View File
@@ -0,0 +1,379 @@
An Overview of the PHP Streams abstraction
==========================================
$Id$
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 TSRMLS_DC,
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(char *path, char *mode,
int options, char **opened_path TSRMLS_DC);
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 TSRMLS_DC);
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
+152
View File
@@ -0,0 +1,152 @@
Submitting Patches to PHP
=========================
This document describes how to submit a patch for PHP. Creating a
patch for PHP is easy!
You don't need any login accounts or special access to download,
build, debug and begin submitting PHP code, tests or documentation for
inclusion in PHP. Once you've followed this README and had several
patches accepted, PHP commit privileges are often quickly granted.
An excellent article to read first is:
http://phpadvent.org/2008/less-whining-more-coding-by-elizabeth-smith
Prework
-------
If you are fixing broken functionality then create a bug or identify
an existing bug at http://bugs.php.net/. This can be used to track
the patch progress and prevent your changes getting lost in the PHP
mail archives.
If your code change is large, then first discuss it with the extension
maintainer and/or a development mail list. Extension maintainers can
be found in the EXTENSIONS file in the PHP source. Use the
internals@lists.php.net mail list to discuss changes to the base PHP
code. Use pecl-dev@lists.php.net for changes to code that is only
available from PECL (http://pecl.php.net/). Use pear-dev@lists.php.net
for PEAR modules (http://pear.php.net/). Use phpdoc@lists.php.net for
PHP documentation questions. Mail list subscription is explained on
http://www.php.net/mailing-lists.php.
If a PHP or PECL patch affects user functionality or makes significant
internal changes then create a simple Request For Comment (RFC) page
on http://wiki.php.net/rfc before starting discussion. This RFC can be
used for initial discussion and later for documentation. Wiki accounts
can be requested on http://wiki.php.net/start?do=register
Online 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 reference is the book "Extending and Embedding PHP" by Sara
Golemon.
Information on contributing to PEAR is available at
http://pear.php.net/manual/en/guide-developers.php
Information on contributing to PHP documentation is at
http://php.net/dochowto and http://wiki.php.net/doc/howto
There are several IRC channels where PHP developers are often
available to discuss questions. They include #php.pecl and #php.doc
on the EFNet network and #php-dev-win on FreeNode.
How to create your patch
------------------------
PHP uses Subversion (SVN) for revision control. Read
http://www.php.net/svn.php for help on using SVN to get and build PHP
source code. We recommend using a Sparse Directory checkout described
in http://wiki.php.net/vcs/svnfaq. If you are new to SVN, read
http://svnbook.red-bean.com.
Generally we ask that patches work on the current stable PHP
development branch and on "trunk".
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:
svn diff > your_patch.txt
For ease of review and later troubleshooting, submit individual
patches for each bug or feature.
Checklist for submitting your patch
-----------------------------------
- Update SVN source just before running your final 'diff' and
before testing.
- 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 the PHP tests.
- Rebuild PHP with --enable-maintainer-zts to check your patch compiles
on multi-threaded web servers.
- Create test scripts for use with "make test".
- Add in-line comments and/or have external documentation ready.
- Review the patch once more just before submitting it.
Where to send your patch
------------------------
If you are patching PHP C source then email the patch to
internals@lists.php.net
If you patching a PECL extension then send the patch to
pecl-dev@lists.php.net
If you are patching PEAR then send the patch to
pear-dev@lists.php.net
If you are patching PHP's documentation then send the patch to
phpdoc@lists.php.net
The mail can be CC'd to the extension maintainer (see EXTENSIONS).
Please make the subject prefix "[PATCH]", for example "[PATCH] Fix
return value of all array functions"
Include the patch as an attachment with a file extension of ".txt".
This is because only MIME attachments of type 'text/*' are accepted.
Explain what has been fixed/added/changed by your patch. Test scripts
should be included in the email.
Include the bug id(s) which can be closed by your patch.
Finally, update any open bugs and add a link to the source of your
patch.
What happens after you submit your 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 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 which factors?
- Are there any unwanted white space changes?
What happens when your patch is applied
---------------------------------------
Your name will be included in the SVN 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!
+146
View File
@@ -0,0 +1,146 @@
====================
SVN Commit Rules
====================
This is the first file you should be reading after you get your SVN account.
We'll assume you're basically familiar with SVN, but feel free to post
your questions on the mailing list. Please have a look at
http://svnbook.red-bean.com/ for more detailed information on SVN.
PHP is developed through the efforts of a large number of people.
Collaboration is a Good Thing(tm), and SVN lets us do this. Thus, following
some basic rules with regards to SVN usage will::
a. Make everybody happier, especially those responsible for maintaining
the SVN 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-maintainer-zts switch to ensure your
code handles TSRM correctly and doesn't break for thos who need that.
Currently we have the following branches in use::
trunk Will become PHP 6.0. This branch is for active development.
branches/PHP_5_3 Is used to release the PHP 5.3.x series. It still allows for
larger enhancements.
branches/PHP_5_2 Is used to release the PHP 5.2.x series. Only bugfixes are permitted
on this branch (Consult the releasemaster prior to commit).
branches/PHP_5_1 This branch is closed.
branches/PHP_4_4 This branch is closed.
The next few rules are more of a technical nature::
1. All changes should first go to trunk and then get merged from trunk
(aka MFH'ed) to all other relevant branches.
2. DO NOT TOUCH ChangeLog! It is automagically updated from the commit
messages every day. Woe be to those who attempt to mess with it.
3. All news updates intended for public viewing, such as new features,
bug fixes, improvements, etc., should go into the NEWS file of the
*first* to be released version with the given change. In other words
any NEWS file change only needs to done in one branch.
NB! Lines, starting with @ will go automagically into NEWS file, but
this is NOT recommended, though. Please, add news entries directly to
NEWS file and don't forget to keep them adjusted and sorted.
4. Do not commit multiple file 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.
5. 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.
6. 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.
7. 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.
Use a - to start a new item in your commit message.
If a line begins with #, it is taken to be a comment and will not appear
in the ChangeLog. Everything else goes into the ChangeLog.
It is important to note that if your comment or news logline spans multiple
lines, you have to put # at the beginning of **every** such line.
Example. Say you modified two files, datetime.c and string.c. In datetime.c you
added a new format option for the date() function, and in string.c you fixed a
memory leak in php_trim(). Don't commit both of these at once. Commit them
separately and try to make sure your commit messages look something like the
following.
For datetime.c::
- Added new 'K' format modifier to date() for printing out number of days
until New Year's Eve.
For string.c::
- Fixed a memory leak in php_trim() resulting from improper use of zval_dtor().
#- Man, that thing was leaking all over the place!
The # lines will be omitted from the ChangeLog automagically.
Use the [DOC] tag in your log message whenever you feel that your changes
imply a documentation modification. The php-doc team will automatically
get notified about your commit through the php-doc mailing list.
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 SVN via LXR or Bonsai.
Example::
Fixed bug #14016 (pgsql notice handler double free crash bug.)
If you don't see your messages in ChangeLog right away, don't worry!
These files are updated once a day, so your stuff will not show up until
somewhat later.
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 LXR (http://lxr.php.net/) and Bonsai (http://bonsai.php.net/)
to look at PHP SVN repository in various ways.
To receive daily updates to ChangeLog and NEWS, send an empty message to
php-cvs-daily-subscribe@lists.php.net.
Happy hacking,
PHP Team
+180
View File
@@ -0,0 +1,180 @@
[IMPORTANT NOTICE]
------------------
Failed tests usualy indicate a problem with your local system setup
and not within PHP itself (at least for official PHP release versions).
You may decide to automaticaly 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 'SKIP' 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/php5
MYMAIL=qa-test@domain.com
TMPDIR=/var/tmp
TODAY=`date +"%Y%m%d"`
# Make sure compilation enviroment 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);
?>
+137
View File
@@ -0,0 +1,137 @@
[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 accessable 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 equivelant 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 inital 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
+644
View File
@@ -0,0 +1,644 @@
Audience
========
This README describes how PHP 6 provides native support for the Unicode
Standard. Readers of this document should be proficient with PHP and have a
basic understanding of Unicode concepts. For more technical details about
PHP 6 design principles and for guidelines about writing Unicode-ready PHP
extensions, refer to README.UNICODE-UPGRADES.
Introduction
============
As successful as PHP has proven to be over the years, its support for
multilingual and multinational environments has languished. PHP can no
longer afford to remain outside the overall movement towards the Unicode
standard. Although recent updates involving the mbstring extension have
enabled easier multibyte data processing, this does not constitute native
Unicode support.
Since the full implementation of the Unicode Standard is very involved, our
approach is to speed up implementation by using the well-tested,
full-featured, and freely available ICU (International Components for
Unicode) library.
General Remarks
===============
International Components for Unicode
------------------------------------
ICU (International Components for Unicode is a mature, widely used set of
C/C++ and Java libraries for Unicode support, software internationalization
and globalization. It provides:
- Encoding conversions
- Collations
- Unicode text processing
- and much more
When building PHP 6, Unicode support is always enabled. The only
configuration option during development should be the location of the ICU
headers and libraries.
--with-icu-dir=<dir>
where <dir> specifies the location of ICU header and library files. If you do
not specify this option, PHP attempts to find ICU under /usr and /usr/local.
NOTE: ICU is not bundled with PHP 6 yet. To download the distribution, visit
http://icu.sourceforge.net. PHP requires ICU version 3.4 or higher.
Backwards Compatibility
-----------------------
Our paramount concern for providing Unicode support is backwards compatibility.
Because PHP is used on so many sites, existing data types and functions must
work as they always have. However, although PHP's interfaces must remain
backwards-compatible, the speed of certain operations might be affected due to
internal implementation changes.
Encoding Names
--------------
All the encoding settings discussed in this document can accept any valid
encoding name supported by ICU. For a full list of encodings, refer to the ICU
online documentation.
NOTE: References to "Unicode" in this document generally mean the UTF-16
character encoding, unless explicitly stated otherwise.
Unicode Semantics Switch
========================
Because many applications do not require Unicode, PHP 6 provides a server-wide
INI setting to enable Unicode support:
unicode.semantics = On/Off
This switch is off by default. If your applications do not require native
Unicode support, you may leave this switch off, and continue to use Unicode
strings only when you need to.
However, if your application is ready to fully support Unicode, you should
turn this switch on. This activates various Unicode support mechanisms,
including:
* All string literals become Unicode
* All variables received from HTTP requests become Unicode
* PHP identifiers may use Unicode characters
More fundamentally, your PHP environment is now a Unicode environment. Strings
inside PHP are Unicode, and the system is responsible for converting non-Unicode
strings on PHP's periphery (for example, in HTTP input and output, streams, and
filesystem operations). With unicode.semantics on, you must specify binary
strings explicitly. PHP makes no assumptions about the content of a binary
string, so your application must handle all binary string appropriately.
Conversely, if unicode.semantics is off, PHP behaves as it did in the past.
String literals do not become Unicode, and files are binary strings for
backwards compatibility. You can always create Unicode strings programmatically,
and all functions and operators support Unicode strings transparently.
Fallback Encoding
=================
The fallback encoding provides a default value for all other unicode.*_encoding
INI settings. If you do not set a particular unicode.*_encoding setting, PHP
uses the fallback encoding. If you do not specify a fallback encoding, PHP uses
UTF-8.
unicode.fallback_encoding = "iso-8859-1"
Runtime Encoding
================
The runtime encoding specifies the encoding PHP uses for converting binary
strings within the PHP engine itself.
unicode.runtime_encoding = "iso-8859-1"
This setting has no effect on I/O-related operations such as writing to
standard out, reading from the filesystem, or decoding HTTP input variables.
PHP enables you to explicitly convert strings using casting:
* (binary) -- casts to binary string type
* (unicode) -- casts to Unicode string type
* (string) -- casts to Unicode string type if unicode.semantics is on,
to binary otherwise
For example, if unicode.runtime_encoding is iso-8859-1, and $uni is a unicode
string, then
$str = (binary)$uni
creates a binary string $str in the ISO-8859-1 encoding.
Implicit conversions include concatenation, comparison, and parameter passing.
For better precision, PHP attempts to convert strings to Unicode before
performing these sorts of operations. For example, if we concatenate our binary
string $str with a unicode literal, PHP converts $str to Unicode first, using
the encoding specified by unicode.runtime_encoding.
Output Encoding
===============
PHP automatically converts output for commands that write to the standard
output stream, such as 'print' and 'echo'.
unicode.output_encoding = "utf-8"
However, PHP does not convert binary strings. When writing to files or external
resources, you must rely on stream encoding features or manually encode the data
using functions provided by the unicode extension.
The existing default_charset INI setting is DEPRECATED in favor of
unicode.output_setting. Previously, default_charset only specified the charset
portion of the Content-Type MIME header. Now default_charset only takes effect
when unicode.semantics is off, and it does not affect the actual transcoding of
the output stream. Setting unicode.output_encoding causes PHP to add the
'charset' portion to the Content-Type header, overriding any value set for
default_charset.
HTTP Input Encoding
===================
The HTTP input encoding specifies the encoding of variables received via
HTTP, such as the contents of the $_GET and _$POST arrays.
This functionality is currently under development. For a discussion of the
approach that the PHP 6 team is taking, refer to:
http://marc.theaimsgroup.com/?t=116613047300005&r=1&w=2
Filesystem Encoding
===================
The filesystem encoding specifies the encoding of file and directory names
on the filesystem.
unicode.filename_encoding = "utf-8"
Filesystem-related functions such as opendir() perform this conversion when
accepting and returning file names. You should set the filename encoding to
the encoding used by your filesystem.
Script Encoding
===============
You may write PHP scripts in any encoding supported by ICU. To specify the
script encoding site-wide, use the INI setting:
unicode.script_encoding = utf-8
If you cannot change the encoding system wide, you can use a pragma to
override the INI setting in a local script:
<?php declare(encoding = 'Shift-JIS'); ?>
The pragma setting must be the first statement in the script. It only affects
the script in which it occurs, and does not propagate to any included files.
INI Files
=========
If unicode.semantics is on, INI files are presumed to contain UTF-8 encoded
keys and values. If unicode.semantics is off, the data is taken as-is,
similar to PHP 5. No validation occurs during parsing. Instead invalid UTF-8
sequences are caught during access by ini_*() functions.
Stream I/O
==========
PHP has a streams-based I/O system for generalized filesystem access,
networking, data compression, and other operations. Since the data on the
other end of the stream can be in any encoding, you need to think about
data conversion.
Okay, this needs to be clarified. By "default", streams are actually
opened in binary mode. You have to specify 't' flag or use FILE_TEXT in
order to open it in text mode, where conversions apply. And for the text
mode streams, the default stream encoding is UTF-8 indeed.
By default, PHP opens streams in binary mode. To open a file in text mode,
you must use the 't' flag (or the FILE_TEXT parameter -- see below). The
default encoding for streams in text mode is UTF-8. This means that if
'file.txt' is a UTF-8 text file, this code snippet:
$fp = fopen('file.txt', 'rt');
$str = fread($fp, 100)
returns 100 Unicode characters, while:
$fp = fopen('file.txt', 'wt');
$fwrite($fp, $uni)
writes to a UTF-8 text file.
If you mainly work with files in an encoding other than UTF-8, you can
change the default context encoding setting:
stream_default_encoding('Shift-JIS');
$data = file_get_contents('file.txt', FILE_TEXT);
// work on $data
file_put_contents('file.txt', $data, FILE_TEXT);
The file_get_contents() and file_put_contents() functions now accept an
additional parameter, FILE_TEXT. If you provide FILE_TEXT for
file_get_contents(), PHP returns a Unicode string. Without FILE_TEXT, PHP
returns a binary string (which would be appropriate for true binary data, such
as an image file). When writing a Unicode string with file_put_contents(), you
must supply the FILE_TEXT parameter, or PHP generates a warning.
If you need to work with multiple encodings, you can create custom contexts
using stream_context_create() and then pass in the custom context as an
additional parameter. For example:
$ctx = stream_context_create(NULL, array('encoding' => 'big5'));
$data = file_get_contents('file.txt', FILE_TEXT, $ctx);
// work on $data
file_put_contents('file.txt', $data, FILE_TEXT, $ctx);
Conversion Semantics and Error Handling
=======================================
PHP can convert strings explicitly (casting) and implicitly (concatenation,
comparison, and parameter passing. For example, when concatenating a Unicode
string and a binary string, PHP converts the binary string to Unicode for better
precision.
However, not all characters can be converted between Unicode and legacy
encodings. The first possibility is that a string contains corrupt data or
an illegal byte sequence. In this case, the converter simply stops with
a message that resembles:
Warning: Could not convert binary string to Unicode string
(converter UTF-8 failed on bytes (0xE9) at offset 2)
Conversely, if a similar error occurs when attempting to convert Unicode to
a legacy string, the converter generates a message that resembles:
Warning: Could not convert Unicode string to binary string
(converter ISO-8859-1 failed on character {U+DC00} at offset 2)
To customize this behavior, refer to "Creating a Custom Error Handler" below.
The second possibility is that a Unicode character simply cannot be represented
in the legacy encoding. By default, when downconverting from Unicode, the
converter substitutes any missing sequences with the appropriate substitution
sequence for that codepage, such as 0x1A (Control-Z) in ISO-8859-1. When
upconverting to Unicode, the converter replaces any byte sequence that has no
Unicode equivalent with the Unicode substitution character (U+FFFD).
You can customize the conversion error behavior to:
- stop the conversion and return an empty string
- skip any invalid characters
- substitute invalid characters with a custom substitution character
- escape the invalid character in various formats
To control the global conversion error settings, use the functions:
unicode_set_error_mode(int direction, int mode)
unicode_set_subst_char(unicode char)
where direction is either FROM_UNICODE or TO_UNICODE, and mode is one of these
constants:
U_CONV_ERROR_STOP
U_CONV_ERROR_SKIP
U_CONV_ERROR_SUBST
U_CONV_ERROR_ESCAPE_UNICODE
U_CONV_ERROR_ESCAPE_ICU
U_CONV_ERROR_ESCAPE_JAVA
U_CONV_ERROR_ESCAPE_XML_DEC
U_CONV_ERROR_ESCAPE_XML_HEX
As an example, with a runtime encoding of ISO-8859-1, the conversion:
$str = (binary)"< \u30AB >";
results in:
MODE RESULT
--------------------------------------
stop ""
skip "< >"
substitute "< ? >"
escape (Unicode) "< {U+30AB} >"
escape (ICU) "< %U30AB >"
escape (Java) "< \u30AB >"
escape (XML decimal) "< &#12459; >"
escape (XML hex) "< &#x30AB; >"
With a runtime encoding of UTF-8, the conversion of the (illegal) sequence:
$str = (unicode)b"< \xe9\xfe >";
results in:
MODE RESULT
--------------------------------------
stop ""
skip ""
substitute ""
escape (Unicode) "< %XE9%XFE >"
escape (ICU) "< %XE9%XFE >"
escape (Java) "< \xE9\xFE >"
escape (XML decimal) "< &#233;&#254; >"
escape (XML hex) "< &#xE9;&#xFE; >"
The substitution character can be set only for FROM_UNICODE direction and has to
exist in the target character set. The default substitution character is (?).
NOTE: Casting is just a shortcut for using unicode.runtime_encoding. To convert
using an alternative encoding, use the unicode_encode() and unicode_decode()
functions. For example,
$str = unicode_encode($uni, 'koi8-r', U_CONV_ERROR_SUBST);
results in a binary KOI8-R encoded string.
Creating a Custom Error Handler
-------------------------------
If an error occurs during the conversion, PHP outputs a warning describing the
problem. Instead of this default behavior, PHP can invoke a user-provided error
handler, similar to how the current user-defined error handler works. To set
the custom conversion error handler, call:
mixed unicode_set_error_handler(callback error_handler)
The function returns the previously defined custom error handler. If no error
handler was defined, or if an error occurs when returning the handler, this
function returns NULL.
When the custom handler is set, the standard error handler is bypassed. It is
the responsibility of the custom handler to output or log any messages, raise
exceptions, or die(), if necessary. However, if the custom error handler returns
FALSE, the standard handler will be invoked afterwards.
The user function specified as the error_handler must accept five parameters:
mixed error_handler($direction, $encoding, $char_or_byte, $offset,
$message)
where:
$direction - the direction of conversion, FROM_UNICODE/TO_UNICODE
$encoding - the name of the encoding to/from which the conversion
was attempted
$char_or_byte - either Unicode character or byte sequence (depending
on direction) which caused the error
$offset - the offset of the failed character/byte sequence in
the source string
$message - the error message describing the problem
NOTE: If the error mode set by unicode_set_error_mode() is substitute,
skip, or escape, the handler won't be called, since these are non-error
causing operations. To always invoke your handler, set the error mode to
U_CONV_ERROR_STOP.
Unicode String Type
===================
The Unicode string type (IS_UNICODE) is supposed to contain text data encoded in
UTF-16. This is the main string type in PHP when Unicode semantics switch is
turned on. Unicode strings can exist when the switch is off, but they have to be
produced programmatically via calls to functions that return Unicode types.
Binary String Type
==================
Binary string type (IS_STRING) serves two purposes: backwards compatibility and
representing non-Unicode strings and binary data. When Unicode semantics switch
is off, it is used for all strings in PHP, same in previous versions. When the
switch is on, this type will be used to store text in other encodings as well as
true binary data such as images, PDFs, etc.
Printing binary data to the standard output passes it through as-is, independent
of the output encoding.
For examples of specifying binary string literals, refer to the section
"Language Modfications".
Language Modifications
======================
If a Unicode switch is turned on, PHP string literals -- single-quoted,
double-quoted, and heredocs -- become Unicode strings (IS_UNICODE type). String
literals support all the same escape sequences and variable interpolations as
before, plus several new escape sequences.
PHP interprets the contents of strings as follows:
- all non-escaped characters are interpreted as a corresponding Unicode
codepoint based on the current script encoding, e.g. ASCII 'a' (0x61) =>
U+0061, Shift-JIS (0x92 0x86) => U+4E2D
- existing PHP escape sequences are also interpreted as Unicode codepoints,
including \xXX (hex) and \OOO (octal) numbers, e.g. "\x20" => U+0020
- two new escape sequences, \uXXXX and \UXXXXXX, are interpreted as a 4 or
6-hex Unicode codepoint value, e.g. \u0221 => U+0221, \U010410 =>
U+10410. (Having two sequences avoids the ambiguity of \u020608 --
is that supposed to be U+0206 followed by "08", or U+020608 ?)
- a new escape sequence allows specifying a character by its full
Unicode name, e.g. \C{THAI CHARACTER PHO SAMPHAO} => U+0E20
PHP allows variable interpolation inside the double-quoted and heredoc strings.
However, the parser separates the string into literal and variable chunks during
compilation, e.g. "abc $var def" -> "abc" . $var . "def". This means that PHP
can handle literal chunks in the normal way as far as Unicode support is
concerned.
Since all string literals become Unicode by default, PHP 6 introduces new syntax
for creating byte-oriented or binary strings. Prefixing a string literal with
the letter 'b' creates a binary string:
$var = b'abc\001';
$var = b"abc\001";
$var = b<<<EOD
abc\001
EOD;
The content of a binary string is the literal byte sequence inside the
delimiters, which depends on the script encoding (unicode.script_encoding).
Binary string literals support the same escape sequences as PHP 5 strings. If
the Unicode switch is turned off, then the binary string literals generate the
normal string (IS_STRING) type internally without any effect on the application.
The string operators now accomodate the new IS_UNICODE and IS_BINARY types:
- The concatenation operator (.) and concatenation assignment operator (.=)
automatically coerce the IS_STRING type to the more precise IS_UNICODE if
the operands are of different string types.
- The string indexing operator [] now accommodates IS_UNICODE type strings
and extracts the specified character. To support supplementary characters,
the index specifies a code point, not a byte or a code unit.
- Bitwise operators and increment/decrement operators do not work on
Unicode strings. They do work on binary strings.
- Two new casting operators are introduced, (unicode) and (binary). The
(string) operator casts to Unicode type if the Unicode semantics switch is
on, and to binary type otherwise.
- The comparison operators compare Unicode strings in binary code point
order. They also coerce strings to Unicode if the strings are of different
types.
- The arithmetic operators use the same semantics as today for converting
strings to numbers. A Unicode string is considered numeric if it
represents a long or a double number in the en_US_POSIX locale.
Unicode Support in Existing Functions
=====================================
All functions in the PHP default distribution are undergoing analysis to
determine which functions need to be upgraded for native Unicode support.
You can track progress here:
http://www.php.net/~scoates/unicode/render_func_data.php
Key extensions that are fully converted include:
* curl
* dom
* json
* mysql
* mysqli
* oci8
* pcre
* reflection
* simplexml
* soap
* sqlite
* xml
* xmlreader/xmlwriter
* xsl
* zlib
NOTE: Unsafe functions might still work, since PHP performs Unicode conversions
at runtime. However, unsafe functions might not work correctly with multibyte
binary strings, or Unicode characters that are not representable in the
specified unicode.runtime_encoding.
Identifiers
===========
Since scripts may be written in various encodings, we do not restrict
identifiers to be ASCII-only. PHP allows any valid identifier based
on the Unicode Standard Annex #31.
Numbers
=======
Unlike identifiers, numbers must consist only of ASCII digits,.and are
restricted to the en_US_POSIX or C locale. In other words, numbers have no
thousands separator, and the fractional separator is (.) "full stop". Numeric
strings adhere to the same rules, so "10,3" is not interpreted as a number even
if the current locale's fractional separator is a comma.
TextIterators
=============
Instead of using the offset operator [] to access characters in a linear
fashion, use a TextIterator instead. TextIterator is very fast and enables you
to iterate over code points, combining sequences, characters, words, lines, and
sentences, both forward and backward. For example:
$text = "nai\u308ve";
foreach (new TextIterator($text) as $u) {
var_inspect($u)
}
lists six code points, including the umlaut (U+0308) as a separate code point.
Instantiating the TextIterator to iterate over characters,
$text = "nai\u308ve";
foreach (new TextIterator($text, TextIterator::CHARACTER) as $u) {
var_inspect($u)
}
lists five characters, including an "i" with an umlaut as a single character.
Locales
=======
Unicode support in PHP relies exclusively on ICU locales, NOT the POSIX locales
installed on the system. You may access the default ICU locale using:
locale_set_default()
locale_get_default()
ICU locale IDs have a somewhat different format from POSIX locale IDs. The ICU
syntax is:
<language>[_<script>]_<country>[_<variant>][@<keywords>]
For example, sr_Latn_YU_REVISED@currency=USD is Serbian (Latin, Yugoslavia,
Revised Orthography, Currency=US Dollar).
Do not use the deprecated setlocale() function. This function interacts with the
POSIX locale. If Unicode semantics are on, using setlocale() generates
a deprecation warning.
Document TODO
==========================================
- Final review.
- Fix the HTTP Input Encoding section, that's obsolete now.
References
==========
Unicode
http://www.unicode.org
Unicode Glossary
http://www.unicode.org/glossary/
UTF-8
http://www.utf-8.com/
UTF-16
http://www.ietf.org/rfc/rfc2781.txt
ICU Homepage
http://www.ibm.com/software/globalization/icu/
ICU User Guide and API Reference
http://icu.sourceforge.net/
Unicode Annex #31
http://www.unicode.org/reports/tr31/
PHP Parameter Parsing API
http://www.php.net/manual/en/zend.arguments.retrieval.php
Authors
=======
Andrei Zmievski <andrei@gravitonic.com>
Evan Goer <goer@yahoo-inc.com>
vim: set et tw=80 :
+806
View File
@@ -0,0 +1,806 @@
This document attempts to describe portions of the API related to the new
Unicode functionality and the best practices for upgrading existing
functions to support Unicode.
Your first stop should be README.UNICODE: it covers the general Unicode
functionality and concepts without going into technical implementation
details.
Internal Encoding
=================
UTF-16 is the internal encoding used for Unicode strings. UTF-16 consumes
two bytes for any Unicode character in the Basic Multilingual Plane, which
is where most of the current world's languages are represented. While being
less memory efficient for basic ASCII text it simplifies the processing and
makes interfacing with ICU easier, since ICU uses UTF-16 for its internal
processing as well.
Zval Structure Changes
======================
For IS_UNICODE type, we add another structure to the union:
union {
....
struct {
UChar *val; /* Unicode string value */
int len; /* number of UChar's */
} ustr;
....
} value;
This cleanly separates the two types of strings and helps preserve backwards
compatibility.
To optimize access to IS_STRING and IS_UNICODE storage at runtime, we need yet
another structure:
union {
....
struct { /* Universal string type */
zstr val;
int len;
} uni;
....
} value;
Where zstr is a union of char*, UChar*, and void*.
Parameter Parsing API Modifications
===================================
There are now five new specifiers: 'u', 't', 'T', 'U', 'S', 'x' and a new '&'
modifier.
't' specifier
-------------
This specifier indicates that the caller requires the incoming parameter to be
string data (IS_STRING, IS_UNICODE). The caller has to provide the storage for
string value, length, and type.
void *str;
int len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &str, &len, &type) == FAILURE) {
return;
}
if (type == IS_UNICODE) {
/* process Unicode string */
} else {
/* process binary string */
}
For IS_STRING type, the length represents the number of bytes, and for
IS_UNICODE the number of UChar's. When converting other types (numbers,
booleans, etc) to strings, the exact behavior depends on the Unicode semantics
switch: if on, they are converted to IS_UNICODE, otherwise to IS_STRING.
'u' specifier
-------------
This specifier indicates that the caller requires the incoming parameter
to be a Unicode encoded string. If a non-Unicode string is passed, the engine
creates a copy of the string and automatically convert it to Unicode type before
passing it to the internal function. No such conversion is necessary for Unicode
strings, obviously.
UChar *str;
int len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &len) == FAILURE) {
return;
}
/* process Unicode string */
'T' specifier
-------------
This specifier is useful when the function takes two or more strings and
operates on them. Using 't' specifier for each one would be somewhat
problematic if the passed-in strings are of mixed types, and multiple
checks need to be performed in order to do anything. All parameters
marked by the 'T' specifier are promoted to the same type.
If at least one of the 'T' parameters is of Unicode type, then the rest of
them are converted to IS_UNICODE. Otherwise all 'T' parameters are conveted to
IS_STRING type.
void *str1, *str2;
int len1, len2;
zend_uchar type1, type2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "TT", &str1, &len1,
&type1, &str2, &len2, &type2) == FAILURE) {
return;
}
if (type1 == IS_UNICODE) {
/* process as Unicode, str2 is guaranteed to be Unicode as well */
} else {
/* process as binary string, str2 is guaranteed to be the same */
}
'x' specifier
-------------
This specifier acts as either 'u' or 's', depending on the value of the
unicode semantics switch. If UG(unicode) is on, it behaves as 'u', and as
's' otherwise.
The existing 's' specifier has been modified as well. If a Unicode string is
passed in, it automatically copies and converts the string to the runtime
encoding, and issues a warning. If a binary type is passed-in, no conversion
is necessary. The '&' modifier can be used after 's' specifier to force
a different converter instead.
char *str;
int len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &str, &len, UG(utf8_conv)) == FAILURE) {
return;
}
/* here str is in UTF-8, if a Unicode string was passed in */
The 'U' and 'S' specifiers are similar to 'u' and 's' but they are more strict
about the type of the passed-in parameter. If 'U' is specified and the binary
string is passed in, the engine will issue a warning instead of doing automatic
conversion. The converse applies to the 'S' specifier.
Working in Unicode World
========================
Strings
-------
A lot of internal functionality is controlled by the unicode.semantics
switch. Its value is found in the Unicode globals variable, UG(unicode). It
is either on or off for the entire request.
The big thing is that there is a new string types: IS_UNICODE.
This has its own storage in the value union part of
zval (value.ustr) while non-unicode (binary) strings reuse the
IS_STRING type and the value.str element of the zval.
New macros exist (parallel to Z_STRVAL/Z_STRLEN) for accessing unicode strings.
Z_USTRVAL(), Z_USTRLEN()
- accesses the value (as a UChar*) and length (in code units) of the Unicode type string
value.ustr.val value.ustr.len
Z_UNIVAL(), Z_UNILEN()
- accesses the value (as a zstr) and length (in type-appropriate units)
value.uni.val value.uni.len
Z_USTRCPLEN()
- gives the number of codepoints (not units) in the Unicode type string
This macro examines the actual string taking into account Surrogate Pairs
and returns the number of UChar32(UTF32) codepoints which may be less than the
number of UChar(UTF16) codeunits found in the string buffer.
If this value will be used repeatedly, consider storing it in a local variable
to avoid having to reexamine the string every time.
ZVAL_* macros
-------------
The 'dup' parameter to the ZVAL_STRING()/RETVAL_STRING()/RETURN_STRING() type
macros has been extended slightly. The following defines are now encouraged instead:
#define ZSTR_DUPLICATE (1<<0)
#define ZSTR_AUTOFREE (1<<1)
ZSTR_DUPLICATE (which has a resulting value of 1) serves the same purpose as a
truth value in old-style 'dup' flags. The value of 1 was specifically chosen
to match the common practice of passing a 1 for this parameter.
Warning: If you find extension code which uses a truth value other than one for
the dup flag, its logic should be modified to explicitly pass ZSTR_DUPLICATE instead.
ZSTR_AUTOFREE is used with macros such as ZVAL_RT_STRING which may populate Unicode
zvals from non-unicode source strings. When UG(unicode) is on, the source string
will be implicitly copied (to make a UChar* version). If the original string
needed copying anyway this is fine. However if the original string was emalloc()'d
and would have ordinarily been given to the engine (i.e. RETURN_STRING(estrdup("foo"), 0))
then it will need to be freed in UG(unicode) mode to avoid leaking.
The ZSTR_AUTOFREE flag ensures that the original string is freed in UG(unicode) mode.
ZVAL_UNICODE(pzv, str, dup), ZVAL_UNICODEL(pzv, str, str_len, dup)
- Sets zval to hold a Unicode string. Takes the same parameters as
Z_STRING(), Z_STRINGL().
ZVAL_U_STRING(conv, pzv, str, dup), ZVAL_U_STRINGL(conv, pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), ZSTRINGL()
and the conv parameter is ignored.
When UG(unicode) is on, it sets zval to hold a Unicode representation of the
passed-in string using the UConverter* specified by conv.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_RT_STRING(pzv, str, dup), ZVAL_RT_STRINGL(pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), Z_STRINGL().
When UG(unicode) is on, it takes the input string, converts it to Unicode
using the runtime_encoding converter and sets zval to it.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_ASCII_STRING(pzv, str, dup), ZVAL_ASCII_STRINGL(pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), Z_STRINGL().
When UG(unicode) is on, it takes the input string, converts it to Unicode
using an ASCII converter and sets zval to it.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_UTF8_STRING(pzv, str, dup), ZVAL_UTF8_STRINGL(pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), Z_STRINGL().
When UG(unicode) is on, it takes the input string, converts it to Unicode
using a UTF8 converter and sets zval to it.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_ZSTR(pzv, type, zstr, dup), ZVAL_ZSTRL(pzv, type, zstr, zstr_len, dup)
- This macro uses 'type' to switch between calling ZVAL_STRING(pzv, zstr.s, dup)
and ZVAL_UNICODE(pzv, zstr.u, dup). No conversion happens so the
presense of absense of ZSTR_AUTOFREE is ignored.
ZVAL_TEXT(pzv, zstr, dup), ZVAL_TEXTL(pzv, zstr, zstr_len, dup)
- This macro sets the zval to hold either a Unicode or a normal string,
depending on the value of UG(unicode). No conversion happens, so be certain
that the string passed in matches the type expected by UG(unicode).
One example of its usage would be to initialize zval to hold the name
of a user function.
ZVAL_EMPTY_UNICODE(pzv) / ZVAL_EMPTY_TEXT(pzv)
- These macros work identically to ZVAL_EMPTY_STRING() with the UNICODE
version always generating an IS_UNICODE zval, and the TEXT version
generating a UG(unicode) dependent string type.
ZVAL_UCHAR32(pzv, char)
- Converts the character provided into a UChar string (which may potentially
be 1 or 2 characters long in the case of surrogate pairs) and dispatches
to ZVAL_UNICODEL().
As usual, for each ZVAL_* macro, there is a matching RETVAL_* and RETURN_* macro.
Conversion Macros
-----------------
convert_to_string_with_converter(zval *op, UConverter *conv)
- converts a zval to native string using the specified converter, if necessary.
convert_to_unicode_with_converter(zval *op, UConverter *conv)
- converts a zval to Unicode string using the specified converter, if
necessary.
convert_to_unicode(zval *op)
- converts a zval to Unicode string.
convert_to_string(zval *op)
- Behaves just as it currently does, converting to IS_STRING type
convert_to_text(zval *op)
- converts a zval to either Unicode or native string, depending on the
value of UG(unicode) switch
zend_ascii_to_unicode() function can be used to convert an ASCII char*
string to Unicode. This is useful especially for inline string literals, in
which case you can simply use USTR_MAKE() macro, e.g.:
UChar* ustr;
ustr = USTR_MAKE("main");
If you need to initialize a few such variables, it may be more efficient to
use ICU macros, which avoid the conversion, depending on the platform. See
[1] for more information.
USTR_FREE(zstr) can be used to free a UChar* string safely, since it checks for
NULL argument. USTR_LEN() takes a zstr as its argument, and
depending on the UG(unicode) value, and returns its strlen() or u_strlen().
Array Manipulation
------------------
The add_next_index_*(), add_index_*() and add_assoc_*() functions have been
significantly expanded both to allow for the unicode type as a value and to
permit various types of keys.
Values: In the following examples, {1} represents a placeholder for the keytype and
its arguments (covered later).
add_{1}_unicode(zval *arr, {1}, UChar *ustr, int dup);
add_{1}_unicodel(zval *arr, {1}, UChar *ustr, int ustr_len, int dup);
- Works like add_{1}_string() and add_{1}_stringl() but takes a UChar* value
and adds an IS_UNICODE type.
add_{1}_rt_string(zval *arr, {1}, char *str, int dup);
add_{1}_rt_stringl(zval *arr, {1}, char *str, int str_len, int dup);
- Works like add_{1}_string() and add_{1}_stringl() but converts the char*
value to Unicode using runtime encoding when UG(unicode) is on.
add_{1}_ascii_string(zval *arr, {1}, char *str, int dup);
add_{1}_ascii_stringl(zval *arr, {1}, char *str, int str_len, int dup);
- Works like add_{1}_rt_string() and add_{1}_rt_stringl() but uses
an ASCII converter rather than runtime encoding.
add_{1}_utf8_string(zval *arr, {1}, char *str, int dup);
add_{1}_utf8_stringl(zval *arr, {1}, char *str, int str_len, int dup);
- Works like add_{1}_rt_string() and add_{1}_rt_stringl() but uses
a UTF8 converter rather than runtime encoding.
add_{1}_text(zval *arr, {1}, zstr str, int dup);
add_{1}_textl(zval *arr, {1}, zstr str, int str_len, int dup);
- Wrapper which dispatches to add_{1}_string(l)() or add_{1}_unicode(l)()
depending on the setting of UG(unicode).
add_{1}_zstr(zval *arr, {1}, zend_uchar type, zstr str, int dup);
add_{1}_zstrl(zval *arr, {1}, zend_uchar type, zstr str, int str_len, int dup);
- Works like add_{1}_text() and add_{1}_textl(), but dispatches based on 'type'.
Keys: In the following example, the zval* type is used for values, however
each of the value types (including those listed above) are supported.
The existing key types work as they always have:
add_next_index_zval(zval *arr, zval *val);
add_index_zval(zval *arr, long idx, zval *val);
add_assoc_zval(zval *arr, char *key, zval *val);
add_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. Associative keys are considered binary (IS_STRING)
. Remember that key_len includes the terminating NULL
The following additional methods provide unicode capable keytypes:
add_u_assoc_zval(zval *arr, zend_uchar type, zstr key, zval *val);
add_u_assoc_zval_ex(zval *arr, zend_uchar type, zstr key, int key_len, zval *val);
. When type==IS_STRING, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When type==IS_STRING, the key is considered to be Unicode (UChar*).
add_rt_assoc_zval(zval *arr, char *key, zval *val);
add_rt_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. When UG(unicode) is off, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When UG(unicode) is on, key is converted to Unicode using runtime encoding.
add_ascii_assoc_zval(zval *arr, char *key, zval *val);
add_ascii_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. When UG(unicode) is off, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When UG(unicode) is on, key is converted to Unicode using an ASCII converter.
add_utf8_assoc_zval(zval *arr, char *key, zval *val);
add_utf8_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. When UG(unicode) is off, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When UG(unicode) is on, key is converted to Unicode using a UTF8 converter.
Keytype and Valuetype specification may be mixed in any combination, for example:
add_utf8_assoc_ascii_stringl_ex(zval *arr, char *key, int key_len, char *val, int val_len, int dup);
Miscellaneous
-------------
UBYTES() macro can be used to obtain the number of bytes necessary to store
the given number of UChar's. The typical usage is:
char *constant_name = colon + (UG(unicode)?UBYTES(2):2);
Code Points and Code Units
--------------------------
Unicode type strings are in the UTF-16 encoding where 1 Unicode character
may be represented by 1 or 2 UChar's. Each UChar is referred to as a "code
unit", and a full Unicode character as a "code point". Consequently, number
of code units and number of code points for the same Unicode string may be
different. This has many implications, the most important of which is that
you cannot simply index the UChar* string to get the desired codepoint.
The zval's value.ustr.len contains the number of code units (UChar -- UTF16).
To obtain the number of code points, one can use u_countChar32() ICU API
function or Z_USTRCPLEN() macro.
ICU provides a number of macros for working with UTF-16 strings on the
codepoint level [2]. They allow you to do things like obtain a codepoint at
random code unit offset, move forward and backward over the string, etc.
There are two versions of iterator macros, *_SAFE and *_UNSAFE. It is strong
recommended to use *_SAFE version, since they handle unpaired surrogates and
check for string boundaries. Here is an example of how to move through
UChar* string and work on codepoints.
UChar *str = ...;
int32_t str_len = ...;
UChar32 codepoint;
int32_t offset = 0;
while (offset < str_len) {
U16_NEXT(str, offset, str_len, codepoint);
/* now we have the Unicode character in codepoint */
}
There is not macro to get a codepoint at a certain code point offset, but
there is a Zend API function that does it.
inline UChar32 zend_get_codepoint_at(UChar *str, int32_t length, int32_t n);
To retrieve 3rd codepoint, you would call:
zend_get_codepoint_at(str, str_len, 3);
If you have a UChar32 codepoint and need to put it into a UChar* string,
there is another helper function, zend_codepoint_to_uchar(). It takes
a single UChar32 and converts it to a UChar sequence (1 or 2 UChar's).
UChar buf[8];
UChar32 codepoint = 0x101a2;
int8_t num_uchars;
num_uchars = zend_codepoint_to_uchar(codepoint, buf);
The return value is the number of resulting UChar's or 0, which indicates
invalid codepoint.
Memory Allocation
-----------------
For ease of use and to reduce possible bugs, there are memory allocation
functions specific to Unicode strings. Please use them at all times when
allocating UChar's.
eumalloc(size)
eurealloc(ptr, size)
eustrndup(s, length)
eustrdup(s)
peumalloc(size, persistent)
peurealloc(ptr, size, persistent)
The size parameter refers to the number of UChar's, not bytes.
zend_zstrndup(type, zstr, length)
Hashes
------
Hashes API has been upgraded to work with Unicode and binary strings. All
hash functions that worked with string keys now have their equivalent
zend_u_hash_* API. The zend_u_hash_* functions take the type of the key
string as the second argument.
When UG(unicode) switch is on, the IS_STRING keys are upconverted to
IS_UNICODE and then used in the hash lookup.
A new HASH_KEY constant has been added for differentiating key types:
. HASH_KEY_IS_UNICODE
Note that zend_hash_get_current_key_ex() does not have a zend_u_hash_*
version. It returns the key as a char* pointer, you can can cast it
appropriately based on the key type.
Identifiers and Class Entries
-----------------------------
In Unicode mode all the identifiers are Unicode strings. This means that
while various structures such as zend_class_entry, zend_function, etc store
the identifier name as a char* pointer, it will actually point to UChar*
string. Be careful when accessing the names of classes, functions, and such
-- always check UG(unicode) before using them.
Formatted Output
----------------
Since UTF-16 strings frequently contain NULL bytes, you cannot simpley use
%s format to print them out. Towards that end, output functions such as
php_printf(), spprintf(), etc now have three different formats for use with
Unicode strings:
%r
This format treats the corresponding argument as a Unicode string. The
string is automatically converted to the output encoding. If you wish to
apply a different converter to the string, use %*r and pass the
converter before the string argument.
UChar *class_name = USTR_NAME("ReflectionClass");
zend_printf("%r", class_name);
spprintf(&utf8_buffer, 0, "%*r", UG(utf8_conv), class_name);
%R
This format requires at least two arguments: the first one specifies the
type of the string to follow (IS_STRING or IS_UNICODE), and the second
one - the string itself. If the string is of Unicode type, it is
automatically converted to the output encoding. If you wish to apply
a different converter to the string, use %*R and pass the converter
before the string argument.
zend_throw_exception_ex(U_CLASS_ENTRY(reflection_exception_ptr), 0 TSRMLS_CC,
"Interface %R does not exist",
Z_TYPE_P(class_name), Z_UNIVAL_P(class_name));
%v
This format takes only one parameter, the string, but the expected
string type depends on the UG(unicode) value. If the string is of
Unicode type, it is automatically converted to the output encoding. If
you wish to apply a different converter to the string, use %*R and pass
the converter before the string argument.
zend_error(E_WARNING, "%v::__toString() did not return anything",
Z_OBJCE_P(object)->name);
%Z
This format prints a zval's value. You can specify the minimum length
of the string representation using "%*Z" as well as the absolute length
using "%.*Z". The following example is taken from the engine and
therefor uses zend_spprintf rather than spprintf. Further more clen is
an integer that is smaller than Z_UNILEN_P(callable).
zend_spprintf(error, 0, "class '%.*Z' not found", clen, callable);
The function allows to output any kind of zval values, as long as a
string (or unicode) conversion is available. Note that printing non
string zvals outside of request time is not possible.
Since [v]spprintf() can only output native strings there are also the new
functions [v]uspprintf() and [v]zspprintf() that create unicode strings and
return the number of characters printed. That is they return the length rather
than the byte size. The second pair of functions also takes an additional type
parameter that allows to create a string of arbitrary type. The following
example illustrates the use. Assume it fetches a unicode/native string into
path, path_len and path_type inorder to create sub_name, sub_len and sub_type.
zstr path, sub_name;
int path_len, sub_len;
zend_uchar path_type, sub_type;
/* fetch */
if (path.v) {
sub_type = path_type;
sub_len = zspprintf(path_type, &sub_name, 0, "%R%c%s",
path_type, path,
DEFAULT_SLASH,
entry.d_name);
}
Upgrading Functions
===================
Let's take a look at a couple of functions that have been upgraded to
support new string types.
substr()
--------
This functions returns part of a string based on offset and length
parameters.
zstr str;
int str_len, cp_len;
zend_uchar str_type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "tl|l", &str, &str_len, &str_type, &f, &l) == FAILURE) {
return;
}
The first thing we notice is that the incoming string specifier is 't',
which means that we can accept all 3 string types. The 'str' variable is
declared as zstr, because it can point to either UChar* or char*.
The actual type of the incoming string is stored in 'str_type' variable.
if (str_type == IS_UNICODE) {
cp_len = u_countChar32(str.u, str_len);
} else {
cp_len = str_len;
}
If the string is a Unicode one, we cannot rely on the str_len value to tell
us the number of characters in it. Instead, we call u_countChar32() to
obtain it.
The next several lines normalize start and length parameters to fit within the
string. Nothing new here. Then we locate the appropriate segment.
if (str_type == IS_UNICODE) {
int32_t start = 0, end = 0;
U16_FWD_N(str.u, end, str_len, f);
start = end;
U16_FWD_N(str.u, end, str_len, l);
RETURN_UNICODEL(str.u + start, end-start, ZSTR_DUPLICATE);
Since codepoint (character) #n is not necessarily at offset #n in Unicode
strings, we start at the beginning and iterate forward until we have gone
through the required number of codepoints to reach the start of the segment.
Then we save the location in 'start' and continue iterating through the number
of codepoints specified by the offset. Once that's done, we can return the
segment as a Unicode string.
} else {
RETURN_STRINGL(str.s + f, l, ZSTR_DUPLICATE);
}
For native strings, we can return the segment directly.
strrev()
--------
Let's look at strrev() which requires somewhat more complicated upgrade.
While one of the guidelines for upgrades is that combining sequences are not
really taken into account during processing -- substr() can break them up,
for example -- in this case, we actually should be concerned, because
reversing combining sequence may result in a completely different string. To
illustrate:
a (U+0061 LATIN SMALL LETTER A)
o (U+006f LATIN SMALL LETTER O)
+ ' (U+0301 COMBINING ACUTE ACCENT)
+ _ (U+0320 COMBINING MINUS SIGN BELOW)
l (U+006C LATIN SMALL LETTER L)
Reversing this would result in:
l (U+006C LATIN SMALL LETTER L)
+ _ (U+0320 COMBINING MINUS SIGN BELOW)
+ ' (U+0301 COMBINING ACUTE ACCENT)
o (U+006f LATIN SMALL LETTER O)
a (U+0061 LATIN SMALL LETTER A)
All of a sudden the combining marks are being applied to 'l' instead of 'o'.
To avoid this, we need to treat combininig sequences as a unit, by checking
the combining character class of each character with u_getCombiningClass().
strrev() obtains its single argument, a string, and unless the string is of
Unicode type, processes it exactly as before, simply swapping bytes around.
For Unicode case, the magic is like this:
int32_t i, x1, x2;
UChar32 ch;
UChar *u_s, *u_n, *u_p;
u_n = eumalloc(Z_USTRLEN_PP(str)+1);
u_p = u_n;
u_s = Z_USTRVAL_PP(str);
i = Z_USTRLEN_PP(str);
while (i > 0) {
U16_PREV(u_s, 0, i, ch);
if (u_getCombiningClass(ch) == 0) {
u_p += zend_codepoint_to_uchar(ch, u_p);
} else {
x2 = i;
do {
U16_PREV(u_s, 0, i, ch);
} while (u_getCombiningClass(ch) != 0);
x1 = i;
while (x1 <= x2) {
U16_NEXT(u_s, x1, Z_USTRLEN_PP(str), ch);
u_p += zend_codepoint_to_uchar(ch, u_p);
}
}
}
*u_p = 0;
The basic idea is to walk the string backwards from the end, using
U16_PREV() macro. If the combining class of the current character is 0,
meaning it's a base character and not a combining mark, we simply append it
to the new string. Otherwise, we save the location of the index and do a run
over the characters until we get to the next one with combining class 0. At
that point we append the sequence as is, without reversing, to the new
string. Voila.
Note that the code uses zend_codepoint_to_uchar() to convert full Unicode
characters (UChar32 type) to 1 or 2 UTF-16 code units (UChar type).
realpath()
----------
Filenames use their own converter as it's not uncommon, for example,
to need to access files on a filesystem with latin1 entries while outputting
UTF8 runtime content.
The most common approach to parsing filenames can be found in realpath():
zval **ppfilename;
char *filename;
int filename_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &ppfilename) == FAILURE ||
php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
return;
}
Here, the filename is taken first as a generic zval**, then converted (separating if necessary)
and populated into local char* and int storage. The filename will be converted according to
unicode.filesystem_encoding unless the wrapper specified overrides this with its own conversion
function (The http:// wrapper, for example, enforces utf8 conversion).
rmdir()
-------
If the function accepts a context parameter, then this context should be used in place of FG(default_context)
zval **ppdir, *zcontext = NULL;
char *dir;
int dir_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|r", &ppdir, &zcontext) == FAILURE) {
return;
}
context = php_stream_context_from_zval(zcontext, 0);
if (php_stream_path_param_encode(ppdir, &dir, &dir_len, REPORT_ERRORS, context) == FAILURE) {
return;
}
sqlite_query()
--------------
If the function's underlying library expects a particular encoding (i.e. UTF8), then the alternate form of
the string parameter may be used with zend_parse_parameters().
char *sql;
int sql_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &sql, &sql_len, UG(utf8_conv)) == FAILURE) {
return;
}
Converters
==========
Standard Converters
-------------------
The following converters (UConverter*) are initialized by Zend and are always available (regardless of UG(unicode) mode):
UG(utf8_conv)
UG(ascii_conv)
UG(fallback_encoding_conv) - UTF8 unless overridden by INI setting unicode.fallback_encoding
Additional converters will be optionally initialized depending on INI settings:
UG(runtime_encoding_conv) - unicode.runtime_encoding
. Unicode output generated by a script will be encoding using this converter
UG(script_encoding_conv) - unicode.script_encoding
. Scripts read from disk will be decoded using this converter
UG(filesystem_encoding_conv) - unicode.filesystem_encoding
. Filenames and paths will be encoding using this converter
Since these additional converters may not be instatiated (because their INI value is not set), all uses of these converters must
be wrapped in ZEND_U_CONVERTER() for safety. If the converter hasn't been instantiated, then UG(fallback_encoding_conv) will be
used instead.
For example, RETURN_RT_STRING("foo", ZSTR_DUPLICATE); expands out to:
RETURN_U_STRING(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), "foo", ZSTR_DUPLICATE);
Which uses UG(runtime_encoding_conv) if it's been set, otherwise using UG(fallback_encoding_conv).
Note that the INI setting unicode.stream_encoding does not instantiate a UConverter* automatically for use by the process/thread,
it stores the value as a string for use during fopen() style calls where a UConverter* is instantiated for that particular stream.
References
==========
[1] http://icu.sourceforge.net/apiref/icu4c/ustring_8h.html#a1
[2] http://icu.sourceforge.net/apiref/icu4c/utf16_8h.html
vim: set et ai tw=76 fo=tron21:
+123
View File
@@ -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_php5.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.
+172
View File
@@ -0,0 +1,172 @@
Updating your script to PHP6
============================
This document attempts to describe portions of PHP that changed or
disapeared in PHP6 and the best practices for upgrading existing
applications to support PHP6.
1. Language
1.1 Functions and function aliases
1.2 Register globals
1.3 Magic quotes
1.4 Register long arrays ($HTTP_*_VARS)
1.5 ZE1 compatibility mode
1.6 dl() function
1.7 E_ALL and E_STRICT constants
1.8 References
2. Unicode (see README.UNICODE-UPGRADES)
2. Extensions
2.1 GD
1.1 Functions and function aliases
------------------------------
<TODO: List all arguments order changes, aliases droped in php6...>
1.2 Register globals
----------------
For security reasons, register_globals has been removed from php6.
ini_get('register_globals') will always return false.
You can emulate its behavior with some minimum changes in your code.
*DISCLAIMER*
people should get a short-term solution if they are willing to run
an insecure app.
Here is an example to emulate the session related functions and
a snippet to register variables:
$_register_globals_order = strrev(ini_get("variables_order"));
$_register_globals_order_len = strlen($_register_globals_order);
for($_register_globals_i=0;$_register_globals_i<$_register_globals_order_len;$_register_globals_i++) {
switch($_register_globals_order{$_register_globals_i}) {
case "E":
extract($_ENV, EXTR_REFS|EXTR_SKIP);
break;
case "G":
extract($_GET, EXTR_REFS|EXTR_SKIP);
break;
case "P":
extract($_POST, EXTR_REFS|EXTR_SKIP);
break;
case "C":
extract($_COOKIE, EXTR_REFS|EXTR_SKIP);
break;
case "S":
extract($_SERVER, EXTR_REFS|EXTR_SKIP);
break;
}
}
unset($_register_globals_order, $_register_globals_order_len, $_register_globals_i);
function session_register($mixed) {
static $started;
if(!isset($started) || session_id() === "") {
session_start();
$started = true;
}
$array = func_get_args();
foreach($array as $mixed) {
if(is_scalar($mixed)) {
$_SESSION[$mixed] =& $GLOBALS[$mixed];
}
elseif(is_array($mixed)) {
foreach($mixed as $name) {
$ok = session_register($name);
if(!$ok) {
return false;
}
}
}
else {
return false;
}
}
return true;
}
function session_is_registered($name) {
if(is_scalar($name)) {
return isset($_SESSION[$name]);
}
return false;
}
function session_unregister($name) {
if(isset($_SESSION[$name]) && is_scalar($name)) {
unset($_SESSION[$name]);
return true;
}
return false;
}
1.3 Magic quotes
------------
1.4 Register long arrays ($HTTP_*_VARS)
-----------------------------------
register_long_arrays and the long versions of super globals had been removed.
PHP will emit E_CORE_ERROR during PHP startup if it would detect
register_long_arrays setting.
You can emulate long arrays by including the following file:
<?php
if (!ini_get('register_long_arrays')) {
$HTTP_POST_VARS =& $_POST;
$HTTP_GET_VARS =& $_GET;
$HTTP_COOKIE_VARS =& $_COOKIE;
$HTTP_SERVER_VARS =& $_SERVER;
$HTTP_ENV_VARS =& $_ENV;
$HTTP_POST_FILES =& $_FILES;
}
?>
1.5 ZE1 compatibility mode
----------------------
ZE1 compatibility mode (PHP4 object model) was introduced to migrate from PHP4
to PHP5 in an easier way, but it never keeped 100% compatibility.
It is completly removed in PHP6, and there is no way to emulate it.
Applications should assume PHP5/PHP6 object model.
1.6 dl() function
-------------
Now dl() function is supported only in CLI, CGI and EMBED SAPI.
There is no way to emulte it. You can just check if dl() is supported by SAPI:
<?php
if (!function_exists("dl")) {
die("dl() function is required\n!");
}
?>
1.7 E_ALL and E_STRICT constants
----------------------------
Now E_ALL error reporting mask includes E_STRICT.
You can filter E_STRICT error messages using the following code:
<?php
error_reporting(error_reporting() & ~E_STRICT);
?>
1.8 References
----------
<TODO: Derick plans to clean the reference mess in php6>
2.1 GD
<TODO: gd2/ft2 only, functions droped>
+6
View File
@@ -0,0 +1,6 @@
The Win32 Build System.
See http://wiki.php.net/internals/windows/stepbystepbuild
vim:tw=78:sw=1:ts=1:et
+112
View File
@@ -0,0 +1,112 @@
Using PHP 5 with the Zeus Web Server
-----------------------------------
Zeus fully supports running PHP in combination with our
webserver. There are three different interfaces that can be used to
enable PHP:
* CGI
* ISAPI
* FastCGI
Of the three, we recommend using FastCGI, which has been tested and
benchmarked as providing the best performance and reliability.
Full details of how to install PHP are available from our
website, at:
http://support.zeus.com/products/php.html
If you have any problems, please check the support site for more
up-to-date information and advice.
Quick guide to installing CGI/FastCGI with Zeus
-----------------------------------------------
Step 1 - Compile PHP as FastCGI.
Compile as follows:
./configure --enable-fastcgi
make
Note that PHP has many options to the configure script -
e.g. --with-mysql. You will probably want to select your usual options
before compiling; the above is just a bare minimum, for illustration.
After compilation finishes, you will be left with an executable
program called 'php'. Copy this into your document root, under a
dedicated FastCGI directory (e.g. $DOCROOT/fcgi-bin/php)
Step 2 - configure Zeus
Four stages:
- enable FastCGI
- configure FastCGI
- setup alias for FastCGI
- setup alias for PHP
1) Using the admin server, go to the 'module configuration' page for
your virtual server, and ensure that 'fastcgi' is enabled (select the
tickbox to the left).
2) While we can run FastCGI's locally, there are known problems with
some OS's (specifically, the communication between web server and
FastCGI happens over a unix domain socket, and some OS's have trouble
sustaining high connection rates over these sockets). So instead, we
are going to set up the PHP FastCGI to run 'remotely' over localhost
(this uses TCP sockets, which do not suffer this problem). Go to the
'fastcgi configuration' page, and under 'add remote fastcgi':
Add Remote FastCGI
Docroot path /fcgi-bin/php
Remote machine localhost:8002
The first entry is where you saved PHP, above.
The second entry is localhost:<any unused port>
We will start the FastCGI listening on this port shortly.
Click 'update' to commit these changes.
3) Go to the path mapping module and add an alias for FastCGI:
Add Alias
Docroot path /fcgi-bin
Filesystem directory /path/to/docroot/fcgi-bin
Alias type fastcgi
Click 'update' to commit these changes
4) Also on the path mapping module, add a handler for PHP:
Add handler
File extension php
Handler /fcgi-bin/php
Click 'update' to commit these changes
Finally restart your virtual server for these changes to take effect.
Step 3 - start PHP as a FastCGI runner
When you start PHP, it will pre-fork a given number of child processes
to handle incoming PHP requests. Each process will handle a given
number of requests before exiting (and being replaced by a newly
forked process). You can control these two parameters by setting the
following environment variables BEFORE starting the FastCGI runner:
PHP_FCGI_CHILDREN - the number of child processes to pre-fork. This
variable MUST be set, if not then the PHP will not run as a FastCGI.
We recommend a value of 8 for a fairly busy site. If you have many,
long-running PHP scripts, then you may need to increase this further.
PHP_FCGI_MAX_REQUESTS - the number of requests each PHP child process
handles before exiting. If not set, defaults to 500.
To start the FastCGI runner, execute '$ZEUSHOME/web/bin/fcgirunner
8002 $DOCROOT/fcgi-bin/php'. Substitute the appropriate values for
$ZEUSHOME and $DOCROOT; also substitute for 8002 the port you chose,
above.
To stop the runner (e.g. to experiment with the above environment
variables) you will need to manually stop and running PHP
processes. (Use 'ps' and 'kill'). As it is PHP which is forking lots
of children and not the runner, Zeus unfortunately cannot keep track
of what processes are running, sorry. A typical command line may look
like 'ps -efl | grep $DOCROOT/fcgi-bin/php | grep -v grep | awk
'{print $4}' | xargs kill'
+193
View File
@@ -0,0 +1,193 @@
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.
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. If register_globals is turned on, the default globals that
are created will be stripped ($foo) while a $RAW_foo is created with the
original user input.
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_row( 2, "Revision", "$Revision$");
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 TSRMLS_DC);
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;
HashTable *hash_ptr;
char *raw_var;
if(zend_parse_parameters(2 TSRMLS_CC, "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;
/*
* I'm changing the variable name here because when running with register_globals on,
* the variable will end up in the global symbol table
*/
raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
strcpy(raw_var, "RAW_");
strlcat(raw_var,var,var_len+5);
hash_ptr = HASH_OF(array_ptr);
if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
*return_value = **tmp;
zval_copy_ctor(return_value);
} else {
RETVAL_FALSE;
}
efree(raw_var);
}
-142
View File
@@ -1,142 +0,0 @@
<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
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).
[![Build status](https://travis-ci.org/php/php-src.svg?branch=master)](https://travis-ci.org/php/php-src)
[![Build status](https://ci.appveyor.com/api/projects/status/meyur6fviaxgdwdy/branch/master?svg=true)](https://ci.appveyor.com/project/php/php-src)
[![Build Status](https://dev.azure.com/phpazuredevops/php/_apis/build/status/php.php-src?branchName=master)](https://dev.azure.com/phpazuredevops/php/_build/latest?definitionId=1&branchName=master)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/php.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:php)
## Documentation
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`.
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.
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.
### 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).
+174
View File
@@ -0,0 +1,174 @@
Design
======
Main assumption of the model is that the problem that we are to solve is the
problem of the very long class names in PHP libraries. We would not attempt
to take autoloader's job or create packaging model - only make names
manageable.
Namespaces are defined the following way:
Zend/DB/Connection.php:
<?php
namespace Zend\DB;
class Connection {
}
function connect() {
}
?>
Namespace definition does the following:
All class and function names inside are automatically prefixed with
namespace name. Inside namespace, local name always takes precedence over
global name. Several files may be using the same namespace.
The namespace declaration statement must be the very first statement in
the file. The only exception is "declare" statement that can be used before.
Every class and function in a namespace can be referred to by the full name
- e.g. Zend\DB\Connection or Zend\DB\connect - at any time.
<?php
require 'Zend/Db/Connection.php';
$x = new Zend\DB\Connection;
Zend\DB\connect();
?>
Namespace or class name can be imported:
<?php
require 'Zend/Db/Connection.php';
use Zend\DB;
use Zend\DB\Connection as DbConnection;
$x = new Zend\DB\Connection();
$y = new DB\connection();
$z = new DbConnection();
DB\connect();
?>
The use statement only defines name aliasing. It may create name alias for
namespace or class. The simple form of statement "use A\B\C\D;" is
equivalent to "use A\B\C\D as D;". The use statement can be used at any
time in the global scope (not inside function/class) and takes effect from
the point of definition down to the end of file. It is recommended however to
place the use statements at the beginning of the file. The use statements have
effect only on the file where they appear.
The special "empty" namespace (\ prefix) is useful as explicit global
namespace qualification. All class and function names started from \
interpreted as global.
<?php
namespace A\B\C;
$con = \mysql_connect(...);
?>
A special constant __NAMESPACE__ contains the name of the current namespace.
It can be used to construct fully-qualified names to pass them as callbacks.
<?php
namespace A\B\C;
function foo() {
}
set_error_handler(__NAMESPACE__ . "\foo");
?>
In global namespace __NAMESPACE__ constant has the value of empty string.
Names inside namespace are resolved according to the following rules:
1) all qualified names are translated during compilation according to
current import rules. So if we have "use A\B\C" and then "C\D\e()"
it is translated to "A\B\C\D\e()".
2) unqualified class names translated during compilation according to
current import rules. So if we have "use A\B\C" and then "new C()" it
is translated to "new A\B\C()".
3) inside namespace, calls to unqualified functions that are defined in
current namespace (and are known at the time the call is parsed) are
interpreted as calls to these namespace functions.
4) inside namespace, calls to unqualified functions that are not defined
in current namespace are resolved at run-time. The call to function foo()
inside namespace (A\B) first tries to find and call function from current
namespace A\B\foo() and if it doesn't exist PHP tries to call internal
function foo(). Note that using foo() inside namespace you can call only
internal PHP functions, however using \foo() you are able to call any
function from the global namespace.
5) unqualified class names are resolved at run-time. E.q. "new Exception()"
first tries to use (and autoload) class from current namespace and in case
of failure uses internal PHP class. Note that using "new A" in namespace
you can only create class from this namespace or internal PHP class, however
using "new \A" you are able to create any class from the global namespace.
6) Calls to qualified functions are resolved at run-time. Call to
A\B\foo() first tries to call function foo() from namespace A\B, then
it tries to find class A\B (__autoload() it if necessary) and call its
static method foo()
7) qualified class names are interpreted as class from corresponding
namespace. So "new A\B\C()" refers to class C from namespace A\B.
Examples
--------
<?php
namespace A;
foo(); // first tries to call "foo" defined in namespace "A"
// then calls internal function "foo"
\foo(); // calls function "foo" defined in global scope
?>
<?php
namespace A;
new B(); // first tries to create object of class "B" defined in namespace "A"
// then creates object of internal class "B"
new \B(); // creates object of class "B" defined in global scope
?>
<?php
namespace A;
new A(); // first tries to create object of class "A" from namespace "A" (A\A)
// then creates object of internal class "A"
?>
<?php
namespace A;
B\foo(); // first tries to call function "foo" from namespace "A\B"
// then calls method "foo" of internal class "B"
\B\foo(); // first tries to call function "foo" from namespace "B"
// then calls method "foo" of class "B" from global scope
?>
The worst case if class name conflicts with namespace name
<?php
namespace A;
A\foo(); // first tries to call function "foo" from namespace "A\A"
// then tries to call method "foo" of class "A" from namespace "A"
// then tries to call function "foo" from namespace "A"
// then calls method "foo" of internal class "A"
\A\foo(); // first tries to call function "foo" from namespace "A"
// then calls method "foo" of class "A" from global scope
?>
TODO
====
* Support for namespace constants?
* performance problems
- calls to internal functions in namespaces are slower, because PHP first
looks for such function in current namespace
- calls to static methods are slower, because PHP first tries to look
for corresponding function in namespace
* Extend the Reflection API?
* Add ReflectionNamespace class
+ getName()
+ getClasses()
+ getFunctions()
+ getFiles()
* Add getNamespace() methods to ReflectionClass and ReflectionFunction
* Rename namespaces to packages?
+153
View File
@@ -0,0 +1,153 @@
Things to do or at least think about doing in the future. Name in
parenthesis means that person has taken on this project.
Zend
----
* Allow foreach ($array as $k => list($a, $b)) syntax for multi
dimensional arrays.
* Look at replacing c-lib call tolower().
* Make hash API functions work with HASH_OF() to save time.
* Native large number support (probably with GNU GMP)
* Const'ify APIs. Right now, many functions leave parameters untouched,
but don't declare those as const. This makes interaction with other
interfaces difficult which pass const parameters to us.
* Clean up object->string conversion behavior wherever possible (switch(),
comparison, etc)
* Port safe-allocation functions from 5.3 (zend_alloc.[ch])
global
------
* Make sure that all ZTS globals get destructed. Most ts_allocate_id()
calls should have a dtor entry.
* on some platforms unimplemented function will just do nothing
(e.g. symlink) they should print a warning or not even be defined!
(DONE ?)
* --enable-all in configure. (--enable-shared=max ...)
* make configure print out a summary when it's done (like XEmacs)
* replace standard functions which work on static data with
reentrancy-safe functions (DONE?).
* make SAPI conform to CGI/1.1. Currently, all SAPI modules
define REMOTE_ADDR etc. themselves and reach only various level
of compliance.
* see what functions might need to be changed to use HashPosition, so
that the internal array pointer is not affected.
Other
* use thread-safe resolver functions (either require BIND 8 or adns).
* implement javadoc based function docs template system.
* provide optional IPv6 support (seems to be done?).
* find a better way to implement script timeouts. SIGVTALRM is used
by some POSIX threads implementations (i.e. OpenBSD) and is not
available in ZTS mode.
* Implement flush feature suitable for nested output buffers.
Streams
-------
* Route filestat.c through the wrapper layer; isolate the statcache code
so that it is independent of php functions and can be applied to any
stream/path.
* Implement generalized connection pool for stated protocols such as
ftp and http/1.1 (using keep-alive) to avoid having to negotiate
new command/request stream for each subsequent call; Possibly store
resources in contexts (creating a default context if necessary) to
allow segmentation of connection pools.
* Add a method to take ownership of the memory buffer in memory streams so
that generating string values for zvals doesn't require an estrdup.
* bundle and use curl lib for fopen wrapper.
documentation
-------------
* Add remarks in the documentation which functions are not implemented
on win32.
* Add remarks in the documentation which functions are not binary-safe.
* Update curl documentation (DONE?)
* Add developer documentation.
* Add detailed documentation for Java extension.
ext/bz2
-------
* Add an ini directive to specify the size of decompression buffer.
The default 4k is too small for large files and also requires much time
for decompression. 40k is suitable for such files, however it may be too
much under certain environments. There should be appropriate default
settings for the various SAPI modules (e.g. apache and cli).
ext/curl
--------
* Have a warning scheme for when people use unsupported features.
ext/oci8
--------
* All OCIFetch*() functions should return 0 for no more data and false on
error.
* Have a flag that trims trailing spaces from CHAR fields on retrieval.
* Make allow_call_time_pass_reference=Off working.
* For additional todo information, see oci8.c, in ext/oci8
ext/odbc
--------
For PHP 4.3.0:
* update all php_error calls to php_error_docref where valid
* integrate EXPERIMENTAL ODBC update for use in PHP 5.0, use for
testing purposes only.
For PHP 5.0.0
* Activate EXPERIMENTAL ODBC codebase update
ext/pcre
--------
* Allow user to set PCRE_NOTEMPTY, PCRE_ANCHORED at execution time, maybe
ext/pcntl
---------
* Change internal callback handler to use TICKS
* Remove all zend_extension code
* Add object callback support to pcntl_signal()
ext/pgsql
---------
For PHP 4.3.0:
* Add pg_metadata() with metadata cache feature.
* Add pg_convert() to check and convert array value for query.
* Add pg_insert/pg_update/pg_delete/pg_select for simple query.
ext/session
-----------
For PHP 4.3.0:
* session_abort() to abort session. ie: Do not save session data.
* Allow unset($_SESSION) or unset($HTTP_SESSION_VARS) to unset
session vars regardless of register_globals setting.
Other:
* Maybe implement finer-grained session variables that could be
locked individually.
* Write a network-transparent storage back-end with fallover
facilities
* Provide a callback facility which is executed upon encountering
an unknown class name during deserialization
ext/standard
------------
* Add a version number to data serialized via serialize().
* Possibly modify parsing of GPC data to automatically create arrays if
variable name is seen more than once.
* Implement regex-cache for url-functions.
* Move socket related functions to fsock.c.
ext/wddx
--------
* See if we can support the remaining data types:
dateTime
binary
http://www.wddx.org/WDDX_SDK_10a/7__References/WDDX_DTD.htm
(Andrei)
* implement wddx_packet_as_javascript(). (Andrei)
other cool stuff
----------------
* PVM extension
vim:et:sw=4:ts=4
+5
View File
@@ -0,0 +1,5 @@
Zend Engine
-----------
- Look at making zend_constant value member be a zval* instead of zval. (Andi)
- Implement inheritance rules for type hints. (Marcus)
- Find a keyword for the if-set-or operator (apply the patch). (Marcus, all)
+109
View File
@@ -0,0 +1,109 @@
Component: Zend Engine 2
Important stuff to finish: PPP members/PPP methods,
support of overloaded extensions, possibly differentiate
between class and namespace as discussed with Stig in
Germany.
Responsibility: Zeev, Andi, Stas
Time frame: Couple of months for first part and extensions will be
ongoing while PHP is being fixed.
Things to leave for later versions: Native aggregation
support, accessing static members via object and not class.
Component: Aggregation
Responsibility: Andi, Stig?
Time frame: ?
Component: Redesign of API Versioning
Responsibility: ?
Time frame: 1 month
Component: Thread Safety
Identify the extensions that are not thread safe by design
or due to dependant libraries and identify them as such.
If possible try to resolve thread safety issue via code
improvements (if php code or patches will be accepted by
library maintainers). For situations where thread safety
cannot easily be acheived a flag in the extension API is
set so PHP can identify non-thread safe extensions. These
extensions will not be loaded in a ZTS compiled binary
(unless it is cli/cgi).
Responsibility: ?
Time frame: ?
Component: SAPI
Environment variables defined in the CGI spec need to be
verified in each SAPI module that they conform to the CGI
spec correctly. If they do not, the SAPI module needs to
fix the variable prior to script execution. Having this
conformity will aid in having PHP scripts run correctly
under different sapi modules.
Responsibility: Shane Caraveo & each sapi module owner
Timeframe: ? (but shouldn't be much effort, most modules are probably ok)
Component: Input Filtering
- Implement a SAPI input filter hook that will get called
just before registering a variable in the
treat_data/post_handler hooks. (done)
- Make sure this is also done in mbstring (done)
- Provide access functions, or perhaps a new
$_RAW_GET/POST/Cookie set of superglobals to get at the
unfiltered data
- Provide a .ini directive which allows people to set their
input filter to one of the built-in strip_tags,
htmlspecialchars or whatever other internal function might
be useful here.
- (The main benefit of this is to make it easier for people
to solve the XSS problem once and for all without having
to go through every line of their code and adding input
validation/filtering everywhere)
Responsibility: Rasmus
Timeframe: Yesterday
Component: RPC Abstraction Layer
Porting java, com, dotnet, xmlrpc, corba, soap and python, srm
(are there more ?) to work with the new oo api and preferably
by using ext/rpc.
Responsibility: Harald
Time frame: 2 months (but i have to wait for a few engine features first)
Component: OO Extensions
Each OO extension has to be revised and rewritten to fit into
the new OO model. We should decide which extensions are a must
to have for the release and which can be ported by the maintainer
later as a separate pecl release.
A list of extensions to be extended that have to be investigated:
* browscap
* aggregate
* all *sql extensions (*_fetch_object)
* domxml (seems like christian is rewriting it anyways)
* ming
Responsibility: Harald (, extension maintainers)
Component: Abstract Data Types (ADT)
Responsibility: Sterling, Harald
Time frame: ?
Component: Test Suite
Extending the test suite with atleast a test for every
function in an extension that doesn't require external
resources. Also developing an automated test thing which
cvs ups's, compiles and tests the build on a daily base on
as much platforms/extensions as possible.
The test suite will also be extended to support threaded
testing and testing for differing sapi modules (via http
calls or other methods).
Reponsibility: Derick (, extension maintainers)
Time frame: 3 months
+6
View File
@@ -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 tsrm_virtual_cwd.c
depend:
+2
View File
@@ -0,0 +1,2 @@
- Improve the lock in ts_resource_ex() in order to cover less code.
This can probably be done by more careful hash table access
+327 -317
View File
@@ -2,11 +2,11 @@
+----------------------------------------------------------------------+
| Thread Safe Resource Manager |
+----------------------------------------------------------------------+
| Copyright (c) 1999-2011, Andi Gutmans, Sascha Schumann, Zeev Suraski |
| Copyright (c) 1999-2009, Andi Gutmans, Sascha Schumann, Zeev Suraski |
| This source file is subject to the TSRM license, that is bundled |
| with this package in the file LICENSE |
+----------------------------------------------------------------------+
| Authors: Zeev Suraski <zeev@php.net> |
| Authors: Zeev Suraski <zeev@zend.com> |
+----------------------------------------------------------------------+
*/
@@ -15,20 +15,13 @@
#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;
/* TSRMLS_CACHE_DEFINE; is already done in Zend, this is being always compiled statically. */
TSRMLS_CACHE_EXTERN();
struct _tsrm_tls_entry {
void **storage;
int count;
@@ -41,7 +34,6 @@ typedef struct {
size_t size;
ts_allocate_ctor ctor;
ts_allocate_dtor dtor;
size_t fast_offset;
int done;
} tsrm_resource_type;
@@ -55,17 +47,12 @@ 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;
static tsrm_thread_end_func_t tsrm_new_thread_end_handler = NULL;
static tsrm_shutdown_func_t tsrm_shutdown_handler = NULL;
static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler;
static tsrm_thread_end_func_t tsrm_new_thread_end_handler;
/* Debug support */
int tsrm_error(int level, const char *format, ...);
@@ -74,7 +61,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,32 +89,49 @@ 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(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)
#endif
TSRM_TLS uint8_t in_main_thread = 0;
TSRM_TLS uint8_t is_thread_shutdown = 0;
#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)
#elif defined(BETHREADS)
static int32 tls_key;
# define tsrm_tls_set(what) tls_set(tls_key, (void*)(what))
# define tsrm_tls_get() (tsrm_tls_entry*)tls_get(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
/* 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)
{/*{{{*/
#ifdef TSRM_WIN32
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
{
#if defined(GNUPTH)
pth_init();
#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);
#elif defined(BETHREADS)
tls_key = tls_allocate();
#endif
/* ensure singleton */
in_main_thread = 1;
is_thread_shutdown = 0;
tsrm_error_file = stderr;
tsrm_error_set(debug_level, debug_filename);
tsrm_tls_table_size = expected_threads;
@@ -135,7 +139,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,132 +147,75 @@ 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_new_thread_begin_handler = tsrm_new_thread_end_handler = NULL;
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;
}/*}}}*/
}
/* Shutdown TSRM (call once for the entire process) */
TSRM_API void tsrm_shutdown(void)
{/*{{{*/
{
int i;
if (is_thread_shutdown) {
/* shutdown must only occur once */
return;
}
if (tsrm_tls_table) {
for (i=0; i<tsrm_tls_table_size; i++) {
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
is_thread_shutdown = 1;
while (p) {
int j;
if (!in_main_thread) {
/* only the main thread may shutdown tsrm */
return;
}
for (i=0; i<tsrm_tls_table_size; i++) {
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
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], &p->storage);
}
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();
}
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);
@@ -280,140 +226,100 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate
/* 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) {
resource_types_table = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);
if (!resource_types_table) {
tsrm_mutex_unlock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
*rsrc_id = 0;
return 0;
}
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 = 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->storage);
}
}
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));
return *rsrc_id;
}/*}}}*/
}
static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T thread_id)
{/*{{{*/
{
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)->storage = NULL;
if (id_count > 0) {
(*thread_resources_ptr)->storage = (void **) malloc(sizeof(void *)*id_count);
}
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
(*thread_resources_ptr)->storage = (void **) malloc(sizeof(void *)*id_count);
(*thread_resources_ptr)->count = id_count;
(*thread_resources_ptr)->thread_id = thread_id;
(*thread_resources_ptr)->next = NULL;
/* 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);
tsrm_new_thread_begin_handler(thread_id, &((*thread_resources_ptr)->storage));
}
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]);
resource_types_table[i].ctor((*thread_resources_ptr)->storage[i], &(*thread_resources_ptr)->storage);
}
}
}
if (tsrm_new_thread_end_handler) {
tsrm_new_thread_end_handler(thread_id);
tsrm_new_thread_end_handler(thread_id, &((*thread_resources_ptr)->storage));
}
tsrm_mutex_unlock(tsmm_mutex);
}/*}}}*/
}
/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
{/*{{{*/
{
THREAD_T thread_id;
int hash_value;
tsrm_tls_entry *thread_resources;
#ifdef NETWARE
/* The below if loop is added for NetWare to fix an abend while unloading PHP
* when an Apache unload command is issued on the system console.
* While exiting from PHP, at the end for some reason, this function is called
* with tsrm_tls_table = NULL. When this happened, the server abends when
* tsrm_tls_table is accessed since it is NULL.
*/
if(tsrm_tls_table) {
#endif
if (!th_id) {
/* Fast path for looking up the resources for the current
* thread. Its used by just about every call to
@@ -467,20 +373,80 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
* changes to the structure as we read it.
*/
TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
}/*}}}*/
#ifdef NETWARE
} /* if(tsrm_tls_table) */
#endif
}
/* 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], &thread_resources->storage);
}
}
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)
{/*{{{*/
{
tsrm_tls_entry *thread_resources;
int i;
THREAD_T thread_id = tsrm_thread_id();
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];
@@ -489,13 +455,11 @@ void ts_free_thread(void)
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]);
resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
}
}
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) {
@@ -513,11 +477,58 @@ void ts_free_thread(void)
thread_resources = thread_resources->next;
}
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], &thread_resources->storage);
}
}
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)
{/*{{{*/
{
int i;
int j = TSRM_UNSHUFFLE_RSRC_ID(id);
@@ -532,11 +543,9 @@ void ts_free_id(ts_rsrc_id id)
while (p) {
if (p->count > j && p->storage[j]) {
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]);
resource_types_table[j].dtor(p->storage[j], &p->storage);
}
free(p->storage[j]);
p->storage[j] = NULL;
}
p = p->next;
@@ -548,7 +557,9 @@ void ts_free_id(ts_rsrc_id id)
tsrm_mutex_unlock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id));
}/*}}}*/
}
/*
@@ -557,49 +568,83 @@ void ts_free_id(ts_rsrc_id id)
/* Obtain the current thread id */
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(NSAPI)
return systhread_current();
#elif defined(PI3WEB)
return PIThread_getCurrent();
#elif defined(TSRM_ST)
return st_thread_self();
#elif defined(BETHREADS)
return find_thread(NULL);
#endif
}/*}}}*/
}
/* Allocate a mutex */
TSRM_API MUTEX_T tsrm_mutex_alloc(void)
{/*{{{*/
{
MUTEX_T mutexp;
#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(NSAPI)
mutexp = crit_init();
#elif defined(PI3WEB)
mutexp = PIPlatform_allocLocalMutex();
#elif defined(TSRM_ST)
mutexp = st_mutex_new();
#elif defined(BETHREADS)
mutexp = (beos_ben*)malloc(sizeof(beos_ben));
mutexp->ben = 0;
mutexp->sem = create_sem(1, "PHP sempahore");
#endif
#ifdef THR_DEBUG
printf("Mutex created thread: %d\n",mythreadid());
#endif
return( mutexp );
}/*}}}*/
}
/* Free a mutex */
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
{/*{{{*/
{
if (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(NSAPI)
crit_terminate(mutexp);
#elif defined(PI3WEB)
PISync_delete(mutexp);
#elif defined(TSRM_ST)
st_mutex_destroy(mutexp);
#elif defined(BETHREADS)
delete_sem(mutexp->sem);
free(mutexp);
#endif
}
#ifdef THR_DEBUG
printf("Mutex freed thread: %d\n",mythreadid());
#endif
}/*}}}*/
}
/*
@@ -607,15 +652,31 @@ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
{/*{{{*/
{
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
#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(NSAPI)
crit_enter(mutexp);
return 0;
#elif defined(PI3WEB)
return PISync_lock(mutexp);
#elif defined(TSRM_ST)
return st_mutex_lock(mutexp);
#elif defined(BETHREADS)
if (atomic_add(&mutexp->ben, 1) != 0)
return acquire_sem(mutexp->sem);
return 0;
#endif
}/*}}}*/
}
/*
@@ -623,63 +684,59 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
{/*{{{*/
{
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id()));
#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(NSAPI)
crit_exit(mutexp);
return 0;
#elif defined(PI3WEB)
return PISync_unlock(mutexp);
#elif defined(TSRM_ST)
return st_mutex_unlock(mutexp);
#elif defined(BETHREADS)
if (atomic_add(&mutexp->ben, -1) != 1)
return release_sem(mutexp->sem);
return 0;
#endif
}/*}}}*/
/*
Changes the signal mask of the calling thread
*/
#ifdef HAVE_SIGPROCMASK
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);
}/*}}}*/
#endif
}
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler)
{/*{{{*/
{
void *retval = (void *) tsrm_new_thread_begin_handler;
tsrm_new_thread_begin_handler = new_thread_begin_handler;
return retval;
}/*}}}*/
}
TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler)
{/*{{{*/
{
void *retval = (void *) tsrm_new_thread_end_handler;
tsrm_new_thread_end_handler = new_thread_end_handler;
return retval;
}/*}}}*/
}
TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler)
{/*{{{*/
void *retval = (void *) tsrm_shutdown_handler;
tsrm_shutdown_handler = shutdown_handler;
return retval;
}/*}}}*/
/*
* Debug support
*/
#ifdef TSRM_DEBUG
#if TSRM_DEBUG
int tsrm_error(int level, const char *format, ...)
{/*{{{*/
{
if (level<=tsrm_error_level) {
va_list args;
int size;
@@ -694,15 +751,15 @@ int tsrm_error(int level, const char *format, ...)
} else {
return 0;
}
}/*}}}*/
}
#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);
}
@@ -716,53 +773,6 @@ void tsrm_error_set(int level, const char *debug_filename)
tsrm_error_file = stderr;
}
#endif
}/*}}}*/
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
return "Windows Threads";
#else
return "POSIX Threads";
#endif
}/*}}}*/
}
#endif /* ZTS */
+186
View File
@@ -0,0 +1,186 @@
# Microsoft Developer Studio Project File - Name="TSRM" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=TSRM - Win32 Debug_TS
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "TSRM.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "TSRM.mak" CFG="TSRM - Win32 Debug_TS"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "TSRM - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
!MESSAGE "TSRM - Win32 Release_TS" (based on "Win32 (x86) Static Library")
!MESSAGE "TSRM - Win32 Release_TS_inline" (based on "Win32 (x86) Static Library")
!MESSAGE "TSRM - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "TSRM - Win32 Debug_TS"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "TSRM___Win32_Debug_TS"
# PROP BASE Intermediate_Dir "TSRM___Win32_Debug_TS"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_TS"
# PROP Intermediate_Dir "Debug_TS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "C:\Projects\TSRM" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /D "_DEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=1 /YX /FD /GZ /c
# ADD BASE RSC /l 0x40d /d "_DEBUG"
# ADD RSC /l 0x40d /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "TSRM - Win32 Release_TS"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "TSRM___Win32_Release_TS"
# PROP BASE Intermediate_Dir "TSRM___Win32_Release_TS"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_TS"
# PROP Intermediate_Dir "Release_TS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
# ADD BASE RSC /l 0x40d /d "NDEBUG"
# ADD RSC /l 0x40d /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "TSRM - Win32 Release_TS_inline"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "TSRM___Win32_Release_TS_inline"
# PROP BASE Intermediate_Dir "TSRM___Win32_Release_TS_inline"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_TS_inline"
# PROP Intermediate_Dir "Release_TS_inline"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "TSRM_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
# ADD BASE RSC /l 0x40d /d "NDEBUG"
# ADD RSC /l 0x40d /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "TSRM - Win32 Release_TSDbg"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "TSRM___Win32_Release_TSDbg"
# PROP BASE Intermediate_Dir "TSRM___Win32_Release_TSDbg"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_TSDbg"
# PROP Intermediate_Dir "Release_TSDbg"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
# ADD BASE RSC /l 0x40d /d "NDEBUG"
# ADD RSC /l 0x40d /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "TSRM - Win32 Debug_TS"
# Name "TSRM - Win32 Release_TS"
# Name "TSRM - Win32 Release_TS_inline"
# Name "TSRM - Win32 Release_TSDbg"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\TSRM.c
# End Source File
# Begin Source File
SOURCE=.\tsrm_strtok_r.c
# End Source File
# Begin Source File
SOURCE=.\tsrm_virtual_cwd.c
# End Source File
# Begin Source File
SOURCE=.\tsrm_win32.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\readdir.h
# End Source File
# Begin Source File
SOURCE=.\TSRM.h
# End Source File
# Begin Source File
SOURCE=.\tsrm_config.w32.h
# End Source File
# Begin Source File
SOURCE=.\tsrm_config_common.h
# End Source File
# Begin Source File
SOURCE=.\tsrm_strtok_r.h
# End Source File
# Begin Source File
SOURCE=.\tsrm_virtual_cwd.h
# End Source File
# Begin Source File
SOURCE=.\tsrm_win32.h
# End Source File
# End Group
# End Target
# End Project
+70 -85
View File
@@ -2,11 +2,11 @@
+----------------------------------------------------------------------+
| Thread Safe Resource Manager |
+----------------------------------------------------------------------+
| Copyright (c) 1999-2011, Andi Gutmans, Sascha Schumann, Zeev Suraski |
| Copyright (c) 1999-2009, Andi Gutmans, Sascha Schumann, Zeev Suraski |
| This source file is subject to the TSRM license, that is bundled |
| with this package in the file LICENSE |
+----------------------------------------------------------------------+
| Authors: Zeev Suraski <zeev@php.net> |
| Authors: Zeev Suraski <zeev@zend.com> |
+----------------------------------------------------------------------+
*/
@@ -15,13 +15,11 @@
#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"
#ifdef TSRM_WIN32
# ifdef TSRM_EXPORTS
# define TSRM_API __declspec(dllexport)
@@ -34,8 +32,13 @@
# define TSRM_API
#endif
typedef intptr_t tsrm_intptr_t;
typedef uintptr_t tsrm_uintptr_t;
#ifdef _WIN64
typedef __int64 tsrm_intptr_t;
typedef unsigned __int64 tsrm_uintptr_t;
#else
typedef long tsrm_intptr_t;
typedef unsigned long tsrm_uintptr_t;
#endif
/* Only compile multi-threading functions if we're in ZTS mode */
#ifdef ZTS
@@ -44,16 +47,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,15 +66,32 @@ 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(NSAPI)
# define THREAD_T SYS_THREAD
# define MUTEX_T CRITICAL
#elif defined(PI3WEB)
# define THREAD_T PIThread *
# define MUTEX_T PISync *
#elif defined(TSRM_ST)
# define THREAD_T st_thread_t
# define MUTEX_T st_mutex_t
#elif defined(BETHREADS)
# define THREAD_T thread_id
typedef struct {
sem_id sem;
int32 ben;
} beos_ben;
# define MUTEX_T beos_ben *
#endif
#include <signal.h>
typedef void (*ts_allocate_ctor)(void *);
typedef void (*ts_allocate_dtor)(void *);
typedef void (*ts_allocate_ctor)(void *, void ***);
typedef void (*ts_allocate_dtor)(void *, void ***);
#define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
@@ -79,20 +100,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 +113,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);
@@ -109,13 +125,12 @@ TSRM_API void ts_free_id(ts_rsrc_id id);
#define TSRM_ERROR_LEVEL_CORE 2
#define TSRM_ERROR_LEVEL_INFO 3
typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id);
typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id);
typedef void (*tsrm_shutdown_func_t)(void);
typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id, void ***tsrm_ls);
typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id, void ***tsrm_ls);
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);
@@ -123,54 +138,27 @@ TSRM_API MUTEX_T tsrm_mutex_alloc(void);
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp);
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp);
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp);
#ifdef HAVE_SIGPROCMASK
TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset);
#endif
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler);
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);
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)
#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")))
#endif
/* 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);
#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
#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_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
#define TSRMLS_CACHE _tsrm_ls_cache
#define TSRMLS_FETCH() void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL)
#define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
#define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
#define TSRMLS_D void ***tsrm_ls
#define TSRMLS_DC , TSRMLS_D
#define TSRMLS_C tsrm_ls
#define TSRMLS_CC , TSRMLS_C
#ifdef __cplusplus
}
@@ -178,16 +166,13 @@ TSRM_API const char *tsrm_api_name(void);
#else /* non ZTS */
#define tsrm_env_lock()
#define tsrm_env_unlock()
#define TSRMG_STATIC(id, type, element)
#define TSRMLS_CACHE_EXTERN()
#define TSRMLS_CACHE_DEFINE()
#define TSRMLS_CACHE_UPDATE()
#define TSRMLS_CACHE
#define TSRM_TLS
#define TSRMLS_FETCH()
#define TSRMLS_FETCH_FROM_CTX(ctx)
#define TSRMLS_SET_CTX(ctx)
#define TSRMLS_D void
#define TSRMLS_DC
#define TSRMLS_C
#define TSRMLS_CC
#endif /* ZTS */
+1
View File
@@ -0,0 +1 @@
#undef PTHREADS
+5
View File
@@ -0,0 +1,5 @@
AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[
LIBTOOL='$(SHELL) $(top_builddir)/libtool $1'
])
+43
View File
@@ -0,0 +1,43 @@
# Makefile to generate build tools
#
# Standard usage:
# make -f build.mk
#
# Written by Sascha Schumann
#
# $Id$
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.in acinclude.m4
aclocal
$(config_h_in): configure.in acconfig.h
# explicitly remove target since autoheader does not seem to work
# correctly otherwise (timestamps are not updated)
@rm -f $@
autoheader
configure: aclocal.m4 configure.in
autoconf
Executable
+33
View File
@@ -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
+8 -2
View File
@@ -1,4 +1,10 @@
// vim:ft=javascript
// $Id$
if (CHECK_HEADER_ADD_INCLUDE("NewAPIs.h", "CFLAGS_PHP", php_usual_include_suspects)) {
// Need to add the flag directly, since TSRM doesn't include the config
// header
ADD_FLAG("CFLAGS_PHP", "/DHAVE_NEWAPIS_H=1");
}
ADD_SOURCES("TSRM", "TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c tsrm_win32.c");
ADD_SOURCES("TSRM", "TSRM.c tsrm_win32.c");
ADD_FLAG("CFLAGS_BD_TSRM", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
+31
View File
@@ -0,0 +1,31 @@
dnl $Id$
dnl
dnl Minimalistic configure.in for TSRM.
dnl
AC_INIT(TSRM.c)
AM_INIT_AUTOMAKE(TSRM, 1.0, nodefine)
AM_CONFIG_HEADER(tsrm_config.h)
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_OUTPUT(Makefile)
+45
View File
@@ -0,0 +1,45 @@
#ifndef READDIR_H
#define READDIR_H
/*
* Structures and types used to implement opendir/readdir/closedir
* on Windows 95/NT.
*/
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <direct.h>
/* struct dirent - same as Unix */
struct dirent {
long d_ino; /* inode (always 1 in WIN32) */
off_t d_off; /* offset to this dirent */
unsigned short d_reclen; /* length of d_name */
char d_name[_MAX_FNAME + 1]; /* filename (null terminated) */
};
/* typedef DIR - not the same as Unix */
typedef struct {
HANDLE handle; /* _findfirst/_findnext handle */
short offset; /* offset into directory */
short finished; /* 1 if there are not more files */
WIN32_FIND_DATA fileinfo; /* from _findfirst/_findnext */
char *dir; /* the dir we are reading */
struct dirent dent; /* the dirent to return */
} DIR;
/* Function prototypes */
DIR *opendir(const char *);
struct dirent *readdir(DIR *);
int readdir_r(DIR *, struct dirent *, struct dirent **);
int closedir(DIR *);
int rewinddir(DIR *);
#endif /* READDIR_H */
+69 -36
View File
@@ -1,17 +1,17 @@
dnl Copyright (c) 1999, 2000 Sascha Schumann. All rights reserved.
dnl
dnl
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that the following conditions
dnl are met:
dnl
dnl
dnl 1. Redistributions of source code must retain the above copyright
dnl notice, this list of conditions and the following disclaimer.
dnl
dnl
dnl 2. Redistributions in binary form must reproduce the above copyright
dnl notice, this list of conditions and the following disclaimer in
dnl the documentation and/or other materials provided with the
dnl distribution.
dnl
dnl
dnl THIS SOFTWARE IS PROVIDED BY SASCHA SCHUMANN ``AS IS'' AND ANY
dnl EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -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,20 +52,21 @@ 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([
AC_TRY_RUN( [
#include <pthread.h>
#include <stddef.h>
@@ -79,17 +80,23 @@ int main() {
int data = 1;
pthread_mutexattr_init(&mattr);
return pthread_create(&thd, NULL, thread_routine, &data);
} ]) ], [
pthreads_checked=yes
} ], [
pthreads_working=yes
], [
pthreads_checked=no
]
) ] )
pthreads_working=no
], [
dnl For cross compiling running this test is of no use. NetWare supports pthreads
pthreads_working=no
case $host_alias in
*netware*)
pthreads_working=yes
esac
]
) ] )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)
@@ -97,36 +104,49 @@ dnl -Kthread UDK cc (UnixWare)
dnl -mt WorkShop cc (Solaris)
dnl -mthreads gcc (AIX)
dnl -pthread gcc (Linux, FreeBSD, NetBSD, OpenBSD)
dnl -pthreads gcc (Solaris)
dnl -pthreads gcc (Solaris)
dnl -qthreaded AIX cc V5
dnl -threads gcc (HP-UX)
dnl
AC_DEFUN([PTHREADS_CHECK],[
AC_CACHE_CHECK(for pthreads_cflags,ac_cv_pthreads_cflags,[
ac_cv_pthreads_cflags=
if test "$pthreads_working" != "yes"; then
for flag in -kthread -pthread -pthreads -mthreads -Kthread -threads -mt -qthreaded; do
ac_save=$CFLAGS
CFLAGS="$CFLAGS $flag"
PTHREADS_CHECK_COMPILE
CFLAGS=$ac_save
if test "$pthreads_checked" = "yes"; then
ac_cv_pthreads_cflags=$flag
break
fi
done
if test "$beos_threads" = "1"; then
pthreads_working="yes"
ac_cv_pthreads_cflags=""
else
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
for flag in -kthread -pthread -pthreads -mthreads -Kthread -threads -mt -qthreaded; do
ac_save=$CFLAGS
CFLAGS="$CFLAGS $flag"
PTHREADS_CHECK_COMPILE
CFLAGS=$ac_save
if test "$pthreads_working" = "yes"; then
ac_cv_pthreads_cflags=$flag
break
fi
done
fi
fi
])
AC_CACHE_CHECK(for pthreads_lib, ac_cv_pthreads_lib,[
ac_cv_pthreads_lib=
if test "$pthreads_working" != "yes"; then
for lib in pthread pthreads c_r; do
for lib in pthread pthreads c_r; do
ac_save=$LIBS
LIBS="$LIBS -l$lib"
PTHREADS_CHECK_COMPILE
LIBS=$ac_save
if test "$pthreads_checked" = "yes"; then
if test "$pthreads_working" = "yes"; then
ac_cv_pthreads_lib=$lib
break
fi
@@ -134,7 +154,20 @@ if test "$pthreads_working" != "yes"; then
fi
])
if test "x$ac_cv_pthreads_cflags" != "x" -o "x$ac_cv_pthreads_lib" != "x"; then
pthreads_working="yes"
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
+122 -11
View File
@@ -1,17 +1,128 @@
dnl This file contains TSRM specific autoconf macros.
dnl
dnl TSRM_CHECK_PTHREADS
dnl
AC_DEFUN([TSRM_CHECK_PTHREADS],[
PTHREADS_CHECK
dnl TSRM_CHECK_GCC_ARG(ARG, ACTION-IF-FOUND, ACTION-IF-NOT_FOUND)
AC_DEFUN([TSRM_CHECK_GCC_ARG],[
gcc_arg_name=[ac_cv_gcc_arg]translit($1,A-Z-,a-z_)
AC_CACHE_CHECK([whether $CC supports $1], [ac_cv_gcc_arg]translit($1,A-Z-,a-z_), [
echo 'void somefunc() { };' > conftest.c
cmd='$CC $1 -c conftest.c'
if eval $cmd 2>&1 | egrep -e $1 >/dev/null ; then
ac_result=no
else
ac_result=yes
fi
eval $gcc_arg_name=$ac_result
rm -f conftest.*
])
if eval test "\$$gcc_arg_name" = "yes"; then
$2
else
:
$3
fi
])
if test "$pthreads_working" != "yes"; then
AC_MSG_ERROR(Your system seems to lack POSIX threads.)
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_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
AC_DEFINE(PTHREADS, 1, Whether to use Pthreads)
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)
AC_DEFUN([TSRM_CHECK_PTHREADS],[
PTHREADS_CHECK
if test "$beos_threads" = "1"; then
AC_DEFINE(BETHREADS, 1, Whether to use native BeOS threads)
else
if test "$pthreads_working" != "yes"; then
AC_MSG_ERROR(Your system seems to lack POSIX threads.)
fi
AC_DEFINE(PTHREADS, 1, Whether to use Pthreads)
AC_MSG_CHECKING(for POSIX threads)
AC_MSG_RESULT(yes)
fi
])
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
AC_MSG_CHECKING(for POSIX threads)
AC_MSG_RESULT(yes)
])
+22
View File
@@ -0,0 +1,22 @@
#ifndef TSRM_CONFIG_W32_H
#define TSRM_CONFIG_W32_H
#include <../main/config.w32.h>
#define HAVE_UTIME 1
#define HAVE_ALLOCA 1
#define HAVE_REALPATH 1
#include <malloc.h>
#include <stdlib.h>
#include <crtdbg.h>
#undef inline
#ifdef ZEND_WIN32_FORCE_INLINE
# define inline __forceinline
#else
# define inline
#endif
#endif
+70
View File
@@ -0,0 +1,70 @@
#ifndef TSRM_CONFIG_COMMON_H
#define TSRM_CONFIG_COMMON_H
#ifndef __CYGWIN__
# if WINNT|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 */
# ifndef NETWARE
char *alloca ();
# endif
# endif
# endif
# endif
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#ifndef MAXPATHLEN
# ifdef 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 */
+240
View File
@@ -0,0 +1,240 @@
/*
+----------------------------------------------------------------------+
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 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: |
| http://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. |
+----------------------------------------------------------------------+
| Authors: Venkat Raghavan S <rvenkat@novell.com> |
| Anantha Kesari H Y <hyanantha@novell.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include "TSRM.h"
#ifdef NETWARE
#ifdef USE_MKFIFO
#include <sys/stat.h>
#elif !defined(USE_PIPE_OPEN) /* NXFifoOpen */
#include <nks/fsio.h>
#endif
#include <nks/vm.h>
#include <nks/memory.h>
#include <string.h>
#include "mktemp.h"
/* strtok() call in LibC is abending when used in a different address space
* -- hence using PHP's version itself for now
*/
#include "tsrm_strtok_r.h"
#define tsrm_strtok_r(a,b,c) strtok((a),(b))
#define WHITESPACE " \t"
#define MAX_ARGS 10
TSRM_API FILE* popen(const char *commandline, const char *type)
{
char *command = NULL, *argv[MAX_ARGS] = {'\0'}, **env = NULL;
char *tempName = "sys:/php/temp/phpXXXXXX.tmp";
char *filePath = NULL;
char *ptr = NULL;
int ptrLen = 0, argc = 0, i = 0, envCount = 0, err = 0;
FILE *stream = NULL;
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
int pipe_handle;
int mode = O_RDONLY;
#else
NXHandle_t pipe_handle;
NXMode_t mode = NX_O_RDONLY;
#endif
NXExecEnvSpec_t envSpec;
NXNameSpec_t nameSpec;
NXVmId_t newVM = 0;
/* Check for validity of input parameters */
if (!commandline || !type)
return NULL;
/* Get temporary file name */
filePath = mktemp(tempName);
if (!filePath)
return NULL;
/* Set pipe mode according to type -- for now allow only "r" or "w" */
if (strcmp(type, "r") == 0)
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
mode = O_RDONLY;
#else
mode = NX_O_RDONLY;
#endif
else if (strcmp(type, "w") == 0)
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
mode = O_WRONLY;
#else
mode = NX_O_WRONLY;
#endif
else
return NULL;
#ifdef USE_PIPE_OPEN
pipe_handle = pipe_open(filePath, mode);
if (pipe_handle == -1)
return NULL;
#elif defined(USE_MKFIFO)
pipe_handle = mkfifo(filePath, mode);
if (pipe_handle == -1)
return NULL;
#else
/* - NetWare doesn't require first parameter
* - Allowing LibC to choose the buffer size for now
*/
err = NXFifoOpen(0, filePath, mode, 0, &pipe_handle);
if (err)
return NULL;
#endif
/* Copy the environment variables in preparation for the spawn call */
envCount = NXGetEnvCount() + 1; /* add one for NULL */
env = (char **) NXMemAlloc(sizeof(char *) * envCount, 0);
if (!env)
return NULL;
err = NXCopyEnv(env, envCount);
if (err) {
NXMemFree (env);
return NULL;
}
/* Separate commandline string into words */
ptr = tsrm_strtok_r((char*)commandline, WHITESPACE, NULL);
ptrLen = strlen(ptr);
command = (char*)malloc(ptrLen + 1);
if (!command) {
NXMemFree (env);
return NULL;
}
strcpy (command, ptr);
ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
while (ptr && (argc < MAX_ARGS)) {
ptrLen = strlen(ptr);
argv[argc] = (char*)malloc(ptrLen + 1);
if (!argv[argc]) {
NXMemFree (env);
if (command)
free (command);
for (i = 0; i < argc; i++) {
if (argv[i])
free (argv[i]);
}
return NULL;
}
strcpy (argv[argc], ptr);
argc++;
ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
}
/* Setup the execution environment and spawn new process */
envSpec.esFlags = 0; /* Not used */
envSpec.esArgc = argc;
envSpec.esArgv = (void **) argv;
envSpec.esEnv = (void **) env;
/* envSpec.esStdin.ssType = */
envSpec.esStdout.ssType = NX_OBJ_FIFO;
envSpec.esStderr.ssType = NX_OBJ_FILE;
/* 'ssHandle' is not a struct/union/class member */
/*
envSpec.esStdin.ssHandle =
envSpec.esStdout.ssHandle =
envSpec.esStderr.ssHandle = -1;
*/
envSpec.esStdin.ssPathCtx = NULL;
envSpec.esStdout.ssPathCtx = NULL;
envSpec.esStderr.ssPathCtx = NULL;
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
if (mode == O_RDONLY) {
#else
if (mode == NX_O_RDONLY) {
#endif
envSpec.esStdin.ssPath = filePath;
envSpec.esStdout.ssPath = stdout;
} else { /* Write Only */
envSpec.esStdin.ssPath = stdin;
envSpec.esStdout.ssPath = filePath;
}
envSpec.esStderr.ssPath = stdout;
nameSpec.ssType = NX_OBJ_FIFO;
/* nameSpec.ssHandle = 0; */ /* 'ssHandle' is not a struct/union/class member */
nameSpec.ssPathCtx = NULL; /* Not used */
nameSpec.ssPath = argv[0];
err = NXVmSpawn(&nameSpec, &envSpec, 0, &newVM);
if (!err)
/* Get file pointer corresponding to the pipe (file) opened */
stream = fdopen(pipe_handle, type);
/* Clean-up */
if (env)
NXMemFree (env);
if (pipe_handle)
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
close(pipe_handle);
#else
NXClose(pipe_handle);
#endif
if (command)
free (command);
for (i = 0; i < argc; i++) {
if (argv[i])
free (argv[i]);
}
return stream;
}
TSRM_API int pclose(FILE* stream)
{
int err = 0;
NXHandle_t fd = 0;
/* Get the process associated with this pipe (file) handle and terminate it */
fd = fileno(stream);
NXClose (fd);
err = fclose(stream);
return err;
}
#endif /* NETWARE */
+29
View File
@@ -0,0 +1,29 @@
/*
+----------------------------------------------------------------------+
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 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: |
| http://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. |
+----------------------------------------------------------------------+
| Authors: Venkat Raghavan S <rvenkat@novell.com> |
| Anantha Kesari H Y <hyanantha@novell.com> |
+----------------------------------------------------------------------+
*/
#ifndef TSRM_NW_H
#define TSRM_NW_H
#include "TSRM.h"
TSRM_API FILE* popen(const char *command, const char *type);
TSRM_API int pclose(FILE* stream);
#endif
+63
View File
@@ -0,0 +1,63 @@
#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;
}
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
+6
View File
@@ -0,0 +1,6 @@
#ifndef TSRM_STRTOK_R
#define TSRM_STRTOK_R
char *tsrm_strtok_r(char *s, const char *delim, char **last);
#endif
File diff suppressed because it is too large. Load diff
+351
View File
@@ -0,0 +1,351 @@
/*
+----------------------------------------------------------------------+
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 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: |
| http://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. |
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <andi@zend.com> |
| Sascha Schumann <sascha@schumann.cx> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef VIRTUAL_CWD_H
#define VIRTUAL_CWD_H
#include "TSRM.h"
#include "tsrm_config_common.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef ZTS
#define VIRTUAL_DIR
#endif
#ifndef TSRM_WIN32
#include <unistd.h>
#else
#include <direct.h>
#endif
#if defined(__osf__) || defined(_AIX)
#include <errno.h>
#endif
#ifdef TSRM_WIN32
#include "readdir.h"
#include <sys/utime.h>
/* mode_t isn't defined on Windows */
typedef unsigned short mode_t;
#define DEFAULT_SLASH '\\'
#define DEFAULT_DIR_SEPARATOR ';'
#define IS_SLASH(c) ((c) == '/' || (c) == '\\')
#define IS_SLASH_P(c) (*(c) == '/' || \
(*(c) == '\\' && !IsDBCSLeadByte(*(c-1))))
#define DEFAULT_U_SLASH ((UChar)0x5c) /*'\\'*/
#define DEFAULT_U_DIR_SEPARATOR ((UChar)0x3b) /*';'*/
#define IS_U_SLASH(c) ((UChar32)(c) == (UChar32)0x2f /*'/'*/ || (UChar32)(c) == (UChar32)0x5c /*'\\'*/)
#define IS_U_SLASH_P(c) IS_SLASH(*(c))
/* COPY_WHEN_ABSOLUTE is 2 under Win32 because by chance both regular absolute paths
in the file system and UNC paths need copying of two characters */
#define COPY_WHEN_ABSOLUTE(path) 2
#define IS_UNC_PATH(path, len) \
(len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1]))
#define IS_ABSOLUTE_PATH(path, len) \
(len >= 2 && ((isalpha(path[0]) && path[1] == ':') || IS_UNC_PATH(path, len)))
#elif defined(NETWARE)
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#define DEFAULT_SLASH '/'
#define DEFAULT_DIR_SEPARATOR ';'
#define IS_SLASH(c) ((c) == '/' || (c) == '\\')
#define IS_SLASH_P(c) IS_SLASH(*(c))
#define DEFAULT_U_SLASH ((UChar)0x2f) /*'/'*/
#define DEFAULT_U_DIR_SEPARATOR ((UChar)0x3b) /*';'*/
#define IS_U_SLASH(c) ((UChar32)(c) == (UChar32)0x2f /*'/'*/ || (UChar32)(c) == (UChar32)0x5c /*'\\'*/)
#define IS_U_SLASH_P(c) IS_U_SLASH(*(c))
/* Colon indicates volume name, either first character should be forward slash or backward slash */
#define IS_ABSOLUTE_PATH(path, len) \
((strchr(path, ':') != NULL) || ((len >= 1) && ((path[0] == '/') || (path[0] == '\\'))))
#else
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#define DEFAULT_SLASH '/'
#ifdef __riscos__
#define DEFAULT_DIR_SEPARATOR ';'
#define DEFAULT_U_DIR_SEPARATOR ((UChar)0x3b) /*';'*/
#else
#define DEFAULT_DIR_SEPARATOR ':'
#define DEFAULT_U_DIR_SEPARATOR ((UChar)0x3a) /*':'*/
#endif
#define IS_SLASH(c) ((c) == '/')
#define IS_SLASH_P(c) IS_SLASH(*(c))
#define DEFAULT_U_SLASH ((UChar)0x2f) /*'/'*/
#define IS_U_SLASH(c) ((UChar32)(c) == (UChar32)0x2f /*'/'*/)
#define IS_U_SLASH_P(c) IS_U_SLASH(*(c))
#endif
#ifndef COPY_WHEN_ABSOLUTE
#define COPY_WHEN_ABSOLUTE(path) 0
#endif
#ifndef IS_ABSOLUTE_PATH
#define IS_ABSOLUTE_PATH(path, len) \
(IS_SLASH(path[0]))
#endif
#ifdef TSRM_EXPORTS
#define CWD_EXPORTS
#endif
#ifdef TSRM_WIN32
# ifdef CWD_EXPORTS
# define CWD_API __declspec(dllexport)
# else
# define CWD_API __declspec(dllimport)
# endif
#elif defined(__GNUC__) && __GNUC__ >= 4
# define CWD_API __attribute__ ((visibility("default")))
#else
# define CWD_API
#endif
#ifdef TSRM_WIN32
CWD_API int php_sys_stat(const char *path, struct stat *buf);
#else
# define php_sys_stat stat
#endif
typedef struct _cwd_state {
char *cwd;
int cwd_length;
} cwd_state;
typedef int (*verify_path_func)(const cwd_state *);
CWD_API void virtual_cwd_startup(void);
CWD_API void virtual_cwd_shutdown(void);
CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC);
CWD_API int virtual_chdir(const char *path TSRMLS_DC);
CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC);
CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC);
CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC);
CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC);
CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC);
CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...);
CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC);
CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC);
CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC);
#if !defined(TSRM_WIN32)
CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC);
#endif
CWD_API int virtual_unlink(const char *path TSRMLS_DC);
CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC);
CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC);
CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC);
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC);
CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC);
#if defined(TSRM_WIN32)
/* these are not defined in win32 headers */
#ifndef W_OK
#define W_OK 0x02
#endif
#ifndef R_OK
#define R_OK 0x04
#endif
#ifndef X_OK
#define X_OK 0x01
#endif
#ifndef F_OK
#define F_OK 0x00
#endif
#endif
#if HAVE_UTIME
CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC);
#endif
CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC);
#if !defined(TSRM_WIN32) && !defined(NETWARE)
CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link TSRMLS_DC);
#endif
/* One of the following constants must be used as the last argument
in virtual_file_ex() call. */
#define CWD_EXPAND 0 /* expand "." and ".." but dont resolve symlinks */
#define CWD_FILEPATH 1 /* resolve symlinks if file is exist otherwise expand */
#define CWD_REALPATH 2 /* call realpath(), resolve symlinks. File must exist */
CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath);
CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC);
#define REALPATH_CACHE_TTL (2*60) /* 2 minutes */
#define REALPATH_CACHE_SIZE 0 /* disabled while php.ini isn't loaded */
typedef struct _realpath_cache_bucket {
unsigned long key;
char *path;
int path_len;
char *realpath;
int realpath_len;
int is_dir;
time_t expires;
#ifdef PHP_WIN32
unsigned char is_rvalid;
unsigned char is_readable;
unsigned char is_wvalid;
unsigned char is_writable;
#endif
struct _realpath_cache_bucket *next;
} realpath_cache_bucket;
typedef struct _virtual_cwd_globals {
cwd_state cwd;
long realpath_cache_size;
long realpath_cache_size_limit;
long realpath_cache_ttl;
realpath_cache_bucket *realpath_cache[1024];
} virtual_cwd_globals;
#ifdef ZTS
extern ts_rsrc_id cwd_globals_id;
# define CWDG(v) TSRMG(cwd_globals_id, virtual_cwd_globals *, v)
#else
extern virtual_cwd_globals cwd_globals;
# define CWDG(v) (cwd_globals.v)
#endif
CWD_API void realpath_cache_clean(TSRMLS_D);
CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC);
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t TSRMLS_DC);
CWD_API int realpath_cache_size(TSRMLS_D);
CWD_API int realpath_cache_max_buckets(TSRMLS_D);
CWD_API realpath_cache_bucket** realpath_cache_get_buckets(TSRMLS_D);
/* The actual macros to be used in programs using TSRM
* If the program defines VIRTUAL_DIR it will use the
* virtual_* functions
*/
#ifdef VIRTUAL_DIR
#define VCWD_GETCWD(buff, size) virtual_getcwd(buff, size TSRMLS_CC)
#define VCWD_FOPEN(path, mode) virtual_fopen(path, mode TSRMLS_CC)
/* Because open() has two modes, we have to macros to replace it */
#define VCWD_OPEN(path, flags) virtual_open(path TSRMLS_CC, flags)
#define VCWD_OPEN_MODE(path, flags, mode) virtual_open(path TSRMLS_CC, flags, mode)
#define VCWD_CREAT(path, mode) virtual_creat(path, mode TSRMLS_CC)
#define VCWD_CHDIR(path) virtual_chdir(path TSRMLS_CC)
#define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, virtual_chdir TSRMLS_CC)
#define VCWD_GETWD(buf)
#define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path TSRMLS_CC)
#define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname TSRMLS_CC)
#define VCWD_STAT(path, buff) virtual_stat(path, buff TSRMLS_CC)
#if !defined(TSRM_WIN32)
# define VCWD_LSTAT(path, buff) virtual_lstat(path, buff TSRMLS_CC)
#endif
#define VCWD_UNLINK(path) virtual_unlink(path TSRMLS_CC)
#define VCWD_MKDIR(pathname, mode) virtual_mkdir(pathname, mode TSRMLS_CC)
#define VCWD_RMDIR(pathname) virtual_rmdir(pathname TSRMLS_CC)
#define VCWD_OPENDIR(pathname) virtual_opendir(pathname TSRMLS_CC)
#define VCWD_POPEN(command, type) virtual_popen(command, type TSRMLS_CC)
#define VCWD_ACCESS(pathname, mode) virtual_access(pathname, mode TSRMLS_CC)
#if HAVE_UTIME
#define VCWD_UTIME(path, time) virtual_utime(path, time TSRMLS_CC)
#endif
#define VCWD_CHMOD(path, mode) virtual_chmod(path, mode TSRMLS_CC)
#if !defined(TSRM_WIN32) && !defined(NETWARE)
#define VCWD_CHOWN(path, owner, group) virtual_chown(path, owner, group, 0 TSRMLS_CC)
#if HAVE_LCHOWN
#define VCWD_LCHOWN(path, owner, group) virtual_chown(path, owner, group, 1 TSRMLS_CC)
#endif
#endif
#else
#define VCWD_GETCWD(buff, size) getcwd(buff, size)
#define VCWD_FOPEN(path, mode) fopen(path, mode)
#define VCWD_OPEN(path, flags) open(path, flags)
#define VCWD_OPEN_MODE(path, flags, mode) open(path, flags, mode)
#define VCWD_CREAT(path, mode) creat(path, mode)
/* rename on windows will fail if newname already exists.
MoveFileEx has to be used */
#if defined(TSRM_WIN32)
# define VCWD_RENAME(oldname, newname) (MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED) == 0 ? -1 : 0)
#else
# define VCWD_RENAME(oldname, newname) rename(oldname, newname)
#endif
#define VCWD_CHDIR(path) chdir(path)
#define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir)
#define VCWD_GETWD(buf) getwd(buf)
#define VCWD_STAT(path, buff) php_sys_stat(path, buff)
#define VCWD_LSTAT(path, buff) lstat(path, buff)
#define VCWD_UNLINK(path) unlink(path)
#define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode)
#define VCWD_RMDIR(pathname) rmdir(pathname)
#define VCWD_OPENDIR(pathname) opendir(pathname)
#define VCWD_POPEN(command, type) popen(command, type)
#if defined(TSRM_WIN32)
#define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode)
#else
#define VCWD_ACCESS(pathname, mode) access(pathname, mode)
#endif
#define VCWD_REALPATH(path, real_path) tsrm_realpath(path, real_path TSRMLS_CC)
#if HAVE_UTIME
# ifdef TSRM_WIN32
# define VCWD_UTIME(path, time) win32_utime(path, time)
# else
# define VCWD_UTIME(path, time) utime(path, time)
# endif
#endif
#define VCWD_CHMOD(path, mode) chmod(path, mode)
#if !defined(TSRM_WIN32) && !defined(NETWARE)
#define VCWD_CHOWN(path, owner, group) chown(path, owner, group)
#if HAVE_LCHOWN
#define VCWD_LCHOWN(path, owner, group) lchown(path, owner, group)
#endif
#endif
#endif
#endif /* VIRTUAL_CWD_H */
+258 -365
View File
@@ -1,6 +1,8 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 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 |
@@ -14,6 +16,8 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
@@ -28,8 +32,7 @@
#ifdef TSRM_WIN32
#include <Sddl.h>
#include "tsrm_win32.h"
#include "zend_virtual_cwd.h"
#include "win32/ioutil.h"
#include "tsrm_virtual_cwd.h"
#ifdef ZTS
static ts_rsrc_id win32_globals_id;
@@ -37,19 +40,16 @@ static ts_rsrc_id win32_globals_id;
static tsrm_win32_globals win32_globals;
#endif
static void tsrm_win32_ctor(tsrm_win32_globals *globals)
{/*{{{*/
#ifdef ZTS
TSRMLS_CACHE_UPDATE();
#endif
static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
{
globals->process = NULL;
globals->shm = NULL;
globals->process_size = 0;
globals->shm_size = 0;
globals->comspec = _strdup("cmd.exe");
globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
/* Set it to INVALID_HANDLE_VALUE
* It will be initialized correctly in tsrm_win32_access or set to
* It will be initialized correctly in tsrm_win32_access or set to
* NULL if no impersonation has been done.
* the impersonated token can't be set here as the impersonation
* will happen later, in fcgi_accept_request (or whatever is the
@@ -57,10 +57,10 @@ TSRMLS_CACHE_UPDATE();
*/
globals->impersonation_token = INVALID_HANDLE_VALUE;
globals->impersonation_token_sid = NULL;
}/*}}}*/
}
static void tsrm_win32_dtor(tsrm_win32_globals *globals)
{/*{{{*/
static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
{
shm_pair *ptr;
if (globals->process) {
@@ -85,63 +85,65 @@ static void tsrm_win32_dtor(tsrm_win32_globals *globals)
if (globals->impersonation_token_sid) {
free(globals->impersonation_token_sid);
}
}/*}}}*/
}
TSRM_API void tsrm_win32_startup(void)
{/*{{{*/
{
#ifdef ZTS
ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
#else
tsrm_win32_ctor(&win32_globals);
tsrm_win32_ctor(&win32_globals TSRMLS_CC);
#endif
}/*}}}*/
}
TSRM_API void tsrm_win32_shutdown(void)
{/*{{{*/
{
#ifndef ZTS
tsrm_win32_dtor(&win32_globals);
tsrm_win32_dtor(&win32_globals TSRMLS_CC);
#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 TSRMLS_DC)
{
PSID pSid = TWG(impersonation_token_sid);
char *ptcSid = NULL;
DWORD sid_len = pSid ? GetLengthSid(pSid) : 0;
TCHAR *ptcSid = NULL;
char *bucket_key = NULL;
size_t ptc_sid_len;
if (!pSid) {
*key_len = pathname_len;
return pathname;
bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(pathname) + 1);
if (!bucket_key) {
return NULL;
}
memcpy(bucket_key, pathname, strlen(pathname));
return bucket_key;
}
if (!ConvertSidToStringSid(pSid, &ptcSid)) {
*key_len = 0;
return NULL;
}
ptc_sid_len = strlen(ptcSid);
*key_len = pathname_len + ptc_sid_len;
bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *key_len + 1);
bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(pathname) + strlen(ptcSid) + 1);
if (!bucket_key) {
LocalFree(ptcSid);
*key_len = 0;
return NULL;
}
memcpy(bucket_key, ptcSid, ptc_sid_len);
memcpy(bucket_key + ptc_sid_len, pathname, pathname_len + 1);
memcpy(bucket_key, ptcSid, strlen(ptcSid));
memcpy(bucket_key + strlen(ptcSid), pathname, strlen(pathname) + 1);
LocalFree(ptcSid);
return bucket_key;
}/*}}}*/
}
PSID tsrm_win32_get_token_sid(HANDLE hToken)
{/*{{{*/
{
BOOL bSuccess = FALSE;
DWORD dwLength = 0;
PTOKEN_USER pTokenUser = NULL;
PSID sid;
PSID *ppsid = &sid;
DWORD sid_len;
PSID pResultSid = NULL;
@@ -186,12 +188,12 @@ Finished:
HeapFree(GetProcessHeap(), 0, (LPVOID)pTokenUser);
}
return NULL;
}/*}}}*/
}
TSRM_API int tsrm_win32_access(const char *pathname, int mode)
{/*{{{*/
{
time_t t;
HANDLE thread_token = NULL;
HANDLE thread_token;
PSID token_sid;
SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
GENERIC_MAPPING gen_map = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS };
@@ -202,176 +204,184 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
BYTE * psec_desc = NULL;
BOOL fAccess = FALSE;
BOOL bucket_key_alloc = FALSE;
realpath_cache_bucket * bucket = NULL;
char real_path[MAXPATHLEN] = {0};
char * real_path = NULL;
if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
if(tsrm_realpath(pathname, real_path) == NULL) {
SET_ERRNO_FROM_WIN32_CODE(ERROR_FILE_NOT_FOUND);
return -1;
TSRMLS_FETCH();
if (mode == 1 /*X_OK*/) {
DWORD type;
return GetBinaryType(pathname, &type) ? 0 : -1;
} else {
if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
real_path = (char *)malloc(MAX_PATH);
if(tsrm_realpath(pathname, real_path TSRMLS_CC) == NULL) {
goto Finished;
}
pathname = real_path;
}
if(access(pathname, mode)) {
free(real_path);
return errno;
}
pathname = real_path;
}
PHP_WIN32_IOUTIL_INIT_W(pathname)
if (!pathw) {
return -1;
}
/* Either access call failed, or the mode was asking for a specific check.*/
int ret = php_win32_ioutil_access_w(pathw, mode);
if (0 > ret || X_OK == mode || F_OK == mode) {
PHP_WIN32_IOUTIL_CLEANUP_W()
return ret;
}
/* If only existence check is made, return now */
if (mode == 0) {
free(real_path);
return 0;
}
/* Only in NTS when impersonate==1 (aka FastCGI) */
/*
AccessCheck() requires an impersonation token. We first get a primary
token and then create a duplicate impersonation token. The
impersonation token is not actually assigned to the thread, but is
used in the call to AccessCheck. Thus, this function itself never
impersonates, but does use the identity of the thread. If the thread
was impersonating already, this function uses that impersonation context.
*/
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
if (GetLastError() == ERROR_NO_TOKEN) {
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &thread_token)) {
TWG(impersonation_token) = NULL;
goto Finished;
}
}
}
/* token_sid will be freed in tsrmwin32_dtor */
token_sid = tsrm_win32_get_token_sid(thread_token);
if (!token_sid) {
if (TWG(impersonation_token_sid)) {
free(TWG(impersonation_token_sid));
}
TWG(impersonation_token_sid) = NULL;
goto Finished;
}
/* Different identity, we need a new impersontated token as well */
if (!TWG(impersonation_token_sid) || !EqualSid(token_sid, TWG(impersonation_token_sid))) {
if (TWG(impersonation_token_sid)) {
free(TWG(impersonation_token_sid));
}
TWG(impersonation_token_sid) = token_sid;
/* Duplicate the token as impersonated token */
if (!DuplicateToken(thread_token, SecurityImpersonation, &TWG(impersonation_token))) {
goto Finished;
}
} else {
/* we already have it, free it then */
free(token_sid);
}
if (CWDG(realpath_cache_size_limit)) {
t = time(0);
bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
if(bucket == NULL && !real_path[0]) {
/* We used the pathname directly. Call tsrm_realpath */
/* so that entry is created in realpath cache */
if(tsrm_realpath(pathname, real_path) != NULL) {
pathname = real_path;
bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
PHP_WIN32_IOUTIL_REINIT_W(pathname);
/*
AccessCheck() requires an impersonation token. We first get a primary
token and then create a duplicate impersonation token. The
impersonation token is not actually assigned to the thread, but is
used in the call to AccessCheck. Thus, this function itself never
impersonates, but does use the identity of the thread. If the thread
was impersonating already, this function uses that impersonation context.
*/
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
DWORD err = GetLastError();
if (GetLastError() == ERROR_NO_TOKEN) {
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &thread_token)) {
TWG(impersonation_token) = NULL;
goto Finished;
}
}
}
}
/* Do a full access check because access() will only check read-only attribute */
if(mode == 0 || mode > 6) {
if(bucket != NULL && bucket->is_rvalid) {
fAccess = bucket->is_readable;
/* token_sid will be freed in tsrmwin32_dtor */
token_sid = tsrm_win32_get_token_sid(thread_token);
if (!token_sid) {
if (TWG(impersonation_token_sid)) {
free(TWG(impersonation_token_sid));
}
TWG(impersonation_token_sid) = NULL;
goto Finished;
}
desired_access = FILE_GENERIC_READ;
} else if(mode <= 2) {
if(bucket != NULL && bucket->is_wvalid) {
fAccess = bucket->is_writable;
/* Different identity, we need a new impersontated token as well */
if (!TWG(impersonation_token_sid) || !EqualSid(token_sid, TWG(impersonation_token_sid))) {
if (TWG(impersonation_token_sid)) {
free(TWG(impersonation_token_sid));
}
TWG(impersonation_token_sid) = token_sid;
/* Duplicate the token as impersonated token */
if (!DuplicateToken(thread_token, SecurityImpersonation, &TWG(impersonation_token))) {
goto Finished;
}
} else {
/* we already have it, free it then */
free(token_sid);
}
if (CWDG(realpath_cache_size_limit)) {
t = time(0);
bucket = realpath_cache_lookup(pathname, strlen(pathname), t TSRMLS_CC);
if(bucket == NULL && real_path == NULL) {
/* We used the pathname directly. Call tsrm_realpath */
/* so that entry is created in realpath cache */
real_path = (char *)malloc(MAX_PATH);
if(tsrm_realpath(pathname, real_path TSRMLS_CC) != NULL) {
pathname = real_path;
bucket = realpath_cache_lookup(pathname, strlen(pathname), t TSRMLS_CC);
}
}
}
/* Do a full access check because access() will only check read-only attribute */
if(mode == 0 || mode > 6) {
if(bucket != NULL && bucket->is_rvalid) {
fAccess = bucket->is_readable;
goto Finished;
}
desired_access = FILE_GENERIC_READ;
} else if(mode <= 2) {
if(bucket != NULL && bucket->is_wvalid) {
fAccess = bucket->is_writable;
goto Finished;
}
desired_access = FILE_GENERIC_WRITE;
} else if(mode <= 4) {
if(bucket != NULL && bucket->is_rvalid) {
fAccess = bucket->is_readable;
goto Finished;
}
desired_access = FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS;
} else { // if(mode <= 6)
if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) {
fAccess = bucket->is_readable & bucket->is_writable;
goto Finished;
}
desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
}
if(TWG(impersonation_token) == NULL) {
goto Finished;
}
desired_access = FILE_GENERIC_WRITE;
} else if(mode <= 4) {
if(bucket != NULL && bucket->is_rvalid) {
fAccess = bucket->is_readable;
/* Get size of security buffer. Call is expected to fail */
if(GetFileSecurity(pathname, sec_info, NULL, 0, &sec_desc_length)) {
goto Finished;
}
desired_access = FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS;
} else { // if(mode <= 6)
if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) {
fAccess = bucket->is_readable & bucket->is_writable;
psec_desc = (BYTE *)malloc(sec_desc_length);
if(psec_desc == NULL ||
!GetFileSecurity(pathname, sec_info, (PSECURITY_DESCRIPTOR)psec_desc, sec_desc_length, &sec_desc_length)) {
goto Finished;
}
desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
}
if(TWG(impersonation_token) == NULL) {
goto Finished;
}
MapGenericMask(&desired_access, &gen_map);
/* Get size of security buffer. Call is expected to fail */
if(GetFileSecurityW(pathw, sec_info, NULL, 0, &sec_desc_length)) {
goto Finished;
}
psec_desc = (BYTE *)malloc(sec_desc_length);
if(psec_desc == NULL ||
!GetFileSecurityW(pathw, sec_info, (PSECURITY_DESCRIPTOR)psec_desc, sec_desc_length, &sec_desc_length)) {
goto Finished;
}
MapGenericMask(&desired_access, &gen_map);
if(!AccessCheck((PSECURITY_DESCRIPTOR)psec_desc, TWG(impersonation_token), desired_access, &gen_map, &privilege_set, &priv_set_length, &granted_access, &fAccess)) {
goto Finished_Impersonate;
}
/* Keep the result in realpath_cache */
if(bucket != NULL) {
if(desired_access == (FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS)) {
bucket->is_rvalid = 1;
bucket->is_readable = fAccess;
if(!AccessCheck((PSECURITY_DESCRIPTOR)psec_desc, TWG(impersonation_token), desired_access, &gen_map, &privilege_set, &priv_set_length, &granted_access, &fAccess)) {
goto Finished_Impersonate;
}
else if(desired_access == FILE_GENERIC_WRITE) {
bucket->is_wvalid = 1;
bucket->is_writable = fAccess;
} else if (desired_access == (FILE_GENERIC_READ | FILE_GENERIC_WRITE)) {
bucket->is_rvalid = 1;
bucket->is_readable = fAccess;
bucket->is_wvalid = 1;
bucket->is_writable = fAccess;
/* Keep the result in realpath_cache */
if(bucket != NULL) {
if(desired_access == (FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS)) {
bucket->is_rvalid = 1;
bucket->is_readable = fAccess;
}
else if(desired_access == FILE_GENERIC_WRITE) {
bucket->is_wvalid = 1;
bucket->is_writable = fAccess;
} else if (desired_access == (FILE_GENERIC_READ | FILE_GENERIC_WRITE)) {
bucket->is_rvalid = 1;
bucket->is_readable = fAccess;
bucket->is_wvalid = 1;
bucket->is_writable = fAccess;
}
}
}
Finished_Impersonate:
if(psec_desc != NULL) {
free(psec_desc);
psec_desc = NULL;
}
if(psec_desc != NULL) {
free(psec_desc);
psec_desc = NULL;
}
Finished:
if(thread_token != NULL) {
CloseHandle(thread_token);
if(real_path != NULL) {
free(real_path);
real_path = NULL;
}
if(fAccess == FALSE) {
errno = EACCES;
return errno;
} else {
return 0;
}
}
PHP_WIN32_IOUTIL_CLEANUP_W()
if(fAccess == FALSE) {
errno = EACCES;
return errno;
} else {
return 0;
}
}/*}}}*/
}
static process_pair *process_get(FILE *stream)
{/*{{{*/
static process_pair *process_get(FILE *stream TSRMLS_DC)
{
process_pair *ptr;
process_pair *newptr;
@@ -394,12 +404,13 @@ static process_pair *process_get(FILE *stream)
ptr = newptr + TWG(process_size);
TWG(process_size)++;
return ptr;
}/*}}}*/
}
static shm_pair *shm_get(key_t key, void *addr)
{/*{{{*/
static shm_pair *shm_get(int key, void *addr)
{
shm_pair *ptr;
shm_pair *newptr;
TSRMLS_FETCH();
for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
if (!ptr->descriptor) {
@@ -424,79 +435,57 @@ static shm_pair *shm_get(key_t key, void *addr)
TWG(shm) = newptr;
ptr = newptr + TWG(shm_size);
TWG(shm_size)++;
memset(ptr, 0, sizeof(*ptr));
return ptr;
}/*}}}*/
}
static HANDLE dupHandle(HANDLE fh, BOOL inherit)
{/*{{{*/
static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
HANDLE copy, self = GetCurrentProcess();
if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
return NULL;
}
return copy;
}/*}}}*/
}
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;
STARTUPINFOW startup;
int fno, type_len = strlen(type), read, mode;
STARTUPINFO startup;
PROCESS_INFORMATION process;
SECURITY_ATTRIBUTES security;
HANDLE in, out;
DWORD dwCreateFlags = 0;
BOOL res;
process_pair *proc;
char *cmd = NULL;
wchar_t *cmdw = NULL, *cwdw = NULL, *envw = NULL;
char *cmd;
int i;
char *ptype = (char *)type;
HANDLE thread_token = NULL;
HANDLE token_user = NULL;
BOOL asuser = TRUE;
TSRMLS_FETCH();
if (!type) {
return NULL;
}
type_len = (int)strlen(type);
if (type_len < 1 || type_len > 2) {
/*The following two checks can be removed once we drop XP support */
type_len = strlen(type);
if (type_len <1 || type_len > 2) {
return NULL;
}
if (ptype[0] != 'r' && ptype[0] != 'w') {
return NULL;
}
if (type_len > 1 && (ptype[1] != 'b' && ptype[1] != 't')) {
return NULL;
}
cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /s /c ")+2);
if (!cmd) {
return NULL;
}
sprintf(cmd, "%s /s /c \"%s\"", TWG(comspec), command);
cmdw = php_win32_cp_any_to_w(cmd);
if (!cmdw) {
free(cmd);
return NULL;
}
if (cwd) {
cwdw = php_win32_ioutil_any_to_w(cwd);
if (!cwdw) {
free(cmd);
free(cmdw);
for (i=0; i < type_len; i++) {
if (!(*ptype == 'r' || *ptype == 'w' || *ptype == 'b' || *ptype == 't')) {
return NULL;
}
ptype++;
}
security.nLength = sizeof(SECURITY_ATTRIBUTES);
@@ -504,16 +493,13 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd,
security.lpSecurityDescriptor = NULL;
if (!type_len || !CreatePipe(&in, &out, &security, 2048L)) {
free(cmdw);
free(cwdw);
free(cmd);
return NULL;
}
memset(&startup, 0, sizeof(STARTUPINFOW));
memset(&startup, 0, sizeof(STARTUPINFO));
memset(&process, 0, sizeof(PROCESS_INFORMATION));
startup.cb = sizeof(STARTUPINFOW);
startup.cb = sizeof(STARTUPINFO);
startup.dwFlags = STARTF_USESTDHANDLES;
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
@@ -545,35 +531,22 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd,
}
}
envw = php_win32_cp_env_any_to_w(env);
if (envw) {
dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT;
} else {
if (env) {
free(cmd);
free(cmdw);
free(cwdw);
return NULL;
}
}
cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")+2);
sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
if (asuser) {
res = CreateProcessAsUserW(token_user, NULL, cmdw, &security, &security, security.bInheritHandle, dwCreateFlags, envw, cwdw, &startup, &process);
res = CreateProcessAsUser(token_user, NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, env, cwd, &startup, &process);
CloseHandle(token_user);
} else {
res = CreateProcessW(NULL, cmdw, &security, &security, security.bInheritHandle, dwCreateFlags, envw, cwdw, &startup, &process);
res = CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, env, cwd, &startup, &process);
}
free(cmd);
free(cmdw);
free(cwdw);
free(envw);
if (!res) {
return NULL;
}
CloseHandle(process.hThread);
proc = process_get(NULL);
proc = process_get(NULL TSRMLS_CC);
if (read) {
fno = _open_osfhandle((tsrm_intptr_t)in, _O_RDONLY | mode);
@@ -587,14 +560,15 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd,
proc->prochnd = process.hProcess;
proc->stream = stream;
return stream;
}/*}}}*/
}
TSRM_API int pclose(FILE *stream)
{/*{{{*/
{
DWORD termstat = 0;
process_pair *process;
TSRMLS_FETCH();
if ((process = process_get(stream)) == NULL) {
if ((process = process_get(stream TSRMLS_CC)) == NULL) {
return 0;
}
@@ -607,68 +581,46 @@ TSRM_API int pclose(FILE *stream)
CloseHandle(process->prochnd);
return termstat;
}/*}}}*/
}
TSRM_API int shmget(key_t key, size_t size, int flags)
{/*{{{*/
TSRM_API int shmget(int key, int 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);
shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
if (size < 0) {
return -1;
}
if (!shm_handle && !info_handle) {
sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
sprintf(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);
if ((!shm_handle && !info_handle)) {
if (flags & IPC_CREAT) {
#if SIZEOF_SIZE_T == 8
DWORD high = size >> 32;
DWORD low = (DWORD)size;
#else
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, 0, size, shm_segment);
info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
created = TRUE;
}
if (!shm_handle || !info_handle) {
if (shm_handle) {
CloseHandle(shm_handle);
}
if (info_handle) {
CloseHandle(info_handle);
}
if ((!shm_handle || !info_handle)) {
return -1;
}
} else {
if (flags & IPC_EXCL) {
if (shm_handle) {
CloseHandle(shm_handle);
}
if (info_handle) {
CloseHandle(info_handle);
}
return -1;
}
}
shm = shm_get(key, NULL);
if (!shm) {
CloseHandle(shm_handle);
CloseHandle(info_handle);
return -1;
}
shm->segment = shm_handle;
shm->info = info_handle;
shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
if (NULL != shm->descriptor && created) {
if (created) {
shm->descriptor->shm_perm.key = key;
shm->descriptor->shm_segsz = size;
shm->descriptor->shm_ctime = time(NULL);
@@ -682,45 +634,36 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
}
if (NULL != shm->descriptor && (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz)) {
if (NULL != shm->segment) {
CloseHandle(shm->segment);
}
if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
CloseHandle(shm->segment);
UnmapViewOfFile(shm->descriptor);
CloseHandle(shm->info);
return -1;
}
return key;
}/*}}}*/
}
TSRM_API void *shmat(int key, const void *shmaddr, int flags)
{/*{{{*/
{
shm_pair *shm = shm_get(key, NULL);
if (!shm->segment) {
return (void*)-1;
}
shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
if (NULL == shm->addr) {
int err = GetLastError();
SET_ERRNO_FROM_WIN32_CODE(err);
return (void*)-1;
}
shm->descriptor->shm_atime = time(NULL);
shm->descriptor->shm_lpid = getpid();
shm->descriptor->shm_nattch++;
shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
return shm->addr;
}/*}}}*/
}
TSRM_API int shmdt(const void *shmaddr)
{/*{{{*/
{
shm_pair *shm = shm_get(0, (void*)shmaddr);
int ret;
if (!shm->segment) {
return -1;
@@ -730,16 +673,10 @@ 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)
{/*{{{*/
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
shm_pair *shm = shm_get(key, NULL);
if (!shm->segment) {
@@ -767,59 +704,15 @@ TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf)
default:
return -1;
}
}/*}}}*/
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;
pft->dwLowDateTime = (DWORD)ll;
pft->dwHighDateTime = ll >> 32;
}
/* }}} */
TSRM_API int win32_utime(const char *filename, struct utimbuf *buf) /* {{{ */
TSRM_API char *realpath(char *orig_path, char *buffer)
{
FILETIME mtime, atime;
HANDLE hFile;
PHP_WIN32_IOUTIL_INIT_W(filename)
if (!pathw) {
return -1;
int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
if(!ret || ret > _MAX_PATH) {
return NULL;
}
hFile = CreateFileW(pathw, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,
OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
PHP_WIN32_IOUTIL_CLEANUP_W()
/* OPEN_ALWAYS mode sets the last error to ERROR_ALREADY_EXISTS but
the CreateFile operation succeeds */
if (GetLastError() == ERROR_ALREADY_EXISTS) {
SetLastError(0);
}
if ( hFile == INVALID_HANDLE_VALUE ) {
return -1;
}
if (!buf) {
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &mtime);
atime = mtime;
} else {
UnixTimeToFileTime(buf->modtime, &mtime);
UnixTimeToFileTime(buf->actime, &atime);
}
if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
CloseHandle(hFile);
return -1;
}
CloseHandle(hFile);
return 1;
return buffer;
}
/* }}} */
#endif
+13 -10
View File
@@ -1,6 +1,8 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
| PHP Version 6 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 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 |
@@ -14,16 +16,16 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef TSRM_WIN32_H
#define TSRM_WIN32_H
#include "TSRM.h"
#include <windows.h>
#include <sys/utime.h>
#include "win32/ipc.h"
struct ipc_perm {
key_t key;
int key;
unsigned short uid;
unsigned short gid;
unsigned short cuid;
@@ -34,7 +36,7 @@ struct ipc_perm {
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
int shm_segsz;
time_t shm_atime;
time_t shm_dtime;
time_t shm_ctime;
@@ -66,8 +68,7 @@ typedef struct {
} tsrm_win32_globals;
#ifdef ZTS
# define TWG(v) TSRMG_STATIC(win32_globals_id, tsrm_win32_globals *, v)
TSRMLS_CACHE_EXTERN()
# define TWG(v) TSRMG(win32_globals_id, tsrm_win32_globals *, v)
#else
# define TWG(v) (win32_globals.v)
#endif
@@ -89,19 +90,21 @@ 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 TSRMLS_DC);
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);
TSRM_API int win32_utime(const char *filename, struct utimbuf *buf);
TSRM_API int shmget(key_t key, size_t size, int flags);
TSRM_API int shmget(int key, int size, int flags);
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);
TSRM_API char *realpath(char *orig_path, char *buffer);
#endif
-1159
View File
File diff suppressed because it is too large. Load diff
-461
View File
@@ -1,461 +0,0 @@
PHP 8.0 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
2. Build system changes
a. Abstract
b. Unix build system changes
c. Windows build system changes
3. Module changes
========================
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.
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.
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
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).
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.
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.
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:
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;
h. Added the zend_value_error() function, which is intended to be used
to raise ValueError when inappropriate argument values are passed
to functions.
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.
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.
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
The 'v' format from the custom snprintf and spprintf implementations has
been removed. Use the standard 's' format instead.
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).
m. All internal functions and methods are now required to specify arginfo
information, otherwise warnings will be thrown on startup.
n. The zend_hash_sort and zend_hash_minmax APIs now accept a comparison
function with the following signature:
typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b);
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.
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.
p. The ARG_COUNT() macro has been removed use ZEND_NUM_ARGS() instead.
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.
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:
ZEND_METHOD(MyClass, getIterator) {
ZEND_PARSE_PARAMETERS_NONE();
zend_create_internal_iterator_zval(return_value, ZEND_THIS);
}
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().
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()
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.
Error observering callbacks are guaranteed to be called regardless of
the users error_reporting setting or userland error handler return values.
Register observer callbacks during MINIT of an extension:
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);
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
w. The following APIs have been renamed:
- _zend_ts_hash_init() to zend_ts_hash_init()
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.
========================
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.
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.
========================
3. Module changes
========================
+41998
View File
File diff suppressed because it is too large. Load diff
+12 -12
View File
@@ -1,25 +1,25 @@
--------------------------------------------------------------------
--------------------------------------------------------------------
The Zend Engine License, Version 2.00
Copyright (c) 1999-2006 Zend Technologies Ltd. All rights reserved.
--------------------------------------------------------------------
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is 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
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 "Zend" and "Zend Engine" must not be used to endorse
or promote products derived from this software without prior
permission from Zend Technologies Ltd. For written permission,
please contact license@zend.com.
please contact license@zend.com.
4. Zend Technologies Ltd. may publish revised and/or new versions
of the license from time to time. Each version will be given a
distinguishing version number.
@@ -40,9 +40,9 @@ are met:
software must display the following acknowledgment:
"The Zend Engine is freely available at http://www.zend.com"
THIS SOFTWARE IS PROVIDED BY ZEND TECHNOLOGIES LTD. ``AS IS'' AND
THIS SOFTWARE IS PROVIDED BY ZEND TECHNOLOGIES LTD. ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ZEND
TECHNOLOGIES LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@@ -53,4 +53,4 @@ 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.
--------------------------------------------------------------------
--------------------------------------------------------------------
+54
View File
@@ -0,0 +1,54 @@
## 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_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_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.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_strtod.c zend_strtol.c zend_closures.c zend_float.c
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) --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) --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
View File
@@ -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
+195
View File
@@ -0,0 +1,195 @@
Creating an object
------------------
Object can be created in the following ways:
1. As a result of a function call. E.g.:
$foo = create_new_foo("parameter");
$foo->run();
The function should create a new zval, create new object and get the
handle for it, set handle and handler table as needed. Note that the
handle is the only ID of the object, so it should be enough to
identify it.
2. Overriding create_object handler for class. E.g.:
$foo = new Java("some.Class.here", "parameter");
$foo->run();
The create_object handler function should create a new zval, create
new object and get the handle for it, set handle and handler table as
needed, and also provide constructor method that would handle
constructor call. The get_constructor handler table entry should be
used for that. Do not rely class entry's constructor, unless you refer
to it from get_constructor handler.
Object maintenance
------------------
The handlers add_ref and del_ref are called when a new zval referring
to the object is created. This does not create a new object - both
zvals still refer to the same object.
clone_obj handler should create a new object, identical to an old one,
but being a separate entity.
delete_obj should destroy an object, all references to it become
invalid.
Object access - read
--------------------
read_property is used to read object's property. This value is not
meant to be changed. The handler returns zval * with the value.
Object access - write
---------------------
write_property is used to directly write object's property by
name. This handler is used to assign property variables or to change them
in operations like += or ++ (unless get_property_zval_ptr is also set).
get_property_zval_ptr is used to obtain pointer to modifiable zval for
operations like += or ++. This should be used only if your object model
stores properties as real zval's that can be modified from outside.
Otherwise this handler should be NULL and the engine will use
read_property and write_property instead.
get_property_ptr is used to obtain zval ** for future writing to
it. If your object properties are stored as zval*, return real place
where the property is stored. If the aren't, the best way is to create
proxy object and handle it via get and set methods (see below).
This method is meant to be used for send-by-reference and assign-by-reference
use of object properties. If you don;t want to implement property
referencing for your objects, you can set this handler to NULL.
get and set handlers are used when engine needs to access the object
as a value. E.g., in the following situation:
$foo =& $obj->bar;
$foo = 1;
if $foo is an object (e.g., proxy object from get_property_ptr) it
would be accessed using write handler.
Object access - method call
---------------------------
get_method handler is used to find method description by name. It
should set right type, function name and parameter mask for the
method. If the type is ZEND_OVERLOADED_FUNCTION, the method would be
called via call_method handler, otherwise it would be called with
standard Zend means.
get_constructor performs the same function as get_method, but for the
object constructor.
call_method handler is used to perform method call. Parameters are
passed like to any other Zend internal function.
Object - comparison
-------------------
Objects can be compared via compare_objects handler. This is used with
== operation, === compares objects by handles, i.e., return true if
and only if it's really the same object. Note that objects from
different object types (i.e., having different handlers) can not be
compared.
Objects - reflection
--------------------
get_class_name is used to retrieve class name of the object.
get_class_entry returns class entry (zend_class_entry) for the object,
in case there exists PHP class for it.
No other reflection functions are currently implemented.
Objects - data structures and handlers
---------------------------------------
The object is represented by the following structure:
struct _zend_object_value {
zend_object_handle handle;
zend_object_handlers *handlers;
};
handle is an ID of the object among the objects of the same type (not
class!). The type of the object and how it behaves is determined by
the handler table.
typedef struct _zend_object_handlers {
zend_object_add_ref_t add_ref;
zend_object_del_ref_t del_ref;
zend_object_delete_obj_t delete_obj;
zend_object_clone_obj_t clone_obj;
zend_object_read_property_t read_property;
zend_object_write_property_t write_property;
zend_object_get_property_ptr_t get_property_ptr;
zend_object_get_property_zval_ptr_t get_property_zval_ptr;
zend_object_get_t get;
zend_object_set_t set;
zend_object_has_property_t has_property;
zend_object_unset_property_t unset_property;
zend_object_get_properties_t get_properties;
zend_object_get_method_t get_method;
zend_object_call_method_t call_method;
zend_object_get_constructor_t get_constructor;
zend_object_get_class_entry_t get_class_entry;
zend_object_get_class_name_t get_class_name;
zend_object_compare_t compare_objects;
} zend_object_handlers;
See zend_object_handlers.h for prototypes. All objects are passed as zval's.
Handlers explained:
add_ref - called when a copy of the object handle is created.
del_ref - called when a copy of the object handle is destroyed.
delete_obj - called when an object needs to be destroyed.
clone_obj - called when a new object identical to an old one should be
created (unlike Zend Engine 1, this never happens unless explicitly
asked for).
read_property - returns zval *, containing the value of the
property. Is used when value of the property should be retrieved for
reading.
write_property - assigns value to certain property of the object.
get_property_zval_ptr - retrieves zval** for being directly modified by
the engine. If your properties are not zval's, don't define it.
get_property_ptr - retrieves zval** for the property of the value, to
be used for read and write. If object properties are not zval's
natively, this method should create and return proxy object for use
with get and set methods.
get - retrieves zval* for object contents. To be used mainly with
proxy objects from get_property_ptr, but also may be used for
convert_to_* functions.
set - sets value for object contents. To be used mainly with
proxy objects from get_property_ptr.
has_property - checks if the object has certain property set.
unset_property - removes value for the property of the object
get_method - retrieves description of the method
call_method - calls the method (parameters should be put on stack like
for any other PHP internal function).
get_constructor - get description for the object constructor method
get_class_entry - should return the class entry for the object
get_class_name - get the name of the class the object belongs to
compare_objects - compares if two objects are equal
+34
View File
@@ -0,0 +1,34 @@
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();'
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.
+108
View File
@@ -0,0 +1,108 @@
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 callls 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
Zend Engine II currently includes two executors during the build process, one
is the specialized version and the other is the old one non-specialized with
function handlers. By default Zend Engine II uses the specialized one but you
can switch to the old executor at runtime by calling zend_vm_use_old_executor().
-139
View File
@@ -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
```
+136
View File
@@ -0,0 +1,136 @@
Revamped object model using object handles
===========================================
Background
----------
In the Zend Engine 1.0 (and its predecessor the PHP 3 scripting
engine) the object model's design is that instantiated objects are
language values. This means that when programmers are performing
operations, such variable assignment and passing parameters to
functions, objects are handled very similarly to the way other
primitive types are handled such as integers and strings.
Semantically this means that the whole object is being copied. The
approach Java takes is different where one refers to objects by handle
and not by value (one can think of a handle as an objects' ID).
Need
----
Unfortunately, the approach taken up to now has severely limited the
Zend Engine's object oriented model, both feature and simplicity
wise. One of the main problems with the former approach is that object
instantiation and duplication is very hard to control, a problem which
can not only lead to inefficient development but also often to strange
run-time behavior. Changing the object model to a handle oriented
model will allow the addressing of many needs such as destructors,
de-referencing method return values, tight control of object
duplication and more.
Overview
--------
The proposed object model is very much influenced by the Java
model. In general, when you create a new object you will be getting a
handle to the object instead of the object itself. When this handle is
sent to functions, assigned and copied it is only the handle which is
copied/sent/assigned. The object itself is never copied nor
duplicated. This results in all handles of this object to always point
at the same object making it a very consistent solution and saving
unnecessary duplication and confusing behavior.
Functionality
-------------
After this change the basic use of objects will be almost identical to
previous versions of the scripting engine. However, you won't bump
into awkward and confusing copying & destructing of objects. In order
to create and use a new object instance you will do the following:
$object = new MyClass(); $object->method();
The previous code will assign $object the handle of a new instance of
the class MyClass and call one of its methods.
Consider the following code:
1 class MyClass
2 {
3 function setMember($value)
4 {
5 $this->member = $value;
6 }
7
8 function getMember()
9 {
10 return $this->member;
11 }
12 }
13
14 function foo($obj)
15 {
16 $obj->setMember("foo");
17 }
18
19 $object = new MyClass();
20 $object->setMember("bar");
21 foo($object);
22 print $object->getMember();
Without the new Java-like handles, at line 20 the objects' data member
member is set to the string value of "bar". Because of the internal
representation of objects in the Zend Engine 1.0, the object is marked
as a reference, and when it is sent by value to the function foo, it
is duplicated (!). Therefore, the call to foo() on line 21 will
result in the $obj->setMember("foo") call being called on a duplicate
of $object. Line 22 will then result in "bar" being printed.
This is how the scripting engine has worked until today. Most
developers are probably unaware of the fact that they aren't always
talking to the same object but often duplicates; others may have
realized this can usually be solved by always passing objects by
reference (unless a replica is actually desired, which is uncommon).
The new object model will allow for a much more intuitive
implementation of the code. On line 21, the object's handle (ID) is
passed to foo() by value. Inside foo(), the object is fetched
according to this handle and, therefore, the setMember() method is
called on the originally instantiated object and not a copy. Line 22
will therefore result in "foo" being printed. This approach gives
developers tighter control of when objects are created and duplicated.
An additional not-as-important benefit is that the object handle will
be passed to foo() by value, which most probably will also save
unnecessary duplication of the value containing the ID itself and thus
additionally improving run-time performance.
This was just a simple description of why the new object model solves
awkward behavior and makes object handling much easier, intuitive and
efficient. The importance of this change goes far beyond what is
mentioned in this section as you will see in further sections which
describe new features with a majority of them being based on this
change.
Compatibility Notes
--------------------
Many PHP programmers aren't even aware of the copying quirks of the
current object model and, therefore, there is a relatively good chance
that the amount of PHP applications that will work out of the box or
after a very small amount of modifications would be high.
To simplify migration, version 2.0 will support an optional
'auto-clone' feature, which will perform a cloning of the object
whenever it would have been copied in version 1.0. Optionally, it
will also be possible to request that the engine will emit an E_NOTICE
message whenever such an automatic clone occurs, in order to allow
developers to gradually migrate to the version 2.0-style behavior
(without automatic clones).
Dependencies
------------
The new object model is not dependent on other features. Many of the
other Zend Engine 2.0 features, such as the $foo->bar()->barbara()
syntax, destructors and others completely rely on this new object
model.
+169
View File
@@ -0,0 +1,169 @@
Title: Zend 2.0 Namespaces
Version: $Revision$
Status: declined
Maintainer: Stig S. Bakken <ssb@php.net>
Created: 2001-09-08
Modified: 2001-09-08
1. Background/Need
==================
PHP and Zend 1.0 have come to a point where a lot of reusable code is
being written; from simple functions and classes to entire application
frameworks. It is becoming increasingly difficult to avoid symbol
name collisions with the current scoping methods.
The symbol scopes available in Zend 1.0 are the global scope, the
class scope and the function scope. All scopes but classes may
contain variables, only the class and global scopes may contain
functions, while only the global scope may contain constants and
classes. This means that all of Zend 1.0's scoping methods are
inherently limited for solving symbol name collision problems.
2. Overview
===========
Namespaces in Zend 2.0 provide a way to manage the symbol collision
problem by making it possible to define multiple symbol tables able to
contain all types of symbols. Zend will get the notion of a current
namespace, defaulting to the current global one. The current name
space may be changed on a file-by-file basis. Symbols in other name
spaces than the current one may be referenced using a new namespace
operator. It will be possible to "import" symbols from one namespace
into another.
3. Functionality
================
3.1. Namespace Syntax
=====================
The namespace operator ":" is used to refer to symbols in other
namespaces than the current one:
Class: Namespace:class
Function: Namespace:function
Static method: Namespace:class::method
Variable: $Namespace:variable
Constant: Namespace:CONSTANT
Class variable: $Namespace:class::variable
To refer to symbols in the global namespace, symbols are prefixed with
only the namespace operator:
Class: :class
Function: :function
Static method: :class::method
Variable: $:variable
Constant: :CONSTANT
Class variable: $:class::variable
Note: $:variable will effectively be just another syntax for
$GLOBALS['variable'].
A namespace may have a name containing a ":", it is always the last
":" character in the symbol qualifier that is the actual namespace
operator:
Class: Name:Space:class
Function: Name:Space:function
Static method: Name:Space:class::method
Variable: $Name:Space:variable
Constant: Name:Space:CONSTANT
Class variable: $Name:Space:class::variable
(Here, the ":" between "Name" and "Space" is part of the name, it is
the one after "Space" that is the namespace operator.)
3.2. Defining Namespaces
========================
Individual files may define a namespace that will apply to the entire
file. If no "namespace" operator occurs in the file, it will be in
the global namespace:
1 namespace HTML;
2
3 class Form {
4 function Form() {
5 // constructor
6 }
7 // ...
8 }
Or with the "nested" name syntax:
1 namespace HTML:Form;
2
3 class Image {
4 var $src;
5 function Image($src) {
6 $this->src = $src;
7 }
8 // ...
9 }
Code executed within the "HTML" namespace may refer to the Form class
as just "Form". Code executed from within other namespaces has to
refer to it as "HTML:Form". The "namespace" statement must occur
before any other statements in the file.
# [ssb 2001-09-08]:
# Should it be possible to "add" symbols to a namespace by including a
# second file with the same namespace statement?
3.3. Importing Symbols
======================
It is possible to import symbols from another namespace into the
current one with the "import" statement:
import * from HTML; // all symbols
import Form from HTML; // single symbols
import Form,Table from HTML; // multiple symbols
There is a potential for name clashes between symols of different
types that have the same qualifier syntax. These are resolved in this
order: class, function, constant.
Optionally, the symbol type may be explicitly given to import (as
"class", "function", "variable" or "constant"):
import class Form from HTML;
And finally, you may import all symbols of a given type:
import constant * from HTML:Table;
The namespace with its symbols must already be defined before using
"import".
4. Compatibility Notes
======================
Old code that does not take advantage of namespaces will run without
modifications.
5. Dependencies
===============
The class variable syntax depends on this class variables being
implemented in the new ZE2 object model.
6. Acknowledgements
===================
Andi Gutmans <andi@zend.com> and Zeev Suraski <zeev@zend.com> for
initial ZE2 namespaces proposal
Dean Hall <php@apt7.com> for the initial symbol qualification syntax
+72
View File
@@ -0,0 +1,72 @@
Title: Loose type requirements for functions
Version: $Revision$
Status: draft
Maintainer: Brian Moon <brianm@dealnews.com>
Created: 2001-09-17
Modified: 2001-09-17
1. Background/Need
==================
Many internal function of PHP will reject parameters because of their
type (the array and variable function come to mind). For userland
this is not an easy task as there is no uniform way to do it. An
addition to the engine for requiring loose types would allow
delevopers to know that the data passed to their functions is of the
correct type and reduce the need for duplicating the same code in
every function to check for the type of data.
2. Overview
===========
Loose typing mostly means evaluating the contents of the variable and
not the type of the variable itself. The requirements for this would
and should work much like several of the is_* functions do now.
The typing of parameters would be optional and those not typed would
simply continue to be treated as they are now.
3. Functionality
================
3.1. Allowed Types
==================
Only loose types should be needed to ensure the data is usable by the
function. Duplicating the functionallity of is_scalar, is_resource,
is_array and is_object should give developers all the information they
need to use a variable correctly.
3.2. Syntax
===========
The current function syntax should be expanded to allow typing of
variables inline in a C style.
function foo ($var){
}
could be changed to require an array such as:
function foo (array $var){
}
3.3. Errors
===========
Mis-matches in type should be reported as fatal errors and should halt
the execution of a script as that function can not be run and code
following could not reliably run.
4. Compatibility Notes
======================
Old code that does not take advantage of this will run without
modifications.
+1166
View File
File diff suppressed because it is too large. Load diff
+602
View File
@@ -0,0 +1,602 @@
# Microsoft Developer Studio Project File - Name="Zend" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=Zend - Win32 Release_inline
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Zend.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Zend.mak" CFG="Zend - Win32 Release_inline"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Zend - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "Zend - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "Zend - Win32 Release_inline" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Zend - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDebug" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug" /D "_LIB" /D "Zend_EXPORTS" /D ZEND_DEBUG=0 /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D "ZEND_WIN32" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x40d /d "NDebug"
# ADD RSC /l 0x40d /d "NDebug"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /D "_Debug" /D "_LIB" /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D ZEND_DEBUG=1 /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x40d /d "_Debug"
# ADD RSC /l 0x40d /d "_Debug"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "Zend___Win32_Release_inline"
# PROP BASE Intermediate_Dir "Zend___Win32_Release_inline"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Release_inline"
# PROP Intermediate_Dir "Release_inline"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug" /D "_LIB" /D "Zend_EXPORTS" /D ZEND_DEBUG=0 /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /FR /FD /c
# SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug" /D "_LIB" /D "Zend_EXPORTS" /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D "WIN32" /D "_MBCS" /D "ZEND_WIN32" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x40d /d "NDebug"
# ADD RSC /l 0x40d /d "NDebug"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "Zend - Win32 Release"
# Name "Zend - Win32 Debug"
# Name "Zend - Win32 Release_inline"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\zend.c
# End Source File
# Begin Source File
SOURCE=.\zend_alloc.c
# End Source File
# Begin Source File
SOURCE=.\zend_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
SOURCE=.\zend_closures.c
# End Source File
# Begin Source File
SOURCE=.\zend_compile.c
# End Source File
# Begin Source File
SOURCE=.\zend_constants.c
# End Source File
# Begin Source File
SOURCE=.\zend_default_classes.c
# End Source File
# Begin Source File
SOURCE=.\zend_execute.c
# End Source File
# Begin Source File
SOURCE=.\zend_execute_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_extensions.c
# End Source File
# Begin Source File
SOURCE=.\zend_float.c
# End Source File
# Begin Source File
SOURCE=.\zend_hash.c
# End Source File
# Begin Source File
SOURCE=.\zend_highlight.c
# End Source File
# Begin Source File
SOURCE=.\zend_indent.c
# End Source File
# Begin Source File
SOURCE=.\zend_ini.c
# End Source File
# Begin Source File
SOURCE=.\zend_ini_parser.c
# End Source File
# Begin Source File
SOURCE=.\zend_ini_scanner.c
# End Source File
# Begin Source File
SOURCE=.\zend_interfaces.c
# End Source File
# Begin Source File
SOURCE=".\zend_language_parser.c"
# End Source File
# Begin Source File
SOURCE=".\zend_language_scanner.c"
# End Source File
# Begin Source File
SOURCE=.\zend_list.c
# End Source File
# Begin Source File
SOURCE=.\zend_llist.c
# End Source File
# Begin Source File
SOURCE=.\zend_object_handlers.c
# End Source File
# Begin Source File
SOURCE=.\zend_objects.c
# End Source File
# Begin Source File
SOURCE=.\zend_objects_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_opcode.c
# End Source File
# Begin Source File
SOURCE=.\zend_operators.c
# End Source File
# Begin Source File
SOURCE=.\zend_ptr_stack.c
# End Source File
# Begin Source File
SOURCE=.\zend_qsort.c
# End Source File
# Begin Source File
SOURCE=.\zend_reflection_api.c
# End Source File
# Begin Source File
SOURCE=.\zend_sprintf.c
# End Source File
# Begin Source File
SOURCE=.\zend_stack.c
# End Source File
# Begin Source File
SOURCE=.\zend_stream.c
# End Source File
# Begin Source File
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
SOURCE=.\zend_ts_hash.c
# End Source File
# Begin Source File
SOURCE=.\zend_variables.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\FlexLexer.h
# End Source File
# Begin Source File
SOURCE=.\zend.h
# End Source File
# Begin Source File
SOURCE=.\zend_alloc.h
# End Source File
# Begin Source File
SOURCE=.\zend_API.h
# End Source File
# Begin Source File
SOURCE=.\zend_builtin_functions.h
# End Source File
# Begin Source File
SOURCE=.\zend_compile.h
# End Source File
# Begin Source File
SOURCE=.\zend_config.w32.h
# End Source File
# Begin Source File
SOURCE=.\zend_constants.h
# End Source File
# Begin Source File
SOURCE=.\zend_default_classes.h
# End Source File
# Begin Source File
SOURCE=.\zend_errors.h
# End Source File
# Begin Source File
SOURCE=.\zend_execute.h
# End Source File
# Begin Source File
SOURCE=.\zend_execute_locks.h
# End Source File
# Begin Source File
SOURCE=.\zend_extensions.h
# End Source File
# Begin Source File
SOURCE=.\zend_fast_cache.h
# End Source File
# Begin Source File
SOURCE=.\zend_globals.h
# End Source File
# Begin Source File
SOURCE=.\zend_globals_macros.h
# End Source File
# Begin Source File
SOURCE=.\zend_hash.h
# End Source File
# Begin Source File
SOURCE=.\zend_highlight.h
# End Source File
# Begin Source File
SOURCE=.\zend_indent.h
# End Source File
# Begin Source File
SOURCE=.\zend_ini.h
# End Source File
# Begin Source File
SOURCE=.\zend_ini_parser.h
# End Source File
# Begin Source File
SOURCE=.\zend_ini_scanner.h
# End Source File
# Begin Source File
SOURCE=.\zend_interfaces.h
# End Source File
# Begin Source File
SOURCE=.\zend_istdiostream.h
# End Source File
# Begin Source File
SOURCE=".\zend_language_parser.h"
# End Source File
# Begin Source File
SOURCE=".\zend_language_scanner.h"
# End Source File
# Begin Source File
SOURCE=.\zend_list.h
# End Source File
# Begin Source File
SOURCE=.\zend_llist.h
# End Source File
# Begin Source File
SOURCE=.\zend_modules.h
# End Source File
# Begin Source File
SOURCE=.\zend_object_handlers.h
# End Source File
# Begin Source File
SOURCE=.\zend_objects.h
# End Source File
# Begin Source File
SOURCE=.\zend_objects_API.h
# End Source File
# Begin Source File
SOURCE=.\zend_operators.h
# End Source File
# Begin Source File
SOURCE=.\zend_ptr_stack.h
# End Source File
# Begin Source File
SOURCE=.\zend_qsort.h
# End Source File
# Begin Source File
SOURCE=.\zend_reflection_api.h
# End Source File
# Begin Source File
SOURCE=.\zend_stack.h
# End Source File
# Begin Source File
SOURCE=.\zend_stream.h
# End Source File
# Begin Source File
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
SOURCE=.\zend_ts_hash.h
# End Source File
# Begin Source File
SOURCE=.\zend_variables.h
# End Source File
# End Group
# Begin Group "Parsers"
# PROP Default_Filter "y"
# Begin Source File
SOURCE=.\zend_ini_parser.y
!IF "$(CFG)" == "Zend - Win32 Release"
!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
# Begin Custom Build
InputDir=.
InputPath=.\zend_ini_parser.y
BuildCmds= \
bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
!ENDIF
# End Source File
# Begin Source File
SOURCE=".\zend_language_parser.y"
!IF "$(CFG)" == "Zend - Win32 Release"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ENDIF
# End Source File
# End Group
# Begin Group "Scanners"
# PROP Default_Filter "l"
# Begin Source File
SOURCE=.\flex.skl
# End Source File
# Begin Source File
SOURCE=.\zend_ini_scanner.l
!IF "$(CFG)" == "Zend - Win32 Release"
!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
# Begin Custom Build
InputPath=.\zend_ini_scanner.l
"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
!ENDIF
# End Source File
# Begin Source File
SOURCE=".\zend_language_scanner.l"
!IF "$(CFG)" == "Zend - Win32 Release"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ENDIF
# End Source File
# End Group
# Begin Group "Text Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\ZEND_BUGS
# End Source File
# Begin Source File
SOURCE=.\ZEND_CHANGES
# End Source File
# Begin Source File
SOURCE=.\ZEND_TODO
# End Source File
# End Group
# Begin Group "Resources"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\zend.ico
# End Source File
# End Group
# End Target
# End Project
+282 -243
View File
@@ -1,139 +1,79 @@
dnl This file contains Zend specific autoconf macros.
dnl
dnl ZEND_CHECK_FLOAT_PRECISION
dnl $Id$
dnl
dnl x87 floating point internal precision control checks
dnl See: http://wiki.php.net/rfc/rounding
dnl This file contains Zend specific autoconf functions.
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_TRY_COMPILE([
#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 \
dlfcn.h)
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
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 +85,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_FUNCS(finite isfinite isinf isnan)
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([[
AC_TRY_RUN([
#include <limits.h>
#include <stdlib.h>
int main()
{
@@ -163,18 +118,18 @@ 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])
AC_MSG_RESULT(yes)
], [
@@ -182,43 +137,114 @@ int main()
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([LIBZEND_ENABLE_DEBUG],[
AC_ARG_ENABLE(debug,
[ --enable-debug Compile with debugging symbols],[
ZEND_DEBUG=$enableval
],[
ZEND_DEBUG=no
])
])
dnl
dnl LIBZEND_OTHER_CHECKS
dnl
AC_DEFUN([LIBZEND_OTHER_CHECKS],[
AC_ARG_WITH(zend-vm,
[ --with-zend-vm=TYPE Set virtual machine dispatch method. Type is
one of "CALL", "SWITCH" or "GOTO" [TYPE=CALL]],[
PHP_ZEND_VM=$withval
],[
PHP_ZEND_VM=CALL
])
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([virtual machine dispatch method])
AC_MSG_RESULT($PHP_ZEND_VM)
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)
case $PHP_ZEND_VM in
SWITCH)
AC_DEFINE(ZEND_VM_KIND,ZEND_VM_KIND_SWITCH,[virtual machine dispatch method])
;;
GOTO)
AC_DEFINE(ZEND_VM_KIND,ZEND_VM_KIND_GOTO,[virtual machine dispatch method])
;;
*)
PHP_ZEND_VM=CALL
AC_DEFINE(ZEND_VM_KIND,ZEND_VM_KIND_CALL,[virtual machine dispatch method])
;;
esac
if test "$ZEND_DEBUG" = "yes"; then
AC_DEFINE(ZEND_DEBUG,1,[ ])
echo " $CFLAGS" | grep ' -g' >/dev/null || DEBUG_CFLAGS="-g"
if test "$CFLAGS" = "-g -O2"; then
CFLAGS=-g
fi
changequote({,})
if test -n "$GCC"; then
DEBUG_CFLAGS="$DEBUG_CFLAGS -Wall"
"$CC" --help=warnings|grep -q -- '-Wpointer-arith[ \t]' && \
DEBUG_CFLAGS="$DEBUG_CFLAGS -Wpointer-arith"
"$CC" --help=warnings|grep -q -- '-Wdeclaration-after-statement[ \t]' && \
DEBUG_CFLAGS="$DEBUG_CFLAGS -Wdeclaration-after-statement"
test "$USE_MAINTAINER_MODE" = "yes" && \
DEBUG_CFLAGS="$DEBUG_CFLAGS -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations"
fi
changequote([,])
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"
LIBZEND_CPLUSPLUS_CHECKS
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 +253,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([[
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
typedef union _mm_align_test {
void *ptr;
@@ -259,122 +284,136 @@ int main()
}
fp = fopen("conftest.zend", "w");
fprintf(fp, "%d %d\n", ZEND_MM_ALIGNMENT, zeros);
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`
LIBZEND_MM_ALIGN_LOG2=`cat conftest.zend | cut -d ' ' -f 2`
AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT, $LIBZEND_MM_ALIGN, [ ])
AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT_LOG2, $LIBZEND_MM_ALIGN_LOG2, [ ])
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_TRY_RUN([
#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_TRY_RUN([
#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
])
if test "$ZEND_SIGNALS" = "yes"; then
AC_DEFINE(ZEND_SIGNALS, 1, [Use zend signal handling])
CFLAGS="$CFLAGS -DZEND_SIGNALS"
fi
AC_MSG_CHECKING(whether to enable zend signal handling)
AC_MSG_RESULT($ZEND_SIGNALS)
AC_DEFUN([LIBZEND_CPLUSPLUS_CHECKS],[
])
AC_MSG_CHECKING(whether /dev/urandom exists)
if test -r "/dev/urandom" && test -c "/dev/urandom"; then
AC_MSG_CHECKING(whether /dev/urandom exists)
if test -r "/dev/urandom" && test -c "/dev/urandom"; then
AC_DEFINE([HAVE_DEV_URANDOM], 1, [Define if the target system has /dev/urandom device])
AC_MSG_RESULT(yes)
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(for global register variables support)
if test "$ZEND_GCC_GLOBAL_REGS" != "no"; then
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if defined(__GNUC__)
# define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#else
# define ZEND_GCC_VERSION 0
#endif
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
# define ZEND_VM_FP_GLOBAL_REG "%esi"
# define ZEND_VM_IP_GLOBAL_REG "%edi"
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
# define ZEND_VM_FP_GLOBAL_REG "%r14"
# define ZEND_VM_IP_GLOBAL_REG "%r15"
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
# define ZEND_VM_FP_GLOBAL_REG "r28"
# define ZEND_VM_IP_GLOBAL_REG "r29"
#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
typedef int (*opcode_handler_t)(void);
register void *FP __asm__(ZEND_VM_FP_GLOBAL_REG);
register const opcode_handler_t *IP __asm__(ZEND_VM_IP_GLOBAL_REG);
int emu(const opcode_handler_t *ip, void *fp) {
const opcode_handler_t *orig_ip = IP;
void *orig_fp = FP;
IP = ip;
FP = fp;
while ((*ip)());
FP = orig_fp;
IP = orig_ip;
}
]], [[
]])], [
ZEND_GCC_GLOBAL_REGS=yes
], [
ZEND_GCC_GLOBAL_REGS=no
])
fi
if test "$ZEND_GCC_GLOBAL_REGS" = "yes"; then
AC_DEFINE([HAVE_GCC_GLOBAL_REGS], 1, [Define if the target system has support for global register variables])
else
HAVE_GCC_GLOBAL_REGS=no
fi
AC_MSG_RESULT($ZEND_GCC_GLOBAL_REGS)
dnl Check whether __cpuid_count is available.
AC_CACHE_CHECK(whether __cpuid_count is available, ac_cv_cpuid_count_available, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <cpuid.h>
]], [[
unsigned eax, ebx, ecx, edx;
__cpuid_count(0, 0, eax, ebx, ecx, edx);
]])], [
ac_cv_cpuid_count_available=yes
], [
ac_cv_cpuid_count_available=no
])])
if test "$ac_cv_cpuid_count_available" = "yes"; then
AC_DEFINE([HAVE_CPUID_COUNT], 1, [whether __cpuid_count is available])
fi
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
+258
View File
@@ -0,0 +1,258 @@
# Microsoft Developer Studio Generated Dependency File, included by ZendCore.mak
.\zend_alloc.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
.\alloca.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_config.w32.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_compile.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_modules.h"\
".\zend_operators.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_API.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
".\zend_ini.h"\
.\zend_constants.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_config.w32.h"\
".\zend_constants.h"\
".\zend_operators.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_execute.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_constants.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_modules.h"\
".\zend_operators.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_API.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
".\zend_ini.h"\
.\zend_highlight.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_execute.h"\
".\zend_highlight.h"\
".\zend_llist.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_language_parser.tab.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
.\zend_llist.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_config.w32.h"\
".\zend_llist.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_opcode.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_modules.h"\
".\zend_operators.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_API.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
".\zend_ini.h"\
.\zend_operators.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_operators.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
.\zend_ptr_stack.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_config.w32.h"\
".\zend_ptr_stack.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_stack.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_config.w32.h"\
".\zend_stack.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_variables.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_constants.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_modules.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_API.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
".\zend_ini.h"\
".\zend_list.h"\
.\zend.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_config.w32.h"\
".\zend_operators.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_API.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_compile.h"\
".\zend_config.w32.h"\
".\zend_constants.h"\
".\zend_execute.h"\
".\zend_llist.h"\
".\zend_modules.h"\
".\zend_operators.h"\
".\zend_ptr_stack.h"\
".\zend_stack.h"\
".\zend_variables.h"\
".\zend.h"\
".\zend_API.h"\
".\zend_errors.h"\
".\zend_globals.h"\
".\zend_hash.h"\
".\zend_ini.h"\
".\zend_list.h"\
.\zend_hash.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_config.w32.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
.\zend_ini.c : \
"..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\
".\zend_alloc.h"\
".\zend_config.w32.h"\
".\zend.h"\
".\zend_errors.h"\
".\zend_hash.h"\
".\zend_ini.h"\
!IF "$(CFG)" == "ZendCore - Win32 Release"
!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug"
!ENDIF
!IF "$(CFG)" == "ZendCore - Win32 Release"
!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug"
!ENDIF
!IF "$(CFG)" == "ZendCore - Win32 Release"
!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug"
!ENDIF
!IF "$(CFG)" == "ZendCore - Win32 Release"
!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug"
!ENDIF
+735
View File
@@ -0,0 +1,735 @@
# Microsoft Developer Studio Project File - Name="ZendTS" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=ZendTS - Win32 Release_TSDbg
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ZendTS.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ZendTS.mak" CFG="ZendTS - Win32 Release_TSDbg"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ZendTS - Win32 Release_TS" (based on "Win32 (x86) Static Library")
!MESSAGE "ZendTS - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
!MESSAGE "ZendTS - Win32 Release_TS_inline" (based on "Win32 (x86) Static Library")
!MESSAGE "ZendTS - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "Release_TS"
# PROP BASE Intermediate_Dir "Release_TS"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Release_TS"
# PROP Intermediate_Dir "Release_TS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDebug_TS" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x40d /d "NDebug_TS"
# ADD RSC /l 0x40d /d "NDebug_TS"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "Debug_TS"
# PROP BASE Intermediate_Dir "Debug_TS"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Debug_TS"
# PROP Intermediate_Dir "Debug_TS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug_TS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /D "_Debug_TS" /D ZEND_DEBUG=1 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x40d /d "_Debug_TS"
# ADD RSC /l 0x40d /d "_Debug_TS"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "ZendTS___Win32_Release_TS_inline"
# PROP BASE Intermediate_Dir "ZendTS___Win32_Release_TS_inline"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Release_TS_inline"
# PROP Intermediate_Dir "Release_TS_inline"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "WIN32" /D "_MBCS" /D ZEND_DEBUG=0 /FR /FD /c
# SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x40d /d "NDebug_TS"
# ADD RSC /l 0x40d /d "NDebug_TS"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
# PROP BASE Use_MFC 0
# PROP BASE Output_Dir "ZendTS___Win32_Release_TSDbg"
# PROP BASE Intermediate_Dir "ZendTS___Win32_Release_TSDbg"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Output_Dir "Release_TSDbg"
# PROP Intermediate_Dir "Release_TSDbg"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
# SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x40d /d "NDebug_TS"
# ADD RSC /l 0x40d /d "NDebug_TS"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "ZendTS - Win32 Release_TS"
# Name "ZendTS - Win32 Debug_TS"
# Name "ZendTS - Win32 Release_TS_inline"
# Name "ZendTS - Win32 Release_TSDbg"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\zend.c
# End Source File
# Begin Source File
SOURCE=.\zend_alloc.c
# End Source File
# Begin Source File
SOURCE=.\zend_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
SOURCE=.\zend_closures.c
# End Source File
# Begin Source File
SOURCE=.\zend_compile.c
# End Source File
# Begin Source File
SOURCE=.\zend_constants.c
# End Source File
# Begin Source File
SOURCE=.\zend_default_classes.c
# End Source File
# Begin Source File
SOURCE=.\zend_exceptions.c
# End Source File
# Begin Source File
SOURCE=.\zend_execute.c
# End Source File
# Begin Source File
SOURCE=.\zend_execute_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_extensions.c
# End Source File
# Begin Source File
SOURCE=.\zend_float.c
# End Source File
# Begin Source File
SOURCE=.\zend_hash.c
# End Source File
# Begin Source File
SOURCE=.\zend_highlight.c
# End Source File
# Begin Source File
SOURCE=.\zend_indent.c
# End Source File
# Begin Source File
SOURCE=.\zend_ini.c
# End Source File
# Begin Source File
SOURCE=.\zend_ini_parser.c
# End Source File
# Begin Source File
SOURCE=.\zend_ini_scanner.c
# End Source File
# Begin Source File
SOURCE=.\zend_interfaces.c
# End Source File
# Begin Source File
SOURCE=.\zend_iterators.c
# End Source File
# Begin Source File
SOURCE=".\zend_language_parser.c"
# End Source File
# Begin Source File
SOURCE=".\zend_language_scanner.c"
# End Source File
# Begin Source File
SOURCE=.\zend_list.c
# End Source File
# Begin Source File
SOURCE=.\zend_llist.c
# End Source File
# Begin Source File
SOURCE=.\zend_object_handlers.c
# End Source File
# Begin Source File
SOURCE=.\zend_objects.c
# End Source File
# Begin Source File
SOURCE=.\zend_objects_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_opcode.c
# End Source File
# Begin Source File
SOURCE=.\zend_operators.c
# End Source File
# Begin Source File
SOURCE=.\zend_ptr_stack.c
# End Source File
# Begin Source File
SOURCE=.\zend_qsort.c
# End Source File
# Begin Source File
SOURCE=.\zend_reflection_api.c
# End Source File
# Begin Source File
SOURCE=.\zend_sprintf.c
# End Source File
# Begin Source File
SOURCE=.\zend_stack.c
# End Source File
# Begin Source File
SOURCE=.\zend_stream.c
# End Source File
# Begin Source File
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
SOURCE=.\zend_ts_hash.c
# End Source File
# Begin Source File
SOURCE=.\zend_variables.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\FlexLexer.h
# End Source File
# Begin Source File
SOURCE=.\zend.h
# End Source File
# Begin Source File
SOURCE=.\zend_alloc.h
# End Source File
# Begin Source File
SOURCE=.\zend_API.h
# End Source File
# Begin Source File
SOURCE=.\zend_builtin_functions.h
# End Source File
# Begin Source File
SOURCE=.\zend_compile.h
# End Source File
# Begin Source File
SOURCE=.\zend_config.w32.h
# End Source File
# Begin Source File
SOURCE=.\zend_constants.h
# End Source File
# Begin Source File
SOURCE=.\zend_default_classes.h
# End Source File
# Begin Source File
SOURCE=.\zend_errors.h
# End Source File
# Begin Source File
SOURCE=.\zend_exceptions.h
# End Source File
# Begin Source File
SOURCE=.\zend_execute.h
# End Source File
# Begin Source File
SOURCE=.\zend_extensions.h
# End Source File
# Begin Source File
SOURCE=.\zend_fast_cache.h
# End Source File
# Begin Source File
SOURCE=.\zend_globals.h
# End Source File
# Begin Source File
SOURCE=.\zend_globals_macros.h
# End Source File
# Begin Source File
SOURCE=.\zend_hash.h
# End Source File
# Begin Source File
SOURCE=.\zend_highlight.h
# End Source File
# Begin Source File
SOURCE=.\zend_indent.h
# End Source File
# Begin Source File
SOURCE=.\zend_ini.h
# End Source File
# Begin Source File
SOURCE=.\zend_ini_parser.h
# End Source File
# Begin Source File
SOURCE=.\zend_ini_scanner.h
# End Source File
# Begin Source File
SOURCE=.\zend_interfaces.h
# End Source File
# Begin Source File
SOURCE=.\zend_istdiostream.h
# End Source File
# Begin Source File
SOURCE=.\zend_iterators.h
# End Source File
# Begin Source File
SOURCE=".\zend_language_parser.h"
# End Source File
# Begin Source File
SOURCE=".\zend_language_scanner.h"
# End Source File
# Begin Source File
SOURCE=.\zend_list.h
# End Source File
# Begin Source File
SOURCE=.\zend_llist.h
# End Source File
# Begin Source File
SOURCE=.\zend_modules.h
# End Source File
# Begin Source File
SOURCE=.\zend_object_handlers.h
# End Source File
# Begin Source File
SOURCE=.\zend_objects.h
# End Source File
# Begin Source File
SOURCE=.\zend_objects_API.h
# End Source File
# Begin Source File
SOURCE=.\zend_operators.h
# End Source File
# Begin Source File
SOURCE=.\zend_ptr_stack.h
# End Source File
# Begin Source File
SOURCE=.\zend_qsort.h
# End Source File
# Begin Source File
SOURCE=.\zend_reflection_api.h
# End Source File
# Begin Source File
SOURCE=.\zend_stack.h
# End Source File
# Begin Source File
SOURCE=.\zend_stream.h
# End Source File
# Begin Source File
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
SOURCE=.\zend_ts_hash.h
# End Source File
# Begin Source File
SOURCE=.\zend_variables.h
# End Source File
# End Group
# Begin Group "Parsers"
# PROP Default_Filter "y"
# Begin Source File
SOURCE=.\zend_ini_parser.y
!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
# Begin Custom Build
InputDir=.
InputPath=.\zend_ini_parser.y
BuildCmds= \
bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
# Begin Custom Build
InputDir=.
InputPath=.\zend_ini_parser.y
BuildCmds= \
bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
# Begin Custom Build
InputDir=.
InputPath=.\zend_ini_parser.y
BuildCmds= \
bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
# Begin Custom Build
InputDir=.
InputPath=.\zend_ini_parser.y
BuildCmds= \
bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ENDIF
# End Source File
# Begin Source File
SOURCE=".\zend_language_parser.y"
!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
# Begin Custom Build
InputDir=.
InputPath=".\zend_language_parser.y"
BuildCmds= \
bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ENDIF
# End Source File
# End Group
# Begin Group "Scanners"
# PROP Default_Filter "l"
# Begin Source File
SOURCE=.\flex.skl
# End Source File
# Begin Source File
SOURCE=.\zend_ini_scanner.l
!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
# Begin Custom Build
InputPath=.\zend_ini_scanner.l
"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
# Begin Custom Build
InputPath=.\zend_ini_scanner.l
"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
# Begin Custom Build
InputPath=.\zend_ini_scanner.l
"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
# Begin Custom Build
InputPath=.\zend_ini_scanner.l
"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
# End Custom Build
!ENDIF
# End Source File
# Begin Source File
SOURCE=".\zend_language_scanner.l"
!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
# Begin Custom Build
InputPath=".\zend_language_scanner.l"
"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
# End Custom Build
!ENDIF
# End Source File
# End Group
# Begin Group "Text Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\LICENSE
# End Source File
# Begin Source File
SOURCE=.\ZEND_BUGS
# End Source File
# Begin Source File
SOURCE=.\ZEND_CHANGES
# End Source File
# End Group
# Begin Group "Resources"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\zend.ico
# End Source File
# End Group
# End Target
# End Project
+127
View File
@@ -0,0 +1,127 @@
/*
+----------------------------------------------------------------------+
| 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: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#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
@TOP@
#undef uint
#undef ulong
/* Define if you want to enable memory limit support */
#define MEMORY_LIMIT 0
@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>
/* To enable the is_nan, is_infinite and is_finite PHP functions */
#ifdef NETWARE
#define HAVE_ISNAN 1
#define HAVE_ISINF 1
#define HAVE_ISFINITE 1
#endif
#ifndef zend_isnan
#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
#endif
#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
#ifdef HAVE_FINITE
#define zend_finite(a) finite(a)
#elif defined(HAVE_ISFINITE) || defined(isfinite)
#define zend_finite(a) isfinite(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 */
#ifdef NETWARE
#ifdef USE_WINSOCK
#/*This detection against winsock is of no use*/ undef HAVE_SOCKLEN_T
#/*This detection against winsock is of no use*/ undef HAVE_SYS_SOCKET_H
#endif
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* indent-tabs-mode: t
* End:
*/
+221
View File
@@ -0,0 +1,221 @@
dnl $Id$
dnl
dnl This file contains local autoconf functions.
AC_DEFUN([LIBZEND_BISON_CHECK],[
# we only support certain bison versions
bison_version_list="1.28 1.35 1.75 1.875 2.0 2.1 2.2 2.3 2.4 2.4.1"
# 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=`bison --version 2> /dev/null | grep 'GNU Bison' | cut -d ' ' -f 4 | $SED -e 's/\./ /' | tr -d a-z`
php_cv_bison_version=invalid
if test -n "$bison_version_vars"; then
set $bison_version_vars
bison_version="${1}.${2}"
for bison_check_version in $bison_version_list; do
if test "$bison_version" = "$bison_check_version"; then
php_cv_bison_version="$bison_check_version (ok)"
break
fi
done
fi
])
fi
case $php_cv_bison_version in
""|invalid[)]
bison_msg="bison versions supported for regeneration of the Zend/PHP parsers: $bison_version_list (found: $bison_version)."
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_TRY_COMPILE([
#include <floatingpoint.h>
],[
fp_except x = (fp_except) 0;
],[
ac_cv_type_fp_except=yes
],[
ac_cv_type_fp_except=no
],[
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_TRY_RUN([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_TRY_RUN(
[
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, [], [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_TRY_LINK([
#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_TRY_LINK([
#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_TRY_LINK([
#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_TRY_LINK([
#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_TRY_LINK([
/* 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
])
+49 -51
View File
@@ -1,22 +1,20 @@
<?php
if (function_exists("date_default_timezone_set")) {
date_default_timezone_set("UTC");
}
date_default_timezone_set('UTC');
function simple() {
$a = 0;
for ($i = 0; $i < 1000000; $i++)
for ($i = 0; $i < 1000000; $i++)
$a++;
$thisisanotherlongname = 0;
for ($thisisalongname = 0; $thisisalongname < 1000000; $thisisalongname++)
for ($thisisalongname = 0; $thisisalongname < 1000000; $thisisalongname++)
$thisisanotherlongname++;
}
/****/
function simplecall() {
for ($i = 0; $i < 1000000; $i++)
for ($i = 0; $i < 1000000; $i++)
strlen("hallo");
}
@@ -26,14 +24,14 @@ function hallo($a) {
}
function simpleucall() {
for ($i = 0; $i < 1000000; $i++)
for ($i = 0; $i < 1000000; $i++)
hallo("hallo");
}
/****/
function simpleudcall() {
for ($i = 0; $i < 1000000; $i++)
for ($i = 0; $i < 1000000; $i++)
hallo2("hallo");
}
@@ -220,30 +218,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 +266,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 +276,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);
}
@@ -345,30 +343,30 @@ function strcat($n) {
/*****/
function gethrtime()
function getmicrotime()
{
$hrtime = hrtime();
return (($hrtime[0]*1000000000 + $hrtime[1]) / 1000000000);
$t = gettimeofday();
return ($t['sec'] + $t['usec'] / 1000000);
}
function start_test()
{
ob_start();
return gethrtime();
ob_start();
return getmicrotime();
}
function end_test($start, $name)
{
global $total;
$end = gethrtime();
$end = getmicrotime();
ob_end_clean();
$total += $end-$start;
$num = number_format($end-$start,3);
$pad = str_repeat(" ", 24-strlen($name)-strlen($num));
echo $name.$pad.$num."\n";
ob_start();
return gethrtime();
ob_start();
return getmicrotime();
}
function total()
@@ -418,5 +416,5 @@ sieve(30);
$t = end_test($t, "sieve(30)");
strcat(200000);
$t = end_test($t, "strcat(200000)");
total();
total($t0, "Total");
?>
+43
View File
@@ -0,0 +1,43 @@
# Makefile to generate build tools
#
# Standard usage:
# make -f build.mk
#
# Written by Sascha Schumann
#
# $Id$
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.in acinclude.m4
aclocal
$(config_h_in): configure.in acconfig.h
# explicitly remove target since autoheader does not seem to work
# correctly otherwise (timestamps are not updated)
@rm -f $@
autoheader
configure: aclocal.m4 configure.in
autoconf
Executable
+33
View File
@@ -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
Loaded 100 of 22360 files, more files were not shown because too many files have changed in this diff. Show more