mirror of
https://github.com/bdnugget/php-src.git
synced 2026-11-08 17:50:50 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ca804ddb8 | ||
|
|
2a069e0403 |
No files matched your search
@@ -1,60 +0,0 @@
|
||||
version: "{branch}.build.{build}"
|
||||
|
||||
image: Visual Studio 2017
|
||||
|
||||
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: vc15
|
||||
# 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
-283
@@ -1,283 +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/
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configuration headers generated by the PHP build system
|
||||
# ------------------------------------------------------------------------------
|
||||
config.h
|
||||
config.h.in
|
||||
/ext/date/lib/timelib_config.h
|
||||
/ext/iconv/php_have_bsd_iconv.h
|
||||
/ext/iconv/php_have_glibc_iconv.h
|
||||
/ext/iconv/php_have_ibm_iconv.h
|
||||
/ext/iconv/php_have_iconv.h
|
||||
/ext/iconv/php_have_libiconv.h
|
||||
/ext/iconv/php_iconv_aliased_libiconv.h
|
||||
/ext/iconv/php_iconv_broken_ignore.h
|
||||
/ext/iconv/php_iconv_supports_errno.h
|
||||
/ext/iconv/php_php_iconv_h_path.h
|
||||
/ext/iconv/php_php_iconv_impl.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/libphp7.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 additionally 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 dependend)
|
||||
/config.nice.bat
|
||||
|
||||
# NTS debug build x86
|
||||
/Debug/
|
||||
|
||||
# ZTS debug build x86
|
||||
/Debug_TS/
|
||||
|
||||
# NTS build x86
|
||||
/Release/
|
||||
|
||||
# ZTS build x86
|
||||
/Release_TS/
|
||||
|
||||
# Generated by x64 compiler, includes Debug, Debug_TS, Release, Release_TS
|
||||
/x64/
|
||||
|
||||
# Miscellaneous files generated by Windows build sytem
|
||||
/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 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
@@ -1,98 +0,0 @@
|
||||
git:
|
||||
quiet: true
|
||||
|
||||
dist: xenial
|
||||
language: c
|
||||
sudo: required
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- locales
|
||||
- language-pack-de
|
||||
- re2c
|
||||
- ccache
|
||||
- mysql-server
|
||||
- libaspell-dev
|
||||
- libbz2-dev
|
||||
- libcurl4-gnutls-dev
|
||||
- libenchant-dev
|
||||
- libfreetype6-dev
|
||||
- libgmp-dev
|
||||
- libicu-dev
|
||||
- libjpeg-dev
|
||||
- libkrb5-dev
|
||||
- libonig-dev
|
||||
- libpng-dev
|
||||
- libpq-dev
|
||||
- libpspell-dev
|
||||
- libsasl2-dev
|
||||
- libsqlite3-dev
|
||||
- libsodium-dev
|
||||
- libtidy-dev
|
||||
- libwebp-dev
|
||||
- libxml2-dev
|
||||
- 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_MAINTAINER_ZTS=0 ENABLE_DEBUG=0
|
||||
arch: amd64
|
||||
- env: ENABLE_MAINTAINER_ZTS=1 ENABLE_DEBUG=1
|
||||
arch: amd64
|
||||
- env: ENABLE_MAINTAINER_ZTS=1 ENABLE_DEBUG=1 SKIP_IO_CAPTURE_TESTS=1 ARM64=1
|
||||
arch: arm64
|
||||
|
||||
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 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
|
||||
@@ -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.
|
||||
@@ -1,342 +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.
|
||||
|
||||
## 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:
|
||||
|
||||
```c
|
||||
/* {{{ 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:
|
||||
|
||||
```c
|
||||
/* {{{ proto object imap_header(int stream_id, int msg_no [, int from_length [, int subject_length [, string default_host]]])
|
||||
Returns a header object with the defined parameters */
|
||||
```
|
||||
|
||||
And yes, please keep the prototype on a single line, even if that line is
|
||||
massive.
|
||||
|
||||
## New and experimental functions
|
||||
|
||||
To reduce the problems normally associated with the first public implementation
|
||||
of a new set of functions, it has been suggested that the first implementation
|
||||
include a file labeled `EXPERIMENTAL` in the function directory, and that the
|
||||
functions follow the standard prefixing conventions during their initial
|
||||
implementation.
|
||||
|
||||
The file labelled `EXPERIMENTAL` should include the following information:
|
||||
|
||||
* Any authoring information (known bugs, future directions of the module).
|
||||
* Ongoing status notes which may not be appropriate for Git comments.
|
||||
|
||||
In general new features should go to PECL or experimental branches until there
|
||||
are specific reasons for directly adding it to the core distribution.
|
||||
|
||||
## Aliases & legacy documentation
|
||||
|
||||
You may also have some deprecated aliases with close to duplicate names, for
|
||||
example, `somedb_select_result` and `somedb_selectresult`. For documentation
|
||||
purposes, these will only be documented by the most current name, with the
|
||||
aliases listed in the documentation for the parent function. For ease of
|
||||
reference, user-functions with completely different names, that alias to the
|
||||
same function (such as `highlight_file` and `show_source`), will be separately
|
||||
documented. The proto should still be included, describing which function is
|
||||
aliased.
|
||||
|
||||
Backwards compatible functions and names should be maintained as long as the
|
||||
code can be reasonably be kept as part of the codebase. See the `README` in the
|
||||
PHP documentation repository for more information on documentation.
|
||||
-430
@@ -1,430 +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`
|
||||
└─ ...
|
||||
└─ xmlrpc/
|
||||
├─ libxmlrpc/ # Forked and maintained in php-src
|
||||
└─ ...
|
||||
└─ 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-maintainer-zts` to check your change compiles on
|
||||
multi-threaded web servers.
|
||||
- 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-maintainer-zts` switch to ensure your code handles TSRM correctly
|
||||
and doesn't break for those who need that.
|
||||
|
||||
Currently we have the following branches in use:
|
||||
|
||||
| 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
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| 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!
|
||||
@@ -0,0 +1,2 @@
|
||||
For the list of people who've put work into PHP, please see
|
||||
http://www.php.net/credits.php
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+187
-163
@@ -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: Unknown
|
||||
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>
|
||||
MAINTENANCE: Unkown
|
||||
STATUS: 5.6
|
||||
EXTENSION: milter
|
||||
MAINTENANCE: Unknown
|
||||
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,94 +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 - 2018)
|
||||
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: Unknown
|
||||
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
|
||||
@@ -238,279 +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)
|
||||
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 - 2019)
|
||||
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 - 2018)
|
||||
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 - 2018)
|
||||
Antony Dovgal <tony2001@php.net> (2005 - 2010)
|
||||
Nikita Popov <nikic@php.net> (2013 - 2019)
|
||||
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 - 2018)
|
||||
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)
|
||||
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 - 2019)
|
||||
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 - 2018)
|
||||
Nikita Popov <nikic@php.net> (2016 - 2019)
|
||||
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)
|
||||
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: Unkown
|
||||
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)
|
||||
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: Unkown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvsem
|
||||
PRIMARY MAINTAINER: Unkown
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvshm
|
||||
PRIMARY MAINTAINER: Unkown
|
||||
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 - 2019)
|
||||
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)
|
||||
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
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -1,7 +1,7 @@
|
||||
--------------------------------------------------------------------
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, version 3.01
|
||||
Copyright (c) 1999 - 2019 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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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:
|
||||
@@ -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
@@ -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");
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
====================
|
||||
Mailinglist Rules
|
||||
====================
|
||||
|
||||
This is the first file you should be reading before doing any posts on PHP
|
||||
mailinglists. Following these rules is considered imperative to the success of
|
||||
the PHP project. Therefore expect your contributions to be of much less positive
|
||||
impact if you do not follow these rules. More importantly you can actually
|
||||
assume that not following these rules will hurt the PHP project.
|
||||
|
||||
PHP is developed through the efforts of a large number of people.
|
||||
Collaboration is a Good Thing(tm), and mailinglists lets us do this. Thus,
|
||||
following some basic rules with regards to mailinglist usage will:
|
||||
|
||||
a. Make everybody happier, especially those responsible for developing PHP
|
||||
itself.
|
||||
|
||||
b. Help in making sure we all use our time more efficiently.
|
||||
|
||||
c. Prevent you from making a fool of yourself in public.
|
||||
|
||||
d. Increase the general level of good will on planet Earth.
|
||||
|
||||
|
||||
Having said that, here are the organizational rules:
|
||||
|
||||
1. Respect other people working on the project.
|
||||
|
||||
2. Do not post when you are angry. Any post can wait a few hours. Review
|
||||
your post after a good breather or a good nights sleep.
|
||||
|
||||
3. Make sure you pick the right mailinglist for your posting. Please review
|
||||
the descriptions on the mailinglist overview page
|
||||
(http://www.php.net/mailing-lists.php). When in doubt ask a friend or
|
||||
someone you trust on IRC.
|
||||
|
||||
4. Make sure you know what you are talking about. PHP is a very large project
|
||||
that strives to be very open. The flip side is that the core developers
|
||||
are faced with a lot of requests. Make sure that you have done your
|
||||
research before posting to the entire developer community.
|
||||
|
||||
5. Patches have a much greater chance of acceptance than just asking the
|
||||
PHP developers to implement a feature for you. For one it makes the
|
||||
discussion more concrete and it shows that the poster put thought and time
|
||||
into the request.
|
||||
|
||||
6. If you are posting to an existing thread, make sure that you know what
|
||||
previous posters have said. This is even more important the longer the
|
||||
thread is already.
|
||||
|
||||
7. Please configure your email client to use a real name and keep message
|
||||
signatures to a maximum of 2 lines if at all necessary.
|
||||
|
||||
The next few rules are more some general hints:
|
||||
|
||||
1. If you notice that your posting ratio is much higher than that of other
|
||||
people, double check the above rules. Try to wait a bit longer before
|
||||
sending your replies to give other people more time to digest your answers
|
||||
and more importantly give you the opportunity to make sure that you
|
||||
aggregate your current position into a single mail instead of multiple
|
||||
ones.
|
||||
|
||||
2. Consider taking a step back from a very active thread now and then. Maybe
|
||||
talking to some friends and fellow developers will help in understanding
|
||||
the other opinions better.
|
||||
|
||||
3. Do not top post. Place your answer underneath anyone you wish to quote
|
||||
and remove any previous comment that is not relevant to your post.
|
||||
|
||||
4. Do not high-jack threads, by bringing up entirely new topics. Please
|
||||
create an entirely new thread copying anything you wish to quote into the
|
||||
new thread.
|
||||
|
||||
Finally, additional hints on how to behave inside the virtual community can be
|
||||
found in RFC 1855 (http://www.faqs.org/rfcs/rfc1855.html).
|
||||
|
||||
Happy hacking,
|
||||
|
||||
PHP Team
|
||||
@@ -0,0 +1,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
|
||||
@@ -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, ¶m) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets an object of class specified by my_ce, and an optional double. */
|
||||
zval *obj;
|
||||
double d = 0.5;
|
||||
zend_class_entry *my_ce;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() 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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
+152
-391
@@ -1,122 +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. libxmlrpc ext/xmlrpc
|
||||
11. main/snprintf.c
|
||||
12. main/strlcat
|
||||
13. main/strlcpy
|
||||
14. libgd (ext/gd)
|
||||
15. ext/phar portions of tar implementations
|
||||
16. ext/phar/zip.c portion extracted from libzip
|
||||
17. libbcmath (ext/bcmath) see ext/bcmath/libbcmath/LICENSE
|
||||
18. 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
|
||||
|
||||
@@ -127,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
|
||||
@@ -146,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:
|
||||
|
||||
@@ -192,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
|
||||
@@ -218,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
|
||||
@@ -248,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
|
||||
@@ -295,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>
|
||||
@@ -310,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.
|
||||
|
||||
@@ -330,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
|
||||
@@ -355,33 +271,63 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
|
||||
10. libxmlrpc ext/xmlrpc
|
||||
13. libxmlrpc ext/xmlrpc
|
||||
|
||||
Copyright 2000 Epinions, Inc.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
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
|
||||
|
||||
11. main/snprintf.c
|
||||
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
|
||||
@@ -408,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
|
||||
@@ -454,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.
|
||||
|
||||
|
||||
12. main/strlcat
|
||||
13. main/strlcpy
|
||||
|
||||
16. main/strlcat
|
||||
17. main/strlcpy
|
||||
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
All rights reserved.
|
||||
|
||||
@@ -465,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
|
||||
@@ -483,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.
|
||||
|
||||
|
||||
14. 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
|
||||
|
||||
|
||||
15. 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.
|
||||
|
||||
|
||||
16. 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.
|
||||
|
||||
|
||||
18. ext/mbstring/ucgendat portions based on the ucgendat.c from the OpenLDAP
|
||||
|
||||
The OpenLDAP Public License
|
||||
Version 2.8, 17 August 2003
|
||||
|
||||
Redistribution and use of this software and associated documentation
|
||||
("Software"), with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
1. Redistributions in source form must retain copyright statements
|
||||
and notices,
|
||||
|
||||
2. Redistributions in binary form must reproduce applicable copyright
|
||||
statements and notices, this list of conditions, and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution, and
|
||||
|
||||
3. Redistributions must contain a verbatim copy of this document.
|
||||
|
||||
The OpenLDAP Foundation may revise this license from time to time.
|
||||
Each revision is distinguished by a version number. You may use
|
||||
this Software under terms of this license revision or under the
|
||||
terms of any subsequent revision of the license.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
|
||||
CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
|
||||
OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The names of the authors and copyright holders must not be used in
|
||||
advertising or otherwise to promote the sale, use or other dealing
|
||||
in this Software without specific, written prior permission. Title
|
||||
to copyright in this Software shall at all times remain with copyright
|
||||
holders.
|
||||
|
||||
OpenLDAP is a registered trademark of the OpenLDAP Foundation.
|
||||
|
||||
Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
|
||||
California, USA. All Rights Reserved. Permission to copy and
|
||||
distribute verbatim copies of this document is granted.
|
||||
@@ -0,0 +1,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.
|
||||
@@ -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
@@ -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
|
||||
@@ -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!
|
||||
@@ -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
@@ -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
@@ -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
@@ -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) "< カ >"
|
||||
escape (XML hex) "< カ >"
|
||||
|
||||
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) "< éþ >"
|
||||
escape (XML hex) "< éþ >"
|
||||
|
||||
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 :
|
||||
@@ -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:
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -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
@@ -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'
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,134 +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.
|
||||
|
||||
[](https://travis-ci.org/php/php-src)
|
||||
[](https://ci.appveyor.com/project/php/php-src)
|
||||
[](https://dev.azure.com/phpazuredevops/php/_build/latest?definitionId=1&branchName=PHP-7.4)
|
||||
|
||||
## 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).*
|
||||
|
||||
PHP uses autotools on Unix systems to configure the build:
|
||||
|
||||
./buildconf
|
||||
./configure [options]
|
||||
|
||||
*See `./configure -h` for configuration options.*
|
||||
|
||||
make [options]
|
||||
|
||||
*See `make -h` for make options.*
|
||||
|
||||
The `-j` option shall set the maximum number of jobs `make` can use for the
|
||||
build:
|
||||
|
||||
make -j4
|
||||
|
||||
Shall run `make` with a maximum of 4 concurrent jobs: Generally the maximum
|
||||
number of jobs should not exceed the number of cores available.
|
||||
|
||||
## 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).
|
||||
Executable
+174
@@ -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?
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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:
|
||||
@@ -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
|
||||
+209
-301
@@ -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>
|
||||
|
||||
#ifdef ZEND_DEBUG
|
||||
# include <assert.h>
|
||||
# define TSRM_ASSERT assert
|
||||
#else
|
||||
# define TSRM_ASSERT
|
||||
#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, ...);
|
||||
@@ -102,12 +89,7 @@ static FILE *tsrm_error_file;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GNUPTH)
|
||||
static pth_key_t tls_key;
|
||||
# define tsrm_tls_set(what) pth_key_setdata(tls_key, (void*)(what))
|
||||
# define tsrm_tls_get() pth_key_getdata(tls_key)
|
||||
|
||||
#elif defined(PTHREADS)
|
||||
#if defined(PTHREADS)
|
||||
/* Thread local storage */
|
||||
static pthread_key_t tls_key;
|
||||
# define tsrm_tls_set(what) pthread_setspecific(tls_key, (void*)(what))
|
||||
@@ -123,21 +105,22 @@ 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
|
||||
|
||||
TSRM_TLS uint8_t in_main_thread = 0;
|
||||
TSRM_TLS uint8_t is_thread_shutdown = 0;
|
||||
|
||||
/* Startup TSRM (call once for the entire process) */
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
|
||||
{/*{{{*/
|
||||
{
|
||||
#if defined(GNUPTH)
|
||||
pth_init();
|
||||
pth_key_create(&tls_key, 0);
|
||||
#elif defined(PTHREADS)
|
||||
pthread_key_create( &tls_key, 0 );
|
||||
#elif defined(TSRM_ST)
|
||||
@@ -145,12 +128,10 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
|
||||
st_key_create(&tls_key, 0);
|
||||
#elif defined(TSRM_WIN32)
|
||||
tls_key = TlsAlloc();
|
||||
#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;
|
||||
@@ -158,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;
|
||||
@@ -167,67 +147,55 @@ 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);
|
||||
@@ -240,61 +208,14 @@ TSRM_API void tsrm_shutdown(void)
|
||||
#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() {
|
||||
tsrm_mutex_lock(tsrm_env_mutex);
|
||||
}
|
||||
|
||||
TSRM_API void tsrm_env_unlock() {
|
||||
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);
|
||||
@@ -305,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
|
||||
@@ -492,12 +373,15 @@ 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;
|
||||
|
||||
@@ -506,22 +390,20 @@ void tsrm_free_interpreter_context(void *context)
|
||||
|
||||
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);
|
||||
free(thread_resources);
|
||||
thread_resources = next;
|
||||
}
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
void *tsrm_set_interpreter_context(void *new_ctx)
|
||||
{/*{{{*/
|
||||
{
|
||||
tsrm_tls_entry *current;
|
||||
|
||||
current = tsrm_tls_get();
|
||||
@@ -534,12 +416,12 @@ void *tsrm_set_interpreter_context(void *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;
|
||||
|
||||
@@ -549,24 +431,22 @@ void *tsrm_new_interpreter_context(void)
|
||||
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];
|
||||
@@ -575,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) {
|
||||
@@ -599,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);
|
||||
|
||||
@@ -618,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;
|
||||
@@ -634,7 +557,7 @@ 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));
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -645,22 +568,28 @@ 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();
|
||||
#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));
|
||||
@@ -671,19 +600,27 @@ TSRM_API MUTEX_T tsrm_mutex_alloc(void)
|
||||
#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);
|
||||
@@ -693,14 +630,21 @@ TSRM_API void tsrm_mutex_free(MUTEX_T 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
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -708,7 +652,7 @@ 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);
|
||||
@@ -720,10 +664,19 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
|
||||
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
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -731,7 +684,7 @@ 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);
|
||||
@@ -743,54 +696,39 @@ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
|
||||
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()));
|
||||
/* TODO: add support for other APIs */
|
||||
#ifdef PTHREADS
|
||||
return pthread_sigmask(how, set, oldset);
|
||||
#else
|
||||
return sigprocmask(how, set, oldset);
|
||||
#endif
|
||||
}/*}}}*/
|
||||
#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
|
||||
@@ -798,7 +736,7 @@ TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler)
|
||||
|
||||
#if TSRM_DEBUG
|
||||
int tsrm_error(int level, const char *format, ...)
|
||||
{/*{{{*/
|
||||
{
|
||||
if (level<=tsrm_error_level) {
|
||||
va_list args;
|
||||
int size;
|
||||
@@ -813,12 +751,12 @@ int tsrm_error(int level, const char *format, ...)
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}/*}}}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void tsrm_error_set(int level, char *debug_filename)
|
||||
{/*{{{*/
|
||||
{
|
||||
tsrm_error_level = level;
|
||||
|
||||
#if TSRM_DEBUG
|
||||
@@ -835,36 +773,6 @@ void tsrm_error_set(int level, char *debug_filename)
|
||||
tsrm_error_file = stderr;
|
||||
}
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
TSRM_API void *tsrm_get_ls_cache(void)
|
||||
{/*{{{*/
|
||||
return tsrm_tls_get();
|
||||
}/*}}}*/
|
||||
|
||||
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)
|
||||
{/*{{{*/
|
||||
#if defined(GNUPTH)
|
||||
return "GNU Pth";
|
||||
#elif defined(PTHREADS)
|
||||
return "POSIX Threads";
|
||||
#elif defined(TSRM_ST)
|
||||
return "State Threads";
|
||||
#elif defined(TSRM_WIN32)
|
||||
return "Windows Threads";
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
#endif /* ZTS */
|
||||
+186
@@ -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
|
||||
+41
-80
@@ -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
|
||||
@@ -52,14 +55,9 @@ typedef uintptr_t tsrm_uintptr_t;
|
||||
# include <pthread.h>
|
||||
#elif defined(TSRM_ST)
|
||||
# include <st.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(BETHREADS)
|
||||
#include <kernel/OS.h>
|
||||
#include <TLS.h>
|
||||
#endif
|
||||
|
||||
typedef int ts_rsrc_id;
|
||||
@@ -74,15 +72,26 @@ typedef int ts_rsrc_id;
|
||||
#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
|
||||
|
||||
@@ -94,17 +103,9 @@ extern "C" {
|
||||
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();
|
||||
TSRM_API void tsrm_env_unlock();
|
||||
|
||||
/* 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)
|
||||
@@ -112,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);
|
||||
|
||||
@@ -121,9 +125,8 @@ 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, ...);
|
||||
@@ -135,13 +138,9 @@ 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);
|
||||
|
||||
/* these 3 APIs should only be used by people that fully understand the threading model
|
||||
* used by PHP/Zend and the selected SAPI. */
|
||||
@@ -149,42 +148,17 @@ TSRM_API void *tsrm_new_interpreter_context(void);
|
||||
TSRM_API void *tsrm_set_interpreter_context(void *new_ctx);
|
||||
TSRM_API void tsrm_free_interpreter_context(void *context);
|
||||
|
||||
TSRM_API void *tsrm_get_ls_cache(void);
|
||||
TSRM_API 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
|
||||
|
||||
#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
|
||||
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
|
||||
|
||||
#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_get_ls_cache()
|
||||
#define TSRMG(id, type, element) (TSRMG_BULK(id, type)->element)
|
||||
#define TSRMG_BULK(id, type) ((type) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(id)])
|
||||
#define TSRMG_FAST(offset, type, element) (TSRMG_FAST_BULK(offset, type)->element)
|
||||
#define TSRMG_FAST_BULK(offset, type) ((type) (((char*) tsrm_get_ls_cache())+(offset)))
|
||||
|
||||
#define TSRMG_STATIC(id, type, element) (TSRMG_BULK_STATIC(id, type)->element)
|
||||
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
|
||||
#define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element)
|
||||
#define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset)))
|
||||
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
|
||||
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
|
||||
#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
|
||||
#define TSRMLS_CACHE _tsrm_ls_cache
|
||||
|
||||
/* BC only */
|
||||
#define TSRMLS_D void
|
||||
#define TSRMLS_DC
|
||||
#define TSRMLS_C
|
||||
#define TSRMLS_CC
|
||||
#define TSRMLS_FETCH()
|
||||
#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
|
||||
}
|
||||
@@ -192,22 +166,9 @@ TSRM_API const char *tsrm_api_name(void);
|
||||
|
||||
#else /* non ZTS */
|
||||
|
||||
#define tsrm_env_lock()
|
||||
#define tsrm_env_unlock()
|
||||
|
||||
#define TSRMLS_FETCH()
|
||||
#define TSRMLS_FETCH_FROM_CTX(ctx)
|
||||
#define TSRMLS_SET_CTX(ctx)
|
||||
|
||||
#define TSRMG_STATIC(id, type, element)
|
||||
#define TSRMLS_CACHE_EXTERN()
|
||||
#define TSRMLS_CACHE_DEFINE()
|
||||
#define TSRMLS_CACHE_UPDATE()
|
||||
#define TSRMLS_CACHE
|
||||
|
||||
#define TSRM_TLS
|
||||
|
||||
/* BC only */
|
||||
#define TSRMLS_D void
|
||||
#define TSRMLS_DC
|
||||
#define TSRMLS_C
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#undef PTHREADS
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[
|
||||
LIBTOOL='$(SHELL) $(top_builddir)/libtool $1'
|
||||
])
|
||||
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
|
||||
+75
-38
@@ -1,9 +1,40 @@
|
||||
dnl This file contains TSRM specific autoconf macros.
|
||||
|
||||
dnl
|
||||
dnl TSRM_CHECK_PTH
|
||||
dnl
|
||||
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
|
||||
])
|
||||
|
||||
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
|
||||
@@ -16,11 +47,9 @@ LIBS="$LIBS `$1 --libs`"
|
||||
|
||||
AC_DEFINE(GNUPTH, 1, [Whether you use GNU Pth])
|
||||
AC_MSG_RESULT(yes - installed in $PTH_PREFIX)
|
||||
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl TSRM_CHECK_ST
|
||||
dnl
|
||||
AC_DEFUN([TSRM_CHECK_ST],[
|
||||
if test -r "$1/include/st.h"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$1/include"
|
||||
@@ -38,46 +67,53 @@ AC_DEFUN([TSRM_CHECK_ST],[
|
||||
AC_DEFINE(TSRM_ST, 1, [ ])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl TSRM_CHECK_PTHREADS
|
||||
dnl
|
||||
sinclude(threads.m4)
|
||||
|
||||
AC_DEFUN([TSRM_CHECK_PTHREADS],[
|
||||
|
||||
PTHREADS_CHECK
|
||||
|
||||
if test "$pthreads_working" != "yes"; then
|
||||
AC_MSG_ERROR(Your system seems to lack POSIX threads.)
|
||||
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_DEFINE(PTHREADS, 1, Whether to use Pthreads)
|
||||
|
||||
AC_MSG_CHECKING(for POSIX threads)
|
||||
AC_MSG_RESULT(yes)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl TSRM_THREADS_CHECKS
|
||||
dnl
|
||||
dnl For the thread implementations, we always use --with-* to maintain
|
||||
dnl consistency.
|
||||
dnl
|
||||
|
||||
AC_DEFUN([TSRM_THREADS_CHECKS],[
|
||||
AC_ARG_WITH([tsrm-pth],
|
||||
[AS_HELP_STRING([[--with-tsrm-pth[=pth-config]]],
|
||||
[Use GNU Pth])],
|
||||
[TSRM_PTH=$withval],
|
||||
[TSRM_PTH=no])
|
||||
|
||||
AC_ARG_WITH([tsrm-st],
|
||||
[AS_HELP_STRING([--with-tsrm-st],
|
||||
[Use SGI's State Threads])],
|
||||
[TSRM_ST=$withval],
|
||||
[TSRM_ST=no])
|
||||
dnl For the thread implementations, we always use --with-*
|
||||
dnl to maintain consistency
|
||||
|
||||
AC_ARG_WITH([tsrm-pthreads],
|
||||
[AS_HELP_STRING([--with-tsrm-pthreads],
|
||||
[Use POSIX threads (default)])],
|
||||
[TSRM_PTHREADS=$withval],
|
||||
[TSRM_PTHREADS=yes])
|
||||
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
|
||||
|
||||
@@ -88,4 +124,5 @@ elif test "$TSRM_ST" != "no"; then
|
||||
elif test "$TSRM_PTHREADS" != "no"; then
|
||||
TSRM_CHECK_PTHREADS
|
||||
fi
|
||||
|
||||
])
|
||||
@@ -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
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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 */
|
||||
+256
-367
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
| PHP Version 6 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
| 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 |
|
||||
@@ -16,6 +16,8 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
@@ -30,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;
|
||||
@@ -39,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
|
||||
@@ -59,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) {
|
||||
@@ -87,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
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -188,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 };
|
||||
@@ -204,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;
|
||||
|
||||
@@ -396,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) {
|
||||
@@ -426,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, ©, 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, 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(" /c ")+2);
|
||||
if (!cmd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(cmd, "%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);
|
||||
@@ -506,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);
|
||||
|
||||
@@ -547,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);
|
||||
@@ -589,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;
|
||||
}
|
||||
|
||||
@@ -609,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);
|
||||
@@ -684,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;
|
||||
@@ -732,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) {
|
||||
@@ -769,61 +704,15 @@ TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf)
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}/*}}}*/
|
||||
|
||||
#if HAVE_UTIME
|
||||
static zend_always_inline void UnixTimeToFileTime(time_t t, LPFILETIME pft) /* {{{ */
|
||||
{
|
||||
// Note that LONGLONG is a 64-bit value
|
||||
LONGLONG ll;
|
||||
|
||||
ll = t * 10000000LL + 116444736000000000LL;
|
||||
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
|
||||
|
||||
#endif
|
||||
+11
-12
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
| PHP Version 6 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
| 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 |
|
||||
@@ -16,18 +16,16 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef TSRM_WIN32_H
|
||||
#define TSRM_WIN32_H
|
||||
|
||||
#include "TSRM.h"
|
||||
#include <windows.h>
|
||||
#if HAVE_UTIME
|
||||
# include <sys/utime.h>
|
||||
#endif
|
||||
#include "win32/ipc.h"
|
||||
|
||||
struct ipc_perm {
|
||||
key_t key;
|
||||
int key;
|
||||
unsigned short uid;
|
||||
unsigned short gid;
|
||||
unsigned short cuid;
|
||||
@@ -38,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;
|
||||
@@ -70,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
|
||||
@@ -93,7 +90,7 @@ TSRMLS_CACHE_EXTERN()
|
||||
#define SHM_RND FILE_MAP_WRITE
|
||||
#define SHM_REMAP FILE_MAP_COPY
|
||||
|
||||
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);
|
||||
@@ -104,8 +101,10 @@ 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
|
||||
@@ -1,849 +0,0 @@
|
||||
PHP 7.4 UPGRADE NOTES
|
||||
|
||||
1. Backward Incompatible Changes
|
||||
2. New Features
|
||||
3. Changes in SAPI modules
|
||||
4. Deprecated Functionality
|
||||
5. Changed Functions
|
||||
6. New Functions
|
||||
7. New Classes and Interfaces
|
||||
8. Removed Extensions and SAPIs
|
||||
9. Other Changes to Extensions
|
||||
10. New Global Constants
|
||||
11. Changes to INI File Handling
|
||||
12. Windows Support
|
||||
13. Migration to pkg-config
|
||||
14. Other Changes
|
||||
15. Performance Improvements
|
||||
|
||||
|
||||
========================================
|
||||
1. Backward Incompatible Changes
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
. Trying to use values of type null, bool, int, float or resource as an
|
||||
array (such as $null["key"]) will now generate a notice. This does not
|
||||
affect array accesses performed by list().
|
||||
RFC: https://wiki.php.net/rfc/notice-for-non-valid-array-container
|
||||
. get_declared_classes() no longer returns anonymous classes that haven't
|
||||
been instantiated yet.
|
||||
. "fn" is now a reserved keyword. In particular, it can no longer be used as a
|
||||
function or class name. It can still be used as a method or class constant
|
||||
name.
|
||||
. Passing the result of a (non-reference) list() assignment by reference is
|
||||
consistently disallowed now. Previously this worked if the right-hand side
|
||||
was a simple (CV) variable and did not occur as part of the list().
|
||||
. `<?php` at the end of the file (without trailing newline) will now be
|
||||
interpreted as an opening PHP tag. Previously it was interpreted either as
|
||||
`<? php` and resulted in a syntax error (with short_open_tag=1) or was
|
||||
interpreted as a literal `<?php` string (with short_open_tag=0).
|
||||
. When using include/require on a stream, stream_set_option() will be invoked
|
||||
with the STREAM_OPTION_READ_BUFFER option. Custom stream wrapper
|
||||
implementations may need to implement the stream_set_option() method to
|
||||
avoid a warning (always returning false is a sufficient implementation).
|
||||
. The "creating default object from empty value" warning is now consistently
|
||||
thrown if a falsy value is promoted into an stdClass object. Previously some
|
||||
cases like `$null->prop[0] = $val` missed this warning.
|
||||
. Previously get_declared_classes() always returned parent classes before
|
||||
child classes. This is no longer the case. No particular order is guaranteed
|
||||
for the get_declared_classes() return value.
|
||||
|
||||
- BCMath:
|
||||
. BCMath functions will now warn if a non well-formed number is passed, such
|
||||
as "32foo". The argument will be interpreted as zero (as before).
|
||||
|
||||
- Curl:
|
||||
. Attempting to serialize a CURLFile class will now generate an exception.
|
||||
Previously the exception was only thrown on unserialization.
|
||||
. Using CURLPIPE_HTTP1 is deprecated, and is no longer supported as of cURL
|
||||
7.62.0.
|
||||
. The $version parameter of curl_version() is deprecated. If any value not
|
||||
equal to the default CURLVERSION_NOW is passed, a warning is raised and the
|
||||
parameter is ignored.
|
||||
|
||||
- Date:
|
||||
. Calling var_dump() or similar on a DateTime(Immutable) instance will no
|
||||
longer leave behind accessible properties on the object.
|
||||
. Comparison of DateInterval objects (using ==, < and so on) will now generate
|
||||
a warning and always return false. Previously all DateInterval objects were
|
||||
considered equal, unless they had properties.
|
||||
|
||||
DOM:
|
||||
. As of PHP 7.4.4, the value of the $childNodes property of DOMDocument,
|
||||
DOMNode, DOMProcessingInstruction, DOMComment, DOMText, DOMCdataSection and
|
||||
DOMNotation is now an empty DOMNodeList instead of NULL, according to the
|
||||
W3C and WHATWG standards and the PHP manual.
|
||||
|
||||
- Intl:
|
||||
. The default parameter value of idn_to_ascii() and idn_to_utf8() is now
|
||||
INTL_IDNA_VARIANT_UTS46 instead of the deprecated INTL_IDNA_VARIANT_2003.
|
||||
|
||||
- MySQLi:
|
||||
. The embedded server functionality has been removed. It was broken since
|
||||
at least PHP 7.0.
|
||||
. The undocumented mysqli::$stat property has been removed in favor of
|
||||
mysqli::stat().
|
||||
|
||||
- Openssl:
|
||||
. The openssl_random_pseudo_bytes() function will now throw an exception in
|
||||
error situations, similar to random_bytes(). In particular, an Error is
|
||||
thrown if the number of requested bytes is less than *or equal to* zero,
|
||||
and an Exception is thrown if sufficient randomness cannot be gathered.
|
||||
The $crypto_strong output argument is guaranteed to always be true if the
|
||||
function does not throw, so explicitly checking it is not necessary.
|
||||
RFC: http://php.net/manual/de/function.openssl-random-pseudo-bytes.php
|
||||
|
||||
- Pcntl:
|
||||
. The $restart_syscalls flag for pcntl_signal() will now be respected for
|
||||
SIGALARM. Previously it was hardcoded to false. To reduce the backwards
|
||||
compatibility impact, the default for SIGALARM will remain false however.
|
||||
|
||||
- PCRE:
|
||||
. When PREG_UNMATCHED_AS_NULL mode is used, trailing unmatched capturing
|
||||
groups will now also be set to null (or [null, -1] if offset capture is
|
||||
enabled). This means that the size of the $matches will always be the same.
|
||||
|
||||
- PEAR:
|
||||
. Installation of PEAR (including PECL) is no longer enabled by default. It
|
||||
can be explicitly enabled using --with-pear. This option is deprecated and
|
||||
may be removed in the future.
|
||||
|
||||
- PDO:
|
||||
. Attempting to serialize a PDO or PDOStatement instance will now generate
|
||||
an Exception rather than a PDOException, consistent with other internal
|
||||
classes which do not support serialization.
|
||||
|
||||
- Reflection:
|
||||
. Reflection objects will now generate an exception if an attempt is made
|
||||
to serialize them. Serialization for reflection objects was never
|
||||
supported and resulted in corrupted reflection objects. It has been
|
||||
explicitly prohibited now.
|
||||
. The signature of the ReflectionMethod::getClosure() method changed to
|
||||
account for existing behavior with static methods:
|
||||
Before: ReflectionMethod::getClosure($object)
|
||||
After: ReflectionMethod::getClosure($object = null)
|
||||
The new signature is also (LSP) compatible with older PHP versions.
|
||||
|
||||
- SAPI:
|
||||
. Starting with 7.4.11, incoming cookie names are not url-decoded. This was never
|
||||
required by the standard, outgoing cookie names aren't encoded and this leads
|
||||
to security issues (CVE-2020-7070).
|
||||
|
||||
- SPL:
|
||||
. Calling get_object_vars() on an ArrayObject instance will now always return
|
||||
the properties of the ArrayObject itself (or a subclass). Previously it
|
||||
returned the values of the wrapped array/object unless the STD_PROP_LIST
|
||||
flag was specified. Other affected operations are:
|
||||
|
||||
* ReflectionObject::getProperties()
|
||||
* reset(), current(), etc. Use Iterator methods instead.
|
||||
* Potentially others working on object properties as a list.
|
||||
* Other internal functions that iterate over an array, but which
|
||||
previously silently accepted an ArrayObject as well; eg curl_setopt()
|
||||
when used with an option that expects an array.
|
||||
|
||||
(array) casts are *not* affected. They will continue to return either the
|
||||
wrapped array, or the ArrayObject properties, depending on whether the
|
||||
STD_PROP_LIST flag is used.
|
||||
. SplPriorityQueue::setExtractFlags() will throw an exception if zero is
|
||||
passed. Previously this would generate a recoverable fatal error on the
|
||||
next extraction operation.
|
||||
. ArrayObject, ArrayIterator, SplDoublyLinkedList and SplObjectStorage now
|
||||
support the __serialize() + __unserialize() mechanism in addition to the
|
||||
Serializable interface. This means that serialization payloads created on
|
||||
older PHP versions can still be unserialized, but new payloads created by
|
||||
PHP 7.4 will not be understood by older versions.
|
||||
|
||||
- Standard:
|
||||
. The "o" serialization format has been removed. As it is never produced by
|
||||
PHP, this may only break unserialization of manually crafted strings.
|
||||
. Password hashing algorithm identifiers are now nullable strings rather
|
||||
than integers.
|
||||
|
||||
* PASSWORD_DEFAULT was int 1; now is null in PHP <7.4.3 and string '2y' afterwards
|
||||
* PASSWORD_BCRYPT was int 1; now is string '2y'
|
||||
* PASSWORD_ARGON2I was int 2; now is string 'argon2i'
|
||||
* PASSWORD_ARGON2ID was int 3; now is string 'argon2id'
|
||||
|
||||
Applications correctly using the constants PASSWORD_DEFAULT,
|
||||
PASSWORD_BCRYPT, PASSWORD_ARGON2I, and PASSWORD_ARGON2ID will continue to
|
||||
function correctly.
|
||||
. htmlentities() will now throw a notice (instead of a strict standards
|
||||
warning) if it is used with an encoding for which only basic entity
|
||||
substitution is supported, in which case it is equivalent to
|
||||
htmlspecialchars().
|
||||
. fread() and fwrite() will now return false if the operation failed.
|
||||
Previously an empty string or 0 was returned. EAGAIN/EWOULDBLOCK are not
|
||||
considered failures.
|
||||
. fread() and fwrite() on plain files will now throw a notice on failure,
|
||||
such as when trying to write to a read-only file resource.
|
||||
. The stream_read() and stream_write() methods on stream wrappers now
|
||||
interpret "false" as a failure return values. If no data is available, but
|
||||
no error occurred, an empty string should be returned instead.
|
||||
. round(-0.0) will now return -0.0 rather than +0.0.
|
||||
|
||||
- Tokenizer:
|
||||
. token_get_all() will now emit a T_BAD_CHARACTER token for unexpected
|
||||
characters instead of leaving behind holes in the token stream.
|
||||
|
||||
========================================
|
||||
2. New Features
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
. Added support for typed properties. For example:
|
||||
|
||||
class User {
|
||||
public int $id;
|
||||
public string $name;
|
||||
}
|
||||
|
||||
This will enforce that $user->id can only be assigned integers and
|
||||
$user->name can only be assigned strings. For more information see the
|
||||
RFC: https://wiki.php.net/rfc/typed_properties_v2
|
||||
|
||||
. Added support for arrow functions with implicit by-value scope binding.
|
||||
For example:
|
||||
|
||||
$factor = 10;
|
||||
$nums = array_map(fn($num) => $num * $factor, $nums);
|
||||
|
||||
RFC: https://wiki.php.net/rfc/arrow_functions_v2
|
||||
|
||||
. Added support for limited return type covariance and argument type
|
||||
contravariance. The following code will now work:
|
||||
|
||||
class A {}
|
||||
class B extends A {}
|
||||
|
||||
class Producer {
|
||||
public function method(): A {}
|
||||
}
|
||||
class ChildProducer extends Producer {
|
||||
public function method(): B {}
|
||||
}
|
||||
|
||||
Full variance support is only available if autoloading is used. Inside a
|
||||
single file only non-cyclic type references are possible, because all
|
||||
classes need to be available before they are referenced.
|
||||
RFC: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters
|
||||
|
||||
. Added support for coalesce assign (??=) operator. For example:
|
||||
|
||||
$array['key'] ??= computeDefault();
|
||||
// is roughly equivalent to
|
||||
if (!isset($array['key'])) {
|
||||
$array['key'] = computeDefault();
|
||||
}
|
||||
|
||||
RFC: https://wiki.php.net/rfc/null_coalesce_equal_operator
|
||||
|
||||
. Added support for unpacking inside arrays. For example:
|
||||
|
||||
$arr1 = [3, 4];
|
||||
$arr2 = [1, 2, ...$arr1, 5];
|
||||
// $arr2 == [1, 2, 3, 4, 5]
|
||||
|
||||
RFC: https://wiki.php.net/rfc/spread_operator_for_array
|
||||
|
||||
. Added support for underscore separators in numeric literals. Some examples:
|
||||
|
||||
6.674_083e-11; // float
|
||||
299_792_458; // decimal
|
||||
0xCAFE_F00D; // hexadecimal
|
||||
0b0101_1111; // binary
|
||||
|
||||
RFC: https://wiki.php.net/rfc/numeric_literal_separator
|
||||
|
||||
. Support for WeakReferences has been added.
|
||||
RFC: https://wiki.php.net/rfc/weakrefs
|
||||
|
||||
. Throwing exceptions from __toString() is now permitted. Previously this
|
||||
resulted in a fatal error. Existing recoverable fatals in string conversions
|
||||
have been converted to Error exceptions.
|
||||
RFC: https://wiki.php.net/rfc/tostring_exceptions
|
||||
|
||||
- CURL:
|
||||
. CURLFile now supports stream wrappers in addition to plain file names, if
|
||||
the extension has been built against libcurl >= 7.56.0. The streams may
|
||||
need to be seekable.
|
||||
|
||||
- Filter:
|
||||
. The FILTER_VALIDATE_FLOAT filter now supports the min_range and max_range
|
||||
options, with the same semantics as FILTER_VALIDATE_INT.
|
||||
|
||||
- FFI:
|
||||
. A new extension which provides a simple way to call native functions, access
|
||||
native variables and create/access data structures defined in C libraries.
|
||||
RFC: https://wiki.php.net/rfc/ffi
|
||||
|
||||
- GD:
|
||||
. Added the "scatter" image filter (IMG_FILTER_SCATTER) to apply a scatter
|
||||
filter to images. This filter has the following prototype:
|
||||
|
||||
imagefilter($im, IMG_FILTER_SCATTER, int $sub, int $plus, array $colors = []);
|
||||
|
||||
The $colors array can be populated with a set of indexed colors to
|
||||
apply the scatter pixel shifting on.
|
||||
|
||||
Note, the result of this filter is always random.
|
||||
|
||||
- Hash:
|
||||
. Added "crc32c" hash using Castagnoli's polynomial. This crc32 variant is
|
||||
used by storage systems, such as iSCSI, SCTP, Btrfs and ext4.
|
||||
|
||||
- Mbstring:
|
||||
. Added mb_str_split() function, which provides the same functionality as
|
||||
str_split(), but operating on code points rather than bytes.
|
||||
RFC: https://wiki.php.net/rfc/mb_str_split
|
||||
. Added mbstring.regex_retry_limit ini setting defaulting to 1000000. It
|
||||
limits the amount of backtracking that may be performed during one mbregex
|
||||
match and thus protects against exponential backtracking attacks (ReDOS).
|
||||
This setting only takes effect when linking against oniguruma >= 6.8.0.
|
||||
|
||||
- OPcache:
|
||||
. Support for preloading code has been added.
|
||||
RFC: https://wiki.php.net/rfc/preload
|
||||
|
||||
- PCRE:
|
||||
. The preg_replace_callback() and preg_replace_callback_array() functions now
|
||||
accept an additional $flags argument, with support for the
|
||||
PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL flags. This influences the
|
||||
format of the matches array passed to the callback function.
|
||||
|
||||
- PDO:
|
||||
. The username and password can now be specified as part of the PDO DSN for
|
||||
the mysql, mssql, sybase, dblib, firebird and oci drivers. Previously this
|
||||
was only supported by the pgsql driver. If a username/password is specified
|
||||
both in the constructor and the DSN, the constructor takes precedence.
|
||||
|
||||
new PDO("mysql:host=xxx;port=xxx;dbname=xxx;user=xxx;password=xxx");
|
||||
|
||||
- PDO_OCI:
|
||||
. PDOStatement::getColumnMeta() is now available
|
||||
|
||||
- PDO_SQLite:
|
||||
. PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) allows
|
||||
checking whether the statement is read-only, i.e. if it doesn't modify
|
||||
the database.
|
||||
. PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true) enables the
|
||||
use of SQLite3 extended result codes in errorInfo().
|
||||
|
||||
- SQLite3:
|
||||
. Added SQLite3::lastExtendedErrorCode() to fetch the last extended result
|
||||
code.
|
||||
. Added SQLite3::enableExtendedResultCodes($enable = true), which will make
|
||||
SQLite3::lastErrorCode() return extended result codes.
|
||||
|
||||
- Standard:
|
||||
. strip_tags() now also accepts an array of allowed tags: Instead of
|
||||
strip_tags($str, '<a><p>') you can now write strip_tags($str, ['a', 'p']).
|
||||
|
||||
. A new mechanism for custom object serialization has been added, which
|
||||
uses two new magic methods:
|
||||
|
||||
// Returns array containing all the necessary state of the object.
|
||||
public function __serialize(): array;
|
||||
|
||||
// Restores the object state from the given data array.
|
||||
public function __unserialize(array $data): void;
|
||||
|
||||
The new serialization mechanism supersedes the Serializable interface,
|
||||
which will be deprecated in the future.
|
||||
|
||||
RFC: https://wiki.php.net/rfc/custom_object_serialization
|
||||
|
||||
. A new 'max_depth' option for unserialize(), as well as an
|
||||
unserialize_max_depth ini setting have been added. These control the
|
||||
maximum depth of structures permitted during unserialization, and are
|
||||
intended to prevent stack overflows. The default depth limit is 4096 and
|
||||
can be disabled by setting unserialize_max_depth=0.
|
||||
|
||||
. array_merge() and array_merge_recursive() may now be called without any
|
||||
arguments, in which case they will return an empty array. This is useful
|
||||
in conjunction with the spread operator, e.g. array_merge(...$arrays).
|
||||
|
||||
. proc_open() now accepts an array instead of a string for the command. In
|
||||
this case the process will be opened directly (without going through a
|
||||
shell) and PHP will take care of any necessary argument escaping.
|
||||
|
||||
proc_open(['php', '-r', 'echo "Hello World\n";'], $descriptors, $pipes);
|
||||
|
||||
. proc_open() now supports "redirect" and "null" descriptors. For example:
|
||||
|
||||
// Like 2>&1 on the shell
|
||||
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);
|
||||
// Like 2>/dev/null or 2>nul on the shell
|
||||
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
|
||||
|
||||
. password_hash() has argon2i(d) implementations from ext/sodium when PHP is
|
||||
built without libargon.
|
||||
|
||||
RFC: https://wiki.php.net/rfc/sodium.argon.hash
|
||||
|
||||
========================================
|
||||
3. Changes in SAPI modules
|
||||
========================================
|
||||
|
||||
========================================
|
||||
4. Deprecated Functionality
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
. Nesting ternary operators without explicit parentheses is deprecated:
|
||||
|
||||
// Code like
|
||||
$a ? $b : $c ? $d : $e
|
||||
// should be replaced by (current interpretation)
|
||||
($a ? $b : $c) ? $d : $e
|
||||
// or (likely intended interpretation)
|
||||
$a ? $b : ($c ? $d : $e)
|
||||
|
||||
RFC: https://wiki.php.net/rfc/ternary_associativity
|
||||
. The array and string offset access syntax using curly braces is deprecated.
|
||||
Use $str[$idx] instead of $str{$idx}.
|
||||
RFC: https://wiki.php.net/rfc/deprecate_curly_braces_array_access
|
||||
. The (real) cast is deprecated, use (float) instead.
|
||||
. Unbinding $this of a non-static method through a combination of
|
||||
ReflectionMethod::getClosure() and closure rebinding is deprecated. Doing
|
||||
so is equivalent to calling a non-static method statically, which has been
|
||||
deprecated since PHP 7.0.
|
||||
. Unbinding $this of a non-static closure that uses $this is deprecated.
|
||||
. Using "parent" inside a class without a parent is deprecated, and will throw
|
||||
a compile-time error in the future. Currently an error will only be
|
||||
generated if/when the parent is accessed at run-time.
|
||||
. The allow_url_include ini directive is deprecated. Enabling it will generate
|
||||
a deprecation notice at startup.
|
||||
|
||||
- COM:
|
||||
. Importing type libraries with case-insensitive constant registering has been
|
||||
deprecated.
|
||||
|
||||
- Filter:
|
||||
. FILTER_SANITIZE_MAGIC_QUOTES is deprecated, use FILTER_SANITIZE_ADD_SLASHES
|
||||
instead.
|
||||
|
||||
- Mbstring:
|
||||
. Passing a non-string pattern to mb_ereg_replace() is deprecated. Currently
|
||||
non-string patterns are interpreted as ASCII codepoints. In PHP 8 the
|
||||
pattern will be interpreted as a string instead.
|
||||
. Passing the encoding as 3rd parameter to mb_strrpos() is deprecated. Instead
|
||||
pass a 0 offset and encoding as 4th parameter.
|
||||
|
||||
- LDAP:
|
||||
. ldap_control_paged_result_response and ldap_control_paged_result are
|
||||
deprecated. Pagination controls can be sent along with ldap_search instead.
|
||||
|
||||
- Reflection:
|
||||
. Calls to ReflectionType::__toString() now generate a deprecation notice.
|
||||
This method has been deprecated in favor of ReflectionNamedType::getName()
|
||||
in the documentation since PHP 7.1, but did not throw a deprecation notice
|
||||
for technical reasons.
|
||||
. The export() methods on all Reflection classes are deprecated. Construct a
|
||||
Reflection object and convert it to string instead:
|
||||
|
||||
// ReflectionClass::export(Foo::class, false) is:
|
||||
echo new ReflectionClass(Foo::class), "\n";
|
||||
// $str = ReflectionClass::export(Foo::class, true) is:
|
||||
$str = (string) new ReflectionClass(Foo::class);
|
||||
|
||||
- Socket:
|
||||
. The AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES flags for
|
||||
socket_addrinfo_lookup() are deprecated, due to an upstream deprecation in
|
||||
glibc.
|
||||
|
||||
- Standard:
|
||||
. Passing invalid characters to ''base_convert()'', ''bindec()'', ''octdec()''
|
||||
and ''hexdec()'' will now generate a deprecation notice. The result will
|
||||
still be computed as if the invalid characters did not exist. Leading and
|
||||
trailing whitespace, as well as prefixes of type 0x (depending on base)
|
||||
continue to be allowed.
|
||||
. Using array_key_exists() on objects is deprecated. Instead either isset()
|
||||
or property_exists() should be used.
|
||||
. The is_real() function is deprecated, use is_float() instead.
|
||||
. The get_magic_quotes_gpc() and get_magic_quotes_runtime() functions are
|
||||
deprecated. They always return false.
|
||||
. The hebrevc() function is deprecated. It can be replaced with
|
||||
nl2br(hebrev($str)), or preferably the use of Unicode RTL support.
|
||||
. The convert_cyr_string() function is deprecated. It can be replaced by one
|
||||
of mb_convert_string(), iconv() or UConverter.
|
||||
. The money_format() function is deprecated. It can be replaced by the
|
||||
intl NumberFormatter functionality.
|
||||
. The ezmlm_hash() function is deprecated.
|
||||
. The restore_include_path() function is deprecated. It can be replaced by
|
||||
ini_restore('include_path').
|
||||
. Passing parameters to implode() in reverse order is deprecated, use
|
||||
implode($glue, $parts) instead of implode($parts, $glue).
|
||||
|
||||
========================================
|
||||
5. Changed Functions
|
||||
========================================
|
||||
|
||||
- SPL:
|
||||
. SplFileObject::fputcsv(), ::fgetcsv() and ::setCsvControl() now accept an
|
||||
empty string as $escape argument, which disables the proprietary PHP
|
||||
escaping mechanism. SplFileObject::getCsvControl() now may also return an
|
||||
empty string for the third array element, accordingly.
|
||||
|
||||
- Standard:
|
||||
. fputcsv() and fgetcsv() now accept an empty string as $escape argument,
|
||||
which disables the proprietary PHP escaping mechanism. The behavior of
|
||||
str_getcsv() has been adjusted accordingly (formerly, an empty string was
|
||||
identical to using the default).
|
||||
. proc_open() on Windows can be passed a "create_process_group" option. It
|
||||
is required, if the child process is supposed to handle CTRL events.
|
||||
. password_hash() now accepts nullable string and int as $algo argument.
|
||||
. password_needs_rehash() now accepts nullable string and int as $algo
|
||||
argument.
|
||||
|
||||
========================================
|
||||
6. New Functions
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
. Added get_mangled_object_vars($object) function, which returns the mangled
|
||||
object properties. It returns the same result as (array) $object, with the
|
||||
exception that it ignores overloaded array casts, such as used by
|
||||
ArrayObject.
|
||||
|
||||
- GD:
|
||||
. Added imagecreatefromtga() function, which allows reading images in TGA
|
||||
format. TGA support is now also indicated by gd_info() and imagetypes().
|
||||
Note that TGA images are not recognized by imagecreatefromstring() and
|
||||
getimagesize().
|
||||
|
||||
- OpenSSL:
|
||||
. Added openssl_x509_verify(mixed cert, mixed key) function that verifies the
|
||||
signature of the certificate using a public key. A wrapper around the
|
||||
OpenSSL's X509_verify() function.
|
||||
See <https://github.com/php/php-src/pull/3624>.
|
||||
|
||||
- Pcntl:
|
||||
. Added bool pcntl_unshare(int flags) function which allows dissociating
|
||||
parts of the process execution context which are currently being shared with
|
||||
other processes. Explicitly, it allows you to unshare the mount, IPC, UTS,
|
||||
network, PID, user and cgroup namespaces.
|
||||
|
||||
- SQLite3:
|
||||
. Added SQLite3Stmt::getSQL() to retrieve the SQL of the statement. If true is
|
||||
passed as $expanded argument, query parameters will be replaced in the
|
||||
return value by their currently bound value, if libsqlite ≥ 3.14 is used.
|
||||
. Added SQLite3::backup() to create database backups via the SQLite3 online
|
||||
backup API.
|
||||
|
||||
- Standard
|
||||
. bool sapi_windows_set_ctrl_handler(callable handler, [, bool add = true]) -
|
||||
set or remove a handler function upon receiving a CTRL event. The handler
|
||||
function is expected to have this signature: "function handler(int $event)".
|
||||
. bool sapi_windows_generate_ctrl_event(int type, int pid) - send a CTRL event
|
||||
to another process.
|
||||
. array password_algos() - return a complete list of all registered password
|
||||
hashing algorithms. For more details see the RFC:
|
||||
https://wiki.php.net/rfc/password_registry
|
||||
|
||||
========================================
|
||||
7. New Classes and Interfaces
|
||||
========================================
|
||||
|
||||
- Reflection:
|
||||
. A new ReflectionReference class has been added, which allows detecting
|
||||
references and comparing them for identity. For more details see the RFC:
|
||||
https://wiki.php.net/rfc/reference_reflection
|
||||
|
||||
========================================
|
||||
8. Removed Extensions and SAPIs
|
||||
========================================
|
||||
|
||||
- Interbase:
|
||||
. The interbase extension has been moved to PECL. Access to an InterBase
|
||||
and/or FireBird based database is still available with the PDO_Firebird
|
||||
extension. For more details see the RFC:
|
||||
https://wiki.php.net/rfc/deprecate-and-remove-ext-interbase
|
||||
|
||||
- Recode:
|
||||
. The recode extension has been moved to PECL. For character set/encoding
|
||||
conversion the iconv or mbstring extensions could be used instead.
|
||||
RFC: https://wiki.php.net/rfc/unbundle_recode
|
||||
|
||||
- WDDX:
|
||||
. The WDDX extension has been deprecated and moved to PECL.
|
||||
RFC: https://wiki.php.net/rfc/deprecate-and-remove-ext-wddx
|
||||
|
||||
========================================
|
||||
9. Other Changes to Extensions
|
||||
========================================
|
||||
|
||||
DBA:
|
||||
. As of PHP 7.4.2, dba_open() accepts a fifth optional parameter for lmdb
|
||||
databases which allows to specify the mapsize. The parameter defaults to
|
||||
zero, in which case the compiled in default mapsize (usually 1048576) will
|
||||
be used. The mapsize should be a multiple of the page size of the OS.
|
||||
|
||||
- GD:
|
||||
. The behavior of imagecropauto() in the bundled libgd has been synced with
|
||||
that of system libgd:
|
||||
* IMG_CROP_DEFAULT is no longer falling back to IMG_CROP_SIDES
|
||||
* Threshold-cropping now uses the algorithm of system libgd
|
||||
. The default $mode parameter of imagecropauto() has been changed to
|
||||
IMG_CROP_DEFAULT; passing -1 is now deprecated.
|
||||
. imagescale() now supports aspect ratio preserving scaling to a fixed height
|
||||
by passing -1 as $new_width.
|
||||
|
||||
- Filter:
|
||||
. The filter extension no longer exposes --with-pcre-dir for Unix builds and
|
||||
can now reliably be built as shared when using ./configure once more.
|
||||
|
||||
- Hash:
|
||||
. The hash extension cannot be disabled anymore and is always an integral part
|
||||
of any PHP build, similar to the date extension.
|
||||
|
||||
- Intl:
|
||||
. The Intl extension now requires at least ICU 50.1.
|
||||
. ResourceBundle now implements Countable.
|
||||
|
||||
- Ldap:
|
||||
. Support for nsldap has been removed.
|
||||
. Support for umich_ldap has been removed.
|
||||
|
||||
- Libxml:
|
||||
. All libxml based extensions now require libxml 2.7.6 or newer.
|
||||
|
||||
- Mbstring:
|
||||
. The oniguruma library is no longer bundled with PHP, instead libonig needs
|
||||
to be available on the system. Alternatively --disable-mbregex can be used
|
||||
to disable the mbregex component.
|
||||
|
||||
- OPcache:
|
||||
. The --disable-opcache-file|--enable-opcache-file configure options have been
|
||||
removed in favor of the opcache.file_cache INI directive.
|
||||
|
||||
- PDO:
|
||||
. It is now possible to escape question marks in SQL queries to avoid them
|
||||
being interpreted as parameter placeholders. Writing "??" allows sending
|
||||
a single question mark to the database and e.g. use the PostgreSQL JSON key
|
||||
exists "?" operator. For more details see the RFC:
|
||||
https://wiki.php.net/rfc/pdo_escape_placeholders
|
||||
|
||||
- PDO_Firebird:
|
||||
. The extension now also support dialect 1 in addition to dialect 3.
|
||||
|
||||
- Reflection:
|
||||
. Numeric value of class, property, function and constant modifiers was
|
||||
changed. Don't filter methods and properties through
|
||||
ReflectionClass::getMethods() and ReflectionClass::getProperties(), or test
|
||||
results of Reflection...::getModifiers(), using hard-coded numeric values.
|
||||
Use corresponding constants instead (e.g. ReflectionMethod::IS_PUBLIC).
|
||||
|
||||
- SimpleXML:
|
||||
. SimpleXMLElement now implements Countable.
|
||||
|
||||
- SQLite3:
|
||||
. The bundled libsqlite has been removed. To build the SQLite3 extension a
|
||||
system libsqlite3 ≥ 3.7.4 is now required. To build the PDO_SQLite extension
|
||||
a system libsqlite3 ≥ 3.5.0 is now required.
|
||||
. (Un)serialization of SQLite3, SQLite3Stmt and SQLite3Result is now
|
||||
explicitly forbidden. Formerly, serialization of instances of these classes
|
||||
was possible, but unserialization yielded unusable objects.
|
||||
. The @param notation can now also be used to denote SQL query parameters.
|
||||
|
||||
- Zip:
|
||||
. The bundled libzip library has been removed. A system libzip >= 0.11 is now
|
||||
necessary to build the extension.
|
||||
|
||||
========================================
|
||||
10. New Global Constants
|
||||
========================================
|
||||
|
||||
- Mbstring:
|
||||
. MB_ONIGURUMA_VERSION specifies the version of the oniguruma library against
|
||||
which mbregex has been built.
|
||||
|
||||
- Socket:
|
||||
. Added FreeBSD-specific socket options:
|
||||
. SO_LABEL
|
||||
. SO_PEERLABEL
|
||||
. SO_LISTENQLIMIT
|
||||
. SO_LISTENQLEN
|
||||
. SO_USER_COOKIE
|
||||
|
||||
- Standard:
|
||||
. PHP_WINDOWS_EVENT_CTRL_C
|
||||
. PHP_WINDOWS_EVENT_CTRL_BREAK
|
||||
|
||||
- Tidy:
|
||||
. TIDY_TAG_ARTICLE
|
||||
. TIDY_TAG_ASIDE
|
||||
. TIDY_TAG_AUDIO
|
||||
. TIDY_TAG_BDI
|
||||
. TIDY_TAG_CANVAS
|
||||
. TIDY_TAG_COMMAND
|
||||
. TIDY_TAG_DATALIST
|
||||
. TIDY_TAG_DETAILS
|
||||
. TIDY_TAG_DIALOG
|
||||
. TIDY_TAG_FIGCAPTION
|
||||
. TIDY_TAG_FIGURE
|
||||
. TIDY_TAG_FOOTER
|
||||
. TIDY_TAG_HEADER
|
||||
. TIDY_TAG_HGROUP
|
||||
. TIDY_TAG_MAIN
|
||||
. TIDY_TAG_MARK
|
||||
. TIDY_TAG_MENUITEM
|
||||
. TIDY_TAG_METER
|
||||
. TIDY_TAG_NAV
|
||||
. TIDY_TAG_OUTPUT
|
||||
. TIDY_TAG_PROGRESS
|
||||
. TIDY_TAG_SECTION
|
||||
. TIDY_TAG_SOURCE
|
||||
. TIDY_TAG_SUMMARY
|
||||
. TIDY_TAG_TEMPLATE
|
||||
. TIDY_TAG_TIME
|
||||
. TIDY_TAG_TRACK
|
||||
. TIDY_TAG_VIDEO
|
||||
|
||||
========================================
|
||||
11. Changes to INI File Handling
|
||||
========================================
|
||||
|
||||
- zend.exception_ignore_args
|
||||
. New INI directive to include or exclude arguments from stack traces
|
||||
generated for exceptions.
|
||||
|
||||
- opcache.preload_user
|
||||
. New INI directive to specify the user account under which preloading code
|
||||
is executed, if it was to be run as root otherwise (which is not allowed
|
||||
for security reasons).
|
||||
|
||||
========================================
|
||||
12. Windows Support
|
||||
========================================
|
||||
|
||||
- stat:
|
||||
. The stat implementation has been refactored.
|
||||
- An inode number is delivered and is based on the NTFS file index.
|
||||
- The device number is now based on the volume serial number.
|
||||
|
||||
Note that both values are derived from the system and provided as is on 64-bit
|
||||
systems. On 32-bit systems, these values might overflow the 32-bit integer in
|
||||
PHP, so they're fake.
|
||||
|
||||
- CTRL+C and CTRL+BREAK on console can be caught by setting a handler function
|
||||
with sapi_windows_set_ctrl_handler().
|
||||
|
||||
- configure now regards additional CFLAGS and LDFLAGS set as environment
|
||||
variables.
|
||||
|
||||
- OPcache now supports an arbitrary amount of separate caches per user via
|
||||
the INI directive opcache.cache_id. All processes with the same cache ID and
|
||||
user share an OPcache instance.
|
||||
|
||||
- The OpenSSL default config path has been changed to
|
||||
"C:\Program Files\Common Files\SSL\openssl.cnf" and
|
||||
"C:\Program Files (x86)\Common Files\SSL\openssl.cnf", respectively.
|
||||
|
||||
========================================
|
||||
13. Migration to pkg-config
|
||||
========================================
|
||||
|
||||
A number of extensions have been migrated to exclusively use pkg-config for the
|
||||
detection of library dependencies. Generally, this means that instead of using
|
||||
--with-foo-dir=DIR or similar only --with-foo is used. Custom library paths can
|
||||
be specified either by adding additional directories to PKG_CONFIG_PATH or by
|
||||
explicitly specifying compilation options through FOO_CFLAGS and FOO_LIBS.
|
||||
|
||||
The following extensions and SAPIs are affected:
|
||||
|
||||
- Curl:
|
||||
. --with-curl no longer accepts a directory.
|
||||
|
||||
- Enchant:
|
||||
. --with-enchant no longer accepts a directory.
|
||||
|
||||
- FPM:
|
||||
. --with-fpm-systemd now uses only pkg-config for libsystem checks. The
|
||||
libsystemd minimum required version is 209.
|
||||
|
||||
- GD:
|
||||
. --with-gd becomes --enable-gd (whether to enable the extension at all) and
|
||||
--with-external-gd (to opt into using an external libgd, rather than the
|
||||
bundled one).
|
||||
. --with-png-dir has been removed. libpng is required.
|
||||
. --with-zlib-dir has been removed. zlib is required.
|
||||
. --with-freetype-dir becomes --with-freetype.
|
||||
. --with-jpeg-dir becomes --with-jpeg.
|
||||
. --with-webp-dir becomes --with-webp.
|
||||
. --with-xpm-dir becomes --with-xpm.
|
||||
|
||||
- IMAP:
|
||||
. --with-kerberos no longer accepts a directory.
|
||||
|
||||
- Intl:
|
||||
. --with-icu-dir has been removed. If --enable-intl is passed, then libicu is
|
||||
always required.
|
||||
|
||||
- Ldap:
|
||||
. --with-ldap-sasl no longer accepts a directory.
|
||||
|
||||
- Libxml:
|
||||
. --with-libxml-dir has been removed.
|
||||
. --enable-libxml becomes --with-libxml.
|
||||
. --with-libexpat-dir has been renamed to --with-expat and no longer accepts a
|
||||
directory.
|
||||
|
||||
- LiteSpeed:
|
||||
. --with-litespeed becomes --enable-litespeed.
|
||||
|
||||
- Mbstring:
|
||||
. --with-onig has been removed. Unless --disable-mbregex has been passed,
|
||||
libonig is required.
|
||||
|
||||
- ODBC:
|
||||
. --with-iodbc no longer accepts a directory.
|
||||
. --with-unixODBC without a directory now uses pkg-config (preferred).
|
||||
Directory is still accepted for old versions without libodbc.pc.
|
||||
|
||||
- OpenSSL:
|
||||
. --with-openssl no longer accepts a directory.
|
||||
. --with-kerberos no longer accepts a directory.
|
||||
|
||||
- PCRE:
|
||||
. --with-pcre-regex has been removed. Instead --with-external-pcre is provided
|
||||
to opt into using an external PCRE library, rather than the bundled one.
|
||||
|
||||
- PDO_SQLite:
|
||||
. --with-pdo-sqlite no longer accepts a directory.
|
||||
|
||||
- Readline:
|
||||
. --with-libedit no longer accepts a directory.
|
||||
|
||||
- Sodium:
|
||||
. --with-sodium no longer accepts a directory.
|
||||
|
||||
- SQLite3:
|
||||
. --with-sqlite3 no longer accepts a directory.
|
||||
|
||||
- XSL:
|
||||
. --with-xsl no longer accepts a directory.
|
||||
|
||||
- Zip:
|
||||
. --with-libzip has been removed.
|
||||
. --enable-zip becomes --with-zip.
|
||||
|
||||
========================================
|
||||
14. Other Changes
|
||||
========================================
|
||||
|
||||
========================================
|
||||
15. Performance Improvements
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
. A specialized VM opcode for the array_key_exists() function has been added,
|
||||
which improves performance of this function if it can be statically
|
||||
resolved. In namespaced code, this may require writing \array_key_exists()
|
||||
or explicitly importing the function.
|
||||
|
||||
- PCRE:
|
||||
. When preg_match() in UTF-8 mode ("u" modifier) is repeatedly called on the
|
||||
same string (but possibly different offsets), it will only be checked for
|
||||
UTF-8 validity once.
|
||||
@@ -1,327 +0,0 @@
|
||||
PHP 7.4 INTERNALS UPGRADE NOTES
|
||||
|
||||
1. Internal API changes
|
||||
a. php_sys_symlink() and php_sys_link()
|
||||
b. zend_lookup_class_ex() and zend_fetch_class_by_name()
|
||||
c. Function/property/class flags
|
||||
d. Removed zend_check_private()
|
||||
e. php_win32_error_to_msg() memory management
|
||||
f. get_properties_for() handler / Z_OBJDEBUG_P
|
||||
g. Required object handlers
|
||||
h. Immutable classes and op_arrays
|
||||
i. php_fgetcsv() and php_fputcsv()
|
||||
j. Removed add_get_assoc_*() and add_get_index_*()
|
||||
k. Class declaration opcodes
|
||||
l. HASH_FLAG_INITIALIZED
|
||||
m. write_property return value
|
||||
n. Assignments to references
|
||||
o. ZEND_COMPILE_EXTENDED_INFO split
|
||||
p. ZEND_EXT_FCALL_BEGIN can access arguments
|
||||
q. ZEND_COMPILE_IGNORE_USER_FUNCTIONS and ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS
|
||||
r. TSRM environment locking
|
||||
s. Typed references support
|
||||
t. Exceptions thrown by string conversions.
|
||||
u. Removed uint and ulong typedefs
|
||||
v. Compound assignment opcodes
|
||||
w. APACHE symbol removed
|
||||
x. php_error_docref0() renamed to php_error_docref()
|
||||
y. Stream wrapper read/write ops
|
||||
|
||||
2. Build system changes
|
||||
a. Abstract
|
||||
b. Unix build system changes
|
||||
c. Windows build system changes
|
||||
|
||||
3. Module changes
|
||||
a. ext/xml
|
||||
b. ext/hash
|
||||
|
||||
========================
|
||||
1. Internal API changes
|
||||
========================
|
||||
|
||||
a. php_sys_symlink() and php_sys_link() portability macros have been
|
||||
added, which behave like POSIX's symlink() and link(), respectively, on
|
||||
POSIX compliant systems and on Windows.
|
||||
|
||||
b. zend_lookup_class_ex() and zend_fetch_class_by_name() prototypes were
|
||||
changed to accept optional lower-case class name as zend_string*,
|
||||
instead of zval*.
|
||||
|
||||
c. Function/property/class flags changes
|
||||
- ZEND_ACC_IMPLEMENTED_ABSTRACT is removed (it was used only internally
|
||||
during inheritance).
|
||||
- ZEND_ACC_IMPLICIT_PUBLIC is removed (it was used only for reflection)
|
||||
- ZEND_ACC_SHADOW property flag is removed. Instead of creating shadow
|
||||
clone, now we use the same private property_info, and should also
|
||||
check property_info->ce (in the same way as with methods).
|
||||
- ZEND_ACC_ANON_BOUND is replaced with ZEND_ACC_LINKED. This flag is set
|
||||
not only during anonymous classes declaration, but also during any
|
||||
run-time or compile-time class declaration.
|
||||
- ZEND_ACC_NO_RT_ARENA renamed into ZEND_ACC_HEAP_RT_CACHE. Now it's used
|
||||
not only for closures, but also for pseudo-main op_arrays.
|
||||
- ZEND_ACC_... flags are re-numbered.
|
||||
|
||||
d. zend_check_private() is removed. Use (func->common.scope == scope) instead.
|
||||
|
||||
e. Pointers returned by php_win32_error_to_msg() have to be freed using
|
||||
php_win32_error_msg_free(). Same regarding php_win_err() vs.
|
||||
php_win_err_free().
|
||||
|
||||
f. A new, optional object handler with the signature
|
||||
|
||||
HashTable *get_properties_for(zval *obj, zend_prop_purpose purpose)
|
||||
|
||||
has been introduced, where zend_prop_purpose (currently) takes one of:
|
||||
|
||||
ZEND_PROP_PURPOSE_DEBUG // var_dump etc.
|
||||
ZEND_PROP_PURPOSE_ARRAY_CAST // (array) $obj
|
||||
ZEND_PROP_PURPOSE_SERIALIZE // "O"-format serialization (__wakeup)
|
||||
ZEND_PROP_PURPOSE_VAR_EXPORT // var_export (__set_state)
|
||||
ZEND_PROP_PURPOSE_JSON // json_encode
|
||||
|
||||
The handler returns a non-null HashTable with increased refcounted, and
|
||||
the return value must be released using zend_release_properties().
|
||||
|
||||
This handler serves the same general function as get_properties(), but
|
||||
provides more control over different property uses, while also making
|
||||
it possible to return a temporary property table.
|
||||
|
||||
get_properties() is still used in cases where none of the above purposes
|
||||
apply, but overloading get_properties() is generally discouraged. If you
|
||||
want to provide purposes for general usage rather than just debugging or
|
||||
serialization, please prefer using properly declared properties.
|
||||
|
||||
get_debug_info() is superseded by get_properties_for() with the
|
||||
ZEND_PROP_PURPOSE_DEBUG purpose, but remains available for backwards-
|
||||
compatibility reasons. However, while it is fine to define this handler,
|
||||
it should never be directly called by consuming code.
|
||||
|
||||
The Z_OBJDEBUG_P macro has been removed. It should be replaced by calls to
|
||||
zend_get_properties_for() with the ZEND_PROP_PURPOSE_DEBUG purpose:
|
||||
|
||||
// OLD
|
||||
int is_temp;
|
||||
HashTable *ht = Z_OBJDEBUG_P(obj, is_temp);
|
||||
// ...
|
||||
if (is_temp) {
|
||||
zend_hash_destroy(ht);
|
||||
FREE_HASHTABLE(ht);
|
||||
}
|
||||
|
||||
// NEW
|
||||
HashTable *ht = zend_get_properties_for(obj, ZEND_PROP_PURPOSE_DEBUG);
|
||||
// ...
|
||||
zend_release_properties(ht);
|
||||
|
||||
g. The following object handlers are now required (must be non-NULL):
|
||||
|
||||
* free_obj
|
||||
* dtor_obj
|
||||
* read_property
|
||||
* write_property
|
||||
* read_dimension
|
||||
* write_dimension
|
||||
* get_property_ptr_ptr
|
||||
* has_property
|
||||
* unset_property
|
||||
* has_dimension
|
||||
* unset_dimension
|
||||
* get_properties
|
||||
* get_method
|
||||
* get_constructor
|
||||
* get_class_name
|
||||
* get_gc
|
||||
|
||||
It is recommended to initialize object handler structures by copying the
|
||||
std object handlers and only overwriting those you want to change.
|
||||
|
||||
h. Opcache may make classes and op_arrays immutable. Such classes are marked
|
||||
by ZEND_ACC_IMMUTABLE flag, they are not going to be copied from opcache
|
||||
shared memory to process memory and must not be modified at all.
|
||||
Few related data structures were changed to allow addressing mutable data
|
||||
structures from immutable ones. This access is implemented through
|
||||
ZEND_MAP_PTR... abstraction macros and, basically, uses additional level of
|
||||
indirection. op_array->run_time_cache, op_array->static_variables_ptr and
|
||||
class_entry->static_members_table now have to be accessed through
|
||||
ZEND_MAP_PTR... macros.
|
||||
It's also not allowed to change op_array->reserved[] handles of immutable
|
||||
op_arrays. Instead, now you have to reserve op_array handle using
|
||||
zend_get_op_array_extension_handle() during MINIT and access its value
|
||||
using ZEND_OP_ARRAY_EXTENSION(op_array, handle).
|
||||
|
||||
i. The type of the escape parameter of php_fgetcsv() and php_fputcsv() has
|
||||
been changed from char to int. This allows to pass the new constant macro
|
||||
PHP_CSV_NO_ESCAPE to this parameter, to disable PHP's proprietary escape
|
||||
mechanism.
|
||||
|
||||
j. add_get_assoc_*() and add_get_index_*() are removed. Use add_assoc*(),
|
||||
add_index*() or zend_hash_*() API functions instead.
|
||||
|
||||
k. Complex class declaration opcodes ZEND_ADD_INTERFACE, ZEND_ADD_TRAIT,
|
||||
ZEND_BIND_TRAITS and ZEND_VERIFY_ABSTRACT_CLASS were removed. Information
|
||||
about interfaces and traits is kept in zend_class_entry structure and
|
||||
actual linked performed by ZEND_DECLARE_...CLASS... opcode(s).
|
||||
Linked classes have ZEND_ACC_LINKED flag set.
|
||||
|
||||
l. HASH_FLAG_INITIALIZED was reverted into HASH_FLAG_UNINITIALIZED. Special
|
||||
HT_IS_INITIALIZED() and HT_INVALIDATE() macro were introduced to hide
|
||||
implementation details.
|
||||
|
||||
m. The write_property() object handler now returns the assigned value (after
|
||||
possible type coercions) rather than void. For extensions, it should
|
||||
usually be sufficient to return whatever was passed as the argument.
|
||||
|
||||
n. Assignments to references now need to ensure that they respect property
|
||||
types that affect the reference. This means that references should no
|
||||
longer be directly assigned to, and instead a set of specialized macros of
|
||||
the form ZEND_TRY_ASSIGN* needs to be used. You can find detailed porting
|
||||
instructions as well as a compatibility shim in the wiki:
|
||||
https://wiki.php.net/rfc/typed_properties_v2#assignments_to_references
|
||||
|
||||
o. ZEND_COMPILE_EXTENDED_INFO has been split into:
|
||||
ZEND_COMPILE_EXTENDED_FCALL and ZEND_COMPILE_EXTENDED_STMT
|
||||
This allows tooling to choose between profiling and debugging behaviour
|
||||
ZEND_COMPILE_EXTENDED_INFO remains and preserves behaviour.
|
||||
|
||||
p. ZEND_EXT_BEGIN_FCALL is emitted after arguments are sent, this means
|
||||
that handlers may access arguments.
|
||||
|
||||
q. ZEND_COMPILE_IGNORE_USER_FUNCTIONS and ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS
|
||||
are respected by zend_get_call_op such that when set, the only possible
|
||||
call opcodes are ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME, previously they
|
||||
were ignored by zend_get_call_op.
|
||||
|
||||
r. TSRM adds tsrm_env_lock() and tsrm_env_unlock() for ZTS:
|
||||
code that may change environ and may run concurrently with user code in ZTS
|
||||
is expected to use this exclusion API to maintain as much safety as
|
||||
reasonable. This results in "thread safe" getenv/putenv in Windows and
|
||||
Unix, however functions that may read the environment without exclusion
|
||||
still exist, for example:
|
||||
- setlocale
|
||||
- mktime
|
||||
- tzset
|
||||
The above is not an exhaustive list of such functions, while getenv/putenv
|
||||
will behave as if they are safe, care should still be taken in
|
||||
multi-threaded environments.
|
||||
|
||||
s. Correct support for typed properties requires the use of new macros to
|
||||
assign values to references. For more information see
|
||||
https://wiki.php.net/rfc/typed_properties_v2#impact_on_extensions.
|
||||
|
||||
t. convert_to_string() and zval_get_string() are now more likely to result in
|
||||
an exception. For instructions on how to gracefully handle this see
|
||||
https://wiki.php.net/rfc/tostring_exceptions#extension_guidelines.
|
||||
|
||||
u. The typedefs uint and ulong are no longer guaranteed to be available, and
|
||||
have to be replaced with standard types.
|
||||
|
||||
v. Compound assignment opcodes were changed. Instead of ZEND_ASSIGN_ADD (and
|
||||
others) with 0, ZEND_ASSIGN_DIM, ZEND_ASSIGN_OBJ or
|
||||
ZEND_ASSIGN_STATIC_PROP in extended value, now we use ZEND_ASSIGN_OP,
|
||||
ZEND_ASSIGN_DIM_OP, ZEND_ASSIGN_OBJ_OP and ZEND_ASSIGN_STATIC_PROP_OP with
|
||||
ZEND_ADD (or other) in extended_value.
|
||||
|
||||
w. APACHE symbol has been removed and is no longer defined.
|
||||
|
||||
x. php_error_docref0() has been removed and renamed to php_error_docref().
|
||||
|
||||
y. The read and write operations of php_stream_ops now return ssize_t, with
|
||||
negative values indicating an error.
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
||||
a. Abstract
|
||||
- The hash extension is now always available, meaning the --enable-hash
|
||||
configure argument has been removed.
|
||||
- The filter extension no longer exposes the --with-pcre-dir configure
|
||||
argument and therefore allows shared builds with ./configure for Unix
|
||||
builds.
|
||||
- Symbols HAVE_DATE, HAVE_REFLECTION, and HAVE_SPL have been removed. It
|
||||
should be considered to have these extensions always available.
|
||||
- Removed unused build time symbols: PHP_ADA_INCLUDE, PHP_ADA_LFLAGS,
|
||||
PHP_ADA_LIBS, PHP_APACHE_INCLUDE, PHP_APACHE_TARGET, PHP_FHTTPD_INCLUDE,
|
||||
PHP_FHTTPD_LIB, PHP_FHTTPD_TARGET, PHP_CFLAGS, PHP_DBASE_LIB,
|
||||
PHP_BUILD_DEBUG, PHP_GDBM_INCLUDE, PHP_IBASE_INCLUDE, PHP_IBASE_LFLAGS,
|
||||
PHP_IBASE_LIBS, PHP_IFX_INCLUDE, PHP_IFX_LFLAGS, PHP_IFX_LIBS,
|
||||
PHP_INSTALL_IT, PHP_IODBC_INCLUDE, PHP_IODBC_LFLAGS, PHP_IODBC_LIBS,
|
||||
PHP_MSQL_LFLAGS, PHP_MSQL_INCLUDE, PHP_MSQL_LFLAGS, PHP_MSQL_LIBS,
|
||||
PHP_MYSQL_INCLUDE, PHP_MYSQL_LIBS, PHP_MYSQL_TYPE, PHP_OCI8_SHARED_LIBADD,
|
||||
PHP_ORACLE_SHARED_LIBADD, PHP_ORACLE_DIR, PHP_ORACLE_VERSION,
|
||||
PHP_PGSQL_INCLUDE, PHP_PGSQL_LFLAGS, PHP_PGSQL_LIBS, PHP_SOLID_INCLUDE,
|
||||
PHP_SOLID_LIBS, PHP_EMPRESS_INCLUDE, PHP_EMPRESS_LIBS, PHP_SYBASE_INCLUDE,
|
||||
PHP_SYBASE_LFLAGS, PHP_SYBASE_LIBS, PHP_DBM_TYPE, PHP_DBM_LIB,
|
||||
PHP_LDAP_LFLAGS, PHP_LDAP_INCLUDE, PHP_LDAP_LIBS.
|
||||
- Removed unused symbols: HAVE_CURL_EASY_STRERROR, HAVE_CURL_MULTI_STRERROR,
|
||||
HAVE_MPIR, HAVE_MBSTR_CN, HAVE_MBSTR_JA, HAVE_MBSTR_KR, HAVE_MBSTR_RU,
|
||||
HAVE_MBSTR_TW.
|
||||
|
||||
b. Unix build system changes
|
||||
- Added --ini-path and --ini-dir options to php-config.
|
||||
- configure --help now also outputs --program-suffix and --program-prefix
|
||||
information by using the Autoconf AC_ARG_PROGRAM macro.
|
||||
- Obsolescent macros AC_FUNC_VPRINTF and AC_FUNC_UTIME_NULL have been
|
||||
removed. Symbols HAVE_VPRINTF and HAVE_UTIME_NULL are no longer defined
|
||||
since they are not needed on the current systems.
|
||||
- Local PHP m4 unused or obsolete macros have been removed:
|
||||
PHP_TARGET_RDYNAMIC, PHP_SOLARIS_PIC_WEIRDNESS, PHP_SYS_LFS,
|
||||
PHP_AC_BROKEN_SPRINTF, PHP_EXTENSION, PHP_DECLARED_TIMEZONE,
|
||||
PHP_CHECK_TYPES, PHP_CHECK_64BIT, PHP_READDIR_R_TYPE,
|
||||
PHP_SETUP_KERBEROS.
|
||||
- Local PHP_TM_GMTOFF m4 macro replaced with Autoconf's AC_CHECK_MEMBERS.
|
||||
The HAVE_TM_GMTOFF symbol is replaced with HAVE_STRUCT_TM_TM_GMTOFF and
|
||||
HAVE_TM_ZONE symbol is replaced with HAVE_STRUCT_TM_TM_ZONE.
|
||||
- new --enable-rtld-now build option allow to switch dlopen behavior
|
||||
from RTLD_LAZY to RTLD_NOW
|
||||
- Minimum Bison version is 3.0+ for generating parser files.
|
||||
- PHP_PROG_BISON macro now takes two optional arguments - minimum required
|
||||
version and excluded versions that aren't supported.
|
||||
- PHP_PROG_RE2C is not called in the generated configure.ac for extensions
|
||||
anymore and now takes one optional argument - minimum required version.
|
||||
- with-pcre-valgrind and with-valgrind are merged, and valgrind detected by
|
||||
pkgconfig
|
||||
- Removed unused AC_PROG_CC_C_O check and the NO_MINUS_C_MINUS_O symbol.
|
||||
- Obsolescant checks for headers and functions that are part of C89 have
|
||||
been removed. The following symbols are therefore no longer defined by the
|
||||
PHP build system at the configure step and shouldn't be used anymore:
|
||||
HAVE_SETLOCALE, HAVE_LOCALECONV, HAVE_STRSTR, HAVE_STRTOL, HAVE_STRBRK,
|
||||
HAVE_PERROR, HAVE_STRFTIME, HAVE_TZNAME, HAVE_STDARG_H, HAVE_STRING_H,
|
||||
HAVE_STDLIB_H, HAVE_SYS_VARARGS_H, HAVE_ASSERT_H, HAVE_SYS_DIR_H,
|
||||
TM_IN_SYS_TIME, HAVE_STRTOD, HAVE_STRCOLL, HAVE_ERRNO_H, HAVE_MEMCPY,
|
||||
HAVE_SNPRINTF, HAVE_STDIO_H, HAVE_STRPBRK, HAVE_TIME_H, HAVE_LIMITS_H,
|
||||
HAVE_STRTOUL, HAVE_SYS_NDIR_H, HAVE_SYS_TIMES_H, PHP_HAVE_STDINT_TYPES,
|
||||
HAVE_SIGNAL_H, HAVE_STRERROR.
|
||||
- Removed unused check for dev/arandom and the HAVE_DEV_ARANDOM symbol.
|
||||
- Remove unused functions checks: HAVE_MBSINIT, HAVE_MEMPCPY, HAVE_SETPGID,
|
||||
HAVE_STRPNCPY, HAVE_STRTOULL, HAVE_VSNPRINTF, HAVE_CUSERID, HAVE_LRAND48,
|
||||
HAVE_RANDOM, HAVE_SRAND48, HAVE_SRANDOM, HAVE_STRDUP, HAVE_GCVT,
|
||||
HAVE_ISASCII, HAVE_LINK, HAVE_LOCKF, HAVE_SOCKOPT, HAVE_SETVBUF, HAVE_SIN,
|
||||
HAVE_TEMPNAM.
|
||||
- Unused check for struct cmsghdr and symbol HAVE_CMSGHDR have been removed.
|
||||
- Unused ApplicationServices/ApplicationServices.h headers check and
|
||||
HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H symbol have been removed.
|
||||
- PHP_DEBUG_MACRO macro has been removed.
|
||||
- PHP_CHECK_CONFIGURE_OPTIONS macro has been removed. Default Autoconf's
|
||||
--enable-option-checking=fatal option can be used in the configure step
|
||||
to enable error when invalid options are used.
|
||||
- Removed unused check and symbols HAVE_SHM_MMAP_ZERO, HAVE_SHM_MMAP_FILE.
|
||||
- Removed unused check and symbol MISSING_MSGHDR_MSGFLAGS.
|
||||
|
||||
c. Windows build system changes
|
||||
|
||||
. Visual Studio 2019 is utilized for the Windows builds
|
||||
. Removed unused defined symbol HAVE_LIBBIND.
|
||||
|
||||
========================
|
||||
3. Module changes
|
||||
========================
|
||||
|
||||
a. ext/xml
|
||||
- The public (internal) API of the ext/xml extension has been removed. All
|
||||
functions and structures are private to the extension now.
|
||||
|
||||
b. ext/hash
|
||||
- The hash extension is now always available, allowing extensions to rely
|
||||
on its functionality to be available without compile time checks.
|
||||
+41998
File diff suppressed because it is too large.
Load diff
+12
-12
@@ -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.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
--------------------------------------------------------------------
|
||||
@@ -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
@@ -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) -p zend -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) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o $@
|
||||
|
||||
$(srcdir)/zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
|
||||
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
|
||||
|
||||
$(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(srcdir)/zend_language_parser.h
|
||||
|
||||
Zend/zend_execute.lo: $(srcdir)/zend_vm_execute.h $(srcdir)/zend_vm_opcodes.h
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
|
||||
```
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+602
@@ -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
|
||||
+266
-378
@@ -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,31 @@ _LT_AC_TRY_DLOPEN_SELF([
|
||||
], [])
|
||||
])
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(getpid kill finite sigsetjmp)
|
||||
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 )
|
||||
|
||||
AC_CHECK_DECLS([isfinite, isnan, isinf], [], [], [[#include <math.h>]])
|
||||
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_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>
|
||||
|
||||
int main()
|
||||
@@ -164,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)
|
||||
], [
|
||||
@@ -183,25 +137,47 @@ 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_ENABLE([maintainer-zts],
|
||||
[AS_HELP_STRING([--enable-maintainer-zts],
|
||||
[Enable thread safety - for code maintainers only!!])],
|
||||
[ZEND_MAINTAINER_ZTS=$enableval],
|
||||
[ZEND_MAINTAINER_ZTS=no])
|
||||
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([inline-optimization],
|
||||
[AS_HELP_STRING([--disable-inline-optimization],
|
||||
[If building zend_execute.lo fails, try this switch])],
|
||||
[ZEND_INLINE_OPTIMIZATION=$enableval],
|
||||
[ZEND_INLINE_OPTIMIZATION=yes])
|
||||
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_MAINTAINER_ZTS)
|
||||
@@ -212,23 +188,50 @@ 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="$CFLAGS -Wall -Wno-strict-aliasing"
|
||||
test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS"
|
||||
|
||||
if test "$ZEND_MAINTAINER_ZTS" = "yes"; then
|
||||
AC_DEFINE(ZTS,1,[ ])
|
||||
CFLAGS="$CFLAGS -DZTS"
|
||||
fi
|
||||
LIBZEND_CPLUSPLUS_CHECKS
|
||||
fi
|
||||
|
||||
changequote({,})
|
||||
if test -n "$GCC" && test "$ZEND_INLINE_OPTIMIZATION" != "yes"; then
|
||||
@@ -250,11 +253,11 @@ 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>
|
||||
|
||||
typedef union _mm_align_test {
|
||||
@@ -281,251 +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 if atof() accepts NAN.
|
||||
AC_CACHE_CHECK(whether atof() accepts NAN, ac_cv_atof_accept_nan,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISNAN
|
||||
#define zend_isnan(a) isnan(a)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
|
||||
#else
|
||||
#define zend_isnan(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return zend_isnan(atof("NAN")) ? 0 : 1;
|
||||
}
|
||||
]])],[
|
||||
ac_cv_atof_accept_nan=yes
|
||||
],[
|
||||
ac_cv_atof_accept_nan=no
|
||||
],[
|
||||
ac_cv_atof_accept_nan=no
|
||||
])])
|
||||
if test "$ac_cv_atof_accept_nan" = "yes"; then
|
||||
AC_DEFINE([HAVE_ATOF_ACCEPTS_NAN], 1, [whether atof() accepts NAN])
|
||||
fi
|
||||
|
||||
dnl Check if atof() accepts INF.
|
||||
AC_CACHE_CHECK(whether atof() accepts INF, ac_cv_atof_accept_inf,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISINF
|
||||
#define zend_isinf(a) isinf(a)
|
||||
#elif defined(INFINITY)
|
||||
/* Might not work, but is required by ISO C99 */
|
||||
#define zend_isinf(a) (((a)==INFINITY)?1:0)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
|
||||
#else
|
||||
#define zend_isinf(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return zend_isinf(atof("INF")) && zend_isinf(atof("-INF")) ? 0 : 1;
|
||||
}
|
||||
]])],[
|
||||
ac_cv_atof_accept_inf=yes
|
||||
],[
|
||||
ac_cv_atof_accept_inf=no
|
||||
],[
|
||||
ac_cv_atof_accept_inf=no
|
||||
])])
|
||||
if test "$ac_cv_atof_accept_inf" = "yes"; then
|
||||
AC_DEFINE([HAVE_ATOF_ACCEPTS_INF], 1, [whether atof() accepts INF])
|
||||
fi
|
||||
|
||||
dnl Check if HUGE_VAL == INF.
|
||||
AC_CACHE_CHECK(whether HUGE_VAL == INF, ac_cv_huge_val_inf,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISINF
|
||||
#define zend_isinf(a) isinf(a)
|
||||
#elif defined(INFINITY)
|
||||
/* Might not work, but is required by ISO C99 */
|
||||
#define zend_isinf(a) (((a)==INFINITY)?1:0)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
|
||||
#else
|
||||
#define zend_isinf(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return zend_isinf(HUGE_VAL) ? 0 : 1;
|
||||
}
|
||||
]])],[
|
||||
ac_cv_huge_val_inf=yes
|
||||
],[
|
||||
ac_cv_huge_val_inf=no
|
||||
],[
|
||||
ac_cv_huge_val_inf=yes
|
||||
])])
|
||||
dnl This is the most probable fallback so we assume yes in case of cross compile.
|
||||
if test "$ac_cv_huge_val_inf" = "yes"; then
|
||||
AC_DEFINE([HAVE_HUGE_VAL_INF], 1, [whether HUGE_VAL == INF])
|
||||
fi
|
||||
|
||||
dnl Check if HUGE_VAL + -HUGEVAL == NAN.
|
||||
AC_CACHE_CHECK(whether HUGE_VAL + -HUGEVAL == NAN, ac_cv_huge_val_nan,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_ISNAN
|
||||
#define zend_isnan(a) isnan(a)
|
||||
#elif defined(HAVE_FPCLASS)
|
||||
#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
|
||||
#else
|
||||
#define zend_isnan(a) 0
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#if defined(__sparc__) && !(__GNUC__ >= 3)
|
||||
/* prevent bug #27830 */
|
||||
return 1;
|
||||
#else
|
||||
return zend_isnan(HUGE_VAL + -HUGE_VAL) ? 0 : 1;
|
||||
#endif
|
||||
}
|
||||
]])],[
|
||||
ac_cv_huge_val_nan=yes
|
||||
],[
|
||||
ac_cv_huge_val_nan=no
|
||||
],[
|
||||
ac_cv_huge_val_nan=yes
|
||||
])])
|
||||
dnl This is the most probable fallback so we assume yes in case of cross compile.
|
||||
if test "$ac_cv_huge_val_nan" = "yes"; then
|
||||
AC_DEFINE([HAVE_HUGE_VAL_NAN], 1, [whether HUGE_VAL + -HUGEVAL == NAN])
|
||||
fi
|
||||
|
||||
dnl 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
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
*/
|
||||
@@ -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
@@ -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");
|
||||
?>
|
||||
@@ -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
@@ -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 20498 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user