diff --git a/NEWS b/NEWS index f65f703..38090f3 100644 --- a/NEWS +++ b/NEWS @@ -30,12 +30,19 @@ Coverager: * percent bar updated Others: + * fix build on rare arch + * fix build on Mac OS X * kill compiler warnings * zts build * all fixes from <=1.0.2 ChangeLog ======== + * merged from trunk: 159,161-162,167-180,182,184,186-187,194 + * [194] PHP_5_2: new element in zend_brk_cont_element + * [186] [187] fix build on some rare arch + * [184] fix tplcov + * [178] fix type processor_t conflict with Mac OS X * remove redundant open_basedir check, it's done before compiling * trick in_compilation state, don't trigger __autoload at compile time * FIX conflict between sandbox and user error handler diff --git a/THANKS b/THANKS index 9ddd21c..2c4c965 100644 --- a/THANKS +++ b/THANKS @@ -2,7 +2,7 @@ Jan , host XCache website Alex , redist to FreeBSD darix , redist to openSUSE -judas_iscariote , redist/test with openSUSE +judas_iscariote , redist/test with openSUSE Finjon Kiang , Chinese Traditional translation There is also many ppl on IRC or forum helped me a lot testing XCache. diff --git a/admin/common.php b/admin/common.php index ff3b218..1d5e86e 100644 --- a/admin/common.php +++ b/admin/common.php @@ -2,18 +2,28 @@ function get_language_file_ex($name, $l, $s) { - static $map = array( + static $lmap = array( 'zh' => 'zh-simplified', 'zh-hk' => 'zh-traditional', 'zh-tw' => 'zh-traditional', ); + static $smap = array( + 'gbk' => 'gb2312', + 'gb18030' => 'gb2312', + ); - if (isset($map[$l])) { - $l = $map[$l]; + if (isset($lmap[$l])) { + $l = $lmap[$l]; } if (file_exists($file = "$name-$l-$s.lang.php")) { return $file; } + if (isset($smap[$s])) { + $s = $smap[$s]; + if (file_exists($file = "$name-$l-$s.lang.php")) { + return $file; + } + } if (file_exists($file = "$name-$l.lang.php")) { return $file; } diff --git a/admin/config.php.example b/admin/config.php.example index a288d5f..a8b9358 100644 --- a/admin/config.php.example +++ b/admin/config.php.example @@ -15,10 +15,13 @@ $show_todo_strings = false; // this ob filter is applied for the cache list, not the whole page function ob_filter_path_nicer($o) { - $o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}/", $o); - $xcachedir = realpath(dirname(__FILE__) . "/../"); - $o = str_replace($xcachedir . "/", "{XCache}/", $o); - $o = str_replace("/home/", "{H}/", $o); + $sep = DIRECTORY_SEPARATOR; + $o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}$sep", $o); + $xcachedir = realpath(dirname(__FILE__) . "$sep..$sep"); + $o = str_replace($xcachedir . $sep, "{XCache}$sep", $o); + if ($sep == '/') { + $o = str_replace("/home/", "{H}/", $o); + } return $o; } diff --git a/config.m4 b/config.m4 index 091009b..94f9804 100644 --- a/config.m4 +++ b/config.m4 @@ -58,8 +58,19 @@ if test "$PHP_XCACHE" != "no"; then PHP_SUBST([XCACHE_ENABLE_TEST]) AC_PATH_PROGS([AWK], [gawk awk]) + dnl clean locale for gawk 3.1.5 assertion bug + if echo | LANG=C "$AWK" -- '' > /dev/null 2>&1 ; then + AWK="LANG=C $AWK" + else + if echo | /usr/bin/env - "$AWK" -- '' > /dev/null 2>&1 ; then + AWK="/usr/bin/env - $AWK" + fi + fi PHP_SUBST([AWK]) AC_PATH_PROGS([M4], [m4]) + if echo | "$M4" -E > /dev/null 2>&1 ; then + M4="$M4 -E" + fi PHP_SUBST([M4]) AC_PATH_PROGS([GREP], [grep]) PHP_SUBST([GREP]) diff --git a/coverager.c b/coverager.c index 47241cc..2caaf82 100644 --- a/coverager.c +++ b/coverager.c @@ -234,6 +234,7 @@ void xc_coverager_request_shutdown(TSRMLS_D) /* {{{ */ xc_coverager_save_cov(ZSTR_S(s), outfilename, *pcov TSRMLS_CC); zend_hash_move_forward(XG(coverages)); } + efree(outfilename); } zend_hash_destroy(XG(coverages)); diff --git a/coverager/common-zh-simplified-gb2312.lang.php b/coverager/common-zh-simplified-gb2312.lang.php new file mode 100644 index 0000000..d085fb2 --- /dev/null +++ b/coverager/common-zh-simplified-gb2312.lang.php @@ -0,0 +1,25 @@ + '开始', + 'Directory' + => '目录', + 'File' + => '文件', + 'Percent' + => '覆盖率', + 'Hits' + => '命中', + 'Lines' + => '行数', + 'TODO' + => '闲置文件', + 'XCache PHP Code Coverage Viewer' + => 'XCache PHP 代码覆盖查看器', + 'module' + => '模块', + '' + => '', + ); + diff --git a/coverager/common.php b/coverager/common.php index ff3b218..1d5e86e 100644 --- a/coverager/common.php +++ b/coverager/common.php @@ -2,18 +2,28 @@ function get_language_file_ex($name, $l, $s) { - static $map = array( + static $lmap = array( 'zh' => 'zh-simplified', 'zh-hk' => 'zh-traditional', 'zh-tw' => 'zh-traditional', ); + static $smap = array( + 'gbk' => 'gb2312', + 'gb18030' => 'gb2312', + ); - if (isset($map[$l])) { - $l = $map[$l]; + if (isset($lmap[$l])) { + $l = $lmap[$l]; } if (file_exists($file = "$name-$l-$s.lang.php")) { return $file; } + if (isset($smap[$s])) { + $s = $smap[$s]; + if (file_exists($file = "$name-$l-$s.lang.php")) { + return $file; + } + } if (file_exists($file = "$name-$l.lang.php")) { return $file; } diff --git a/coverager/config.php.example b/coverager/config.php.example index 8053d43..cb2d4aa 100644 --- a/coverager/config.php.example +++ b/coverager/config.php.example @@ -20,10 +20,13 @@ $usecache = false; function ob_filter_path_nicer($o) { - $o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}/", $o); - $xcachedir = realpath(dirname(__FILE__) . "/../"); - $o = str_replace($xcachedir . "/", "{XCache}/", $o); - $o = str_replace("/home/", "{H}/", $o); + $sep = DIRECTORY_SEPARATOR; + $o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}$sep", $o); + $xcachedir = realpath(dirname(__FILE__) . "$sep..$sep"); + $o = str_replace($xcachedir . $sep, "{XCache}$sep", $o); + if ($sep == '/') { + $o = str_replace("/home/", "{H}/", $o); + } return $o; } diff --git a/coverager/coverager.php b/coverager/coverager.php index 26adead..7b05210 100644 --- a/coverager/coverager.php +++ b/coverager/coverager.php @@ -61,7 +61,9 @@ class XcacheCoverageViewer $this->path = isset($_GET['path']) ? $_GET['path'] : ''; $this->path = preg_replace('!\.{2,}!', '.', $this->path); - $this->path = preg_replace('![\\\\/]{2,}!', '/', $this->path); + $qsep = preg_quote(DIRECTORY_SEPARATOR, '!'); + $this->path = preg_replace("![\\\\$qsep]{2,}!", DIRECTORY_SEPARATOR, $this->path); + $this->path = preg_replace("!$qsep$!", '', $this->path); if ($this->path == '/') { $this->path = ''; } @@ -117,7 +119,7 @@ class XcacheCoverageViewer list($tplfile, $tpllines, $tplcov) = $this->loadTplCov($fileinfo['cov'], substr($this->outpath, $this->datadir_len)); if ($tplfile) { - $tplcov = sprint_cov($tplinfo['tplcov'], $tpllines); + $tplcov = sprint_cov($tplcov, $tpllines); unset($tpllines); } } diff --git a/coverager/coverager.tpl.php b/coverager/coverager.tpl.php index 073a7b2..789884b 100644 --- a/coverager/coverager.tpl.php +++ b/coverager/coverager.tpl.php @@ -1,7 +1,6 @@ - charset" /> @@ -67,6 +66,7 @@ function dir_row($info, $srcdir) { global $cycle; if ($info['files'] || $info['todos']) { + $srcdir .= DIRECTORY_SEPARATOR; $c = $cycle->next(); $srcdir_html = htmlspecialchars($srcdir); $todos = number_format($info['todos']); diff --git a/mkstructinfo.awk b/mkstructinfo.awk index 267fe12..423d216 100755 --- a/mkstructinfo.awk +++ b/mkstructinfo.awk @@ -2,8 +2,35 @@ # vim:ts=4:sw=4 BEGIN { brace = 0; + incomment = 0; buffer_len = 0; } + +# multiline comment handling +{ + # removes one line comment + gsub(/\/\*(.+?)\*\//, " "); +} +/\*\// { + if (incomment) { + sub(/.*\*\//, ""); + incomment = 0; + } +} +incomment { + next; +} +/\/\*/ { + sub(/\/\*.*/, ""); + incomment = 1; + # fall through +} + +# skip file/line mark here to be faster +/^#/ { + next; +} + /^}.*;/ { if (instruct) { sub(";", ""); @@ -50,6 +77,7 @@ BEGIN { { if (brace == 1 && instruct) { + gsub(/(^[\t ]+|[\t ]+$)/, ""); # trim whitespaces sub(/.*[{}]/, ""); gsub(/\[[^\]]+\]/, ""); # ignore [...] gsub(/:[0-9]+/, ""); # ignore struct bit @@ -62,38 +90,57 @@ BEGIN { buffer_len ++; } else { + # process normal variables + # ignore any ()s while (gsub(/(\([^)]*\))/, "")) { } if (match($0, /[()]/)) { next; } + # unsigned int *a, b; int c; gsub(/[*]/, " "); + # unsigned int a, b; int c; gsub(/ +/, " "); + # unsigned int a, b; int c; gsub(/ *[,;]/, ";"); + # unsigned int a; b; int c; if (!match($0, /;/)) { next; } + # print "=DEBUG=" $0 "=="; split($0, chunks, ";"); - # get var of "int *var, var;" etc - for (i in chunks) { + # [unsigned int a, b, c] + + for (i = 1; i in chunks; i ++) { if (chunks[i] == "") { delete chunks[i]; continue; } split(chunks[i], pieces, " "); + # [unsigned, int, a] + # [b] + # [c] - for (j in pieces) { + last_piece = ""; + for (j = 1; j in pieces; j ++) { last_piece = pieces[j]; - delete pieces[i]; + delete pieces[j]; } if (last_piece == "") { - print "=====" chunks[i]; + # print "=ERROR=" chunks[i] "=="; + delete chunks[i]; + continue; } + # a + # b + # c + buffer[buffer_len] = last_piece; buffer_len ++; - delete chunks[i]; + delete chunks[i] } + last_piece = ""; } next; } @@ -104,7 +151,7 @@ BEGIN { typedefs[$3] = $4; next; } -/^typedef struct .*\{/ { +/^typedef struct .*\{[^}]*$/ { brace = 1; instruct = 1; next; diff --git a/mmap.c b/mmap.c index ba0b28c..4af2973 100644 --- a/mmap.c +++ b/mmap.c @@ -84,19 +84,19 @@ static XC_SHM_IS_READONLY(xc_mmap_is_readonly) /* {{{ */ static XC_SHM_TO_READWRITE(xc_mmap_to_readwrite) /* {{{ */ { if (shm->diff) { - assert(xc_mmap_is_readonly(p)); + assert(xc_mmap_is_readonly(shm, p)); p = PTR_SUB(p, shm->diff); } - assert(xc_mmap_is_readwrite(p)); + assert(xc_mmap_is_readwrite(shm, p)); return p; } /* }}} */ static XC_SHM_TO_READONLY(xc_mmap_to_readonly) /* {{{ */ { - assert(xc_shm_is_readwrite(p)); + assert(xc_mmap_is_readwrite(shm, p)); if (shm->diff) { p = PTR_ADD(p, shm->diff); - assert(xc_mmap_is_readonly(p)); + assert(xc_mmap_is_readonly(shm, p)); } return p; } diff --git a/processor/head.m4 b/processor/head.m4 index 29317df..8b5d0c0 100644 --- a/processor/head.m4 +++ b/processor/head.m4 @@ -53,8 +53,8 @@ typedef char zstr_char; #define MAX_DUP_STR_LEN 256 dnl }}} -/* export: typedef struct _processor_t processor_t; :export {{{ */ -struct _processor_t { +/* export: typedef struct _xc_processor_t xc_processor_t; :export {{{ */ +struct _xc_processor_t { char *p; zend_uint size; HashTable strings; @@ -116,7 +116,7 @@ static inline int xc_zstrlen(int type, zstr s) #endif /* {{{ xc_calc_string_n */ REDEF(`KIND', `calc') -static inline void xc_calc_string_n(processor_t *processor, zend_uchar type, zstr str, long size IFASSERT(`, int relayline')) { +static inline void xc_calc_string_n(xc_processor_t *processor, zend_uchar type, zstr str, long size IFASSERT(`, int relayline')) { pushdef(`__LINE__', `relayline') int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size); long dummy = 1; @@ -138,7 +138,7 @@ static inline void xc_calc_string_n(processor_t *processor, zend_uchar type, zst /* }}} */ /* {{{ xc_store_string_n */ REDEF(`KIND', `store') -static inline zstr xc_store_string_n(processor_t *processor, zend_uchar type, zstr str, long size IFASSERT(`, int relayline')) { +static inline zstr xc_store_string_n(xc_processor_t *processor, zend_uchar type, zstr str, long size IFASSERT(`, int relayline')) { pushdef(`__LINE__', `relayline') int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size); zstr ret, *pret; @@ -165,7 +165,7 @@ static inline zstr xc_store_string_n(processor_t *processor, zend_uchar type, zs /* {{{ xc_get_class_num * return class_index + 1 */ -static zend_ulong xc_get_class_num(processor_t *processor, zend_class_entry *ce) { +static zend_ulong xc_get_class_num(xc_processor_t *processor, zend_class_entry *ce) { zend_ulong i; const xc_entry_t *xce = processor->xce_src; zend_class_entry *ceptr; @@ -187,7 +187,7 @@ static zend_ulong xc_get_class_num(processor_t *processor, zend_class_entry *ce) /* }}} */ /* {{{ xc_get_class */ #ifdef ZEND_ENGINE_2 -static zend_class_entry *xc_get_class(processor_t *processor, zend_ulong class_num) { +static zend_class_entry *xc_get_class(xc_processor_t *processor, zend_ulong class_num) { /* must be parent or currrent class */ assert(class_num <= processor->active_class_num); return CestToCePtr(processor->xce_dst->data.php->classinfos[class_num - 1].cest); @@ -196,7 +196,7 @@ static zend_class_entry *xc_get_class(processor_t *processor, zend_ulong class_n /* }}} */ #ifdef ZEND_ENGINE_2 /* fix method on store */ -static void xc_fix_method(processor_t *processor, zend_op_array *dst) /* {{{ */ +static void xc_fix_method(xc_processor_t *processor, zend_op_array *dst) /* {{{ */ { zend_function *zf = (zend_function *) dst; zend_class_entry *ce = processor->active_class_entry_dst; @@ -250,7 +250,7 @@ dnl ================ export API /* export: xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC); :export {{{ */ xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC) { xc_entry_t *dst; - processor_t processor; + xc_processor_t processor; memset(&processor, 0, sizeof(processor)); if (src->type == XC_TYPE_VAR) { @@ -323,7 +323,7 @@ err_alloc: /* }}} */ /* export: xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *src, zend_bool readonly_protection TSRMLS_DC); :export {{{ */ xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *src, zend_bool readonly_protection TSRMLS_DC) { - processor_t processor; + xc_processor_t processor; memset(&processor, 0, sizeof(processor)); processor.readonly_protection = readonly_protection; @@ -334,7 +334,7 @@ xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *s /* }}} */ /* export: zval *xc_processor_restore_zval(zval *dst, const zval *src TSRMLS_DC); :export {{{ */ zval *xc_processor_restore_zval(zval *dst, const zval *src TSRMLS_DC) { - processor_t processor; + xc_processor_t processor; memset(&processor, 0, sizeof(processor)); processor.reference = 1; diff --git a/processor/processor.m4 b/processor/processor.m4 index d9772d1..ce7e368 100644 --- a/processor/processor.m4 +++ b/processor/processor.m4 @@ -55,6 +55,9 @@ DEF_STRUCT_P_FUNC(`zend_try_catch_element', , ` dnl }}} dnl {{{ zend_brk_cont_element DEF_STRUCT_P_FUNC(`zend_brk_cont_element', , ` +#ifdef ZEND_ENGINE_2_2 + DISPATCH(int, start) +#endif DISPATCH(int, cont) DISPATCH(int, brk) DISPATCH(int, parent) diff --git a/processor/struct.m4 b/processor/struct.m4 index fee5254..c9423d8 100644 --- a/processor/struct.m4 +++ b/processor/struct.m4 @@ -8,9 +8,9 @@ define(`DECL_STRUCT_P_FUNC', `translit( ifdef(`EXPORT_'ifelse(`$2', `', `$1', `$2'), `void', `static void inline') FUNC_NAME`'( IFDPRINT( `const $1 * const src, int indent') - IFCALC( `processor_t *processor, const $1 * const src') - IFSTORE( `processor_t *processor, $1 *dst, const $1 * const src') - IFRESTORE(`processor_t *processor, $1 *dst, const $1 * const src') + IFCALC( `xc_processor_t *processor, const $1 * const src') + IFSTORE( `xc_processor_t *processor, $1 *dst, const $1 * const src') + IFRESTORE(`xc_processor_t *processor, $1 *dst, const $1 * const src') IFDASM( `zval *dst, const $1 * const src') IFASM( `$1 *dst, const $1 * const src') TSRMLS_DC diff --git a/xcache-zh-gb2312.ini b/xcache-zh-gb2312.ini index f9f9f2d..3a633c5 100644 --- a/xcache-zh-gb2312.ini +++ b/xcache-zh-gb2312.ini @@ -19,9 +19,12 @@ xcache.admin.pass = "" [xcache] ; 这里的多数选项仅在 ini 里可以修改, 这里列出的都是默认值, 除非另外说明 + +; select low level shm/allocator scheme implemenation +xcache.shm_scheme = "mmap" ; 禁用: xcache.size=0 -; 启用: xcache.size=任意>0的值, 同时请注意您的系统 mmap 上限 -xcache.size = 0 +; 启用: xcache.size=64M 之类 (任意>0的值) 同时请注意您的系统 mmap 上限 +xcache.size = 0M ; 建议设置为 cpu 数 (cat /proc/cpuinfo |grep -c processor) xcache.count = 1 ; 只是个参考值, 您可以放心地存储多于此数量的项目(php脚本/变量) @@ -32,7 +35,7 @@ xcache.ttl = 0 xcache.gc_interval = 0 ; 同上, 只是针对变量缓存设置 -xcache.var_size = 0 +xcache.var_size = 0M xcache.var_count = 1 xcache.var_slots = 8K ; 默认, 允许 ini_set() @@ -58,6 +61,7 @@ xcache.mmap_path = "/dev/zero" xcache.coredump_directory = "" xcache.cacher = On +xcache.stat = On xcache.optimizer = Off [xcache.coverager] diff --git a/xcache.ini b/xcache.ini index 8c91913..f5a43fd 100644 --- a/xcache.ini +++ b/xcache.ini @@ -1,6 +1,7 @@ [xcache-common] ;; install as zend extension (recommended), normally "$extension_dir/xcache.so" zend_extension = /usr/local/lib/php/extensions/non-debug-non-zts-xxx/xcache.so +; zend_extension_ts = /usr/local/lib/php/extensions/non-debug-zts-xxx/xcache.so ;; For windows users, replace xcache.so with php_xcache.dll zend_extension_ts = c:/php/extensions/php_xcache.dll ;; or install as extension, make sure your extension_dir setting is correct @@ -18,9 +19,12 @@ xcache.admin.pass = "" [xcache] ; ini only settings, all the values here is default unless explained + +; select low level shm/allocator scheme implemenation +xcache.shm_scheme = "mmap" ; to disable: xcache.size=0 -; to enable : xcache.size=any size > 0 and your system mmap allows -xcache.size = 0 +; to enable : xcache.size=64M etc (any size > 0) and your system mmap allows +xcache.size = 0M ; set to cpu count (cat /proc/cpuinfo |grep -c processor) xcache.count = 1 ; just a hash hints, you can always store count(items) > slots @@ -31,7 +35,7 @@ xcache.ttl = 0 xcache.gc_interval = 0 ; same as aboves but for variable cache -xcache.var_size = 0 +xcache.var_size = 0M xcache.var_count = 1 xcache.var_slots = 8K ; default ttl