Compare commits

...
Author SHA1 Message Date
SVN Migration acc93cfcc3 This commit was manufactured by cvs2svn to create tag
'BEFORE_HEAD_NS_CHANGE'.
2008-11-13 01:32:15 +00:00
10004 changed files with 0 additions and 2078213 deletions

No files matched your search

-570
View File
@@ -1,570 +0,0 @@
define ____executor_globals
if basic_functions_module.zts
set $tsrm_ls = ts_resource_ex(0, 0)
set $eg = ((zend_executor_globals) (*((void ***) $tsrm_ls))[executor_globals_id-1])
else
set $eg = executor_globals
end
end
document ____executor_globals
portable way of accessing executor_globals, set $eg
ZTS detection is automatically based on ext/standard module struct
end
define dump_bt
set $t = $arg0
while $t
printf "[0x%08x] ", $t
if $t->function_state.function->common.function_name
printf "%s() ", $t->function_state.function->common.function_name
else
printf "??? "
end
if $t->op_array != 0
printf "%s:%d ", $t->op_array->filename, $t->opline->lineno
end
set $t = $t->prev_execute_data
printf "\n"
end
end
document dump_bt
dumps the current execution stack. usage: dump_bt executor_globals.current_execute_data
end
define printztype
____printz_type $arg0
printf "\n"
end
document printztype
prints the type name of a zval type
end
define ____printz_type
set $type = $arg0
if $type == 0
printf "NULL"
end
if $type == 1
printf "long"
end
if $type == 2
printf "double"
end
if $type == 3
printf "bool"
end
if $type == 4
printf "array"
end
if $type == 5
printf "object"
end
if $type == 6
printf "string"
end
if $type == 7
printf "resource"
end
if $type == 8
printf "constant"
end
if $type == 9
printf "const_array"
end
if $type == 10
printf "unicode string"
end
if $type > 10
printf "unknown type %d", $type
end
end
define printzv
set $ind = 1
____printzv $arg0 0
end
document printzv
prints zval contents
end
define printu
set $str = (UChar*)$arg0
if $arg1 > 0
set $max = $arg1
else
set $max = 1024
end
set $pos = 0
while $pos < $max && *(char*)(($str+$pos))
if $str[$pos] < 256
printf "%c", $str[$pos]
else
printf "\\u%04X", $str[$pos]
end
set $pos = $pos + 1
end
if $pos < $max && *((char*)($str+$pos))
printf "[...]"
end
end
document printu
prints a unicode string, optionally with given length
usage: printu str [len]
The function stops at the first zero byte (not char) or when len is reached.
If len is less than or equal to one then a maximum of 1024 characters are
printed.
end
define printt
if $arg0
printu $arg1 $arg2
else
set $len = strlen($arg1)
if $arg2 > 0 && $len > $arg2
set $copy = strdup($arg1)
printf "%p: %s\n", $copy, $copy
set ((char*)$copy)[$arg2] = 0
printf "%s[...]", $copy
call free($copy)
else
printf "%s", $arg1
end
end
end
document printt
prints a binary or unicode string, optionally with given length
usage: printt unicode str [len]
If unicode is 1 the function calls printu, else it uses printf.
end
define ____printzv_contents
set $zvalue = $arg0
set $type = $zvalue->type
printf "(refcount=%d", $zvalue->refcount__gc
if $zvalue->is_ref__gc
printf ",is_ref"
end
printf ") "
if $type == 0
printf "NULL"
end
____printz_type $type
if $type == 1
printf ": %ld", $zvalue->value.lval
end
if $type == 2
printf ": %lf", $zvalue->value.dval
end
if $type == 3
if $zvalue->value.lval
printf ": true"
else
printf ": false"
end
end
if $type == 4
printf "(%d): ", $zvalue->value.ht->nNumOfElements
if ! $arg1
printf "{\n"
set $ind = $ind + 1
____print_ht $zvalue->value.ht 0 1
set $ind = $ind - 1
set $i = $ind
while $i > 0
printf " "
set $i = $i - 1
end
printf "}"
end
set $type = 0
end
if $type == 5
____executor_globals
set $handle = $zvalue->value.obj.handle
set $handlers = $zvalue->value.obj.handlers
if basic_functions_module.zts
set $zobj = zend_objects_get_address($zvalue, $tsrm_ls)
else
set $zobj = zend_objects_get_address($zvalue)
end
if $handlers->get_class_entry == &zend_std_object_get_class
set $cname = $zobj->ce.name.s
else
set $cname = "Unknown"
end
printf "(%s) #%d", $cname, $handle
if ! $arg1
if $handlers->get_properties == &zend_std_get_properties
set $ht = $zobj->properties
if $ht
printf "(%d): ", $ht->nNumOfElements
printf "{\n"
set $ind = $ind + 1
____print_ht $ht 1 1
set $ind = $ind - 1
set $i = $ind
while $i > 0
printf " "
set $i = $i - 1
end
printf "}"
else
echo "no properties found"
end
end
end
set $type = 0
end
if $type == 6
printf "(%d): \"%s\"", $zvalue->value.str.len, $zvalue->value.str.val
end
if $type == 7
printf ": #%d", $zvalue->value.lval
end
if $type == 8
end
if $type == 9
end
if $type == 10
printf "(%d): [%p]: \"", $zvalue->value.str.len, $zvalue->value.str.val
printu $zvalue->value.ustr.val $zvalue->value.str.len
end
if $type > 10
end
printf "\n"
end
define ____printzv
____executor_globals
set $zvalue = $arg0
printf "[0x%08x] ", $zvalue
if $zvalue == $eg.uninitialized_zval_ptr
printf "*uninitialized* "
end
set $zcontents = (zval*) $zvalue
if $arg1
____printzv_contents $zcontents $arg1
else
____printzv_contents $zcontents 0
end
end
define ____print_const_table
set $ht = $arg0
set $p = $ht->pListHead
while $p != 0
set $const = (zend_constant *) $p->pData
set $i = $ind
while $i > 0
printf " "
set $i = $i - 1
end
if $p->nKeyLength > 0
printf "\"%s\" => ", $p->key.arKey.s
else
printf "%d => ", $p->h
end
____printzv_contents &$const->value 0
set $p = $p->pListNext
end
end
define print_const_table
set $ind = 1
printf "[0x%08x] {\n", $arg0
____print_const_table $arg0
printf "}\n"
end
define ____print_ht
set $ht = $arg0
set $obj = $arg1
set $p = $ht->pListHead
set $unicode = $ht->unicode
while $p != 0
set $i = $ind
while $i > 0
printf " "
set $i = $i - 1
end
if $p->nKeyLength > 0
if $obj && $p->key.arKey.s[0] == 0
if $p->key.arKey.s[1] == '*'
printf "\"protected %s\" => ", $p->key.arKey.s+3
else
set $n = 1
while $n < $p->nKeyLength && $p->key.arKey.s[$n] != 0
set $n = $n + 1
end
printf "\"private %s::%s\" => ", $p->key.arKey.s+1, $p->key.arKey.s+$n+1
end
else
printf "\""
printt $unicode $p->key.arKey.v $p->nKeyLength
printf "\" => "
end
else
printf "%d => ", $p->h
end
if $arg1 == 0
printf "%p\n", (void*)$p->pData
end
if $arg1 == 1
set $zval = *(zval **)$p->pData
____printzv $zval 1
end
if $arg1 == 2
printf "%s\n", (char*)$p->pData
end
set $p = $p->pListNext
end
end
define print_ht
set $ind = 1
printf "[0x%08x] (%d) {\n", $arg0, $arg0->nNumOfElements
____print_ht $arg0 0 1
printf "}\n"
end
document print_ht
dumps elements of HashTable made of zval
end
define print_htptr
set $ind = 1
printf "[0x%08x] (%d) {\n", $arg0, $arg0->nNumOfElements
____print_ht $arg0 0 0
printf "}\n"
end
document print_htptr
dumps elements of HashTable made of pointers
end
define print_htstr
set $ind = 1
printf "[0x%08x] (%d) {\n", $arg0, $arg0->nNumOfElements
____print_ht $arg0 0 2
printf "}\n"
end
document print_htstr
dumps elements of HashTable made of strings
end
define ____print_ft
set $ht = $arg0
set $p = $ht->pListHead
set $unicode = $ht->unicode
while $p != 0
set $func = (zend_function*)$p->pData
set $i = $ind
while $i > 0
printf " "
set $i = $i - 1
end
if $p->nKeyLength > 0
printf "\""
printt $unicode $p->key.arKey.u $p->nKeyLength
printf "\" => "
else
printf "%d => ", $p->h
end
printf "[%p]: ", $func
if $func->common.fn_flags & 0x01
printf "static "
end
if $func->common.fn_flags & 0x02
printf "abstract "
end
if $func->common.fn_flags & 0x04
printf "final "
end
set $visibility = zend_visibility_string($func->common.fn_flags)
printf "%s", $visibility
if *$visibility
printf " "
end
if $func->common.return_reference
printf "& "
end
printt $unicode $func->common.function_name.s 0
printf "()\n"
set $p = $p->pListNext
end
end
define print_ft
set $ind = 1
printf "[0x%08x] (%d) {\n", $arg0, $arg0->nNumOfElements
____print_ft $arg0
printf "}\n"
end
document print_ft
dumps a function table (HashTable)
end
define printzn
____executor_globals
set $ind = 0
set $znode = $arg0
if $znode->op_type == 1
set $optype = "IS_CONST"
end
if $znode->op_type == 2
set $optype = "IS_TMP_VAR"
end
if $znode->op_type == 4
set $optype = "IS_VAR"
end
if $znode->op_type == 8
set $optype = "IS_UNUSED"
end
printf "[0x%08x] %s", $znode, $optype
if $znode->op_type == 1
printf ": "
____printzv &$znode->u.constant 0
end
if $znode->op_type == 2
printf ": "
set $tvar = (union _temp_variable *)((char *)$eg.current_execute_data->Ts + $znode->u.var)
____printzv ((union _temp_variable *)$tvar)->tmp_var 0
end
if $znode->op_type == 4
printf ": "
set $tvar = (union _temp_variable *)((char *)$eg.current_execute_data->Ts + $znode->u.var)
____printzv *$tvar->var.ptr_ptr 0
end
if $znode->op_type == 8
printf "\n"
end
end
document printzn
print type and content of znode.
usage: printzn &opline->op1
end
define printzops
printf "op1 => "
printzn &execute_data->opline.op1
printf "op2 => "
printzn &execute_data->opline.op2
printf "result => "
printzn &execute_data->opline.result
end
document printzops
dump operands of the current opline
end
define zbacktrace
____executor_globals
dump_bt $eg.current_execute_data
end
document zbacktrace
prints backtrace.
This command is almost a short cut for
> (gdb) ____executor_globals
> (gdb) dump_bt $eg.current_execute_data
end
define zmemcheck
set $p = alloc_globals.head
set $stat = "?"
set $total_size = 0
if $arg0 != 0
set $not_found = 1
else
set $not_found = 0
end
printf " block size status file:line\n"
printf "-------------------------------------------------------------------------------\n"
while $p
set $aptr = $p + sizeof(struct _zend_mem_header) + sizeof(align_test)
if $arg0 == 0 || (void *)$aptr == (void *)$arg0
if $p->magic == 0x7312f8dc
set $stat = "OK"
end
if $p->magic == 0x99954317
set $stat = "FREED"
end
if $p->magic == 0xfb8277dc
set $stat = "CACHED"
end
set $filename = strrchr($p->filename, '/')
if !$filename
set $filename = $p->filename
else
set $filename = $filename + 1
end
printf " 0x%08x ", $aptr
if $p->size == sizeof(struct _zval_struct) && ((struct _zval_struct *)$aptr)->type >= 0 && ((struct _zval_struct *)$aptr)->type < 10
printf "ZVAL?(%-2d) ", $p->size
else
printf "%-9d ", $p->size
end
set $total_size = $total_size + $p->size
printf "%-06s %s:%d", $stat, $filename, $p->lineno
if $p->orig_filename
set $orig_filename = strrchr($p->orig_filename, '/')
if !$orig_filename
set $orig_filename = $p->orig_filename
else
set $orig_filename = $orig_filename + 1
end
printf " <= %s:%d\n", $orig_filename, $p->orig_lineno
else
printf "\n"
end
if $arg0 != 0
set $p = 0
set $not_found = 0
else
set $p = $p->pNext
end
else
set $p = $p->pNext
end
end
if $not_found
printf "no such block that begins at 0x%08x.\n", $aptr
end
if $arg0 == 0
printf "-------------------------------------------------------------------------------\n"
printf " total: %d bytes\n", $total_size
end
end
document zmemcheck
show status of a memory block.
usage: zmemcheck [ptr].
if ptr is 0, all blocks will be listed.
end
-277
View File
@@ -1,277 +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 (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 "<cvs username here>_0". For example, #if FOO_0, where FOO is your
cvs 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 CVS 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.
-2
View File
@@ -1,2 +0,0 @@
For the list of people who've put work into PHP, please see
http://www.php.net/credits.php
-119060
View File
File diff suppressed because it is too large. Load diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-553
View File
@@ -1,553 +0,0 @@
List of PHP maintainers
=======================
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.
Orphan: No current maintainer [but maybe you could take the
role as you write your new code].
Obsolete: Old code. Something tagged obsolete generally means
it has been replaced by a better system and you
should be using that.
Unknown: Not known at this time.
Status legend
-------------
Working: Working under both Windows and Unix.
Windows: Working only under Windows.
Unix: Working only under Unix.
Experimental: Under development or initial release.
Not Working: Not working.
Unknown: Status unknown.
== 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
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: isapi
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: litespeed
PRIMARY MAINTAINER: George Wang <gwang@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
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
-------------------------------------------------------------------------------
== Database extensions ==
-------------------------------------------------------------------------------
EXTENSION: dba
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: dbase
MAINTENANCE: Orphaned
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: fbsql
PRIMARY MAINTAINER: Frank M. Kromann <fmk@swwwing.com>
MAINTENANCE: Unknown
STATUS: Unknown
-------------------------------------------------------------------------------
EXTENSION: interbase
PRIMARY MAINTAINER: Ard Biesheuvel <ard@ard.nu>, Jouni Ahto <jouni.ahto@exdec.fi>
MAINTENANCE: Odd fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: msql
MAINTENANCE: Unknown
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>, 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: 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>, Antony Dovgal <tony2001@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: odbc
PRIMARY MAINTAINER: Daniel R. Kalowsky <kalowsky@php.net>
MAINTENANCE: Maintained
STATUS: Working
COMMENT: Working
-------------------------------------------------------------------------------
EXTENSION: pdo
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_dblib
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_firebird
PRIMARY MAINTAINER: Lars Westermann <lwe@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_mysql
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
-------------------------------------------------------------------------------
EXTENSION: pdo_odbc
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_oci
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_pgsql
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net>
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pdo_sqlite
PRIMARY MAINTAINER: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.1
-------------------------------------------------------------------------------
EXTENSION: pgsql
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>
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>, Rob Richards <rrichards@php.net>, Marcus Boerger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: simplexml
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: soap
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>, Rob Richards <rrichards@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: libxml
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>, Christian Stocker <chregu@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: xmlrpc
PRIMARY MAINTAINER: Dan Libby
MAINTENANCE: Orphaned
STATUS: Experimental
-------------------------------------------------------------------------------
EXTENSION: xmlwriter
PRIMARY MAINTAINER: Rob Richards <rrichards@php.net>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: xsl
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net>, Rob Richards <rrichards@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0
-------------------------------------------------------------------------------
== Other extensions ==
-------------------------------------------------------------------------------
EXTENSION: bcmath
MAINTENANCE: Andi Gutmans <andi@zend.com>
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: bz2
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>
MAINTENANCE: Odd Fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: com_dotnet
PRIMARY MAINTAINER: Wez Furlong <wez@php.net>
MAINTENANCE: Maintained
STATUS: Windows
SINCE: 5.0
-------------------------------------------------------------------------------
EXTENSION: ctype
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: curl
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>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: exif
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.2
-------------------------------------------------------------------------------
EXTENSION: fileinfo
PRIMARY MAINTAINER: Derick Rethans <derick@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: filter
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: Stefan Esser <sesser@php.net>
MAINTENANCE: Odd fixes
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: gd
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: gettext
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: gmp
PRIMARY MAINTAINER: Stanislav Malyshev <stas@php.net>, Antony Dovgal <tony2001@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.4
-------------------------------------------------------------------------------
EXTENSION: iconv
PRIMARY MAINTAINER: Moriyoshi Koizumi <moriyoshi@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: imap
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: Unknown
MAINTENANCE: Odd fixes
STATUS: Working
SINCE: 5.2
-------------------------------------------------------------------------------
EXTENSION: ldap
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>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: mcrypt
PRIMARY MAINTAINER: Derick Rethans <derick@derickrethans.nl>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
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>, Pierre-Alain Joye <pajoye@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.4
-------------------------------------------------------------------------------
EXTENSION: pcntl
PRIMARY MAINTAINER: Arnaud Le Blanc <lbarnaud@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: pcre
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>, Marcus Börger <helly@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.3
-------------------------------------------------------------------------------
EXTENSION: posix
PRIMARY MAINTAINER: Kristian Köhntopp <kris@koehntopp.de>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: pspell
PRIMARY MAINTAINER: Vlad Krupin <phpdevel@echospace.com>
MAINTENANCE: Unknown
STATUS: Working
SINCE: 4.0.2
-------------------------------------------------------------------------------
EXTENSION: readline
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>, Johannes Schlüter <johannes@php.net>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: session
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>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.3
-------------------------------------------------------------------------------
EXTENSION: snmp
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>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 4.0.2
-------------------------------------------------------------------------------
EXTENSION: spl
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Etienne Kneuss <colder@php.net>
MAINTENANCE: Maintained
STATUS: Working
SINCE: 5.0.0
-------------------------------------------------------------------------------
EXTENSION: sysvmsg
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: sysvsem
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: sysvshm
MAINTENANCE: Unknown
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: tidy
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>
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>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: zlib
PRIMARY MAINTAINER: Stefan Roehrich <sr@linux.de>
MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
-1540
View File
File diff suppressed because it is too large. Load diff
-68
View File
@@ -1,68 +0,0 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2006 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
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.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"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
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 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
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,
please see <http://www.php.net>.
PHP includes the Zend Engine, freely available at
<http://www.zend.com>.
-23
View File
@@ -1,23 +0,0 @@
#
# Zend
#
$(builddir)/zend_language_scanner.lo: $(srcdir)/zend_language_parser.h
$(builddir)/zend_ini_scanner.lo: $(srcdir)/zend_ini_parser.h
$(srcdir)/zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l)
$(srcdir)/zend_language_parser.h: $(srcdir)/zend_language_parser.c
$(srcdir)/zend_language_parser.c: $(srcdir)/zend_language_parser.y
@$(YACC) -p zend -v -d $(srcdir)/zend_language_parser.y -o $@
$(srcdir)/zend_ini_parser.h: $(srcdir)/zend_ini_parser.c
$(srcdir)/zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
@$(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o $@
$(srcdir)/zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
$(builddir)/zend_indent.lo $(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(srcdir)/zend_language_parser.h
-79
View File
@@ -1,79 +0,0 @@
#
# 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/date/lib 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/
-123
View File
@@ -1,123 +0,0 @@
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`
test: all
-@if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \
TEST_PHP_EXECUTABLE=$(PHP_EXECUTABLE) \
TEST_PHP_SRCDIR=$(top_srcdir) \
CC="$(CC)" \
$(PHP_EXECUTABLE) $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -d extension_dir=modules/ $(PHP_TEST_SHARED_EXTENSIONS) tests/; \
elif test ! -z "$(SAPI_CLI_PATH)" && test -x "$(SAPI_CLI_PATH)"; then \
INI_FILE=`$(top_builddir)/$(SAPI_CLI_PATH) -d 'display_errors=stderr' -r 'echo php_ini_loaded_file();' 2> /dev/null`; \
if test "$$INI_FILE"; then \
$(EGREP) -v '^(zend_)?extension(_debug)?(_ts)?[\t\ ]*=' "$$INI_FILE" > $(top_builddir)/tmp-php.ini; \
else \
echo > $(top_builddir)/tmp-php.ini; \
fi; \
INI_SCANNED_PATH=`$(top_builddir)/$(SAPI_CLI_PATH) -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 '^(zend_)?extension(_debug)?(_ts)?[\t\ ]*=' "$$INI_SCANNED_PATH"/*.ini >> $(top_builddir)/tmp-php.ini; \
fi; \
TEST_PHP_EXECUTABLE=$(top_builddir)/$(SAPI_CLI_PATH) \
TEST_PHP_SRCDIR=$(top_srcdir) \
CC="$(CC)" \
$(top_builddir)/$(SAPI_CLI_PATH) -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 config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h stamp-h php5.spec sapi/apache/libphp$(PHP_MAJOR_VERSION).module buildmk.stamp
$(EGREP) define'.*include/php' $(top_srcdir)/configure | $(SED) 's/.*>//'|xargs rm -f
find . -name Makefile | xargs rm -f
.PHONY: all clean install distclean test
.NOEXPORT:
-53
View File
@@ -1,53 +0,0 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 20??, PHP 6.0
- Unicode support. (Andrei, Dmitry, et al)
- Changed dl() to be disabled by default. Enabled only when explicitly
registered by the SAPI layer. Enabled only with CLI, CGI and EMBED. (Dmitry)
- Changed opendir/dir/scandir to use default context
when no context argument is passed. (Sara)
- Changed open_basedir to allow tightening in runtime contexts. (Sara)
- Changed allow_url_fopen/allow_url_include to allow
per-wrapper enable/disable and runtime tightening. (Sara)
- Removed undocumented and incomplete support for strings in list() operator.
(Dmitry)
- Removed old legacy:
. "register_globals" support. (Pierre)
. "register_long_arrays" ini option. (Dmitry)
. "safe_mode" support. (Ilia, Andi)
. "allow_call_time_pass_reference", added E_STRICT error message. (Dmitry)
. session_register(), session_unregister() and session_is_registered()
(needed only with "register_globals=On").
. "magic_quotes_gpc", "magic_quotes_runtime" and "magic_quotes_sybase" ini
options. (Pierre)
. Changed get_magic_quotes_gpc(), get_magic_quotes_runtime to always return
false and set_magic_quotes_runtime() to raise an E_CORE_ERROR.
. "define_syslog_variables" ini option and define_syslog_variables()
(Kalle)
- Removed support for "continue" and "break" operators with non-constant
operands. (Dmitry)
- Removed Freetype 1.x and GD 1.x support from GD extension. (Pierre)
- Moved extensions to PECL:
. ext/ncurses (Hartmut)
- Improved ext/zlib; re-implemented non-file related functionality. (Mike)
- Improved output layer; see README.NEW-OUTPUT-API for internals. (Mike)
- Improved ext/mhash: (Mike)
. Added keygen constants.
. Added new functions: mhash_keygen_count, mhash_get_keygen_name,
mhash_keygen_uses_hash, mhash_keygen_uses_salt, mhash_get_keygen_salt_size,
mhash_keygen.
- Added runtime JIT auto-globals fetching and caching. (Dmitry, Sara)
- Added E_STRICT to E_ALL. (Dmitry)
- Added streams features:
. Second optional parameter to stream_context_create() to
set params during context creation. (Sara)
. "context" and "binary_pipes" params in "other_options" arg. (Sara)
. stream_resolve_include_path(). (Sara)
- Added shm_has_var() function. (Mike)
- Fixed bug #40325 (Vary: header missing in gzip output handlers). (Mike)
-146
View File
@@ -1,146 +0,0 @@
====================
CVS Commit Rules
====================
This is the first file you should be reading after you get your CVS account.
We'll assume you're basically familiar with CVS, but feel free to post
your questions on the mailing list. Please have a look at
http://cvsbook.red-bean.com/ for more detailed information on CVS.
PHP is developed through the efforts of a large number of people.
Collaboration is a Good Thing(tm), and CVS lets us do this. Thus, following
some basic rules with regards to CVS usage will::
a. Make everybody happier, especially those responsible for maintaining
the CVS 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::
HEAD Will become PHP 6.0. This CVS branch is for active development.
PHP_5_3 Is used to release the PHP 5.3.x series. It still allows for
larger enhancements.
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).
PHP_5_1 This branch is closed.
PHP_4_4 This branch is closed.
The next few rules are more of a technical nature::
1. All changes should first go to HEAD and then get merged from HEAD
(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 CVS 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 CVS 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
-39
View File
@@ -1,39 +0,0 @@
Between PHP 4.0.6 and 4.1.0, the Zend module struct changed in a way
that broke both source and binary compatibility. If you are
maintaining a third party extension, here's how to update it:
If this was your old module entry:
zend_module_entry foo_module_entry = {
"foo", /* extension name */
foo_functions, /* extension function list */
NULL, /* extension-wide startup function */
NULL, /* extension-wide shutdown function */
PHP_RINIT(foo), /* per-request startup function */
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
PHP_MINFO(foo), /* information function */
STANDARD_MODULE_PROPERTIES
};
Here's how it should look if you want your code to build with PHP
4.1.0 and up:
zend_module_entry foo_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"foo", /* extension name */
foo_functions, /* extension function list */
NULL, /* extension-wide startup function */
NULL, /* extension-wide shutdown function */
PHP_RINIT(foo), /* per-request startup function */
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
PHP_MINFO(foo), /* information function */
#if ZEND_MODULE_API_NO >= 20010901
FOO_VERSION, /* extension version number (string) */
#endif
STANDARD_MODULE_PROPERTIES
};
If you don't care about source compatibility with earlier PHP releases
than 4.1.0, you can drop the #if/#endif lines.
-194
View File
@@ -1,194 +0,0 @@
(NOTE: you may also want to take a look at the pear package
PECL_Gen, a PHP-only alternative for this script that
supports way more extension writing tasks and is
supposed to replace ext_skel completely in the long run ...)
WHAT IT IS
It's a tool for automatically creating the basic framework for a PHP module
and writing C code handling arguments passed to your functions from a simple
configuration file. See an example at the end of this file.
HOW TO USE IT
Very simple. First, change to the ext/ directory of the PHP 4 sources. If
you just need the basic framework and will be writing all the code in your
functions yourself, you can now do
./ext_skel --extname=module_name
and everything you need is placed in directory module_name.
[ Note that GNU awk is likely required for this script to work. Debian
systems seem to default to using mawk, so you may need to change the
#! line in skeleton/create_stubs and the cat $proto | awk line in
ext_skel to use gawk explicitly. ]
If you don't need to test the existence of any external header files,
libraries or functions in them, the module is already almost ready to be
compiled in PHP. Just remove 3 comments in your_module_name/config.m4,
change back up to PHP sources top directory, and do
./buildconf; ./configure --enable-module_name; make
But if you already have planned the overall scheme of your module, what
functions it will contain, their return types and the arguments they take
(a very good idea) and don't want to bother yourself with creating function
definitions and handling arguments passed yourself, it's time to create a
function definitions file, which you will give as an argument to ext_skel
with option
--proto=filename.
FORMAT OF FUNCTION DEFINITIONS FILE
All the definitions must be on one line. In it's simplest form, it's just
the function name, e.g.
my_function
but then you'll be left with an almost empty function body without any
argument handling.
Arguments are given in parenthesis after the function name, and are of
the form 'argument_type argument_name'. Arguments are separated from each
other with a comma and optional space. Argument_type can be one of int,
bool, double, float, string, array, object or mixed.
An optional argument is separated from the previous by an optional space,
then '[' and of course comma and optional space, like all the other
arguments. You should close a row of optional arguments with same amount of
']'s as there where '['s. Currently, it does not harm if you forget to do it
or there is a wrong amount of ']'s, but this may change in the future.
An additional short description may be added after the parameters.
If present it will be filled into the 'proto' header comments in the stubs
code and the <refpurpose> tag in the XML documentation.
An example:
my_function(int arg1, int arg2 [, int arg3 [, int arg4]]) this is my 1st
Arguments arg3 and arg4 are optional.
If possible, the function definition should also contain it's return type
in front of the definition. It's not actually used for any C code generating
purposes but PHP in-source documentation instead, and as such, very useful.
It can be any of int, double, string, bool, array, object, resource, mixed
or void.
The file must contain nothing else but function definitions, no comments or
empty lines.
OTHER OPTIONS
--no-help
By default, ext_skel creates both comments in the source code and a test
function to help first time module writers to get started and testing
configuring and compiling their module. This option turns off all such things
which may just annoy experienced PHP module coders. Especially useful with
--stubs=file
which will leave out also all module specific stuff and write just function
stubs with function value declarations and passed argument handling, and
function entries and definitions at the end of the file, for copying and
pasting into an already existing module.
--assign-params
--string-lens
By default, function proto 'void foo(string bar)' creates the following:
...
zval **bar;
... (zend_get_parameters_ex() called in the middle...)
convert_to_string_ex(bar);
Specifying both of these options changes the generated code to:
...
zval **bar_arg;
int bar_len;
char *bar = NULL;
... (zend_get_parameters_ex() called in the middle...)
convert_to_string_ex(bar_arg);
bar = Z_STRVAL_PP(bar_arg);
bar_len = Z_STRLEN_PP(bar_arg);
You shouldn't have to ask what happens if you leave --string-lens out. If you
have to, it's questionable whether you should be reading this document.
--with-xml[=file]
Creates the basics for phpdoc .xml file.
--full-xml
Not implemented yet. When or if there will ever be created a framework for
self-contained extensions to use phpdoc system for their documentation, this
option enables it on the created xml file.
CURRENT LIMITATIONS, BUGS AND OTHER ODDITIES
Only arguments of types int, bool, double, float, string and array are
handled. For other types you must write the code yourself. And for type
mixed, it wouldn't even be possible to write anything, because only you
know what to expect.
It can't handle correctly, and probably never will, variable list of
of arguments. (void foo(int bar [, ...])
Don't trust the generated code too much. It tries to be useful in most of
the situations you might encounter, but automatic code generation will never
beat a programmer who knows the real situation at hand. ext_skel is generally
best suited for quickly generating a wrapper for c-library functions you
might want to have available in PHP too.
This program doesn't have a --help option. It has --no-help instead.
EXAMPLE
The following _one_ line
bool my_drawtext(resource image, string text, resource font, int x, int y [, int color])
will create this function definition for you (note that there are a few
question marks to be replaced by you, and you must of course add your own
value definitions too):
/* {{{ proto bool my_drawtext(resource image, string text, resource font, int x, int y[, int color])
*/
PHP_FUNCTION(my_drawtext)
{
zval **image, **text, **font, **x, **y, **color;
int argc;
int image_id = -1;
int font_id = -1;
argc = ZEND_NUM_ARGS();
if (argc < 5 || argc > 6 || zend_get_parameters_ex(argc, &image, &text, &font, &x, &y, &color) == FAILURE) {
WRONG_PARAM_COUNT;
}
ZEND_FETCH_RESOURCE(???, ???, image, image_id, "???", ???_rsrc_id);
ZEND_FETCH_RESOURCE(???, ???, font, font_id, "???", ???_rsrc_id);
switch (argc) {
case 6:
convert_to_long_ex(color);
/* Fall-through. */
case 5:
convert_to_long_ex(y);
convert_to_long_ex(x);
/* font: fetching resources already handled. */
convert_to_string_ex(text);
/* image: fetching resources already handled. */
break;
default:
WRONG_PARAM_COUNT;
}
php_error(E_WARNING, "my_drawtext: not yet implemented");
}
/* }}} */
-79
View File
@@ -1,79 +0,0 @@
====================
Mailinglist Rules
====================
This is the first file you should be reading before doing any posts on PHP
mailinglists. Following these rules is considered imperative to the success of
the PHP project. Therefore expect your contributions to be of much less positive
impact if you do not follow these rules. More importantly you can actually
assume that not following these rules will hurt the PHP project.
PHP is developed through the efforts of a large number of people.
Collaboration is a Good Thing(tm), and mailinglists lets us do this. Thus,
following some basic rules with regards to mailinglist usage will:
a. Make everybody happier, especially those responsible for developing PHP
itself.
b. Help in making sure we all use our time more efficiently.
c. Prevent you from making a fool of yourself in public.
d. Increase the general level of good will on planet Earth.
Having said that, here are the organizational rules:
1. Respect other people working on the project.
2. Do not post when you are angry. Any post can wait a few hours. Review
your post after a good breather or a good nights sleep.
3. Make sure you pick the right mailinglist for your posting. Please review
the descriptions on the mailinglist overview page
(http://www.php.net/mailing-lists.php). When in doubt ask a friend or
someone you trust on IRC.
4. Make sure you know what you are talking about. PHP is a very large project
that strives to be very open. The flip side is that the core developers
are faced with a lot of requests. Make sure that you have done your
research before posting to the entire developer community.
5. Patches have a much greater chance of acceptance than just asking the
PHP developers to implement a feature for you. For one it makes the
discussion more concrete and it shows that the poster put thought and time
into the request.
6. If you are posting to an existing thread, make sure that you know what
previous posters have said. This is even more important the longer the
thread is already.
7. Please configure your email client to use a real name and keep message
signatures to a maximum of 2 lines if at all necessary.
The next few rules are more some general hints:
1. If you notice that your posting ratio is much higher than that of other
people, double check the above rules. Try to wait a bit longer before
sending your replies to give other people more time to digest your answers
and more importantly give you the opportunity to make sure that you
aggregate your current position into a single mail instead of multiple
ones.
2. Consider taking a step back from a very active thread now and then. Maybe
talking to some friends and fellow developers will help in understanding
the other opinions better.
3. Do not top post. Place your answer underneath anyone you wish to quote
and remove any previous comment that is not relevant to your post.
4. Do not high-jack threads, by bringing up entirely new topics. Please
create an entirely new thread copying anything you wish to quote into the
new thread.
Finally, additional hints on how to behave inside the virtual community can be
found in RFC 1855 (http://www.faqs.org/rfcs/rfc1855.html).
Happy hacking,
PHP Team
-142
View File
@@ -1,142 +0,0 @@
$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
-278
View File
@@ -1,278 +0,0 @@
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*)
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*)
l - long (long)
o - object of any type (zval*)
O - object of specific type given by class entry (zval*, zend_class_entry)
r - resource (zval*)
s - string (with possible null bytes) and its length (char*, int)
S - binary string, does not allow conversion from Unicode strings
t - text (zstr (string union), int (length), zend_uchar (IS_STRING/..))
accepts either Unicode or binary string
T - text (zstr (string union), int (length), zend_uchar (IS_STRING/..))
coalesces all T parameters to common type (Unicode or binary)
u - unicode (UChar*, int)
U - Unicode string, does not allow conversion from binary strings
x - Unicode or binary string depending on UG(unicode). In unicode this
behaves like 'u' and in nonunicode mode it behaves like 's'.
z - the actual zval (zval*)
Z - the actual zval (zval**)
* - variable arguments list (0 or more)
+ - variable arguments list (1 or more)
The following characters also have a meaning in the specifier string:
| - indicates that the remaining parameters are optional, they
should be initialized to default values by the extension since they
will not be touched by the parsing function if they are not
passed to it.
/ - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
! - the parameter it follows can be of specified type or NULL (applies
to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the
results pointer is set to NULL as well.
& - alternate format (currently used for 's' only to specify a converter to
use when converting from Unicode strings)
^ - returns original string type before conversion (only for 's' and 'u'
specifiers)
Note on 64bit compatibility
---------------------------
Please do not forget that int and long are two different things on 64bit
OSes (int is 4 bytes and long is 8 bytes), so make sure you pass longs to "l"
and ints to strings length (i.e. for "s" you need to pass char * and int),
not the other way round!
Remember: "l" is the only case when you need to pass long (and that's why
it's "l", not "i" btw).
Both mistakes cause memory corruptions and segfaults on 64bit OSes:
1)
char *str;
long str_len; /* XXX THIS IS WRONG!! Use int instead. */
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)
2)
int num; /* XXX THIS IS WRONG!! Use long instead. */
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num)
If you're in doubt, use check_parameters.php script to the parameters
and their types (it can be found in ./scripts/dev/ directory of PHP sources):
# php ./scripts/dev/check_parameters.php /path/to/your/sources/
Examples
--------
/* Gets a long, a string and its length, and a zval */
long l;
char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
&l, &s, &s_len, &param) == FAILURE) {
return;
}
/* Gets an object of class specified by my_ce, and an optional double. */
zval *obj;
double d = 0.5;
zend_class_entry *my_ce;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
&obj, my_ce, &d) == FAILURE) {
return;
}
/* Gets an object or null, and an array.
If null is passed for object, obj will be set to NULL. */
zval *obj;
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
&obj, &arr) == FAILURE) {
return;
}
/* Gets a separated array which can also be null. */
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
&arr) == FAILURE) {
return;
}
/* Gets a binary string in UTF-8 */
char *str;
int str_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &str, &str_len, UG(utf8_conv)) == FAILURE) {
return;
}
/* Gets a Unicode string */
UChar *str;
int len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &len) == FAILURE) {
return;
}
/* Gets a Unicode or binary string */
zstr str;
int len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &str, &len, &type) == FAILURE) {
return;
}
if (type == IS_UNICODE) {
/* process str.u as Unicode string */
} else {
/* process str.s binary string */
}
/* Gets two string parameters, both of which will be guaranteed to be of the same type */
zstr str1, str2;
int len1, len2;
zend_uchar type1, type2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "TT", &str1, &len1,
&type1, &str2, &len2, &type2) == FAILURE) {
return;
}
if (type1 == IS_UNICODE) {
/* process as Unicode, str2 is guaranteed to be Unicode as well */
} else {
/* process as binary string, str2 is guaranteed to be the same */
}
/* Get either a set of 3 longs or a string. */
long l1, l2, l3;
char *s;
/*
* The function expects a pointer to a integer in this case, not a long
* or any other type. If you specify a type which is larger
* than a 'int', the upper bits might not be initialized
* properly, leading to random crashes on platforms like
* Tru64 or Linux/Alpha.
*/
int length;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"lll", &l1, &l2, &l3) == SUCCESS) {
/* manipulate longs */
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"s", &s, &length) == SUCCESS) {
/* manipulate string */
} else {
/* output error */
return;
}
/* Function that accepts only varargs (0 or more) */
int i, num_varargs;
zval ***varargs = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &varargs, &num_varargs) == FAILURE) {
return;
}
for (i = 0; i < num_varargs; i++) {
/* do something with varargs[i] */
}
if (varargs) {
efree(varargs);
}
/* Function that accepts a string, followed by varargs (1 or more) */
char *str;
int str_len;
int i, num_varargs;
zval ***varargs = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
return;
}
for (i = 0; i < num_varargs; i++) {
/* do something with varargs[i] */
}
if (varargs) {
efree(varargs);
}
/* Function that takes an array, followed by varargs, and ending with a long */
long num;
zval *array;
int i, num_varargs;
zval ***varargs = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
return;
}
for (i = 0; i < num_varargs; i++) {
/* do something with varargs[i] */
}
if (varargs) {
efree(varargs);
}
-11
View File
@@ -1,11 +0,0 @@
To install the PEAR installer, please use go-pear.
On linux:
$ lynx -source http://pear.php.net/go-pear | php
or save the setup script under go-pear.php and run:
php go-pear.php
For more informations see the PEAR manual:
http://pear.php.net/manual/en/installation.getting.php
-155
View File
@@ -1,155 +0,0 @@
1. strrpos() and strripos() now use the entire string as a needle. Be aware
that the existing scripts may no longer work as you expect.
EX :
<?php
var_dump(strrpos("ABCDEF","DEF"));
var_dump(strrpos("ABCDEF","DAF"));
?>
Will give you different results. The former returns 3 while the latter
returns false rather than the position of the last occurrence of 'D'.
The same applies to strripos().
2. Illegal use of string offsets causes E_ERROR instead of E_WARNING.
EX :
<?php
$a = "foo";
unset($a[0][1][2]);
?>
Fatal error: Cannot use string offset as an array in ... on line 1
3. array_merge() was changed to accept only arrays. If a non-array variable is
passed, a E_WARNING will be thrown for every such parameter. Be careful
because your code may start emitting E_WARNING out of the blue.
4. Be careful when porting from ext/mysql to ext/mysqli. The following
functions return NULL when no more data is available in the result set
(ext/mysql's functions return FALSE).
- mysqli_fetch_row()
- mysqli_fetch_array()
- mysqli_fetch_assoc()
5. PATH_TRANSLATED server variable is no longer set implicitly under
Apache2 SAPI in contrast to the situation in PHP 4, where it is set to the
same value as the SCRIPT_FILENAME server variable when it is not populated
by Apache. This change was made to comply with the CGI specification.
Please refer to bug #23610 for further information.
6. Starting PHP 5.0.0 the T_ML_CONSTANT constant is no longer defined by the
ext/tokenizer extension. If error_reporting is set to E_ALL notices will
be produced. Instead of T_ML_CONSTANT for /* */ the T_COMMENT constant
is used, thus both // and /* */ are resolved as the T_COMMENT constant.
However the PHPDoc style comments /** */ ,which starting PHP 5 are parsed
by PHP, are recongnized as T_DOC_COMMENT.
7. $_SERVER should be populated with argc and argv if variables_order
includes "S". If you have specifically configured your system to not
create $_SERVER, then of course it shouldn't be there. The change was to
always make argc and argv available in the CLI version regardless of the
variables_order setting. As in, the CLI version will now always populate
the global $argc and $argv variables.
8. In some cases classes must be declared before used. It only happens only
if some of the new features of PHP 5 are used. Otherwise the behaviour is
the old.
Example 1 (works with no errors):
<?php
$a = new a();
class a {
}
?>
Example 2 (throws an error):
<?php
$a = new a();
interface b{
}
class a implements b {
}
?>
Output (example 2) :
Fatal error: Class 'a' not found in /tmp/cl.php on line 2
9. get_class() starting PHP 5 returns the name of the class as it was
declared which may lead to problems in older scripts that rely on
the previous behaviour - the class name is lowercased. Expect the
same behaviour from get_parent_class() when applicable.
Example :
<?php
class FooBar {
}
class ExtFooBar extends FooBar{}
$a = new FooBar();
var_dump(get_class($a), get_parent_class($a));
?>
Output (PHP 4):
string(6) "foobar"
string(9) "extfoobar"
Output (PHP 5):
string(6) "FooBar"
string(9) "ExtFooBar"
----------------------------------------------------------------------
Example code that will break :
//....
function someMethod($p) {
if (get_class($p) != 'helpingclass') {
return FALSE;
}
//...
}
//...
Possible solution is to search for get_class() and get_parent_class() in
all your scripts and use strtolower().
10. get_class_methods() returns the names of the methods of a class as they
declared. In PHP4 the names are all lowercased.
Example code :
<?php
class Foo{
function doFoo(){}
function hasFoo(){}
}
var_dump(get_class_methods("Foo"));
?>
Output (PHP4):
array(2) {
[0]=>
string(5) "dofoo"
[1]=>
string(6) "hasfoo"
}
Output (PHP5):
array(2) {
[0]=>
string(5) "doFoo"
[1]=>
string(6) "hasFoo"
}
11. Assignment $this is impossible. Starting PHP 5.0.0 $this has special
meaning in class methods and is recognized by the PHP parser. The latter
will generate a parse error when assignment to $this is found
Example code :
<?php
class Foo {
function assignNew($obj) {
$this = $obj;
}
}
$a = new Foo();
$b = new Foo();
$a->assignNew($b);
echo "I was executed\n";
?>
Output (PHP 4):
I was executed
Output (PHP 5):
PHP Fatal error: Cannot re-assign $this in /tmp/this_ex.php on line 4
-57
View File
@@ -1,57 +0,0 @@
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
-256
View File
@@ -1,256 +0,0 @@
=======================
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. Only for an RC release also send an email
(see example here http://news.php.net/php.qa/26069) **To**
``php-qa@lists.php.net`` and **CC** ``primary-qa-tests@lists.php.net``.
This email is to notify the selected projects about a new RC 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 ``qaweb/include/rc-md5sums.txt`` (no empty lines).
4. Update in ``qaweb/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-web/include/functions.inc`` the ``show_version_option``
function to include the new RC and commit.
2. Run the bumpRelease script for phpweb in your local checkout
a. ``php bin/bumpRelease 5`` (or ``php bin/bumpRelease 4`` for PHP4)
3. Update ``phpweb/include/version.inc`` (x=major version number)
a. ``$PHP_x_RC`` = "5.3.0RC1"
b. ``$PHP_x_RC_DATE`` = "06 September 2007"
4. Commit those changes:
a. ``cvs commit include/version.inc include/releases.inc``
5. 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); ?>/``
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
12. Rebuild the English and Japanese docs (ask Derick)
-155
View File
@@ -1,155 +0,0 @@
$Id$
=============================================================================
HOW TO CREATE A SELF-CONTAINED PHP EXTENSION
A self-contained extension can be distributed independently of
the PHP source. To create such an extension, two things are
required:
- Configuration file (config.m4)
- Source code for your module
We will describe now how to create these and how to put things
together.
PREPARING YOUR SYSTEM
While the result will run on any system, a developer's setup needs these
tools:
GNU autoconf
GNU automake
GNU libtool
GNU m4
All of these are available from
ftp://ftp.gnu.org/pub/gnu/
CONVERTING AN EXISTING EXTENSION
Just to show you how easy it is to create a self-contained
extension, we will convert an embedded extension into a
self-contained one. Install PHP and execute the following
commands.
$ mkdir /tmp/newext
$ cd /tmp/newext
You now have an empty directory. We will copy the files from
the mysql extension:
$ cp -rp php-4.0.X/ext/mysql/* .
It is time to finish the module. Run:
$ phpize
You can now ship the contents of the directory - the extension
can live completely on its own.
The user instructions boil down to
$ ./configure \
[--with-php-config=/path/to/php-config] \
[--with-mysql=MYSQL-DIR]
$ make install
The MySQL module will either use the embedded MySQL client
library or the MySQL installation in MYSQL-DIR.
DEFINING THE NEW EXTENSION
Our demo extension is called "foobar".
It consists of two source files "foo.c" and "bar.c"
(and any arbitrary amount of header files, but that is not
important here).
The demo extension does not reference any external
libraries (that is important, because the user does not
need to specify anything).
LTLIBRARY_SOURCES specifies the names of the sources files. You can
name an arbitrary number of source files here.
CREATING THE M4 CONFIGURATION FILE
The m4 configuration can perform additional checks. For a
self-contained extension, you do not need more than a few
macro calls.
------------------------------------------------------------------------------
PHP_ARG_ENABLE(foobar,whether to enable foobar,
[ --enable-foobar Enable foobar])
if test "$PHP_FOOBAR" != "no"; then
PHP_NEW_EXTENSION(foobar, foo.c bar.c, $ext_shared)
fi
------------------------------------------------------------------------------
PHP_ARG_ENABLE will automatically set the correct variables, so
that the extension will be enabled by PHP_NEW_EXTENSION in shared mode.
The first argument of PHP_NEW_EXTENSION describes the name of the
extension. The second names the source-code files. The third passes
$ext_shared which is set by PHP_ARG_ENABLE/WITH to PHP_NEW_EXTENSION.
Please use always PHP_ARG_ENABLE or PHP_ARG_WITH. Even if you do not
plan to distribute your module with PHP, these facilities allow you
to integrate your module easily into the main PHP module framework.
CREATING SOURCE FILES
ext_skel can be of great help when creating the common code for all modules
in PHP for you and also writing basic function definitions and C code for
handling arguments passed to your functions. See README.EXT_SKEL for further
information.
As for the rest, you are currently alone here. There are a lot of existing
modules, use a simple module as a starting point and add your own code.
CREATING THE SELF-CONTAINED EXTENSION
Put config.m4 and the source files into one directory. Then, run phpize
(this is installed during make install by PHP 4.0).
For example, if you configured PHP with --prefix=/php, you would run
$ /php/bin/phpize
This will automatically copy the necessary build files and create
configure from your config.m4.
And that's it. You now have a self-contained extension.
INSTALLING A SELF-CONTAINED EXTENSION
An extension can be installed by running:
$ ./configure \
[--with-php-config=/path/to/php-config]
$ make install
ADDING SHARED MODULE SUPPORT TO A MODULE
In order to be useful, a self-contained extension must be loadable
as a shared module. I will explain now how you can add shared module
support to an existing module called foo.
1. In config.m4, use PHP_ARG_WITH/PHP_ARG_ENABLE. Then you will
automatically be able to use --with-foo=shared[,..] or
--enable-foo=shared[,..].
2. In config.m4, use PHP_NEW_EXTENSION(foo,.., $ext_shared) to enable
building the extension.
3. Add the following lines to your C source file:
#ifdef COMPILE_DL_FOO
ZEND_GET_MODULE(foo)
#endif
-379
View File
@@ -1,379 +0,0 @@
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
-126
View File
@@ -1,126 +0,0 @@
Submitting Patch for PHP
========================
This document describes how to submit a patch for PHP. Since you are
reading this document, you are willing to submit a patch for PHP.
Please keep reading! Submitting a patch for PHP is easy. The hard
part is making it acceptable for inclusion into our repository. :-)
How to create patch?
--------------------
We are working with CVS. You need to get CVS source to create a patch
that we accept. Visit http://www.php.net/anoncvs.php to get CVS
source. You can check out older versions, but make sure you get
the default branch (i.e. Do not use -r option when you check out the
CVS source)
Read CODING_STANDARDS file before you start working.
Now you are ready to create a patch. Modify source to fix a bug in PHP or
add a new feature to PHP. After you finished editing, please test your
patch. Read README.TESTING for testing.
After you finish testing your patch, take diff file using
"cvs diff > your.patch" command.
Read README.TESTING for submitting a test script for your patch. This is
not strictly required, but it is preferred to submit a test script along
with your patch. Making new test script is very easy. It also helps us
to understand what you have been fixed or added to PHP.
Tips for creating patch
-----------------------
If you would like to fix multiple bugs. It is easier for us if you
could create 1 patch for 1 bug, but this is not strictly required.
Note though that you might get little response, if your patch is
too hard to review.
If you would like change/add many lines, it is better to ask module
maintainer and/or internals@lists.php.net, or pear-dev@lists.php.net if
you are patching PEAR. Official module maintainers can be found in
EXTENSIONS file in PHP source.
If you are new to CVS (Concurrent Versions System), visit
http://cvshome.org/ for details.
Recommended CVS client settings for creating patch file
------------------------------------------------------
Recommended ~/.cvsrc file setting is:
------
cvs -z3
update -d -P
checkout -P
diff -u
------
diff -u means:
-u Use the unified output format.
With this CVS setting, you don't have to worry about adding/deleting
newlines and spaces.
Check list for submitting patch
-------------------------------
- Did you run "make test" to check if your patch didn't break
other features?
- Did you compile PHP with --enable-debug and check the PHP and
web server error logs when you test your patch?
- Did you build PHP for multi-threaded web servers. (Optional)
- Did you create test script for "make test"? (Recommended)
- Did you check your patch is unified format and it does not
contain white space changes? (If you are not using recommended
cvs setting)
- Did you update CVS source before you take final patch?
- Did you read the patch again?
Where to send your patch?
-------------------------
If you are patching C source, send the patch to internals@lists.php.net.
If you are patching a module, you should also send the patch to the
maintainer. Official module maintainers are listed in EXTENSION file
in source.
If you are patching PEAR, send the patch to pear-dev@lists.php.net.
Please add the prefix "[PATCH]" to your email subject and make sure
to include the patch as a MIME attachment even if it is short.
NOTE: only MIME attachments of type 'text/*' are accepted. The
easiest way to accomplish this, is to make the extension
'.txt'.
Test scripts should be included in the same email.
Explain what has been fixed/added/changed by your patch.
Finally, add the bug Id(s) which can be closed by your patch, if any.
What happens after you submit your patch
----------------------------------------
If your patch is easy to review and has obviously no side-effects,
it might take up to a few hours until someone commits it.
Because this is a volunteer-driven effort, more complex patches will
require more patience on your side.
If you did not receive any feedback in a few days, please consider
resubmitting the description of your patch, along-side with
these questions:
- Is my patch too hard to review? Because of which factors?
- Should I split it up in multiple parts?
- Are there any unwanted whitespace changes?
What happens when your patch is applied?
----------------------------------------
Your name will be included together with your email address in the CVS
commit log. If your patch affects end-users, a brief description
and your name might be added to the NEWS file.
Thank you for submitting patch for PHP!
-179
View File
@@ -1,179 +0,0 @@
[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]
---------------------------------------------
You must use TEST_PHP_EXECUTABLE environment variable to explicitly
select the php executable to be used to run the tests. That can either
be the CLI or CGI executable.
"make test" executes "run-tests.php" script with "php" binary. Some
test scripts such as session must be executed by CGI SAPI. Therefore,
you must build PHP with CGI SAPI to perform all tests.
NOTE: PHP binary executing "run-tests.php" and php binary used for
executing test scripts may differ. If you use different PHP binary for
executing "run-tests.php" script, you may get errors.
[Which php.ini is used]
-----------------------
"make test" uses the same php.ini file as it would once installed.
The tests have been written to be independent of that php.ini file,
so if you find a test that is affected by a setting, please report
this, so we can address the issue.
[Which test scripts are executed]
---------------------------------
"run-tests.php" ("make test"), without any arguments executes all
test scripts by extracting all directories named "tests"
from the source root and any subdirectories below. If there are files,
which have a "phpt" extension, "run-tests.php" looks at the sections
in these files, determines whether it should run it, by evaluating
the 'SKIP' section. If the test is eligible for execution, the 'FILE'
section is extracted into a ".php" file (with the same name besides
the extension) and gets executed.
When an argument is given or TESTS environment variable is set, the
GLOB is expanded by the shell and any file with extension "*.phpt" is
regarded as a test file.
Tester can easily execute tests selectively with as follows.
Examples:
./sapi/cli/php run-tests.php ext/mbstring/*
./sapi/cli/php run-tests.php ext/mbstring/020.phpt
[Test results]
--------------
Test results are printed to standard output. If there is a failed test,
the "run-tests.php" script saves the result, the expected result and the
code executed to the test script directory. For example, if
ext/myext/tests/myext.phpt fails to pass, the following files are created:
ext/myext/tests/myext.php - actual test file executed
ext/myext/tests/myext.log - log of test execution (L)
ext/myext/tests/myext.exp - expected output (E)
ext/myext/tests/myext.out - output from test script (O)
ext/myext/tests/myext.diff - diff of .out and .exp (D)
Failed tests are always bugs. Either the test is bugged or not considering
factors applying to the tester's environment, or there is a bug in PHP.
If this is a known bug, we strive to provide bug numbers, in either the
test name or the file name. You can check the status of such a bug, by
going to: http://bugs.php.net/12345 where 12345 is the bug number.
For clarity and automated processing, bug numbers are prefixed by a hash
sign '#' in test names and/or test cases are named bug12345.phpt.
NOTE: The files generated by tests can be selected by setting the
environment variable TEST_PHP_LOG_FORMAT. For each file you want to be
generated use the character in brackets as shown above (default is LEOD).
The php file will be generated always.
NOTE: You can set environment variable TEST_PHP_DETAILED to enable
detailed test information.
[Automated testing]
If you like to keep up to speed, with latest developments and quality
assurance, setting the environment variable NO_INTERACTION to 1, will not
prompt the tester for any user input.
Normally, the exit status of "make test" is zero, regardless of the results
of independent tests. Set the environment variable REPORT_EXIT_STATUS to 1,
and "make test" will set the exit status ("$?") to non-zero, when an
individual test has failed.
Example script to be run by cron(1):
========== qa-test.sh =============
#!/bin/sh
CO_DIR=$HOME/cvs/php5
MYMAIL=qa-test@domain.com
TMPDIR=/var/tmp
TODAY=`date +"%Y%m%d"`
# Make sure compilation enviroment is correct
CONFIGURE_OPTS='--disable-all --enable-cli --with-pcre'
export MAKE=gmake
export CC=gcc
# Set test environment
export NO_INTERACTION=1
export REPORT_EXIT_STATUS=1
cd $CO_DIR
cvs update . >>$TMPDIR/phpqatest.$TODAY
./cvsclean ; ./buildconf ; ./configure $CONFIGURE_OPTS ; $MAKE
$MAKE test >>$TMPDIR/phpqatest.$TODAY 2>&1
if test $? -gt 0
then
cat $TMPDIR/phpqatest.$TODAY | mail -s"PHP-QA Test Failed for $TODAY" $MYMAIL
fi
========== end of qa-test.sh =============
NOTE: the exit status of run-tests.php will be 1 when
REPORT_EXIT_STATUS is set. The result of "make test" may be higher
than that. At present, gmake 3.79.1 returns 2, so it is
advised to test for non-zero, rather then a specific value.
[Creating new test files]
-------------------------
Writing test file is very easy if you are used to PHP.
See the HOWTO at http://qa.php.net/write-test.php
[How to help us]
----------------
If you find bug in PHP, you can submit bug report AND test script
for us. You don't have to write complete script, just give us test
script with following format. Please test the script and make sure
you write the correct ACTUAL OUTPUT and EXPECTED OUTPUT before you
submit.
<?php
/*
Bug #12345
substr() bug. Do not return expected string.
ACTUAL OUTPUT
XYXA
EXPECTED OUTPUT
ABCD
*/
$str = "XYZABCD";
echo substr($str,3,7);
?>
-137
View File
@@ -1,137 +0,0 @@
[IMPORTANT NOTICE]
------------------
This is an addendum to README.TESTING with additional information
specific to server-tests.php.
server-tests.php is backward compatible with tests developed for
the original run-tests.php script. server-tests is *not* used by
'make test'. server-tests was developed to provide support for
testing PHP under it's primary environment, HTTP, and can run the
PHP tests under any of the SAPI modules that are direct executables,
or are accessable via HTTP.
[New features]
----------------
* Command line interface:
You can run 'php server-tests.php -h' to get all the possible options.
* Configuration file:
the -c argument will allow you to use a configuration file. This is
handy if you are testing multiple environments and need various options
depending on the environment.
see server-tests-config.php for details.
* CGI Emulation:
Will emulate a CGI environment when testing with the cgi sapi executable.
* HTTP testing:
can be configured to run test scripts through an HTTP server running
on localhost. localhost is required since either the web server must
alias a directory to the php source directory, or the test scripts
must be copied to a directory under the web server
(see config options TEST_WEB_BASE_URL, TEST_BASE_PATH, and TEST_WEB_EXT)
* New sections supported for test files (see below)
When running tests over http, tests that require ini settings different that what
the web server runs under will be skipped. Since the test harness defines a number
of ini settings by default, the web server may require special configuration to
make testing work.
[Example Usage]
----------------
Some (but not all!) examples of usage:
1. run tests from the php source directory
php server-tests.php -p /path/to/php-cli
2. run tests using cgi emulation
php server-tests.php -p /path/to/php-cgi
3. run tests over http, copying test files into document root
php server-tests.php -w -u http://localhost/test -m /path/to/htdocs/test
4. run tests over http, php sources have been aliased in web server
php server-tests.php -w -u http://localhost/test
5. run tests using configuration file
php server-tests.php -c /path/to/server-tests-config.php
6. run tests using configuration file, but overriding some settings:
(config file must be first)
php server-tests.php -c /path/to/server-tests-config.php -w -t 3 -d /path/to/testdir
NOTE: configuration as described in README.TESTING still works.
[New Test Sections]
----------------
In addition to the traditional test sections
(see http://qa.php.net/write-test.php), several new sections are available
under server-tests.
--POST--
This is not a new section, but not multipart posts are supported for testing
file uploads, or other types of POST data.
--CGI--
This section takes no value. It merely provides a simple marker for tests
that MUST be run as CGI, even if there is no --POST-- or --GET-- sections
in the test file.
--DESCRIPTION--
Not used for anything, just a section for documenting the test
--ENV--
This section get's eval()'d to help build an environment for the
execution of the test. This can be used to change environment
vars that are used for CGI emulation, or simply to set env vars
for cli testing. A full example looks like:
--ENV--
return <<<END
PATH_TRANSLATED=$filename
PATH_INFO=$scriptname
SCRIPT_NAME=$scriptname
END;
Some variables are made easily available for use in this section, they
include:
$filename full native path to file, will become PATH_TRANSLATED
$filepath =dirname($filename)
$scriptname this is what will become SCRIPT_NAME unless you override it
$docroot the equivelant of DOCUMENT_ROOT under Apache
$cwd the directory that the test is being initiated from
$this->conf all server-tests configuration vars
$this->env all environment variables that will get passed to the test
--REQUEST--
This section is also eval'd, and is similar in nature to --ENV--. However,
this section is used to build the url used in an HTTP request. Valid values
to set in this section would include:
SCRIPT_NAME The inital part of the request url
PATH_INFO The pathinfo part of a request url
FRAGMENT The fragment section of a url (after #)
QUERY_STRING The query part of a url (after ?)
--REQUEST--
return <<<END
PATH_INFO=/path/info
END;
--HEADERS--
This section is also eval'd. It is used to provide additional headers sent
in an HTTP request, such as content type for multipart posts, cookies, etc.
--HEADERS--
return <<<END
Content-Type=multipart/form-data; boundary=---------------------------240723202011929
Content-Length=100
END;
--EXPECTHEADERS--
This section can be used to define what headers are required to be
received back from a request, and is checked in addition to the
regular expect sections. For example:
--EXPECTHEADERS--
Status: 404
-644
View File
@@ -1,644 +0,0 @@
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
- substibute invalid characters with a custom substitution character
- escape the invalid character in various formats
To control the global conversion error settings, use the functions:
unicode_set_error_mode(int direction, int mode)
unicode_set_subst_char(unicode char)
where direction is either FROM_UNICODE or TO_UNICODE, and mode is one of these
constants:
U_CONV_ERROR_STOP
U_CONV_ERROR_SKIP
U_CONV_ERROR_SUBST
U_CONV_ERROR_ESCAPE_UNICODE
U_CONV_ERROR_ESCAPE_ICU
U_CONV_ERROR_ESCAPE_JAVA
U_CONV_ERROR_ESCAPE_XML_DEC
U_CONV_ERROR_ESCAPE_XML_HEX
As an example, with a runtime encoding of ISO-8859-1, the conversion:
$str = (binary)"< \u30AB >";
results in:
MODE RESULT
--------------------------------------
stop ""
skip "< >"
substitute "< ? >"
escape (Unicode) "< {U+30AB} >"
escape (ICU) "< %U30AB >"
escape (Java) "< \u30AB >"
escape (XML decimal) "< &#12459; >"
escape (XML hex) "< &#x30AB; >"
With a runtime encoding of UTF-8, the conversion of the (illegal) sequence:
$str = (unicode)b"< \xe9\xfe >";
results in:
MODE RESULT
--------------------------------------
stop ""
skip ""
substitute ""
escape (Unicode) "< %XE9%XFE >"
escape (ICU) "< %XE9%XFE >"
escape (Java) "< \xE9\xFE >"
escape (XML decimal) "< &#233;&#254; >"
escape (XML hex) "< &#xE9;&#xFE; >"
The substitution character can be set only for FROM_UNICODE direction and has to
exist in the target character set. The default substitution character is (?).
NOTE: Casting is just a shortcut for using unicode.runtime_encoding. To convert
using an alternative encoding, use the unicode_encode() and unicode_decode()
functions. For example,
$str = unicode_encode($uni, 'koi8-r', U_CONV_ERROR_SUBST);
results in a binary KOI8-R encoded string.
Creating a Custom Error Handler
-------------------------------
If an error occurs during the conversion, PHP outputs a warning describing the
problem. Instead of this default behavior, PHP can invoke a user-provided error
handler, similar to how the current user-defined error handler works. To set
the custom conversion error handler, call:
mixed unicode_set_error_handler(callback error_handler)
The function returns the previously defined custom error handler. If no error
handler was defined, or if an error occurs when returning the handler, this
function returns NULL.
When the custom handler is set, the standard error handler is bypassed. It is
the responsibility of the custom handler to output or log any messages, raise
exceptions, or die(), if necessary. However, if the custom error handler returns
FALSE, the standard handler will be invoked afterwards.
The user function specified as the error_handler must accept five parameters:
mixed error_handler($direction, $encoding, $char_or_byte, $offset,
$message)
where:
$direction - the direction of conversion, FROM_UNICODE/TO_UNICODE
$encoding - the name of the encoding to/from which the conversion
was attempted
$char_or_byte - either Unicode character or byte sequence (depending
on direction) which caused the error
$offset - the offset of the failed character/byte sequence in
the source string
$message - the error message describing the problem
NOTE: If the error mode set by unicode_set_error_mode() is substitute,
skip, or escape, the handler won't be called, since these are non-error
causing operations. To always invoke your handler, set the error mode to
U_CONV_ERROR_STOP.
Unicode String Type
===================
The Unicode string type (IS_UNICODE) is supposed to contain text data encoded in
UTF-16. This is the main string type in PHP when Unicode semantics switch is
turned on. Unicode strings can exist when the switch is off, but they have to be
produced programmatically via calls to functions that return Unicode types.
Binary String Type
==================
Binary string type (IS_STRING) serves two purposes: backwards compatibility and
representing non-Unicode strings and binary data. When Unicode semantics switch
is off, it is used for all strings in PHP, same in previous versions. When the
switch is on, this type will be used to store text in other encodings as well as
true binary data such as images, PDFs, etc.
Printing binary data to the standard output passes it through as-is, independent
of the output encoding.
For examples of specifying binary string literals, refer to the section
"Language Modfications".
Language Modifications
======================
If a Unicode switch is turned on, PHP string literals -- single-quoted,
double-quoted, and heredocs -- become Unicode strings (IS_UNICODE type). String
literals support all the same escape sequences and variable interpolations as
before, plus several new escape sequences.
PHP interprets the contents of strings as follows:
- all non-escaped characters are interpreted as a corresponding Unicode
codepoint based on the current script encoding, e.g. ASCII 'a' (0x61) =>
U+0061, Shift-JIS (0x92 0x86) => U+4E2D
- existing PHP escape sequences are also interpreted as Unicode codepoints,
including \xXX (hex) and \OOO (octal) numbers, e.g. "\x20" => U+0020
- two new escape sequences, \uXXXX and \UXXXXXX, are interpreted as a 4 or
6-hex Unicode codepoint value, e.g. \u0221 => U+0221, \U010410 =>
U+10410. (Having two sequences avoids the ambiguity of \u020608 --
is that supposed to be U+0206 followed by "08", or U+020608 ?)
- a new escape sequence allows specifying a character by its full
Unicode name, e.g. \C{THAI CHARACTER PHO SAMPHAO} => U+0E20
PHP allows variable interpolation inside the double-quoted and heredoc strings.
However, the parser separates the string into literal and variable chunks during
compilation, e.g. "abc $var def" -> "abc" . $var . "def". This means that PHP
can handle literal chunks in the normal way as far as Unicode support is
concerned.
Since all string literals become Unicode by default, PHP 6 introduces new syntax
for creating byte-oriented or binary strings. Prefixing a string literal with
the letter 'b' creates a binary string:
$var = b'abc\001';
$var = b"abc\001";
$var = b<<<EOD
abc\001
EOD;
The content of a binary string is the literal byte sequence inside the
delimiters, which depends on the script encoding (unicode.script_encoding).
Binary string literals support the same escape sequences as PHP 5 strings. If
the Unicode switch is turned off, then the binary string literals generate the
normal string (IS_STRING) type internally without any effect on the application.
The string operators now accomodate the new IS_UNICODE and IS_BINARY types:
- The concatenation operator (.) and concatenation assignment operator (.=)
automatically coerce the IS_STRING type to the more precise IS_UNICODE if
the operands are of different string types.
- The string indexing operator [] now accommodates IS_UNICODE type strings
and extracts the specified character. To support supplementary characters,
the index specifies a code point, not a byte or a code unit.
- Bitwise operators and increment/decrement operators do not work on
Unicode strings. They do work on binary strings.
- Two new casting operators are introduced, (unicode) and (binary). The
(string) operator casts to Unicode type if the Unicode semantics switch is
on, and to binary type otherwise.
- The comparison operators compare Unicode strings in binary code point
order. They also coerce strings to Unicode if the strings are of different
types.
- The arithmetic operators use the same semantics as today for converting
strings to numbers. A Unicode string is considered numeric if it
represents a long or a double number in the en_US_POSIX locale.
Unicode Support in Existing Functions
=====================================
All functions in the PHP default distribution are undergoing analysis to
determine which functions need to be upgraded for native Unicode support.
You can track progress here:
http://www.php.net/~scoates/unicode/render_func_data.php
Key extensions that are fully converted include:
* curl
* dom
* json
* mysql
* mysqli
* oci8
* pcre
* reflection
* simplexml
* soap
* sqlite
* xml
* xmlreader/xmlwriter
* xsl
* zlib
NOTE: Unsafe functions might still work, since PHP performs Unicode conversions
at runtime. However, unsafe functions might not work correctly with multibyte
binary strings, or Unicode characters that are not representable in the
specified unicode.runtime_encoding.
Identifiers
===========
Since scripts may be written in various encodings, we do not restrict
identifiers to be ASCII-only. PHP allows any valid identifier based
on the Unicode Standard Annex #31.
Numbers
=======
Unlike identifiers, numbers must consist only of ASCII digits,.and are
restricted to the en_US_POSIX or C locale. In other words, numbers have no
thousands separator, and the fractional separator is (.) "full stop". Numeric
strings adhere to the same rules, so "10,3" is not interpreted as a number even
if the current locale's fractional separator is a comma.
TextIterators
=============
Instead of using the offset operator [] to access characters in a linear
fashion, use a TextIterator instead. TextIterator is very fast and enables you
to iterate over code points, combining sequences, characters, words, lines, and
sentences, both forward and backward. For example:
$text = "nai\u308ve";
foreach (new TextIterator($text) as $u) {
var_inspect($u)
}
lists six code points, including the umlaut (U+0308) as a separate code point.
Instantiating the TextIterator to iterate over characters,
$text = "nai\u308ve";
foreach (new TextIterator($text, TextIterator::CHARACTER) as $u) {
var_inspect($u)
}
lists five characters, including an "i" with an umlaut as a single character.
Locales
=======
Unicode support in PHP relies exclusively on ICU locales, NOT the POSIX locales
installed on the system. You may access the default ICU locale using:
locale_set_default()
locale_get_default()
ICU locale IDs have a somewhat different format from POSIX locale IDs. The ICU
syntax is:
<language>[_<script>]_<country>[_<variant>][@<keywords>]
For example, sr_Latn_YU_REVISED@currency=USD is Serbian (Latin, Yugoslavia,
Revised Orthography, Currency=US Dollar).
Do not use the deprecated setlocale() function. This function interacts with the
POSIX locale. If Unicode semantics are on, using setlocale() generates
a deprecation warning.
Document TODO
==========================================
- Final review.
- Fix the HTTP Input Encoding section, that's obsolete now.
References
==========
Unicode
http://www.unicode.org
Unicode Glossary
http://www.unicode.org/glossary/
UTF-8
http://www.utf-8.com/
UTF-16
http://www.ietf.org/rfc/rfc2781.txt
ICU Homepage
http://www.ibm.com/software/globalization/icu/
ICU User Guide and API Reference
http://icu.sourceforge.net/
Unicode Annex #31
http://www.unicode.org/reports/tr31/
PHP Parameter Parsing API
http://www.php.net/manual/en/zend.arguments.retrieval.php
Authors
=======
Andrei Zmievski <andrei@gravitonic.com>
Evan Goer <goer@yahoo-inc.com>
vim: set et tw=80 :
-806
View File
@@ -1,806 +0,0 @@
This document attempts to describe portions of the API related to the new
Unicode functionality and the best practices for upgrading existing
functions to support Unicode.
Your first stop should be README.UNICODE: it covers the general Unicode
functionality and concepts without going into technical implementation
details.
Internal Encoding
=================
UTF-16 is the internal encoding used for Unicode strings. UTF-16 consumes
two bytes for any Unicode character in the Basic Multilingual Plane, which
is where most of the current world's languages are represented. While being
less memory efficient for basic ASCII text it simplifies the processing and
makes interfacing with ICU easier, since ICU uses UTF-16 for its internal
processing as well.
Zval Structure Changes
======================
For IS_UNICODE type, we add another structure to the union:
union {
....
struct {
UChar *val; /* Unicode string value */
int len; /* number of UChar's */
} ustr;
....
} value;
This cleanly separates the two types of strings and helps preserve backwards
compatibility.
To optimize access to IS_STRING and IS_UNICODE storage at runtime, we need yet
another structure:
union {
....
struct { /* Universal string type */
zstr val;
int len;
} uni;
....
} value;
Where zstr is a union of char*, UChar*, and void*.
Parameter Parsing API Modifications
===================================
There are now five new specifiers: 'u', 't', 'T', 'U', 'S', 'x' and a new '&'
modifier.
't' specifier
-------------
This specifier indicates that the caller requires the incoming parameter to be
string data (IS_STRING, IS_UNICODE). The caller has to provide the storage for
string value, length, and type.
void *str;
int len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &str, &len, &type) == FAILURE) {
return;
}
if (type == IS_UNICODE) {
/* process Unicode string */
} else {
/* process binary string */
}
For IS_STRING type, the length represents the number of bytes, and for
IS_UNICODE the number of UChar's. When converting other types (numbers,
booleans, etc) to strings, the exact behavior depends on the Unicode semantics
switch: if on, they are converted to IS_UNICODE, otherwise to IS_STRING.
'u' specifier
-------------
This specifier indicates that the caller requires the incoming parameter
to be a Unicode encoded string. If a non-Unicode string is passed, the engine
creates a copy of the string and automatically convert it to Unicode type before
passing it to the internal function. No such conversion is necessary for Unicode
strings, obviously.
UChar *str;
int len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &str, &len) == FAILURE) {
return;
}
/* process Unicode string */
'T' specifier
-------------
This specifier is useful when the function takes two or more strings and
operates on them. Using 't' specifier for each one would be somewhat
problematic if the passed-in strings are of mixed types, and multiple
checks need to be performed in order to do anything. All parameters
marked by the 'T' specifier are promoted to the same type.
If at least one of the 'T' parameters is of Unicode type, then the rest of
them are converted to IS_UNICODE. Otherwise all 'T' parameters are conveted to
IS_STRING type.
void *str1, *str2;
int len1, len2;
zend_uchar type1, type2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "TT", &str1, &len1,
&type1, &str2, &len2, &type2) == FAILURE) {
return;
}
if (type1 == IS_UNICODE) {
/* process as Unicode, str2 is guaranteed to be Unicode as well */
} else {
/* process as binary string, str2 is guaranteed to be the same */
}
'x' specifier
-------------
This specifier acts as either 'u' or 's', depending on the value of the
unicode semantics switch. If UG(unicode) is on, it behaves as 'u', and as
's' otherwise.
The existing 's' specifier has been modified as well. If a Unicode string is
passed in, it automatically copies and converts the string to the runtime
encoding, and issues a warning. If a binary type is passed-in, no conversion
is necessary. The '&' modifier can be used after 's' specifier to force
a different converter instead.
char *str;
int len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &str, &len, UG(utf8_conv)) == FAILURE) {
return;
}
/* here str is in UTF-8, if a Unicode string was passed in */
The 'U' and 'S' specifiers are similar to 'u' and 's' but they are more strict
about the type of the passed-in parameter. If 'U' is specified and the binary
string is passed in, the engine will issue a warning instead of doing automatic
conversion. The converse applies to the 'S' specifier.
Working in Unicode World
========================
Strings
-------
A lot of internal functionality is controlled by the unicode.semantics
switch. Its value is found in the Unicode globals variable, UG(unicode). It
is either on or off for the entire request.
The big thing is that there is a new string types: IS_UNICODE.
This has its own storage in the value union part of
zval (value.ustr) while non-unicode (binary) strings reuse the
IS_STRING type and the value.str element of the zval.
New macros exist (parallel to Z_STRVAL/Z_STRLEN) for accessing unicode strings.
Z_USTRVAL(), Z_USTRLEN()
- accesses the value (as a UChar*) and length (in code units) of the Unicode type string
value.ustr.val value.ustr.len
Z_UNIVAL(), Z_UNILEN()
- accesses the value (as a zstr) and length (in type-appropriate units)
value.uni.val value.uni.len
Z_USTRCPLEN()
- gives the number of codepoints (not units) in the Unicode type string
This macro examines the actual string taking into account Surrogate Pairs
and returns the number of UChar32(UTF32) codepoints which may be less than the
number of UChar(UTF16) codeunits found in the string buffer.
If this value will be used repeatedly, consider storing it in a local variable
to avoid having to reexamine the string every time.
ZVAL_* macros
-------------
The 'dup' parameter to the ZVAL_STRING()/RETVAL_STRING()/RETURN_STRING() type
macros has been extended slightly. The following defines are now encouraged instead:
#define ZSTR_DUPLICATE (1<<0)
#define ZSTR_AUTOFREE (1<<1)
ZSTR_DUPLICATE (which has a resulting value of 1) serves the same purpose as a
truth value in old-style 'dup' flags. The value of 1 was specifically chosen
to match the common practice of passing a 1 for this parameter.
Warning: If you find extension code which uses a truth value other than one for
the dup flag, its logic should be modified to explicitly pass ZSTR_DUPLICATE instead.
ZSTR_AUTOFREE is used with macros such as ZVAL_RT_STRING which may populate Unicode
zvals from non-unicode source strings. When UG(unicode) is on, the source string
will be implicitly copied (to make a UChar* version). If the original string
needed copying anyway this is fine. However if the original string was emalloc()'d
and would have ordinarily been given to the engine (i.e. RETURN_STRING(estrdup("foo"), 0))
then it will need to be freed in UG(unicode) mode to avoid leaking.
The ZSTR_AUTOFREE flag ensures that the original string is freed in UG(unicode) mode.
ZVAL_UNICODE(pzv, str, dup), ZVAL_UNICODEL(pzv, str, str_len, dup)
- Sets zval to hold a Unicode string. Takes the same parameters as
Z_STRING(), Z_STRINGL().
ZVAL_U_STRING(conv, pzv, str, dup), ZVAL_U_STRINGL(conv, pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), ZSTRINGL()
and the conv parameter is ignored.
When UG(unicode) is on, it sets zval to hold a Unicode representation of the
passed-in string using the UConverter* specified by conv.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_RT_STRING(pzv, str, dup), ZVAL_RT_STRINGL(pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), Z_STRINGL().
When UG(unicode) is on, it takes the input string, converts it to Unicode
using the runtime_encoding converter and sets zval to it.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_ASCII_STRING(pzv, str, dup), ZVAL_ASCII_STRINGL(pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), Z_STRINGL().
When UG(unicode) is on, it takes the input string, converts it to Unicode
using an ASCII converter and sets zval to it.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_UTF8_STRING(pzv, str, dup), ZVAL_UTF8_STRINGL(pzv, str, str_len, dup)
- When UG(unicode) is off, it's equivalent to Z_STRING(), Z_STRINGL().
When UG(unicode) is on, it takes the input string, converts it to Unicode
using a UTF8 converter and sets zval to it.
Since a new string is always created in this case, passing ZSTR_DUPLICATE
for 'dup' does not matter, but ZSTR_AUTOFREE will be used will be used to
efree the original value
ZVAL_ZSTR(pzv, type, zstr, dup), ZVAL_ZSTRL(pzv, type, zstr, zstr_len, dup)
- This macro uses 'type' to switch between calling ZVAL_STRING(pzv, zstr.s, dup)
and ZVAL_UNICODE(pzv, zstr.u, dup). No conversion happens so the
presense of absense of ZSTR_AUTOFREE is ignored.
ZVAL_TEXT(pzv, zstr, dup), ZVAL_TEXTL(pzv, zstr, zstr_len, dup)
- This macro sets the zval to hold either a Unicode or a normal string,
depending on the value of UG(unicode). No conversion happens, so be certain
that the string passed in matches the type expected by UG(unicode).
One example of its usage would be to initialize zval to hold the name
of a user function.
ZVAL_EMPTY_UNICODE(pzv) / ZVAL_EMPTY_TEXT(pzv)
- These macros work identically to ZVAL_EMPTY_STRING() with the UNICODE
version always generating an IS_UNICODE zval, and the TEXT version
generating a UG(unicode) dependent string type.
ZVAL_UCHAR32(pzv, char)
- Converts the character provided into a UChar string (which may potentially
be 1 or 2 characters long in the case of surrogate pairs) and dispatches
to ZVAL_UNICODEL().
As usual, for each ZVAL_* macro, there is a matching RETVAL_* and RETURN_* macro.
Conversion Macros
-----------------
convert_to_string_with_converter(zval *op, UConverter *conv)
- converts a zval to native string using the specified converter, if necessary.
convert_to_unicode_with_converter(zval *op, UConverter *conv)
- converts a zval to Unicode string using the specified converter, if
necessary.
convert_to_unicode(zval *op)
- converts a zval to Unicode string.
convert_to_string(zval *op)
- Behaves just as it currently does, converting to IS_STRING type
convert_to_text(zval *op)
- converts a zval to either Unicode or native string, depending on the
value of UG(unicode) switch
zend_ascii_to_unicode() function can be used to convert an ASCII char*
string to Unicode. This is useful especially for inline string literals, in
which case you can simply use USTR_MAKE() macro, e.g.:
UChar* ustr;
ustr = USTR_MAKE("main");
If you need to initialize a few such variables, it may be more efficient to
use ICU macros, which avoid the conversion, depending on the platform. See
[1] for more information.
USTR_FREE(zstr) can be used to free a UChar* string safely, since it checks for
NULL argument. USTR_LEN() takes a zstr as its argument, and
depending on the UG(unicode) value, and returns its strlen() or u_strlen().
Array Manipulation
------------------
The add_next_index_*(), add_index_*() and add_assoc_*() functions have been
significantly expanded both to allow for the unicode type as a value and to
permit various types of keys.
Values: In the following examples, {1} represents a placeholder for the keytype and
its arguments (covered later).
add_{1}_unicode(zval *arr, {1}, UChar *ustr, int dup);
add_{1}_unicodel(zval *arr, {1}, UChar *ustr, int ustr_len, int dup);
- Works like add_{1}_string() and add_{1}_stringl() but takes a UChar* value
and adds an IS_UNICODE type.
add_{1}_rt_string(zval *arr, {1}, char *str, int dup);
add_{1}_rt_stringl(zval *arr, {1}, char *str, int str_len, int dup);
- Works like add_{1}_string() and add_{1}_stringl() but converts the char*
value to Unicode using runtime encoding when UG(unicode) is on.
add_{1}_ascii_string(zval *arr, {1}, char *str, int dup);
add_{1}_ascii_stringl(zval *arr, {1}, char *str, int str_len, int dup);
- Works like add_{1}_rt_string() and add_{1}_rt_stringl() but uses
an ASCII converter rather than runtime encoding.
add_{1}_utf8_string(zval *arr, {1}, char *str, int dup);
add_{1}_utf8_stringl(zval *arr, {1}, char *str, int str_len, int dup);
- Works like add_{1}_rt_string() and add_{1}_rt_stringl() but uses
a UTF8 converter rather than runtime encoding.
add_{1}_text(zval *arr, {1}, zstr str, int dup);
add_{1}_textl(zval *arr, {1}, zstr str, int str_len, int dup);
- Wrapper which dispatches to add_{1}_string(l)() or add_{1}_unicode(l)()
depending on the setting of UG(unicode).
add_{1}_zstr(zval *arr, {1}, zend_uchar type, zstr str, int dup);
add_{1}_zstrl(zval *arr, {1}, zend_uchar type, zstr str, int str_len, int dup);
- Works like add_{1}_text() and add_{1}_textl(), but dispatches based on 'type'.
Keys: In the following example, the zval* type is used for values, however
each of the value types (including those listed above) are supported.
The existing key types work as they always have:
add_next_index_zval(zval *arr, zval *val);
add_index_zval(zval *arr, long idx, zval *val);
add_assoc_zval(zval *arr, char *key, zval *val);
add_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. Associative keys are considered binary (IS_STRING)
. Remember that key_len includes the terminating NULL
The following additional methods provide unicode capable keytypes:
add_u_assoc_zval(zval *arr, zend_uchar type, zstr key, zval *val);
add_u_assoc_zval_ex(zval *arr, zend_uchar type, zstr key, int key_len, zval *val);
. When type==IS_STRING, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When type==IS_STRING, the key is considered to be Unicode (UChar*).
add_rt_assoc_zval(zval *arr, char *key, zval *val);
add_rt_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. When UG(unicode) is off, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When UG(unicode) is on, key is converted to Unicode using runtime encoding.
add_ascii_assoc_zval(zval *arr, char *key, zval *val);
add_ascii_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. When UG(unicode) is off, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When UG(unicode) is on, key is converted to Unicode using an ASCII converter.
add_utf8_assoc_zval(zval *arr, char *key, zval *val);
add_utf8_assoc_zval_ex(zval *arr, char *key, int key_len, zval *val);
. When UG(unicode) is off, these behave identically to their
add_assoc_zval() and add_assoc_zval_ex() counterparts.
When UG(unicode) is on, key is converted to Unicode using a UTF8 converter.
Keytype and Valuetype specification may be mixed in any combination, for example:
add_utf8_assoc_ascii_stringl_ex(zval *arr, char *key, int key_len, char *val, int val_len, int dup);
Miscellaneous
-------------
UBYTES() macro can be used to obtain the number of bytes necessary to store
the given number of UChar's. The typical usage is:
char *constant_name = colon + (UG(unicode)?UBYTES(2):2);
Code Points and Code Units
--------------------------
Unicode type strings are in the UTF-16 encoding where 1 Unicode character
may be represented by 1 or 2 UChar's. Each UChar is referred to as a "code
unit", and a full Unicode character as a "code point". Consequently, number
of code units and number of code points for the same Unicode string may be
different. This has many implications, the most important of which is that
you cannot simply index the UChar* string to get the desired codepoint.
The zval's value.ustr.len contains the number of code units (UChar -- UTF16).
To obtain the number of code points, one can use u_countChar32() ICU API
function or Z_USTRCPLEN() macro.
ICU provides a number of macros for working with UTF-16 strings on the
codepoint level [2]. They allow you to do things like obtain a codepoint at
random code unit offset, move forward and backward over the string, etc.
There are two versions of iterator macros, *_SAFE and *_UNSAFE. It is strong
recommended to use *_SAFE version, since they handle unpaired surrogates and
check for string boundaries. Here is an example of how to move through
UChar* string and work on codepoints.
UChar *str = ...;
int32_t str_len = ...;
UChar32 codepoint;
int32_t offset = 0;
while (offset < str_len) {
U16_NEXT(str, offset, str_len, codepoint);
/* now we have the Unicode character in codepoint */
}
There is not macro to get a codepoint at a certain code point offset, but
there is a Zend API function that does it.
inline UChar32 zend_get_codepoint_at(UChar *str, int32_t length, int32_t n);
To retrieve 3rd codepoint, you would call:
zend_get_codepoint_at(str, str_len, 3);
If you have a UChar32 codepoint and need to put it into a UChar* string,
there is another helper function, zend_codepoint_to_uchar(). It takes
a single UChar32 and converts it to a UChar sequence (1 or 2 UChar's).
UChar buf[8];
UChar32 codepoint = 0x101a2;
int8_t num_uchars;
num_uchars = zend_codepoint_to_uchar(codepoint, buf);
The return value is the number of resulting UChar's or 0, which indicates
invalid codepoint.
Memory Allocation
-----------------
For ease of use and to reduce possible bugs, there are memory allocation
functions specific to Unicode strings. Please use them at all times when
allocating UChar's.
eumalloc(size)
eurealloc(ptr, size)
eustrndup(s, length)
eustrdup(s)
peumalloc(size, persistent)
peurealloc(ptr, size, persistent)
The size parameter refers to the number of UChar's, not bytes.
zend_zstrndup(type, zstr, length)
Hashes
------
Hashes API has been upgraded to work with Unicode and binary strings. All
hash functions that worked with string keys now have their equivalent
zend_u_hash_* API. The zend_u_hash_* functions take the type of the key
string as the second argument.
When UG(unicode) switch is on, the IS_STRING keys are upconverted to
IS_UNICODE and then used in the hash lookup.
A new HASH_KEY constant has been added for differentiating key types:
. HASH_KEY_IS_UNICODE
Note that zend_hash_get_current_key_ex() does not have a zend_u_hash_*
version. It returns the key as a char* pointer, you can can cast it
appropriately based on the key type.
Identifiers and Class Entries
-----------------------------
In Unicode mode all the identifiers are Unicode strings. This means that
while various structures such as zend_class_entry, zend_function, etc store
the identifier name as a char* pointer, it will actually point to UChar*
string. Be careful when accessing the names of classes, functions, and such
-- always check UG(unicode) before using them.
Formatted Output
----------------
Since UTF-16 strings frequently contain NULL bytes, you cannot simpley use
%s format to print them out. Towards that end, output functions such as
php_printf(), spprintf(), etc now have three different formats for use with
Unicode strings:
%r
This format treats the corresponding argument as a Unicode string. The
string is automatically converted to the output encoding. If you wish to
apply a different converter to the string, use %*r and pass the
converter before the string argument.
UChar *class_name = USTR_NAME("ReflectionClass");
zend_printf("%r", class_name);
spprintf(&utf8_buffer, 0, "%*r", UG(utf8_conv), class_name);
%R
This format requires at least two arguments: the first one specifies the
type of the string to follow (IS_STRING or IS_UNICODE), and the second
one - the string itself. If the string is of Unicode type, it is
automatically converted to the output encoding. If you wish to apply
a different converter to the string, use %*R and pass the converter
before the string argument.
zend_throw_exception_ex(U_CLASS_ENTRY(reflection_exception_ptr), 0 TSRMLS_CC,
"Interface %R does not exist",
Z_TYPE_P(class_name), Z_UNIVAL_P(class_name));
%v
This format takes only one parameter, the string, but the expected
string type depends on the UG(unicode) value. If the string is of
Unicode type, it is automatically converted to the output encoding. If
you wish to apply a different converter to the string, use %*R and pass
the converter before the string argument.
zend_error(E_WARNING, "%v::__toString() did not return anything",
Z_OBJCE_P(object)->name);
%Z
This format prints a zval's value. You can specify the minimum length
of the string representation using "%*Z" as well as the absolute length
using "%.*Z". The following example is taken from the engine and
therefor uses zend_spprintf rather than spprintf. Further more clen is
an integer that is smaller than Z_UNILEN_P(callable).
zend_spprintf(error, 0, "class '%.*Z' not found", clen, callable);
The function allows to output any kind of zval values, as long as a
string (or unicode) conversion is available. Note that printing non
string zvals outside of request time is not possible.
Since [v]spprintf() can only output native strings there are also the new
functions [v]uspprintf() and [v]zspprintf() that create unicode strings and
return the number of characters printed. That is they return the length rather
than the byte size. The second pair of functions also takes an additional type
parameter that allows to create a string of arbitrary type. The following
example illustrates the use. Assume it fetches a unicode/native string into
path, path_len and path_type inorder to create sub_name, sub_len and sub_type.
zstr path, sub_name;
int path_len, sub_len;
zend_uchar path_type, sub_type;
/* fetch */
if (path.v) {
sub_type = path_type;
sub_len = zspprintf(path_type, &sub_name, 0, "%R%c%s",
path_type, path,
DEFAULT_SLASH,
entry.d_name);
}
Upgrading Functions
===================
Let's take a look at a couple of functions that have been upgraded to
support new string types.
substr()
--------
This functions returns part of a string based on offset and length
parameters.
zstr str;
int str_len, cp_len;
zend_uchar str_type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "tl|l", &str, &str_len, &str_type, &f, &l) == FAILURE) {
return;
}
The first thing we notice is that the incoming string specifier is 't',
which means that we can accept all 3 string types. The 'str' variable is
declared as zstr, because it can point to either UChar* or char*.
The actual type of the incoming string is stored in 'str_type' variable.
if (str_type == IS_UNICODE) {
cp_len = u_countChar32(str.u, str_len);
} else {
cp_len = str_len;
}
If the string is a Unicode one, we cannot rely on the str_len value to tell
us the number of characters in it. Instead, we call u_countChar32() to
obtain it.
The next several lines normalize start and length parameters to fit within the
string. Nothing new here. Then we locate the appropriate segment.
if (str_type == IS_UNICODE) {
int32_t start = 0, end = 0;
U16_FWD_N(str.u, end, str_len, f);
start = end;
U16_FWD_N(str.u, end, str_len, l);
RETURN_UNICODEL(str.u + start, end-start, ZSTR_DUPLICATE);
Since codepoint (character) #n is not necessarily at offset #n in Unicode
strings, we start at the beginning and iterate forward until we have gone
through the required number of codepoints to reach the start of the segment.
Then we save the location in 'start' and continue iterating through the number
of codepoints specified by the offset. Once that's done, we can return the
segment as a Unicode string.
} else {
RETURN_STRINGL(str.s + f, l, ZSTR_DUPLICATE);
}
For native strings, we can return the segment directly.
strrev()
--------
Let's look at strrev() which requires somewhat more complicated upgrade.
While one of the guidelines for upgrades is that combining sequences are not
really taken into account during processing -- substr() can break them up,
for example -- in this case, we actually should be concerned, because
reversing combining sequence may result in a completely different string. To
illustrate:
a (U+0061 LATIN SMALL LETTER A)
o (U+006f LATIN SMALL LETTER O)
+ ' (U+0301 COMBINING ACUTE ACCENT)
+ _ (U+0320 COMBINING MINUS SIGN BELOW)
l (U+006C LATIN SMALL LETTER L)
Reversing this would result in:
l (U+006C LATIN SMALL LETTER L)
+ _ (U+0320 COMBINING MINUS SIGN BELOW)
+ ' (U+0301 COMBINING ACUTE ACCENT)
o (U+006f LATIN SMALL LETTER O)
a (U+0061 LATIN SMALL LETTER A)
All of a sudden the combining marks are being applied to 'l' instead of 'o'.
To avoid this, we need to treat combininig sequences as a unit, by checking
the combining character class of each character with u_getCombiningClass().
strrev() obtains its single argument, a string, and unless the string is of
Unicode type, processes it exactly as before, simply swapping bytes around.
For Unicode case, the magic is like this:
int32_t i, x1, x2;
UChar32 ch;
UChar *u_s, *u_n, *u_p;
u_n = eumalloc(Z_USTRLEN_PP(str)+1);
u_p = u_n;
u_s = Z_USTRVAL_PP(str);
i = Z_USTRLEN_PP(str);
while (i > 0) {
U16_PREV(u_s, 0, i, ch);
if (u_getCombiningClass(ch) == 0) {
u_p += zend_codepoint_to_uchar(ch, u_p);
} else {
x2 = i;
do {
U16_PREV(u_s, 0, i, ch);
} while (u_getCombiningClass(ch) != 0);
x1 = i;
while (x1 <= x2) {
U16_NEXT(u_s, x1, Z_USTRLEN_PP(str), ch);
u_p += zend_codepoint_to_uchar(ch, u_p);
}
}
}
*u_p = 0;
The basic idea is to walk the string backwards from the end, using
U16_PREV() macro. If the combining class of the current character is 0,
meaning it's a base character and not a combining mark, we simply append it
to the new string. Otherwise, we save the location of the index and do a run
over the characters until we get to the next one with combining class 0. At
that point we append the sequence as is, without reversing, to the new
string. Voila.
Note that the code uses zend_codepoint_to_uchar() to convert full Unicode
characters (UChar32 type) to 1 or 2 UTF-16 code units (UChar type).
realpath()
----------
Filenames use their own converter as it's not uncommon, for example,
to need to access files on a filesystem with latin1 entries while outputting
UTF8 runtime content.
The most common approach to parsing filenames can be found in realpath():
zval **ppfilename;
char *filename;
int filename_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &ppfilename) == FAILURE ||
php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
return;
}
Here, the filename is taken first as a generic zval**, then converted (separating if necessary)
and populated into local char* and int storage. The filename will be converted according to
unicode.filesystem_encoding unless the wrapper specified overrides this with its own conversion
function (The http:// wrapper, for example, enforces utf8 conversion).
rmdir()
-------
If the function accepts a context parameter, then this context should be used in place of FG(default_context)
zval **ppdir, *zcontext = NULL;
char *dir;
int dir_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|r", &ppdir, &zcontext) == FAILURE) {
return;
}
context = php_stream_context_from_zval(zcontext, 0);
if (php_stream_path_param_encode(ppdir, &dir, &dir_len, REPORT_ERRORS, context) == FAILURE) {
return;
}
sqlite_query()
--------------
If the function's underlying library expects a particular encoding (i.e. UTF8), then the alternate form of
the string parameter may be used with zend_parse_parameters().
char *sql;
int sql_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &sql, &sql_len, UG(utf8_conv)) == FAILURE) {
return;
}
Converters
==========
Standard Converters
-------------------
The following converters (UConverter*) are initialized by Zend and are always available (regardless of UG(unicode) mode):
UG(utf8_conv)
UG(ascii_conv)
UG(fallback_encoding_conv) - UTF8 unless overridden by INI setting unicode.fallback_encoding
Additional converters will be optionally initialized depending on INI settings:
UG(runtime_encoding_conv) - unicode.runtime_encoding
. Unicode output generated by a script will be encoding using this converter
UG(script_encoding_conv) - unicode.script_encoding
. Scripts read from disk will be decoded using this converter
UG(filesystem_encoding_conv) - unicode.filesystem_encoding
. Filenames and paths will be encoding using this converter
Since these additional converters may not be instatiated (because their INI value is not set), all uses of these converters must
be wrapped in ZEND_U_CONVERTER() for safety. If the converter hasn't been instantiated, then UG(fallback_encoding_conv) will be
used instead.
For example, RETURN_RT_STRING("foo", ZSTR_DUPLICATE); expands out to:
RETURN_U_STRING(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), "foo", ZSTR_DUPLICATE);
Which uses UG(runtime_encoding_conv) if it's been set, otherwise using UG(fallback_encoding_conv).
Note that the INI setting unicode.stream_encoding does not instantiate a UConverter* automatically for use by the process/thread,
it stores the value as a string for use during fopen() style calls where a UConverter* is instantiated for that particular stream.
References
==========
[1] http://icu.sourceforge.net/apiref/icu4c/ustring_8h.html#a1
[2] http://icu.sourceforge.net/apiref/icu4c/utf16_8h.html
vim: set et ai tw=76 fo=tron21:
-123
View File
@@ -1,123 +0,0 @@
PHP Build System V5 Overview
- supports Makefile.ins during transition phase
- not-really-portable Makefile includes have been eliminated
- supports separate build directories without VPATH by using
explicit rules only
- does not waste disk-space/CPU-time for building temporary libraries
=> especially noticeable on slower systems
- slow recursive make replaced with one global Makefile
- eases integration of proper dependencies
- adds PHP_DEFINE(what[, value]) which creates a single include-file
per what. This will allow more fine-grained dependencies.
- abandoning the "one library per directory" concept
- improved integration of the CLI
- several new targets
build-modules: builds and copies dynamic modules into modules/
install-cli: installs the CLI only, so that the install-sapi
target does only what its name says
- finally abandoned automake (still requires aclocal at this time)
- changed some configure-time constructs to run at buildconf-time
- upgraded shtool to 1.5.4
- removed $(moduledir) (use EXTENSION_DIR)
The Reason For a New System
It became more and more apparent that there is a severe need
for addressing the portability concerns and improving the chance
that your build is correct (how often have you been told to
"make clean"? When this is done, you won't need to anymore).
If You Build PHP on a Unix System
You, as a user of PHP, will notice no changes. Of course, the build
system will be faster, look better and work smarter.
If You Are Developing PHP
Extension developers:
Makefile.ins are abandoned. The files which are to be compiled
are specified in the config.m4 now using the following macro:
PHP_NEW_EXTENSION(foo, foo.c bar.c baz.cpp, $ext_shared)
E.g. this enables the extension foo which consists of three source-code
modules, two in C and one in C++. And, depending on the user's wishes,
the extension will even be built as a dynamic module.
The full syntax:
PHP_NEW_EXTENSION(extname, sources [, shared [,sapi_class[, extra-cflags]]])
Please have a look at acinclude.m4 for the gory details and meanings
of the other parameters.
And that's basically it for the extension side.
If you previously built sub-libraries for this module, add
the source-code files here as well. If you need to specify
separate include directories, do it this way:
PHP_NEW_EXTENSION(foo, foo.c mylib/bar.c mylib/gregor.c,,,-I@ext_srcdir@/lib)
E.g. this builds the three files which are located relative to the
extension source directory and compiles all three files with the
special include directive (@ext_srcdir@ is automatically replaced).
Now, you need to tell the build system that you want to build files
in a directory called $ext_builddir/lib:
PHP_ADD_BUILD_DIR($ext_builddir/lib)
Make sure to call this after PHP_NEW_EXTENSION, because $ext_builddir
is only set by the latter.
If you have a complex extension, you might to need add special
Make rules. You can do this by calling PHP_ADD_MAKEFILE_FRAGMENT
in your config.m4 after PHP_NEW_EXTENSION.
This will read a file in the source-dir of your extension called
Makefile.frag. In this file, $(builddir) and $(srcdir) will be
replaced by the values which are correct for your extension
and which are again determined by the PHP_NEW_EXTENSION macro.
Make sure to prefix *all* relative paths correctly with either
$(builddir) or $(srcdir). Because the build system does not
change the working directory anymore, we must use either
absolute paths or relative ones to the top build-directory.
Correct prefixing ensures that.
SAPI developers:
Instead of using PHP_SAPI=foo/PHP_BUILD_XYZ, you will need to type
PHP_SELECT_SAPI(name, type, sources.c)
I.e. specify the source-code files as above and also pass the
information regarding how PHP is supposed to be built (shared
module, program, etc).
For example for APXS:
PHP_SELECT_SAPI(apache, shared, sapi_apache.c mod_php5.c php_apache.c)
General info
The foundation for the new system is the flexible handling of
sources and their contexts. With the help of macros you
can define special flags for each source-file, where it is
located, in which target context it can work, etc.
Have a look at the well documented macros
PHP_ADD_SOURCES(_X) in acinclude.m4.
-172
View File
@@ -1,172 +0,0 @@
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>
-174
View File
@@ -1,174 +0,0 @@
The Win32 Build System.
$Id$
Wez Furlong <wez@thebrainroom.com>
If you need help with the build system, send mail to
internals@lists.php.net; please don't email me directly.
===========================================================
Contents:
1. How to build PHP under windows
a. Requirements
b. Opening a command prompt
c. Generating configure.js
d. Configuring
e. Building
f. Cleaning up
g. Running the test suite
h. snapshot building
2. How to write config.w32 files
x. to be written.
===========================================================
1. How to build PHP under windows
a. Requirements
You need:
- Windows Scripting Host (cscript.exe)
- Microsoft Build Tools from:
Microsoft Visual Studio (VC6) or later
You also need:
- bindlib_w32 [http://www.php.net/extra/bindlib_w32.zip]
- win32build [http://www.php.net/extra/win32build.zip]
b. Opening the Build Environment Command Prompt:
- Using Visual Studio (VC6)
1. Install it
2. If you have a VC++ Command Prompt icon on your start menu,
click on it to get a Command Prompt with the env vars
set up correctly.
If not, create a new shortcut and set the Target to:
%comspec% /k "C:\Program Files\Microsoft Visual Studio\VC98\Bin\vcvars32.bat"
You might also want to set the prompt to start in
a convenient location (such as the root of your
PHP source checkout).
- Using Visual Studio .Net
1. Install it.
2. Under the Visual Studio .Net Tools sub menu of your start
menu, you should have a Visual Studio .Net Command Prompt
icon. If not, create a new shortcut and set the Target to:
%comspec% /k "C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat"
You might also want to set the prompt to start in
a convenient location (such as the root of your
PHP source checkout).
- Using the Platform SDK tools
1. Download the Platform SDK:
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
- You need the Core SDK, which is approx 200MB to download
and requires approx 500MB of disk space.
- The other components of the SDK are not required by PHP
- You might be able to reduce the download size by downloading
the installer control component first and then selecting
only the Build Environment (around 30MB), but I haven't
tried this.
** Note: it seems that MS don't include the 32 bit
build tools in the platform SDK any longer, so
you will probably have very limited luck if you
don't also have VC++ or VS.Net already installed.
2. Once installed, you will have an icon on your start menu
that will launch the build environment; the latest SDK's
install a number of different versions of this; you probably
want to choose the Windows 2000 Retail build environment.
Clicking on this will open a command prompt with its Path,
Include and Lib env vars set to point to the build tools
and win32 headers.
c. Generating configure
Change directory to where you have your PHP sources.
Run buildconf.bat.
d. Configuring
cscript /nologo configure.js --help
Will give you a list of configuration options; these will
have the form:
--enable-foo or --disable-foo or --with-foo or --without-foo.
--enable-foo will turn something on, and is equivalent to
specifying --enable-foo=yes
--disable-foo will turn something off, and is equivalent to
specifying --enable-foo=no
--enable-foo=shared will attempt to build that feature as
a shared, dynamically loadable module.
Sometimes a configure option needs additional information
about where to find headers and libraries; quite often
you can specify --enable-foo=option where option could be
the path to where to find those files. If you want to
specify a parameter and build it as shared, you can use
this syntax instead: --enable-foo=shared,option
The same rules all apply to --with-foo and --without-foo;
the only difference is the way the options are named;
the convention is that --enable-foo means that you are
switching on something that comes with PHP, whereas
--with-foo means that you want to build in something
external to PHP.
e. Building
Once you have successfully configured your build (make
sure you read the output from the command to make sure
it worked correctly), you can build the code; simply type
"nmake" at the command prompt, and it will build everthing
you asked for.
Once the build has completed, you will find your binaries
in the build dir determined by configure; this is typically
Release_TS for release builds or Debug_TS for debug builds.
If you build a non-thread-safe build, it will use Release
or Debug to store the files. Also in this build dir you
will find sub directories for each module that went into
your PHP build. The files you'll want to keep are the
.exe and .dll files directly in your build dir.
f. Cleaning Up
You can automatically delete everything that was built
by running "nmake clean". This will delete everything
that was put there when you ran nmake, including the
.exe and .dll files.
g. Running the test suite
You can verify that your build is working well by running
the regression test suite. You do this by typing
"nmake test". You can specify the tests you want to run
by defing the TESTS variable - if you wanted to run the
sqlite test suite only, you would type
"nmake /D TESTS=ext/sqlite/tests test"
h. Snapshot Building
If you want to set up an automated build that will tolerate
breakages in some of the modules, you can use the
--enable-snapshot-build configure option to generate a
makefile optimized for that purpose. A snapshot build will
switch the argument parser so that the default option for
configure switches that your don't specify will be set
to "shared". The effect of this is to turn on all options
unless you explicitly disable them. When you have configured
your snapshot build, you can use "nmake build-snap" to build
everything, ignoring build errors in individual extensions
or SAPI.
vim:tw=78:sw=1:ts=1:et
-112
View File
@@ -1,112 +0,0 @@
Using PHP 5 with the Zeus Web Server
-----------------------------------
Zeus fully supports running PHP in combination with our
webserver. There are three different interfaces that can be used to
enable PHP:
* CGI
* ISAPI
* FastCGI
Of the three, we recommend using FastCGI, which has been tested and
benchmarked as providing the best performance and reliability.
Full details of how to install PHP are available from our
website, at:
http://support.zeus.com/products/php.html
If you have any problems, please check the support site for more
up-to-date information and advice.
Quick guide to installing CGI/FastCGI with Zeus
-----------------------------------------------
Step 1 - Compile PHP as FastCGI.
Compile as follows:
./configure --enable-fastcgi
make
Note that PHP has many options to the configure script -
e.g. --with-mysql. You will probably want to select your usual options
before compiling; the above is just a bare minimum, for illustration.
After compilation finishes, you will be left with an executable
program called 'php'. Copy this into your document root, under a
dedicated FastCGI directory (e.g. $DOCROOT/fcgi-bin/php)
Step 2 - configure Zeus
Four stages:
- enable FastCGI
- configure FastCGI
- setup alias for FastCGI
- setup alias for PHP
1) Using the admin server, go to the 'module configuration' page for
your virtual server, and ensure that 'fastcgi' is enabled (select the
tickbox to the left).
2) While we can run FastCGI's locally, there are known problems with
some OS's (specifically, the communication between web server and
FastCGI happens over a unix domain socket, and some OS's have trouble
sustaining high connection rates over these sockets). So instead, we
are going to set up the PHP FastCGI to run 'remotely' over localhost
(this uses TCP sockets, which do not suffer this problem). Go to the
'fastcgi configuration' page, and under 'add remote fastcgi':
Add Remote FastCGI
Docroot path /fcgi-bin/php
Remote machine localhost:8002
The first entry is where you saved PHP, above.
The second entry is localhost:<any unused port>
We will start the FastCGI listening on this port shortly.
Click 'update' to commit these changes.
3) Go to the path mapping module and add an alias for FastCGI:
Add Alias
Docroot path /fcgi-bin
Filesystem directory /path/to/docroot/fcgi-bin
Alias type fastcgi
Click 'update' to commit these changes
4) Also on the path mapping module, add a handler for PHP:
Add handler
File extension php
Handler /fcgi-bin/php
Click 'update' to commit these changes
Finally restart your virtual server for these changes to take effect.
Step 3 - start PHP as a FastCGI runner
When you start PHP, it will pre-fork a given number of child processes
to handle incoming PHP requests. Each process will handle a given
number of requests before exiting (and being replaced by a newly
forked process). You can control these two parameters by setting the
following environment variables BEFORE starting the FastCGI runner:
PHP_FCGI_CHILDREN - the number of child processes to pre-fork. This
variable MUST be set, if not then the PHP will not run as a FastCGI.
We recommend a value of 8 for a fairly busy site. If you have many,
long-running PHP scripts, then you may need to increase this further.
PHP_FCGI_MAX_REQUESTS - the number of requests each PHP child process
handles before exiting. If not set, defaults to 500.
To start the FastCGI runner, execute '$ZEUSHOME/web/bin/fcgirunner
8002 $DOCROOT/fcgi-bin/php'. Substitute the appropriate values for
$ZEUSHOME and $DOCROOT; also substitute for 8002 the port you chose,
above.
To stop the runner (e.g. to experiment with the above environment
variables) you will need to manually stop and running PHP
processes. (Use 'ps' and 'kill'). As it is PHP which is forking lots
of children and not the runner, Zeus unfortunately cannot keep track
of what processes are running, sorry. A typical command line may look
like 'ps -efl | grep $DOCROOT/fcgi-bin/php | grep -v grep | awk
'{print $4}' | xargs kill'
-193
View File
@@ -1,193 +0,0 @@
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);
}
-174
View File
@@ -1,174 +0,0 @@
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?
-152
View File
@@ -1,152 +0,0 @@
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)
global
------
* Make sure that all ZTS globals get destructed. Most ts_allocate_id()
calls should have a dtor entry.
* on some platforms unimplemented function will just do nothing
(e.g. symlink) they should print a warning or not even be defined!
(DONE ?)
* --enable-all in configure. (--enable-shared=max ...)
* make configure print out a summary when it's done (like XEmacs)
* replace standard functions which work on static data with
reentrancy-safe functions (DONE?).
* make SAPI conform to CGI/1.1. Currently, all SAPI modules
define REMOTE_ADDR etc. themselves and reach only various level
of compliance.
* see what functions might need to be changed to use HashPosition, so
that the internal array pointer is not affected.
Other
* use thread-safe resolver functions (either require BIND 8 or adns).
* implement javadoc based function docs template system.
* provide optional IPv6 support (seems to be done?).
* find a better way to implement script timeouts. SIGVTALRM is used
by some POSIX threads implementations (i.e. OpenBSD) and is not
available in ZTS mode.
* Implement flush feature suitable for nested output buffers.
Streams
-------
* Route filestat.c through the wrapper layer; isolate the statcache code
so that it is independent of php functions and can be applied to any
stream/path.
* Implement generalized connection pool for stated protocols such as
ftp and http/1.1 (using keep-alive) to avoid having to negotiate
new command/request stream for each subsequent call; Possibly store
resources in contexts (creating a default context if necessary) to
allow segmentation of connection pools.
* Add a method to take ownership of the memory buffer in memory streams so
that generating string values for zvals doesn't require an estrdup.
* bundle and use curl lib for fopen wrapper.
documentation
-------------
* Add remarks in the documentation which functions are not implemented
on win32.
* Add remarks in the documentation which functions are not binary-safe.
* Update curl documentation (DONE?)
* Add developer documentation.
* Add detailed documentation for Java extension.
ext/bz2
-------
* Add an ini directive to specify the size of decompression buffer.
The default 4k is too small for large files and also requires much time
for decompression. 40k is suitable for such files, however it may be too
much under certain environments. There should be appropriate default
settings for the various SAPI modules (e.g. apache and cli).
ext/curl
--------
* Have a warning scheme for when people use unsupported features.
ext/oci8
--------
* All OCIFetch*() functions should return 0 for no more data and false on
error.
* Have a flag that trims trailing spaces from CHAR fields on retrieval.
* Make allow_call_time_pass_reference=Off working.
* For additional todo information, see oci8.c, in ext/oci8
ext/odbc
--------
For PHP 4.3.0:
* update all php_error calls to php_error_docref where valid
* integrate EXPERIMENTAL ODBC update for use in PHP 5.0, use for
testing purposes only.
For PHP 5.0.0
* Activate EXPERIMENTAL ODBC codebase update
ext/pcre
--------
* Allow user to set PCRE_NOTEMPTY, PCRE_ANCHORED at execution time, maybe
ext/pcntl
---------
* Change internal callback handler to use TICKS
* Remove all zend_extension code
* Add object callback support to pcntl_signal()
ext/pgsql
---------
For PHP 4.3.0:
* Add pg_metadata() with metadata cache feature.
* Add pg_convert() to check and convert array value for query.
* Add pg_insert/pg_update/pg_delete/pg_select for simple query.
ext/session
-----------
For PHP 4.3.0:
* session_abort() to abort session. ie: Do not save session data.
* Allow unset($_SESSION) or unset($HTTP_SESSION_VARS) to unset
session vars regardless of register_globals setting.
Other:
* Maybe implement finer-grained session variables that could be
locked individually.
* Write a network-transparent storage back-end with fallover
facilities
* Provide a callback facility which is executed upon encountering
an unknown class name during deserialization
ext/standard
------------
* Add a version number to data serialized via serialize().
* Possibly modify parsing of GPC data to automatically create arrays if
variable name is seen more than once.
* Implement regex-cache for url-functions.
* Move socket related functions to fsock.c.
ext/wddx
--------
* See if we can support the remaining data types:
dateTime
binary
http://www.wddx.org/WDDX_SDK_10a/7__References/WDDX_DTD.htm
(Andrei)
* implement wddx_packet_as_javascript(). (Andrei)
other cool stuff
----------------
* PVM extension
vim:et:sw=4:ts=4
-5
View File
@@ -1,5 +0,0 @@
Zend Engine
-----------
- Look at making zend_constant value member be a zval* instead of zval. (Andi)
- Implement inheritance rules for type hints. (Marcus)
- Find a keyword for the if-set-or operator (apply the patch). (Marcus, all)
-109
View File
@@ -1,109 +0,0 @@
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
-26
View File
@@ -1,26 +0,0 @@
Copyright (c) 1999-2006, Andi Gutmans, Sascha Schumann, Zeev Suraski.
All rights reserved.
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 notice,
this list of conditions and the following disclaimer.
- Neither name of the copyright holders nor the names of their 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 HOLDERS 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.
-6
View File
@@ -1,6 +0,0 @@
## process this file with automake to produce Makefile.am
AUTOMAKE_OPTIONS=foreign
noinst_LTLIBRARIES=libtsrm.la
libtsrm_la_SOURCES = TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c
depend:
-2
View File
@@ -1,2 +0,0 @@
- Improve the lock in ts_resource_ex() in order to cover less code.
This can probably be done by more careful hash table access
-778
View File
@@ -1,778 +0,0 @@
/*
+----------------------------------------------------------------------+
| Thread Safe Resource Manager |
+----------------------------------------------------------------------+
| Copyright (c) 1999-2008, 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@zend.com> |
+----------------------------------------------------------------------+
*/
#include "TSRM.h"
#ifdef ZTS
#include <stdio.h>
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
typedef struct _tsrm_tls_entry tsrm_tls_entry;
struct _tsrm_tls_entry {
void **storage;
int count;
THREAD_T thread_id;
tsrm_tls_entry *next;
};
typedef struct {
size_t size;
ts_allocate_ctor ctor;
ts_allocate_dtor dtor;
int done;
} tsrm_resource_type;
/* The memory manager table */
static tsrm_tls_entry **tsrm_tls_table=NULL;
static int tsrm_tls_table_size;
static ts_rsrc_id id_count;
/* The resource sizes table */
static tsrm_resource_type *resource_types_table=NULL;
static int resource_types_table_size;
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
/* New thread handlers */
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, ...);
/* Read a resource from a thread's resource storage */
static int tsrm_error_level;
static FILE *tsrm_error_file;
#if TSRM_DEBUG
#define TSRM_ERROR(args) tsrm_error args
#define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
{ \
int unshuffled_offset = TSRM_UNSHUFFLE_RSRC_ID(offset); \
\
if (offset==0) { \
return &array; \
} else if ((unshuffled_offset)>=0 && (unshuffled_offset)<(range)) { \
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Successfully fetched resource id %d for thread id %ld - 0x%0.8X", \
unshuffled_offset, (long) thread_resources->thread_id, array[unshuffled_offset])); \
return array[unshuffled_offset]; \
} else { \
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Resource id %d is out of range (%d..%d)", \
unshuffled_offset, TSRM_SHUFFLE_RSRC_ID(0), TSRM_SHUFFLE_RSRC_ID(thread_resources->count-1))); \
return NULL; \
} \
}
#else
#define TSRM_ERROR(args)
#define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
if (offset==0) { \
return &array; \
} else { \
return array[TSRM_UNSHUFFLE_RSRC_ID(offset)]; \
}
#endif
#if defined(PTHREADS)
/* Thread local storage */
static pthread_key_t tls_key;
# define tsrm_tls_set(what) pthread_setspecific(tls_key, (void*)(what))
# define tsrm_tls_get() pthread_getspecific(tls_key)
#elif defined(TSRM_ST)
static int tls_key;
# define tsrm_tls_set(what) st_thread_setspecific(tls_key, (void*)(what))
# define tsrm_tls_get() st_thread_getspecific(tls_key)
#elif defined(TSRM_WIN32)
static DWORD tls_key;
# define tsrm_tls_set(what) TlsSetValue(tls_key, (void*)(what))
# define tsrm_tls_get() TlsGetValue(tls_key)
#elif defined(BETHREADS)
static int32 tls_key;
# define tsrm_tls_set(what) tls_set(tls_key, (void*)(what))
# define tsrm_tls_get() (tsrm_tls_entry*)tls_get(tls_key)
#else
# define tsrm_tls_set(what)
# define tsrm_tls_get() NULL
# warning tsrm_set_interpreter_context is probably broken on this platform
#endif
/* Startup TSRM (call once for the entire process) */
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
{
#if defined(GNUPTH)
pth_init();
#elif defined(PTHREADS)
pthread_key_create( &tls_key, 0 );
#elif defined(TSRM_ST)
st_init();
st_key_create(&tls_key, 0);
#elif defined(TSRM_WIN32)
tls_key = TlsAlloc();
#elif defined(BETHREADS)
tls_key = tls_allocate();
#endif
tsrm_error_file = stderr;
tsrm_error_set(debug_level, debug_filename);
tsrm_tls_table_size = expected_threads;
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"));
return 0;
}
id_count=0;
resource_types_table_size = expected_resources;
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"));
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));
return 1;
}
/* Shutdown TSRM (call once for the entire process) */
TSRM_API void tsrm_shutdown(void)
{
int i;
if (tsrm_tls_table) {
for (i=0; i<tsrm_tls_table_size; i++) {
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
while (p) {
int j;
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(tsrm_tls_table);
tsrm_tls_table = NULL;
}
if (resource_types_table) {
free(resource_types_table);
resource_types_table=NULL;
}
tsrm_mutex_free(tsmm_mutex);
tsmm_mutex = NULL;
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM"));
if (tsrm_error_file!=stderr) {
fclose(tsrm_error_file);
}
#if defined(GNUPTH)
pth_kill();
#elif defined(PTHREADS)
pthread_setspecific(tls_key, 0);
pthread_key_delete(tls_key);
#elif defined(TSRM_WIN32)
TlsFree(tls_key);
#endif
}
/* 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);
/* obtain a resource id */
*rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
/* store the new resource type in the resource sizes table */
if (resource_types_table_size < id_count) {
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_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)].done = 0;
/* 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];
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++) {
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;
}
}
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(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);
if (tsrm_new_thread_begin_handler) {
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
{
(*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], &(*thread_resources_ptr)->storage);
}
}
}
if (tsrm_new_thread_end_handler) {
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
* ts_resource_ex(). This avoids the need for a mutex lock
* and our hashtable lookup.
*/
thread_resources = tsrm_tls_get();
if (thread_resources) {
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id));
/* Read a specific resource from the thread's resources.
* This is called outside of a mutex, so have to be aware about external
* changes to the structure as we read it.
*/
TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
}
thread_id = tsrm_thread_id();
} else {
thread_id = *th_id;
}
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for thread %ld", id, (long) thread_id));
tsrm_mutex_lock(tsmm_mutex);
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
thread_resources = tsrm_tls_table[hash_value];
if (!thread_resources) {
allocate_new_resource(&tsrm_tls_table[hash_value], thread_id);
return ts_resource_ex(id, &thread_id);
} else {
do {
if (thread_resources->thread_id == thread_id) {
break;
}
if (thread_resources->next) {
thread_resources = thread_resources->next;
} else {
allocate_new_resource(&thread_resources->next, thread_id);
return ts_resource_ex(id, &thread_id);
/*
* thread_resources = thread_resources->next;
* break;
*/
}
} while (thread_resources);
}
tsrm_mutex_unlock(tsmm_mutex);
/* Read a specific resource from the thread's resources.
* This is called outside of a mutex, so have to be aware about external
* changes to the structure as we read it.
*/
TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
#ifdef NETWARE
} /* if(tsrm_tls_table) */
#endif
}
/* frees an interpreter context. You are responsible for making sure that
* it is not linked into the TSRM hash, and not marked as the current interpreter */
void tsrm_free_interpreter_context(void *context)
{
tsrm_tls_entry *next, *thread_resources = (tsrm_tls_entry*)context;
int i;
while (thread_resources) {
next = thread_resources->next;
for (i=0; i<thread_resources->count; i++) {
if (resource_types_table[i].dtor) {
resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
}
}
for (i=0; i<thread_resources->count; i++) {
free(thread_resources->storage[i]);
}
free(thread_resources->storage);
free(thread_resources);
thread_resources = next;
}
}
void *tsrm_set_interpreter_context(void *new_ctx)
{
tsrm_tls_entry *current;
current = tsrm_tls_get();
/* TODO: unlink current from the global linked list, and replace it
* it with the new context, protected by mutex where/if appropriate */
/* Set thread local storage to this new thread resources structure */
tsrm_tls_set(new_ctx);
/* return old context, so caller can restore it when they're done */
return current;
}
/* allocates a new interpreter context */
void *tsrm_new_interpreter_context(void)
{
tsrm_tls_entry *new_ctx, *current;
THREAD_T thread_id;
thread_id = tsrm_thread_id();
tsrm_mutex_lock(tsmm_mutex);
current = tsrm_tls_get();
allocate_new_resource(&new_ctx, thread_id);
/* switch back to the context that was in use prior to our creation
* of the new one */
return tsrm_set_interpreter_context(current);
}
/* frees all resources allocated for the current thread */
void ts_free_thread(void)
{
tsrm_tls_entry *thread_resources;
int i;
THREAD_T thread_id = tsrm_thread_id();
int hash_value;
tsrm_tls_entry *last=NULL;
tsrm_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;
}
tsrm_tls_set(0);
free(thread_resources);
break;
}
if (thread_resources->next) {
last = thread_resources;
}
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);
tsrm_mutex_lock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Freeing resource id %d", id));
if (tsrm_tls_table) {
for (i=0; i<tsrm_tls_table_size; i++) {
tsrm_tls_entry *p = tsrm_tls_table[i];
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], &p->storage);
}
free(p->storage[j]);
p->storage[j] = NULL;
}
p = p->next;
}
}
}
resource_types_table[j].done = 1;
tsrm_mutex_unlock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id));
}
/*
* Utility Functions
*/
/* 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));
InitializeCriticalSection(mutexp);
#elif defined(GNUPTH)
mutexp = (MUTEX_T) malloc(sizeof(*mutexp));
pth_mutex_init(mutexp);
#elif defined(PTHREADS)
mutexp = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexp,NULL);
#elif defined(NSAPI)
mutexp = crit_init();
#elif defined(PI3WEB)
mutexp = PIPlatform_allocLocalMutex();
#elif defined(TSRM_ST)
mutexp = st_mutex_new();
#elif defined(BETHREADS)
mutexp = (beos_ben*)malloc(sizeof(beos_ben));
mutexp->ben = 0;
mutexp->sem = create_sem(1, "PHP sempahore");
#endif
#ifdef THR_DEBUG
printf("Mutex created thread: %d\n",mythreadid());
#endif
return( mutexp );
}
/* Free a mutex */
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
{
if (mutexp) {
#ifdef TSRM_WIN32
DeleteCriticalSection(mutexp);
free(mutexp);
#elif defined(GNUPTH)
free(mutexp);
#elif defined(PTHREADS)
pthread_mutex_destroy(mutexp);
free(mutexp);
#elif defined(NSAPI)
crit_terminate(mutexp);
#elif defined(PI3WEB)
PISync_delete(mutexp);
#elif defined(TSRM_ST)
st_mutex_destroy(mutexp);
#elif defined(BETHREADS)
delete_sem(mutexp->sem);
free(mutexp);
#endif
}
#ifdef THR_DEBUG
printf("Mutex freed thread: %d\n",mythreadid());
#endif
}
/*
Lock a mutex.
A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
{
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
EnterCriticalSection(mutexp);
return 0;
#elif defined(GNUPTH)
if (pth_mutex_acquire(mutexp, 0, NULL)) {
return 0;
}
return -1;
#elif defined(PTHREADS)
return pthread_mutex_lock(mutexp);
#elif defined(NSAPI)
crit_enter(mutexp);
return 0;
#elif defined(PI3WEB)
return PISync_lock(mutexp);
#elif defined(TSRM_ST)
return st_mutex_lock(mutexp);
#elif defined(BETHREADS)
if (atomic_add(&mutexp->ben, 1) != 0)
return acquire_sem(mutexp->sem);
return 0;
#endif
}
/*
Unlock a mutex.
A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
{
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
LeaveCriticalSection(mutexp);
return 0;
#elif defined(GNUPTH)
if (pth_mutex_release(mutexp)) {
return 0;
}
return -1;
#elif defined(PTHREADS)
return pthread_mutex_unlock(mutexp);
#elif defined(NSAPI)
crit_exit(mutexp);
return 0;
#elif defined(PI3WEB)
return PISync_unlock(mutexp);
#elif defined(TSRM_ST)
return st_mutex_unlock(mutexp);
#elif defined(BETHREADS)
if (atomic_add(&mutexp->ben, -1) != 1)
return release_sem(mutexp->sem);
return 0;
#endif
}
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;
}
/*
* Debug support
*/
#if TSRM_DEBUG
int tsrm_error(int level, const char *format, ...)
{
if (level<=tsrm_error_level) {
va_list args;
int size;
fprintf(tsrm_error_file, "TSRM: ");
va_start(args, format);
size = vfprintf(tsrm_error_file, format, args);
va_end(args);
fprintf(tsrm_error_file, "\n");
fflush(tsrm_error_file);
return size;
} else {
return 0;
}
}
#endif
void tsrm_error_set(int level, char *debug_filename)
{
tsrm_error_level = level;
#if TSRM_DEBUG
if (tsrm_error_file!=stderr) { /* close files opened earlier */
fclose(tsrm_error_file);
}
if (debug_filename) {
tsrm_error_file = fopen(debug_filename, "w");
if (!tsrm_error_file) {
tsrm_error_file = stderr;
}
} else {
tsrm_error_file = stderr;
}
#endif
}
#endif /* ZTS */
-186
View File
@@ -1,186 +0,0 @@
# 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
-179
View File
@@ -1,179 +0,0 @@
/*
+----------------------------------------------------------------------+
| Thread Safe Resource Manager |
+----------------------------------------------------------------------+
| Copyright (c) 1999-2008, 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@zend.com> |
+----------------------------------------------------------------------+
*/
#ifndef TSRM_H
#define TSRM_H
#if !defined(__CYGWIN__) && defined(WIN32)
# define TSRM_WIN32
# include "tsrm_config.w32.h"
#else
# include <tsrm_config.h>
#endif
#ifdef TSRM_WIN32
# ifdef TSRM_EXPORTS
# define TSRM_API __declspec(dllexport)
# else
# define TSRM_API __declspec(dllimport)
# endif
#elif defined(__GNUC__) && __GNUC__ >= 4
# define TSRM_API __attribute__ ((visibility("default")))
#else
# define TSRM_API
#endif
#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
#ifdef TSRM_WIN32
# ifndef TSRM_INCLUDE_FULL_WINDOWS_HEADERS
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <shellapi.h>
#elif defined(GNUPTH)
# include <pth.h>
#elif defined(PTHREADS)
# include <pthread.h>
#elif defined(TSRM_ST)
# include <st.h>
#elif defined(BETHREADS)
#include <kernel/OS.h>
#include <TLS.h>
#endif
typedef int ts_rsrc_id;
/* Define THREAD_T and MUTEX_T */
#ifdef TSRM_WIN32
# define THREAD_T DWORD
# define MUTEX_T CRITICAL_SECTION *
#elif defined(GNUPTH)
# define THREAD_T pth_t
# define MUTEX_T pth_mutex_t *
#elif defined(PTHREADS)
# define THREAD_T pthread_t
# define MUTEX_T pthread_mutex_t *
#elif defined(NSAPI)
# define THREAD_T SYS_THREAD
# define MUTEX_T CRITICAL
#elif defined(PI3WEB)
# define THREAD_T PIThread *
# define MUTEX_T PISync *
#elif defined(TSRM_ST)
# define THREAD_T st_thread_t
# define MUTEX_T st_mutex_t
#elif defined(BETHREADS)
# define THREAD_T thread_id
typedef struct {
sem_id sem;
int32 ben;
} beos_ben;
# define MUTEX_T beos_ben *
#endif
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
#ifdef __cplusplus
extern "C" {
#endif
/* startup/shutdown */
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename);
TSRM_API void tsrm_shutdown(void);
/* allocates a new thread-safe-resource id */
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
/* 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)
/* 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);
/* Debug support */
#define TSRM_ERROR_LEVEL_ERROR 1
#define TSRM_ERROR_LEVEL_CORE 2
#define TSRM_ERROR_LEVEL_INFO 3
typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id, void ***tsrm_ls);
typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id, void ***tsrm_ls);
TSRM_API int tsrm_error(int level, const char *format, ...);
TSRM_API void tsrm_error_set(int level, char *debug_filename);
/* utility functions */
TSRM_API THREAD_T tsrm_thread_id(void);
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);
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);
/* these 3 APIs should only be used by people that fully understand the threading model
* used by PHP/Zend and the selected SAPI. */
TSRM_API void *tsrm_new_interpreter_context(void);
TSRM_API void *tsrm_set_interpreter_context(void *new_ctx);
TSRM_API void tsrm_free_interpreter_context(void *context);
#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
#define TSRMLS_FETCH() void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL)
#define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
#define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
#define TSRMLS_D void ***tsrm_ls
#define TSRMLS_DC , TSRMLS_D
#define TSRMLS_C tsrm_ls
#define TSRMLS_CC , TSRMLS_C
#ifdef __cplusplus
}
#endif
#else /* non ZTS */
#define TSRMLS_FETCH()
#define TSRMLS_FETCH_FROM_CTX(ctx)
#define TSRMLS_SET_CTX(ctx)
#define TSRMLS_D void
#define TSRMLS_DC
#define TSRMLS_C
#define TSRMLS_CC
#endif /* ZTS */
#endif /* TSRM_H */
-1
View File
@@ -1 +0,0 @@
#undef PTHREADS
-5
View File
@@ -1,5 +0,0 @@
AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[
LIBTOOL='$(SHELL) $(top_builddir)/libtool $1'
])
-43
View File
@@ -1,43 +0,0 @@
# 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
-33
View File
@@ -1,33 +0,0 @@
#!/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
-10
View File
@@ -1,10 +0,0 @@
// 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");
-31
View File
@@ -1,31 +0,0 @@
dnl $Id$
dnl
dnl Minimalistic configure.in for TSRM.
dnl
AC_INIT(TSRM.c)
AM_INIT_AUTOMAKE(TSRM, 1.0, nodefine)
AM_CONFIG_HEADER(tsrm_config.h)
sinclude(tsrm.m4)
TSRM_BASIC_CHECKS
TSRM_THREADS_CHECKS
AM_PROG_LIBTOOL
if test "$enable_debug" != "yes"; then
AM_SET_LIBTOOL_VARIABLE([--silent])
fi
dnl TSRM_PTHREAD
AC_CHECK_HEADERS(
utime.h \
dirent.h \
stdarg.h \
alloca.h \
unistd.h \
limits.h
)
AC_OUTPUT(Makefile)
-45
View File
@@ -1,45 +0,0 @@
#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 */
-173
View File
@@ -1,173 +0,0 @@
dnl Copyright (c) 1999, 2000 Sascha Schumann. All rights reserved.
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 1. Redistributions of source code must retain the above copyright
dnl notice, this list of conditions and the following disclaimer.
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 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
dnl PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SASCHA SCHUMANN OR
dnl HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
dnl NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
dnl LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
dnl HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
dnl STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
dnl OF THE POSSIBILITY OF SUCH DAMAGE.
dnl
dnl PTHREADS_FLAGS
dnl
dnl Set some magic defines to achieve POSIX threads conformance
dnl
AC_DEFUN([PTHREADS_FLAGS],[
if test -z "$host_alias" && test -n "$host"; then
host_alias=$host
fi
if test -z "$host_alias"; then
AC_MSG_ERROR(host_alias is not set. Make sure to run config.guess)
fi
case $host_alias in
*solaris*)
PTHREAD_FLAGS="-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT";;
*freebsd*)
PTHREAD_FLAGS="-D_REENTRANT -D_THREAD_SAFE";;
*linux*)
PTHREAD_FLAGS=-D_REENTRANT;;
*aix*)
PTHREAD_FLAGS=-D_THREAD_SAFE;;
*irix*)
PTHREAD_FLAGS=-D_POSIX_THREAD_SAFE_FUNCTIONS;;
*hpux*)
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
AC_DEFUN([PTHREADS_CHECK_COMPILE], [
AC_TRY_RUN( [
#include <pthread.h>
#include <stddef.h>
void *thread_routine(void *data) {
return data;
}
int main() {
pthread_t thd;
pthread_mutexattr_t mattr;
int data = 1;
pthread_mutexattr_init(&mattr);
return pthread_create(&thd, NULL, thread_routine, &data);
} ], [
pthreads_working=yes
], [
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
dnl Try to find a way to enable POSIX threads
dnl
dnl Magic flags
dnl -kthread gcc (FreeBSD)
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 -qthreaded AIX cc V5
dnl -threads gcc (HP-UX)
dnl
AC_DEFUN([PTHREADS_CHECK],[
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
ac_save=$LIBS
LIBS="$LIBS -l$lib"
PTHREADS_CHECK_COMPILE
LIBS=$ac_save
if test "$pthreads_working" = "yes"; then
ac_cv_pthreads_lib=$lib
break
fi
done
fi
])
if test "$pthreads_working" = "yes"; then
threads_result="POSIX-Threads found"
else
threads_result="POSIX-Threads not found"
fi
])dnl
dnl
dnl
AC_DEFUN([PTHREADS_ASSIGN_VARS],[
if test -n "$ac_cv_pthreads_lib"; then
LIBS="$LIBS -l$ac_cv_pthreads_lib"
fi
if test -n "$ac_cv_pthreads_cflags"; then
CFLAGS="$CFLAGS $ac_cv_pthreads_cflags"
fi
])dnl
-128
View File
@@ -1,128 +0,0 @@
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
AC_MSG_RESULT(Please check your Pth installation)
fi
CPPFLAGS="$CPPFLAGS `$1 --cflags`"
LDFLAGS="$LDFLAGS `$1 --ldflags`"
LIBS="$LIBS `$1 --libs`"
AC_DEFINE(GNUPTH, 1, [Whether you use GNU Pth])
AC_MSG_RESULT(yes - installed in $PTH_PREFIX)
])
AC_DEFUN([TSRM_CHECK_ST],[
if test -r "$1/include/st.h"; then
CPPFLAGS="$CPPFLAGS -I$1/include"
LDFLAGS="$LDFLAGS -L$1/lib"
elif test -r "$1/st.h"; then
CPPFLAGS="$CPPFLAGS -I$1"
LDFLAGS="$LDFLAGS -L$1"
fi
AC_CHECK_HEADERS(st.h,[],[
AC_MSG_ERROR([Sorry[,] I was unable to locate the State Threads header file. Please specify the prefix using --with-tsrm-st=/prefix])
])
LIBS="$LIBS -lst"
AC_MSG_CHECKING(for SGI's State Threads)
AC_MSG_RESULT(yes)
AC_DEFINE(TSRM_ST, 1, [ ])
])
sinclude(threads.m4)
AC_DEFUN([TSRM_CHECK_PTHREADS],[
PTHREADS_CHECK
if test "$beos_threads" = "1"; then
AC_DEFINE(BETHREADS, 1, Whether to use native BeOS threads)
else
if test "$pthreads_working" != "yes"; then
AC_MSG_ERROR(Your system seems to lack POSIX threads.)
fi
AC_DEFINE(PTHREADS, 1, Whether to use Pthreads)
AC_MSG_CHECKING(for POSIX threads)
AC_MSG_RESULT(yes)
fi
])
AC_DEFUN([TSRM_THREADS_CHECKS],[
dnl For the thread implementations, we always use --with-*
dnl to maintain consistency
AC_ARG_WITH(tsrm-pth,
[ --with-tsrm-pth[=pth-config]
Use GNU Pth],[
TSRM_PTH=$withval
],[
TSRM_PTH=no
])
AC_ARG_WITH(tsrm-st,
[ --with-tsrm-st Use SGI's State Threads],[
TSRM_ST=$withval
],[
TSRM_ST=no
])
AC_ARG_WITH(tsrm-pthreads,
[ --with-tsrm-pthreads Use POSIX threads (default)],[
TSRM_PTHREADS=$withval
],[
TSRM_PTHREADS=yes
])
test "$TSRM_PTH" = "yes" && TSRM_PTH=pth-config
if test "$TSRM_PTH" != "no"; then
TSRM_CHECK_PTH($TSRM_PTH)
elif test "$TSRM_ST" != "no"; then
TSRM_CHECK_ST($TSRM_ST)
elif test "$TSRM_PTHREADS" != "no"; then
TSRM_CHECK_PTHREADS
fi
])
-22
View File
@@ -1,22 +0,0 @@
#ifndef TSRM_CONFIG_W32_H
#define TSRM_CONFIG_W32_H
#include <../main/config.w32.h>
#define HAVE_UTIME 1
#define HAVE_ALLOCA 1
#define HAVE_REALPATH 1
#include <malloc.h>
#include <stdlib.h>
#include <crtdbg.h>
#undef inline
#ifdef ZEND_WIN32_FORCE_INLINE
# define inline __forceinline
#else
# define inline
#endif
#endif
-70
View File
@@ -1,70 +0,0 @@
#ifndef TSRM_CONFIG_COMMON_H
#define TSRM_CONFIG_COMMON_H
#ifndef __CYGWIN__
# if WINNT|WIN32
# define TSRM_WIN32
# endif
#endif
#ifdef TSRM_WIN32
# include "tsrm_config.w32.h"
#else
# include <tsrm_config.h>
# include <sys/param.h>
#endif
#if HAVE_ALLOCA_H && !defined(_ALLOCA_H)
# include <alloca.h>
#endif
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# ifndef HAVE_ALLOCA_H
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
# ifndef NETWARE
char *alloca ();
# endif
# endif
# endif
# endif
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# elif defined(MAX_PATH)
# define MAXPATHLEN MAX_PATH
# else
# define MAXPATHLEN 256
# endif
#endif
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2))
# define TSRM_ALLOCA_MAX_SIZE 4096
# define TSRM_ALLOCA_FLAG(name) \
int name;
# define tsrm_do_alloca_ex(size, limit, use_heap) \
((use_heap = ((size) > (limit))) ? malloc(size) : alloca(size))
# define tsrm_do_alloca(size, use_heap) \
tsrm_do_alloca_ex(size, TSRM_ALLOCA_MAX_SIZE, use_heap)
# define tsrm_free_alloca(p, use_heap) \
do { if (use_heap) free(p); } while (0)
#else
# define TSRM_ALLOCA_FLAG(name)
# define tsrm_do_alloca(p, use_heap) malloc(p)
# define tsrm_free_alloca(p, use_heap) free(p)
#endif
#endif /* TSRM_CONFIG_COMMON_H */
-240
View File
@@ -1,240 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Venkat Raghavan S <rvenkat@novell.com> |
| Anantha Kesari H Y <hyanantha@novell.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include "TSRM.h"
#ifdef NETWARE
#ifdef USE_MKFIFO
#include <sys/stat.h>
#elif !defined(USE_PIPE_OPEN) /* NXFifoOpen */
#include <nks/fsio.h>
#endif
#include <nks/vm.h>
#include <nks/memory.h>
#include <string.h>
#include "mktemp.h"
/* strtok() call in LibC is abending when used in a different address space
* -- hence using PHP's version itself for now
*/
#include "tsrm_strtok_r.h"
#define tsrm_strtok_r(a,b,c) strtok((a),(b))
#define WHITESPACE " \t"
#define MAX_ARGS 10
TSRM_API FILE* popen(const char *commandline, const char *type)
{
char *command = NULL, *argv[MAX_ARGS] = {'\0'}, **env = NULL;
char *tempName = "sys:/php/temp/phpXXXXXX.tmp";
char *filePath = NULL;
char *ptr = NULL;
int ptrLen = 0, argc = 0, i = 0, envCount = 0, err = 0;
FILE *stream = NULL;
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
int pipe_handle;
int mode = O_RDONLY;
#else
NXHandle_t pipe_handle;
NXMode_t mode = NX_O_RDONLY;
#endif
NXExecEnvSpec_t envSpec;
NXNameSpec_t nameSpec;
NXVmId_t newVM = 0;
/* Check for validity of input parameters */
if (!commandline || !type)
return NULL;
/* Get temporary file name */
filePath = mktemp(tempName);
if (!filePath)
return NULL;
/* Set pipe mode according to type -- for now allow only "r" or "w" */
if (strcmp(type, "r") == 0)
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
mode = O_RDONLY;
#else
mode = NX_O_RDONLY;
#endif
else if (strcmp(type, "w") == 0)
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
mode = O_WRONLY;
#else
mode = NX_O_WRONLY;
#endif
else
return NULL;
#ifdef USE_PIPE_OPEN
pipe_handle = pipe_open(filePath, mode);
if (pipe_handle == -1)
return NULL;
#elif defined(USE_MKFIFO)
pipe_handle = mkfifo(filePath, mode);
if (pipe_handle == -1)
return NULL;
#else
/* - NetWare doesn't require first parameter
* - Allowing LibC to choose the buffer size for now
*/
err = NXFifoOpen(0, filePath, mode, 0, &pipe_handle);
if (err)
return NULL;
#endif
/* Copy the environment variables in preparation for the spawn call */
envCount = NXGetEnvCount() + 1; /* add one for NULL */
env = (char **) NXMemAlloc(sizeof(char *) * envCount, 0);
if (!env)
return NULL;
err = NXCopyEnv(env, envCount);
if (err) {
NXMemFree (env);
return NULL;
}
/* Separate commandline string into words */
ptr = tsrm_strtok_r((char*)commandline, WHITESPACE, NULL);
ptrLen = strlen(ptr);
command = (char*)malloc(ptrLen + 1);
if (!command) {
NXMemFree (env);
return NULL;
}
strcpy (command, ptr);
ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
while (ptr && (argc < MAX_ARGS)) {
ptrLen = strlen(ptr);
argv[argc] = (char*)malloc(ptrLen + 1);
if (!argv[argc]) {
NXMemFree (env);
if (command)
free (command);
for (i = 0; i < argc; i++) {
if (argv[i])
free (argv[i]);
}
return NULL;
}
strcpy (argv[argc], ptr);
argc++;
ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
}
/* Setup the execution environment and spawn new process */
envSpec.esFlags = 0; /* Not used */
envSpec.esArgc = argc;
envSpec.esArgv = (void **) argv;
envSpec.esEnv = (void **) env;
/* envSpec.esStdin.ssType = */
envSpec.esStdout.ssType = NX_OBJ_FIFO;
envSpec.esStderr.ssType = NX_OBJ_FILE;
/* 'ssHandle' is not a struct/union/class member */
/*
envSpec.esStdin.ssHandle =
envSpec.esStdout.ssHandle =
envSpec.esStderr.ssHandle = -1;
*/
envSpec.esStdin.ssPathCtx = NULL;
envSpec.esStdout.ssPathCtx = NULL;
envSpec.esStderr.ssPathCtx = NULL;
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
if (mode == O_RDONLY) {
#else
if (mode == NX_O_RDONLY) {
#endif
envSpec.esStdin.ssPath = filePath;
envSpec.esStdout.ssPath = stdout;
} else { /* Write Only */
envSpec.esStdin.ssPath = stdin;
envSpec.esStdout.ssPath = filePath;
}
envSpec.esStderr.ssPath = stdout;
nameSpec.ssType = NX_OBJ_FIFO;
/* nameSpec.ssHandle = 0; */ /* 'ssHandle' is not a struct/union/class member */
nameSpec.ssPathCtx = NULL; /* Not used */
nameSpec.ssPath = argv[0];
err = NXVmSpawn(&nameSpec, &envSpec, 0, &newVM);
if (!err)
/* Get file pointer corresponding to the pipe (file) opened */
stream = fdopen(pipe_handle, type);
/* Clean-up */
if (env)
NXMemFree (env);
if (pipe_handle)
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
close(pipe_handle);
#else
NXClose(pipe_handle);
#endif
if (command)
free (command);
for (i = 0; i < argc; i++) {
if (argv[i])
free (argv[i]);
}
return stream;
}
TSRM_API int pclose(FILE* stream)
{
int err = 0;
NXHandle_t fd = 0;
/* Get the process associated with this pipe (file) handle and terminate it */
fd = fileno(stream);
NXClose (fd);
err = fclose(stream);
return err;
}
#endif /* NETWARE */
-29
View File
@@ -1,29 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Venkat Raghavan S <rvenkat@novell.com> |
| Anantha Kesari H Y <hyanantha@novell.com> |
+----------------------------------------------------------------------+
*/
#ifndef TSRM_NW_H
#define TSRM_NW_H
#include "TSRM.h"
TSRM_API FILE* popen(const char *command, const char *type);
TSRM_API int pclose(FILE* stream);
#endif
-63
View File
@@ -1,63 +0,0 @@
#include <stdio.h>
#include "tsrm_config_common.h"
#include "tsrm_strtok_r.h"
static inline int in_character_class(char ch, const char *delim)
{
while (*delim) {
if (*delim == ch) {
return 1;
}
delim++;
}
return 0;
}
char *tsrm_strtok_r(char *s, const char *delim, char **last)
{
char *token;
if (s == NULL) {
s = *last;
}
while (*s && in_character_class(*s, delim)) {
s++;
}
if (!*s) {
return NULL;
}
token = s;
while (*s && !in_character_class(*s, delim)) {
s++;
}
if (!*s) {
*last = s;
} else {
*s = '\0';
*last = s + 1;
}
return token;
}
#if 0
main()
{
char foo[] = "/foo/bar//\\barbara";
char *last;
char *token;
token = tsrm_strtok_r(foo, "/\\", &last);
while (token) {
printf ("Token = '%s'\n", token);
token = tsrm_strtok_r(NULL, "/\\", &last);
}
return 0;
}
#endif
-6
View File
@@ -1,6 +0,0 @@
#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
-336
View File
@@ -1,336 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 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;
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);
/* 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) == 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
#define VCWD_UTIME(path, time) utime(path, time)
#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 */
-397
View File
@@ -1,397 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 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: Daniel Beulshausen <daniel@php4win.de> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>
#include <time.h>
#define TSRM_INCLUDE_FULL_WINDOWS_HEADERS
#include "TSRM.h"
#ifdef TSRM_WIN32
#include "tsrm_win32.h"
#ifdef ZTS
static ts_rsrc_id win32_globals_id;
#else
static tsrm_win32_globals win32_globals;
#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((GetVersion()<0x80000000)?"cmd.exe":"command.com");
}
static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
{
shm_pair *ptr;
if (globals->process) {
free(globals->process);
}
if (globals->shm) {
for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
UnmapViewOfFile(ptr->addr);
CloseHandle(ptr->segment);
UnmapViewOfFile(ptr->descriptor);
CloseHandle(ptr->info);
}
free(globals->shm);
}
free(globals->comspec);
}
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 TSRMLS_CC);
#endif
}
TSRM_API void tsrm_win32_shutdown(void)
{
#ifndef ZTS
tsrm_win32_dtor(&win32_globals TSRMLS_CC);
#endif
}
TSRM_API int tsrm_win32_access(const char *pathname, int mode)
{
if (mode == 1 /*X_OK*/) {
#if 1
/* This code is not supported by Windows 98,
* but we don't support it anymore */
DWORD type;
return GetBinaryType(pathname, &type)?0:-1;
#else
SHFILEINFO sfi;
return access(pathname, 0) == 0 &&
SHGetFileInfo(pathname, 0, &sfi, sizeof(SHFILEINFO), SHGFI_EXETYPE) != 0 ? 0 : -1;
#endif
} else {
return access(pathname, mode);
}
}
static process_pair *process_get(FILE *stream TSRMLS_DC)
{
process_pair *ptr;
process_pair *newptr;
for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
if (ptr->stream == stream) {
break;
}
}
if (ptr < (TWG(process) + TWG(process_size))) {
return ptr;
}
newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
if (newptr == NULL) {
return NULL;
}
TWG(process) = newptr;
ptr = newptr + TWG(process_size);
TWG(process_size)++;
return ptr;
}
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) {
continue;
}
if (!addr && ptr->descriptor->shm_perm.key == key) {
break;
} else if (ptr->addr == addr) {
break;
}
}
if (ptr < (TWG(shm) + TWG(shm_size))) {
return ptr;
}
newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
if (newptr == NULL) {
return NULL;
}
TWG(shm) = newptr;
ptr = newptr + TWG(shm_size);
TWG(shm_size)++;
return ptr;
}
static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
HANDLE copy, self = GetCurrentProcess();
if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
return NULL;
}
return copy;
}
TSRM_API FILE *popen(const char *command, const char *type)
{
return popen_ex(command, type, NULL, NULL);
}
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
{
FILE *stream = NULL;
int fno, str_len = strlen(type), read, mode;
STARTUPINFO startup;
PROCESS_INFORMATION process;
SECURITY_ATTRIBUTES security;
HANDLE in, out;
char *cmd;
process_pair *proc;
TSRMLS_FETCH();
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL;
if (!str_len || !CreatePipe(&in, &out, &security, 2048L)) {
return NULL;
}
memset(&startup, 0, sizeof(STARTUPINFO));
memset(&process, 0, sizeof(PROCESS_INFORMATION));
startup.cb = sizeof(STARTUPINFO);
startup.dwFlags = STARTF_USESTDHANDLES;
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
read = (type[0] == 'r') ? TRUE : FALSE;
mode = ((str_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
if (read) {
in = dupHandle(in, FALSE);
startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startup.hStdOutput = out;
} else {
out = dupHandle(out, FALSE);
startup.hStdInput = in;
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
}
cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")+2);
sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
if (!CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, env, cwd, &startup, &process)) {
return NULL;
}
free(cmd);
CloseHandle(process.hThread);
proc = process_get(NULL TSRMLS_CC);
if (read) {
fno = _open_osfhandle((tsrm_intptr_t)in, _O_RDONLY | mode);
CloseHandle(out);
} else {
fno = _open_osfhandle((tsrm_intptr_t)out, _O_WRONLY | mode);
CloseHandle(in);
}
stream = _fdopen(fno, type);
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 TSRMLS_CC)) == NULL) {
return 0;
}
fflush(process->stream);
fclose(process->stream);
WaitForSingleObject(process->prochnd, INFINITE);
GetExitCodeProcess(process->prochnd, &termstat);
process->stream = NULL;
CloseHandle(process->prochnd);
return termstat;
}
TSRM_API int shmget(int key, int size, int flags)
{
shm_pair *shm;
char shm_segment[26], shm_info[29];
HANDLE shm_handle, info_handle;
BOOL created = FALSE;
if (size < 0) {
return -1;
}
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) {
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)) {
return -1;
}
} else {
if (flags & IPC_EXCL) {
return -1;
}
}
shm = shm_get(key, NULL);
shm->segment = shm_handle;
shm->info = info_handle;
shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
if (created) {
shm->descriptor->shm_perm.key = key;
shm->descriptor->shm_segsz = size;
shm->descriptor->shm_ctime = time(NULL);
shm->descriptor->shm_cpid = getpid();
shm->descriptor->shm_perm.mode = flags;
shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0;
shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0;
shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0;
shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0;
shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
}
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->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);
if (!shm->segment) {
return -1;
}
shm->descriptor->shm_dtime = time(NULL);
shm->descriptor->shm_lpid = getpid();
shm->descriptor->shm_nattch--;
return UnmapViewOfFile(shm->addr) ? 0 : -1;
}
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
shm_pair *shm = shm_get(key, NULL);
if (!shm->segment) {
return -1;
}
switch (cmd) {
case IPC_STAT:
memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
return 0;
case IPC_SET:
shm->descriptor->shm_ctime = time(NULL);
shm->descriptor->shm_perm.uid = buf->shm_perm.uid;
shm->descriptor->shm_perm.gid = buf->shm_perm.gid;
shm->descriptor->shm_perm.mode = buf->shm_perm.mode;
return 0;
case IPC_RMID:
if (shm->descriptor->shm_nattch < 1) {
shm->descriptor->shm_perm.key = -1;
}
return 0;
default:
return -1;
}
}
TSRM_API char *realpath(char *orig_path, char *buffer)
{
int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
if(!ret || ret > _MAX_PATH) {
return NULL;
}
return buffer;
}
#endif
-106
View File
@@ -1,106 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 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: Daniel Beulshausen <daniel@php4win.de> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef TSRM_WIN32_H
#define TSRM_WIN32_H
#include "TSRM.h"
#include <windows.h>
struct ipc_perm {
int key;
unsigned short uid;
unsigned short gid;
unsigned short cuid;
unsigned short cgid;
unsigned short mode;
unsigned short seq;
};
struct shmid_ds {
struct ipc_perm shm_perm;
int shm_segsz;
time_t shm_atime;
time_t shm_dtime;
time_t shm_ctime;
unsigned short shm_cpid;
unsigned short shm_lpid;
short shm_nattch;
};
typedef struct {
FILE *stream;
HANDLE prochnd;
} process_pair;
typedef struct {
void *addr;
HANDLE info;
HANDLE segment;
struct shmid_ds *descriptor;
} shm_pair;
typedef struct {
process_pair *process;
shm_pair *shm;
int process_size;
int shm_size;
char *comspec;
} tsrm_win32_globals;
#ifdef ZTS
# define TWG(v) TSRMG(win32_globals_id, tsrm_win32_globals *, v)
#else
# define TWG(v) (win32_globals.v)
#endif
#define IPC_PRIVATE 0
#define IPC_CREAT 00001000
#define IPC_EXCL 00002000
#define IPC_NOWAIT 00004000
#define IPC_RMID 0
#define IPC_SET 1
#define IPC_STAT 2
#define IPC_INFO 3
#define SHM_R PAGE_READONLY
#define SHM_W PAGE_READWRITE
#define SHM_RDONLY FILE_MAP_READ
#define SHM_RND FILE_MAP_WRITE
#define SHM_REMAP FILE_MAP_COPY
TSRM_API void tsrm_win32_startup(void);
TSRM_API void tsrm_win32_shutdown(void);
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env);
TSRM_API FILE *popen(const char *command, const char *type);
TSRM_API int pclose(FILE *stream);
TSRM_API int tsrm_win32_access(const char *pathname, int mode);
TSRM_API int 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
View File
@@ -1 +0,0 @@
/* Leave this file alone */
-2872
View File
File diff suppressed because it is too large. Load diff
-73
View File
@@ -1,73 +0,0 @@
# +----------------------------------------------------------------------+
# | PHP Version 5 |
# +----------------------------------------------------------------------+
# | Copyright (c) 1997-2006 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. |
# +----------------------------------------------------------------------+
# | Author: Sascha Schumann <sascha@schumann.cx> |
# +----------------------------------------------------------------------+
#
# $Id$
#
#
# Makefile to generate build tools
#
ZENDDIR = Zend
SUBDIRS = $(ZENDDIR) TSRM
STAMP = buildmk.stamp
ALWAYS = generated_lists
all: $(STAMP) $(ALWAYS)
@$(MAKE) -s -f build/build2.mk
generated_lists:
@echo makefile_am_files = $(ZENDDIR)/Makefile.am \
TSRM/Makefile.am > $@
@echo config_h_files = $(ZENDDIR)/acconfig.h TSRM/acconfig.h >> $@
@echo config_m4_files = $(ZENDDIR)/Zend.m4 TSRM/tsrm.m4 TSRM/threads.m4 \
$(ZENDDIR)/acinclude.m4 ext/*/config*.m4 sapi/*/config.m4 >> $@
$(STAMP): build/buildcheck.sh
@build/buildcheck.sh $(STAMP)
snapshot:
distname='$(DISTNAME)'; \
if test -z "$$distname"; then \
distname='php5-snapshot'; \
fi; \
myname=`basename \`pwd\`` ; \
cd .. && cp -rp $$myname $$distname; \
cd $$distname; \
rm -f $(SUBDIRS) 2>/dev/null || true; \
for i in $(SUBDIRS); do \
test -d $$i || (test -d ../$$i && cp -rp ../$$i $$i); \
done; \
find . -type l -exec rm {} \; ; \
$(MAKE) -f build/build.mk; \
cd ..; \
tar cf $$distname.tar $$distname; \
rm -rf $$distname $$distname.tar.*; \
bzip2 -9 $$distname.tar; \
md5sum $$distname.tar.bz2; \
sync; sleep 2; \
md5sum $$distname.tar.bz2; \
bzip2 -t $$distname.tar.bz2
cvsclean-work:
@for i in `find . -name .cvsignore`; do \
(cd `dirname $$i` 2>/dev/null && rm -rf `cat .cvsignore | grep -v config.nice | sed 's/[[:space:]]/ /g'` *.o *.a .libs || true); \
done
.PHONY: $(ALWAYS) snapshot
-60
View File
@@ -1,60 +0,0 @@
# +----------------------------------------------------------------------+
# | PHP Version 5 |
# +----------------------------------------------------------------------+
# | Copyright (c) 1997-2006 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. |
# +----------------------------------------------------------------------+
# | Author: Sascha Schumann <sascha@schumann.cx> |
# +----------------------------------------------------------------------+
#
# $Id$
#
include generated_lists
TOUCH_FILES = mkinstalldirs install-sh missing
LT_TARGETS = ltmain.sh config.guess config.sub
config_h_in = main/php_config.h.in
acconfig_h_SOURCES = acconfig.h.in $(config_h_files)
targets = $(TOUCH_FILES) configure $(config_h_in)
PHP_AUTOCONF ?= 'autoconf'
PHP_AUTOHEADER ?= 'autoheader'
SUPPRESS_WARNINGS ?= 2>&1 | (egrep -v '(AC_TRY_RUN called without default to allow cross compiling|AC_PROG_CXXCPP was called before AC_PROG_CXX|defined in acinclude.m4 but never used|AC_PROG_LEX invoked multiple times|AC_DECL_YYTEXT is expanded from...|the top level)'||true)
all: $(targets)
acconfig.h: $(acconfig_h_SOURCES)
@echo rebuilding $@
cat $(acconfig_h_SOURCES) > $@
$(config_h_in): configure acconfig.h
# explicitly remove target since autoheader does not seem to work
# correctly otherwise (timestamps are not updated)
@echo rebuilding $@
@rm -f $@
$(PHP_AUTOHEADER) $(SUPPRESS_WARNINGS)
$(TOUCH_FILES):
touch $(TOUCH_FILES)
aclocal.m4: configure.in acinclude.m4
@echo rebuilding $@
cat acinclude.m4 ./build/libtool.m4 > $@
configure: aclocal.m4 configure.in $(config_m4_files)
@echo rebuilding $@
$(PHP_AUTOCONF) $(SUPPRESS_WARNINGS)
-59
View File
@@ -1,59 +0,0 @@
#! /bin/sh
# +----------------------------------------------------------------------+
# | PHP Version 5 |
# +----------------------------------------------------------------------+
# | Copyright (c) 1997-2006 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: Stig Bakken <ssb@php.net> |
# | Sascha Schumann <sascha@schumann.cx> |
# +----------------------------------------------------------------------+
#
# $Id: buildcheck.sh,v 1.39 2006-01-01 13:09:48 sniper Exp $
#
echo "buildconf: checking installation..."
stamp=$1
# Allow the autoconf executable to be overridden by $PHP_AUTOCONF.
if test -z "$PHP_AUTOCONF"; then
PHP_AUTOCONF='autoconf'
fi
# autoconf 2.13 or newer
ac_version=`$PHP_AUTOCONF --version 2>/dev/null|head -n 1|sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
if test -z "$ac_version"; then
echo "buildconf: autoconf not found."
echo " You need autoconf version 2.13 or newer installed"
echo " to build PHP from CVS."
exit 1
fi
IFS=.; set $ac_version; IFS=' '
if test "$1" = "2" -a "$2" -lt "13" || test "$1" -lt "2"; then
echo "buildconf: autoconf version $ac_version found."
echo " You need autoconf version 2.13 or newer installed"
echo " to build PHP from CVS."
exit 1
else
echo "buildconf: autoconf version $ac_version (ok)"
fi
if test "$1" = "2" && test "$2" -ge "50"; then
echo "buildconf: Your version of autoconf likely contains buggy cache code."
echo " Running cvsclean for you."
echo " To avoid this, install autoconf-2.13."
./cvsclean
stamp=
fi
test -n "$stamp" && touch $stamp
exit 0
-8
View File
@@ -1,8 +0,0 @@
#!/bin/sh
#
# $Id$
dir=$1; shift
for stubfile in $dir/*/config0.m4 $dir/*/config.m4 $dir/*/config9.m4; do
echo "sinclude($stubfile)"
done
-41
View File
@@ -1,41 +0,0 @@
#! /bin/sh
# $Id: genif.sh,v 1.6 2005-06-21 13:47:38 sniper Exp $
# replacement for genif.pl
infile=$1
shift
srcdir=$1
shift
extra_module_ptrs=$1
shift
awk=$1
shift
if test -z "$infile" || test -z "$srcdir"; then
echo "please supply infile and srcdir"
exit 1
fi
header_list=
olddir=`pwd`
cd $srcdir
module_ptrs="$extra_module_ptrs`echo $@ | $awk -f ./build/order_by_dep.awk`"
for ext in ${1+"$@"} ; do
header_list="$header_list ext/$ext/*.h"
done
includes=`$awk -f ./build/print_include.awk $header_list`
cd $olddir
cat $infile | \
sed \
-e "s'@EXT_INCLUDE_CODE@'$includes'" \
-e "s'@EXT_MODULE_PTRS@'$module_ptrs'" \
-e 's/@NEWLINE@/\
/g'
-6246
View File
File diff suppressed because it is too large. Load diff
-75
View File
@@ -1,75 +0,0 @@
# +----------------------------------------------------------------------+
# | PHP Version 5 |
# +----------------------------------------------------------------------+
# | Copyright (c) 2000-2005 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. |
# +----------------------------------------------------------------------+
# | Author: Sascha Schumann <sascha@schumann.cx> |
# +----------------------------------------------------------------------+
#
# $Id$
#
# Usage:
#
# echo top_srcdir top_builddir srcdir CPP [CPP-ARGS] filenames | \
# awk -f mkdep.awk > dependencies
{
top_srcdir=$1
top_builddir=$2
srcdir=$3
cmd=$4
for (i = 5; i <= NF; i++) {
if (match($i, "^-[A-Z]") == 0)
break;
cmd=cmd " " $i
}
dif=i-1
for (; i <= NF; i++)
filenames[i-dif]=$i
no_files=NF-dif
for(i = 1; i <= no_files; i++) {
if (system("test -r " filenames[i]) != 0)
continue
target=filenames[i]
sub(srcdir "/", "", target)
target2=target
sub("\.(c|cpp)$", ".lo", target);
sub("\.(c|cpp)$", ".slo", target2);
for (e in used)
delete used[e]
cmdx=cmd " " filenames[i]
done=0
while ((cmdx | getline) > 0) {
if (match($0, "^# [0-9]* \".*\.h\"") != 0) {
if (sub(top_srcdir, "$(top_srcdir)", $3) == 0)
sub(top_builddir, "$(top_builddir)", $3)
if (substr($3,2,1) != "/" && used[$3] != 1) {
if (done == 0)
printf(target " " target2 ":")
done=1
printf(" \\\n\t" substr($3,2,length($3)-2))
used[$3] = 1;
}
}
}
if (done == 1)
print "\n"
}
}
-89
View File
@@ -1,89 +0,0 @@
BEGIN {
orig_rs = RS;
orig_fs = FS;
RS=" ";
mod_count = 0;
SUBSEP=":";
}
function get_deps(module_name, depline, cmd)
{
# this could probably be made *much* better
RS=orig_rs;
FS="[(,) \t]+"
cmd = "grep PHP_ADD_EXTENSION_DEP ext/" module_name "/config*.m4"
while (cmd | getline) {
# printf("GOT: %s,%s,%s,%s,%s\n", $1, $2, $3, $4, $5);
if (!length($5)) {
$5 = 0;
}
mod_deps[module_name, $4] = $5;
}
close(cmd)
RS=" ";
FS=orig_fs;
}
function get_module_index(name, i)
{
for (i in mods) {
if (mods[i] == name) {
return i;
}
}
return -1;
}
function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx)
{
module_name = mods[mod_idx];
mod_name_len = length(module_name);
for (ext in mod_deps) {
if (substr(ext, 0, mod_name_len+1) != module_name SUBSEP) {
continue;
}
val = mod_deps[ext];
ext = substr(ext, mod_name_len+2, length(ext)-mod_name_len);
depidx = get_module_index(ext);
if (depidx >= 0) {
do_deps(depidx);
}
}
#printf(" phpext_%s_ptr,\n", module_name);
printf(" phpext_%s_ptr,@NEWLINE@", module_name);
delete mods[mod_idx];
}
function count(arr, n, i)
{
n = 0;
for (i in arr)
n++;
return n;
}
/^[a-zA-Z0-9_-]+/ {
# mini hack for pedantic awk
gsub("[^a-zA-Z0-9_-]", "", $1)
# add each item to array
mods[mod_count++] = $1
# see if it has any module deps
get_deps($1);
}
END {
# order it correctly
out_count = 0;
while (count(mods)) {
# count down, since we need to assemble it in reverse order
for (i = mod_count-1; i >= 0; --i) {
if (i in mods) {
do_deps(i);
}
}
}
}
-6
View File
@@ -1,6 +0,0 @@
/phpext_/ {
if (old_filename != FILENAME) {
printf "#include \"" FILENAME "\"@NEWLINE@"
old_filename = FILENAME
}
}
-32
View File
@@ -1,32 +0,0 @@
BEGIN {
mode=0
sources=""
}
mode == 0 && /^LTLIBRARY_SOURCES.*\\$/ {
if (match($0, "[^=]*$")) {
sources=substr($0, RSTART, RLENGTH-1)
}
mode=1
next
}
mode == 0 && /^LTLIBRARY_SOURCES.*/ {
if (match($0, "[^=]*$")) {
sources=substr($0, RSTART, RLENGTH)
}
}
mode == 1 && /.*\\$/ {
sources=sources substr($0, 0, length - 1)
next
}
mode == 1 {
sources=sources $0
mode=0
}
END {
print sources
}
-1719
View File
File diff suppressed because it is too large. Load diff
-69
View File
@@ -1,69 +0,0 @@
#!/bin/sh
# $Id$
eval `grep '^PHP_EXTRA_VERSION=' configure.in`
case "$PHP_EXTRA_VERSION" in
*-dev)
dev=1
;;
*)
dev=0
;;
esac
devok=0
debug=no
while test $# -gt 0; do
if test "$1" = "--force"; then
devok=1
echo "Forcing buildconf"
fi
if test "$1" = "--debug"; then
debug=yes
fi
shift
done
if test "$dev" = "0" -a "$devok" = "0"; then
echo "You should not run buildconf in a release package."
echo "use buildconf --force to override this check."
exit 1
fi
if test -z "$ZENDDIR"; then
if grep "PHP_MAJOR_VERSION 6" main/php_version.h >/dev/null; then
v=5
else
v=4
fi
if test "$v" = "5"; then
if test -r "Zend/OBJECTS2_HOWTO"; then
:
else
mv Zend ZendEngine1 2>/dev/null
mv ZendEngine2 Zend
fi
else
if test -r "Zend/zend_execute_globals.h"; then
:
else
mv Zend ZendEngine2 2>/dev/null
mv ZendEngine1 Zend
fi
fi
ZENDDIR=Zend
echo "using default Zend directory"
fi
rm -f generated_lists
if test "$debug" = "yes"; then
${MAKE:-make} -s -f build/build.mk ZENDDIR="$ZENDDIR" SUPPRESS_WARNINGS=""
else
${MAKE:-make} -s -f build/build.mk ZENDDIR="$ZENDDIR"
fi
-2
View File
@@ -1,2 +0,0 @@
@echo off
cscript /nologo win32\build\buildconf.js %*
-1466
View File
File diff suppressed because it is too large. Load diff
Vendored
-1579
View File
File diff suppressed because it is too large. Load diff
-1540
View File
File diff suppressed because it is too large. Load diff
-3
View File
@@ -1,3 +0,0 @@
#! /bin/sh
${MAKE:-make} -f build/build.mk cvsclean-work
-2
View File
@@ -1,2 +0,0 @@
@echo off
cscript /nologo win32\build\cvsclean.js
-2
View File
@@ -1,2 +0,0 @@
BC Math
Andi Gutmans
-572
View File
@@ -1,572 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 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. |
+----------------------------------------------------------------------+
| Author: Andi Gutmans <andi@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#if HAVE_BCMATH
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_bcmath.h"
#include "libbcmath/src/bcmath.h"
ZEND_DECLARE_MODULE_GLOBALS(bcmath)
static PHP_GINIT_FUNCTION(bcmath);
static PHP_GSHUTDOWN_FUNCTION(bcmath);
/* {{{ arginfo */
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcadd, 0, 0, 2)
ZEND_ARG_INFO(0, left_operand)
ZEND_ARG_INFO(0, right_operand)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcsub, 0, 0, 2)
ZEND_ARG_INFO(0, left_operand)
ZEND_ARG_INFO(0, right_operand)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcmul, 0, 0, 2)
ZEND_ARG_INFO(0, left_operand)
ZEND_ARG_INFO(0, right_operand)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcdiv, 0, 0, 2)
ZEND_ARG_INFO(0, left_operand)
ZEND_ARG_INFO(0, right_operand)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO(arginfo_bcmod, 0)
ZEND_ARG_INFO(0, left_operand)
ZEND_ARG_INFO(0, right_operand)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpowmod, 0, 0, 3)
ZEND_ARG_INFO(0, x)
ZEND_ARG_INFO(0, y)
ZEND_ARG_INFO(0, mod)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpow, 0, 0, 2)
ZEND_ARG_INFO(0, x)
ZEND_ARG_INFO(0, y)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bcsqrt, 0, 0, 1)
ZEND_ARG_INFO(0, operand)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_bccomp, 0, 0, 2)
ZEND_ARG_INFO(0, left_operand)
ZEND_ARG_INFO(0, right_operand)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO(arginfo_bcscale, 0)
ZEND_ARG_INFO(0, scale)
ZEND_END_ARG_INFO()
/* }}} */
const zend_function_entry bcmath_functions[] = {
PHP_FE(bcadd, arginfo_bcadd)
PHP_FE(bcsub, arginfo_bcsub)
PHP_FE(bcmul, arginfo_bcmul)
PHP_FE(bcdiv, arginfo_bcdiv)
PHP_FE(bcmod, arginfo_bcmod)
PHP_FE(bcpow, arginfo_bcpow)
PHP_FE(bcsqrt, arginfo_bcsqrt)
PHP_FE(bcscale, arginfo_bcscale)
PHP_FE(bccomp, arginfo_bccomp)
PHP_FE(bcpowmod, arginfo_bcpowmod)
{NULL, NULL, NULL}
};
zend_module_entry bcmath_module_entry = {
STANDARD_MODULE_HEADER,
"bcmath",
bcmath_functions,
PHP_MINIT(bcmath),
PHP_MSHUTDOWN(bcmath),
NULL,
NULL,
PHP_MINFO(bcmath),
NO_VERSION_YET,
PHP_MODULE_GLOBALS(bcmath),
PHP_GINIT(bcmath),
PHP_GSHUTDOWN(bcmath),
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
#ifdef COMPILE_DL_BCMATH
ZEND_GET_MODULE(bcmath)
#endif
/* {{{ PHP_INI */
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateLongGEZero, bc_precision, zend_bcmath_globals, bcmath_globals)
PHP_INI_END()
/* }}} */
/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(bcmath)
{
bcmath_globals->bc_precision = 0;
bc_init_numbers(TSRMLS_C);
}
/* }}} */
/* {{{ PHP_GSHUTDOWN_FUNCTION
*/
static PHP_GSHUTDOWN_FUNCTION(bcmath)
{
_bc_free_num_ex(&bcmath_globals->_zero_, 1);
_bc_free_num_ex(&bcmath_globals->_one_, 1);
_bc_free_num_ex(&bcmath_globals->_two_, 1);
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(bcmath)
{
REGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(bcmath)
{
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(bcmath)
{
php_info_print_table_start();
php_info_print_table_row(2, "BCMath support", "enabled");
php_info_print_table_end();
}
/* }}} */
/* {{{ php_str2num
Convert to bc_num detecting scale */
static void php_str2num(bc_num *num, char *str TSRMLS_DC)
{
char *p;
if (!(p = strchr(str, '.'))) {
bc_str2num(num, str, 0 TSRMLS_CC);
return;
}
bc_str2num(num, str, strlen(p+1) TSRMLS_CC);
}
/* }}} */
/* {{{ proto string bcadd(string left_operand, string right_operand [, int scale]) U
Returns the sum of two arbitrary precision numbers */
PHP_FUNCTION(bcadd)
{
char *left, *right;
int left_len, right_len;
long scale = BCG(bc_precision);
bc_num first, second, result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
bc_add(first, second, &result, scale);
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcsub(string left_operand, string right_operand [, int scale]) U
Returns the difference between two arbitrary precision numbers */
PHP_FUNCTION(bcsub)
{
char *left, *right;
int left_len, right_len;
long scale = BCG(bc_precision);
bc_num first, second, result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
bc_sub(first, second, &result, scale);
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcmul(string left_operand, string right_operand [, int scale]) U
Returns the multiplication of two arbitrary precision numbers */
PHP_FUNCTION(bcmul)
{
char *left, *right;
int left_len, right_len;
long scale = BCG(bc_precision);
bc_num first, second, result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
bc_multiply(first, second, &result, scale TSRMLS_CC);
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcdiv(string left_operand, string right_operand [, int scale]) U
Returns the quotient of two arbitrary precision numbers (division) */
PHP_FUNCTION(bcdiv)
{
char *left, *right;
int left_len, right_len;
long scale = BCG(bc_precision);
bc_num first, second, result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
if (bc_divide(first, second, &result, scale TSRMLS_CC) == 0) {
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
RETVAL_NULL();
}
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcmod(string left_operand, string right_operand) U
Returns the modulus of the two arbitrary precision operands */
PHP_FUNCTION(bcmod)
{
char *left, *right;
int left_len, right_len;
bc_num first, second, result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &left, &left_len, &right, &right_len) == FAILURE) {
return;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
if (bc_modulo(first, second, &result, 0 TSRMLS_CC) == 0) {
RETVAL_STRING(bc_num2str(result), 0);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
RETVAL_NULL();
}
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcpowmod(string x, string y, string mod [, int scale]) U
Returns the value of an arbitrary precision number raised to the power of another reduced by a modulous */
PHP_FUNCTION(bcpowmod)
{
char *left, *right, *modulous;
int left_len, right_len, modulous_len;
bc_num first, second, mod, result;
long scale = BCG(bc_precision);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|l", &left, &left_len, &right, &right_len, &modulous, &modulous_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&mod TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
php_str2num(&mod, modulous TSRMLS_CC);
if (bc_raisemod(first, second, mod, &result, scale TSRMLS_CC) == 0) {
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
RETVAL_NULL();
}
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&mod);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcpow(string x, string y [, int scale]) U
Returns the value of an arbitrary precision number raised to the power of another */
PHP_FUNCTION(bcpow)
{
char *left, *right;
int left_len, right_len;
long scale = BCG(bc_precision);
bc_num first, second, result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_init_num(&result TSRMLS_CC);
php_str2num(&first, left TSRMLS_CC);
php_str2num(&second, right TSRMLS_CC);
bc_raise (first, second, &result, scale TSRMLS_CC);
if (result->n_scale > scale) {
result->n_scale = scale;
}
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
}
/* }}} */
/* {{{ proto string bcsqrt(string operand [, int scale]) U
Returns the square root of an arbitray precision number */
PHP_FUNCTION(bcsqrt)
{
char *operand;
int operand_len;
long scale = BCG(bc_precision);
bc_num result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &operand, &operand_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&result TSRMLS_CC);
php_str2num(&result, operand TSRMLS_CC);
if (bc_sqrt (&result, scale TSRMLS_CC) != 0) {
if (result->n_scale > scale) {
result->n_scale = scale;
}
RETVAL_STRING(bc_num2str(result), 0);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Square root of negative number");
RETVAL_NULL();
}
bc_free_num(&result);
}
/* }}} */
/* {{{ proto int bccomp(string left_operand, string right_operand [, int scale]) U
Compares two arbitrary precision numbers */
PHP_FUNCTION(bccomp)
{
char *left, *right;
int left_len, right_len;
long scale = BCG(bc_precision);
bc_num first, second;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
scale = 0;
}
bc_init_num(&first TSRMLS_CC);
bc_init_num(&second TSRMLS_CC);
bc_str2num(&first, left, scale TSRMLS_CC);
bc_str2num(&second, right, scale TSRMLS_CC);
RETVAL_LONG(bc_compare(first, second));
bc_free_num(&first);
bc_free_num(&second);
}
/* }}} */
/* {{{ proto bool bcscale(int scale) U
Sets default scale parameter for all bc math functions */
PHP_FUNCTION(bcscale)
{
long scale;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &scale) == FAILURE) {
return;
}
if ((int)scale < 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid scale given, using zero");
RETURN_FALSE;
}
BCG(bc_precision) = scale;
RETURN_TRUE;
}
/* }}} */
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
-17
View File
@@ -1,17 +0,0 @@
dnl
dnl $Id$
dnl
PHP_ARG_ENABLE(bcmath, whether to enable bc style precision math functions,
[ --enable-bcmath Enable bc style precision math functions])
if test "$PHP_BCMATH" != "no"; then
PHP_NEW_EXTENSION(bcmath, bcmath.c \
libbcmath/src/add.c libbcmath/src/div.c libbcmath/src/init.c libbcmath/src/neg.c libbcmath/src/outofmem.c libbcmath/src/raisemod.c libbcmath/src/rt.c libbcmath/src/sub.c \
libbcmath/src/compare.c libbcmath/src/divmod.c libbcmath/src/int2num.c libbcmath/src/num2long.c libbcmath/src/output.c libbcmath/src/recmul.c \
libbcmath/src/sqrt.c libbcmath/src/zero.c libbcmath/src/debug.c libbcmath/src/doaddsub.c libbcmath/src/nearzero.c libbcmath/src/num2str.c libbcmath/src/raise.c \
libbcmath/src/rmzero.c libbcmath/src/str2num.c,
$ext_shared,,-I@ext_srcdir@/libbcmath/src)
PHP_ADD_BUILD_DIR($ext_builddir/libbcmath/src)
AC_DEFINE(HAVE_BCMATH, 1, [Whether you have bcmath])
fi
-14
View File
@@ -1,14 +0,0 @@
// $Id$
// vim:ft=javascript
ARG_ENABLE("bcmath", "bc style precision math functions", "yes");
if (PHP_BCMATH == "yes") {
EXTENSION("bcmath", "bcmath.c", null, "-Iext/bcmath/libbcmath/src");
ADD_SOURCES("ext/bcmath/libbcmath/src", "add.c div.c init.c neg.c \
outofmem.c raisemod.c rt.c sub.c compare.c divmod.c int2num.c \
num2long.c output.c recmul.c sqrt.c zero.c debug.c doaddsub.c \
nearzero.c num2str.c raise.c rmzero.c str2num.c", "bcmath");
AC_DEFINE('HAVE_BCMATH', 1, 'Have BCMATH library');
}
-3
View File
@@ -1,3 +0,0 @@
Phil Nelson <philnelson@acm.org> wrote bcmath library.
-515
View File
@@ -1,515 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
^L
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
^L
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
^L
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
^L
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
^L
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
^L
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
^L
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
^L
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
<one line to give the library's name and a brief idea of what it
does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper
mail.
You should also get your employer (if you work as a programmer) or
your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
-10
View File
@@ -1,10 +0,0 @@
Wed Jun 7 09:39:02 2000 Phil Nelson <phil@cs.wwu.edu>
* configure.in and many others: version number now at 0.2.
Many other changes/additions for getting a distribution
to work.
2000-05-21 Phil Nelson <phil@cs.wwu.edu>
* Initial setup of bcmath library., calling it version 0.1.
-21
View File
@@ -1,21 +0,0 @@
BCMATH FAQ:
1) Why BCMATH?
The math routines of GNU bc become more generally useful in a
library form. By separating the BCMATH library from GNU bc,
GNU bc can be under the GPL and BCMATH can be under the LGPL.
2) Why BCMATH when GMP exists?
GMP has "integers" (no digits after a decimal), "rational numbers"
(stored as 2 integers) and "floats". None of these will correctly
represent a POSIX BC number. Floats are the closest, but will not
behave correctly for many computations. For example, BC numbers have
a "scale" that represent the number of digits to represent after the
decimal point. The multiplying two of these numbers requires one to
calculate an exact number of digits after the decimal point regardless
of the number of digits in the integer part. GMP floats have a
"fixed, but arbitrary" mantissa and so multiplying two floats will end
up dropping digits BC must calculate.
-9
View File
@@ -1,9 +0,0 @@
Currently, only libbcmath.a is built. To build and install it, do
configure
make
make install
Typical configure parameters are available. (e.g. PREFIX)
Bugs and comments to philnelson@acm.org.
-12
View File
@@ -1,12 +0,0 @@
## Process this file with automake to produce Makefile.in
SUBDIRS= src doc
MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
stamp-h.in *~
dist-hook:
cp $(srcdir)/doc/bcmath.1 $(distdir)/doc
cp $(srcdir)/src/private.h $(distdir)/src
cp $(srcdir)/FAQ $(distdir)
-3
View File
@@ -1,3 +0,0 @@
NEWS for bcmath library:
May 2000: The library is created.
Loaded 100 of 10004 files, more files were not shown because too many files have changed in this diff. Show more