sean Wed Jan 31 03:00:21 2007 UTC
Added files:
/phpdoc/scripts functable.php
Log:
new functable -- all PHP; needs testing
http://cvs.php.net/viewvc.cgi/phpdoc/scripts/functable.php?view=markup&rev=1.1
Index: phpdoc/scripts/functable.php
+++ phpdoc/scripts/functable.php
<?php
/*
+----------------------------------------------------------------------+
| Functable Generator |
+----------------------------------------------------------------------+
| Copyright (c) 2006-2007 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 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_0.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 |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Sean Coates <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
// direct the output of this fine into phpdoc/phpbook/phpbook-xsl/version.xml
// errors go to STDERR
// To do:
// - TEST, please
// - PECL support
// set up config:
// set $_ENV['PATH_TMP'] to change the temporary directory
define('PATH_TMP', getenv('PATH_TMP') ? getenv('PATH_TMP') : '/tmp/functable');
fwrite(STDERR, 'PATH_TMP=' . PATH_TMP ."\n");
// set $_ENV['PATH_DB'] to change the sqlite db file
define('PATH_DB', getenv('PATH_DB') ? getenv('PATH_DB') : dirname(__FILE__)
.'/functable.sqlite');
fwrite(STDERR, 'PATH_DB=' . PATH_DB ."\n");
// set $_ENV['PATH_CVS'] to change the path to your cvs binary
define('PATH_CVS', getenv('PATH_CVS') ? getenv('PATH_CVS') : '/usr/bin/cvs');
fwrite(STDERR, 'PATH_CVS=' . PATH_CVS ."\n");
// set $_ENV['FUNCTABLE_TAGS'] if you'd like to only grab specific tags
function rm_recursive($path)
{
$dir = new DirectoryIterator($path);
while($dir->valid()) {
if(!$dir->isDot()) {
if ($dir->isDir()) {
rm_recursive($path . DIRECTORY_SEPARATOR . $dir->current());
} else {
unlink($path . DIRECTORY_SEPARATOR . $dir->current());
}
}
$dir->next();
}
rmdir($path);
}
function get_release_tags()
{
rm_recursive(PATH_TMP);
mkdir(PATH_TMP);
chdir(PATH_TMP);
$cmd = PATH_CVS .' -q -d :pserver:[EMAIL PROTECTED]:/repository co
php-src/ChangeLog';
exec($cmd);
chdir(PATH_TMP . '/php-src');
$cmd = PATH_CVS .' log ChangeLog';
$log = explode("\n", `$cmd`);
do {
$l = array_shift($log);
if ($l == 'symbolic names:') {
break;
}
} while (1);
if (!$standalone) {
$tags = array();
}
foreach ($log as $l) {
if (substr($l, 0, 1) != "\t") {
break;
}
list($tag,) = explode(': ', trim($l));
if (preg_match('/^PHP_[456]_[0-9]+_[0-9+]$/i', $tag)) {
$tags[] = $tag;
}
}
return array_reverse($tags);
}
function checkout_tag($tag)
{
rm_recursive(PATH_TMP);
mkdir(PATH_TMP);
chdir(PATH_TMP);
$cmd = PATH_CVS .' -d :pserver:[EMAIL PROTECTED]:/repository co -r '.
escapeshellarg($tag) . ' php-src';
exec($cmd);
}
function get_src_files($path, $depth=0)
{
if ($depth > 100) {
die("TOO DEEP\n");
}
$files = array();
$dir = scandir($path);
foreach ($dir AS $f) {
if ($f != '.' && $f != '..') {
$p = $path . DIRECTORY_SEPARATOR . $f;
if (is_dir($p)) {
$files = array_merge($files, get_src_files($p, $depth+1));
} elseif (substr($f, -2) == '.c') {
$files[] = $p;
}
}
}
return $files;
}
function parse_protos($path)
{
$funcs = array();
$protoFuncs = array();
$files = get_src_files($path);
foreach ($files AS $f) {
$protoRegex = '/
{{{\s*proto\s+ # proto identifier
(.*?)\s+ # type
([^(\s]+?)\s? # functon name
\((.*)\)\s* # params
([^*;{]*) # suffix
/ix';
$protos = preg_grep($protoRegex, file($f));
if ($protos) {
foreach ($protos AS $line => $p) {
preg_match($protoRegex, $p, $m);
$thisProto = array(
'file' => substr($f, strlen(SRC_DIR) + 1),
'type' => $m[1],
'func' => $m[2],
'params' => $m[3],
'suffix' => $m[4],
'line' => $line + 1
);
if ($m[4] && trim($m[4]) == 'U') {
$thisProto['unicode'] = true;
} else {
$thisProto['unicode'] = false;
}
$funcs[] = $thisProto;
$protoFuncs[] = $m[2];
}
}
}
return $funcs;
}
function tag2ver($tag, $vertical)
{
if ($vertical) {
return chunk_split(str_replace('_', ' ', $tag), 1, "\n");
}
}
function convert_array_to_words($func)
{
// globals suck )-:
global $tags4, $tags5;
static $regex = '/PHP_([45])_([0-9])_([0-9])/';
static $rep = '$1.$2.$3';
$text4 = '';
$ft4 = array();
foreach ($tags4 as $t) {
if (isset($func[$t])) {
$ft4[] = $t;
}
}
if (!$ft4) {
$text4 = '';
} elseif ($ft4 == $tags4) {
$text4 = "PHP 4";
} else {
if ($ft4[0] == $tags4[0]) {
$text4 = "PHP 4 <= " . preg_replace($regex, $rep, $ft4[count($ft4)
- 1]);
} else {
$text4 = "PHP 4 >= " . preg_replace($regex, $rep, $ft4[0]);
}
}
$text5 = '';
$ft5 = array();
foreach ($tags5 as $t) {
if (isset($func[$t])) {
$ft5[] = $t;
}
}
if (!$ft5) {
$text5 = '';
} elseif ($ft5 == $tags5) {
$text5 = "PHP 5";
} else {
if ($ft5[0] == $tags5[0]) {
$text5 = "PHP 5 <= " . preg_replace($regex, $rep, $ft5[count($ft5)
- 1]);
} else {
$text5 = "PHP 5 >= " . preg_replace($regex, $rep, $ft5[0]);
}
}
if ($text4 && $text5) {
return "$text4, $text5";
} elseif ($text4) {
return "$text4";
} elseif ($text5) {
return "$text5";
} else {
die("Error.");
}
}
if (getenv('SKIP_CVS')) {
fwrite(STDERR, "Skipping CVS\n");
} else {
fwrite(STDERR, "Using CVS\n");
if (getenv('FUNCTABLE_TAGS')) {
$tags = explode(' ', getenv('FUNCTABLE_TAGS'));
} else {
$tags = get_release_tags();
}
fwrite(STDERR, "Tags: " . implode(' ', $tags) ."\n");
foreach ($tags as $tag) {
fwrite(STDERR, "Getting tag: $tag\n");
checkout_tag($tag);
$protos = parse_protos(PATH_TMP . DIRECTORY_SEPARATOR . 'php-src');
$dbh = new PDO('sqlite:' . PATH_DB);
$s = $dbh->prepare('DELETE FROM func_tag WHERE tag_name = ?');
$s->bindParam(1, $tag);
$s->execute();
foreach ($protos as $p) {
$s = $dbh->prepare("INSERT INTO "
. "func_tag (func_name, tag_name, has_proto, unicode_safe,
source) "
. "VALUES (?, ?, 1, ?, 'php-src')");
$s->bindParam(1, $p['func']);
$s->bindParam(2, $tag);
$s->bindParam(3, $p['unicode']);
$s->execute();
}
}
}
// generate versions.xsl
echo "<?xml version='1.0' encoding='iso-8859-1'?>\n"; // short tags )-:
?>
<!-- DO NOT EDIT THIS FILE !!!
;; It was generated programmatically
;; see cvs:phpdoc/scripts/functable.php
;; -->
<versions>
<function name='array' from='PHP 4, PHP 5'/>
<function name='die' from='PHP 4, PHP 5'/>
<function name='echo' from='PHP 4, PHP 5'/>
<function name='empty' from='PHP 4, PHP 5'/>
<function name='eval' from='PHP 4, PHP 5'/>
<function name='exit' from='PHP 4, PHP 5'/>
<function name='isset' from='PHP 4, PHP 5'/>
<function name='list' from='PHP 4, PHP 5'/>
<function name='print' from='PHP 4, PHP 5'/>
<function name='unset' from='PHP 4, PHP 5'/>
<?php
$dbh = new PDO('sqlite:' . PATH_DB);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$tags = array();
$funcs = array();
$s = $dbh->prepare("
SELECT
func_name
FROM
func_tag
WHERE
UPPER(tag_name) = ?
ORDER BY
tag_name
");
$tq = $dbh->query("
SELECT
DISTINCT UPPER(tag_name) AS tag_name
FROM
func_tag
WHERE
tag_name LIKE 'PHP\\__\\__\\__' ESCAPE '\\'
ORDER BY
UPPER(tag_name)
");
foreach ($tq as $tr) {
$tags[] = $tr['tag_name'];
if ($s->execute(array($tr['tag_name']))) {
while ($fr = $s->fetch()) {
if ($fr['func_name']) {
$funcs[$fr['func_name']][$tr['tag_name']] = 1;
}
}
}
}
ksort($funcs);
$tags4 = array();
$tags5 = array();
foreach ($tags as $t) {
if (substr($t,0,5) == 'PHP_4') {
$tags4[] = $t;
} elseif (substr($t,0,5) == 'PHP_5') {
$tags5[] = $t;
} else {
die('ERROR: '. $t);
}
}
foreach ($funcs as $funcname => $func) {
$text = htmlspecialchars(convert_array_to_words($func));
echo " <function name='{$funcname}' from='{$text}'/>\n";
}
?>
</versions>
?>