diff options
Diffstat (limited to 'scripts/dev')
-rw-r--r-- | scripts/dev/check_parameters.php | 373 | ||||
-rwxr-xr-x | scripts/dev/conv_proto | 30 | ||||
-rwxr-xr-x | scripts/dev/conv_z_macros | 61 | ||||
-rwxr-xr-x | scripts/dev/credits | 26 | ||||
-rw-r--r-- | scripts/dev/extern_c.php | 45 | ||||
-rwxr-xr-x | scripts/dev/phpextdist | 27 | ||||
-rwxr-xr-x | scripts/dev/search_underscores.php | 97 |
7 files changed, 0 insertions, 659 deletions
diff --git a/scripts/dev/check_parameters.php b/scripts/dev/check_parameters.php deleted file mode 100644 index cefb32d645..0000000000 --- a/scripts/dev/check_parameters.php +++ /dev/null @@ -1,373 +0,0 @@ -<?php -/* - +----------------------------------------------------------------------+ - | 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: Nuno Lopes <nlopess@php.net> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - - -define('REPORT_LEVEL', 2); // 0 reports less false-positives. up to level 5. -define('VERSION', '5.2'); // minimum is 5.2 -define('PHPDIR', realpath(dirname(__FILE__) . '/../..')); - - -// be sure you have enough memory and stack for PHP. pcre will push the limits! -ini_set('pcre.backtrack_limit', 10000000); - - -// ------------------------ end of config ---------------------------- - - -$API_params = array( - 'a' => array('zval**'), // array as zval* - 'b' => array('zend_bool*'), // boolean - 'C' => array('zend_class_entry**'), // class - 'd' => array('double*'), // double - 'f' => array('zend_fcall_info*', 'zend_fcall_info_cache*'), // function - 'h' => array('HashTable**'), // array as an HashTable* - 'l' => array('long*'), // long - 'o' => array('zval**'), //object - 'O' => array('zval**', 'zend_class_entry*'), // object of given type - 'r' => array('zval**'), // resource - 's' => array('char**', 'int*'), // string - 'z' => array('zval**'), // zval* - 'Z' => array('zval***') // zval** -); - -// specific to PHP >= 6 -if (version_compare(VERSION, '6', 'ge')) { - $API_params['S'] = $API_params['s']; // binary string - $API_params['t'] = array('zstr*', 'int*', 'zend_uchar*'); // text - $API_params['T'] = $API_params['t']; - $API_params['u'] = array('UChar**', 'int*'); // unicode - $API_params['U'] = $API_params['u']; -} - - -/** reports an error, according to its level */ -function error($str, $level = 0) -{ - global $current_file, $current_function, $line; - - if ($level <= REPORT_LEVEL) { - if (strpos($current_file,PHPDIR) === 0) { - $filename = substr($current_file, strlen(PHPDIR)+1); - } else { - $filename = $current_file; - } - echo $filename , " [$line] $current_function : $str\n"; - } -} - - -/** this updates the global var $line (for error reporting) */ -function update_lineno($offset) -{ - global $lines_offset, $line; - - $left = 0; - $right = $count = count($lines_offset)-1; - - // a nice binary search :) - do { - $mid = intval(($left + $right)/2); - $val = $lines_offset[$mid]; - - if ($val < $offset) { - if (++$mid > $count || $lines_offset[$mid] > $offset) { - $line = $mid; - return; - } else { - $left = $mid; - } - } else if ($val > $offset) { - if ($lines_offset[--$mid] < $offset) { - $line = $mid+1; - return; - } else { - $right = $mid; - } - } else { - $line = $mid+1; - return; - } - } while (true); -} - - -/** parses the sources and fetches its vars name, type and if they are initialized or not */ -function get_vars($txt) -{ - $ret = array(); - preg_match_all('/((?:(?:unsigned|struct)\s+)?\w+)(?:\s*(\*+)\s+|\s+(\**))(\w+(?:\[\s*\w*\s*\])?)\s*(?:(=)[^,;]+)?((?:\s*,\s*\**\s*\w+(?:\[\s*\w*\s*\])?\s*(?:=[^,;]+)?)*)\s*;/S', $txt, $m, PREG_SET_ORDER); - - foreach ($m as $x) { - // the first parameter is special - if (!in_array($x[1], array('else', 'endif', 'return'))) // hack to skip reserved words - $ret[$x[4]] = array($x[1] . $x[2] . $x[3], $x[5]); - - // are there more vars? - if ($x[6]) { - preg_match_all('/(\**)\s*(\w+(?:\[\s*\w*\s*\])?)\s*(=?)/S', $x[6], $y, PREG_SET_ORDER); - foreach ($y as $z) { - $ret[$z[2]] = array($x[1] . $z[1], $z[3]); - } - } - } - -// if ($GLOBALS['current_function'] == 'for_debugging') { print_r($m);print_r($ret); } - return $ret; -} - - -/** run diagnostic checks against one var. */ -function check_param($db, $idx, $exp, $optional) -{ - global $error_few_vars_given; - - if ($idx >= count($db)) { - if (!$error_few_vars_given) { - error("too few variables passed to function"); - $error_few_vars_given = true; - } - return; - } elseif ($db[$idx][0] === '**dummy**') { - return; - } - - if ($db[$idx][1] != $exp) { - error("{$db[$idx][0]}: expected '$exp' but got '{$db[$idx][1]}' [".($idx+1).']'); - } - - if ($optional && !$db[$idx][2]) { - error("optional var not initialized: {$db[$idx][0]} [".($idx+1).']', 1); - - } elseif (!$optional && $db[$idx][2]) { - error("not optional var is initialized: {$db[$idx][0]} [".($idx+1).']', 2); - } -} - - -/** fetch params passed to zend_parse_params*() */ -function get_params($vars, $str) -{ - $ret = array(); - preg_match_all('/(?:\([^)]+\))?(&?)([\w>.()-]+(?:\[\w+\])?)\s*,?((?:\)*\s*=)?)/S', $str, $m, PREG_SET_ORDER); - - foreach ($m as $x) { - $name = $x[2]; - - // little hack for last parameter - if (strpos($name, '(') === false) { - $name = rtrim($name, ')'); - } - - if (empty($vars[$name][0])) { - error("variable not found: '$name'", 3); - $ret[][] = '**dummy**'; - - } else { - $ret[] = array($name, $vars[$name][0] . ($x[1] ? '*' : ''), $vars[$name][1]); - } - - // the end (yes, this is a little hack :P) - if ($x[3]) { - break; - } - } - -// if ($GLOBALS['current_function'] == 'for_debugging') { var_dump($m); var_dump($ret); } - return $ret; -} - - -/** run tests on a function. the code is passed in $txt */ -function check_function($name, $txt, $offset) -{ - global $API_params; - - if (preg_match_all('/zend_parse_parameters(?:_ex\s*\([^,]+,[^,]+|\s*\([^,]+),\s*"([^"]*)"\s*,\s*([^{;]*)/S', $txt, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { - - $GLOBALS['current_function'] = $name; - - foreach ($matches as $m) { - $GLOBALS['error_few_vars_given'] = false; - update_lineno($offset + $m[2][1]); - - $vars = get_vars(substr($txt, 0, $m[0][1])); // limit var search to current location - $params = get_params($vars, $m[2][0]); - $optional = $varargs = false; - $last_last_char = $last_char = ''; - $j = -1; - $len = strlen($m[1][0]); - - for ($i = 0; $i < $len; ++$i) { - switch($char = $m[1][0][$i]) { - // separator for optional parameters - case '|': - if ($optional) { - error("more than one optional separator at char #$i"); - } else { - $optional = true; - if ($i == $len-1) { - error("unnecessary optional separator"); - } - } - break; - - // separate_zval_if_not_ref - case '/': - if (!in_array($last_char, array('r', 'z'))) { - error("the '/' specifier cannot be applied to '$last_char'"); - } - break; - - // nullable arguments - case '!': - if (!in_array($last_char, array('a', 'C', 'f', 'h', 'o', 'O', 'r', 's', 't', 'z', 'Z'))) { - error("the '!' specifier cannot be applied to '$last_char'"); - } - break; - - case '&': - if (version_compare(VERSION, '6', 'ge')) { - if ($last_char == 's' || ($last_last_char == 's' && $last_char == '!')) { - check_param($params, ++$j, 'UConverter*', $optional); - - } else { - error("the '&' specifier cannot be applied to '$last_char'"); - } - } else { - error("unknown char ('&') at column $i"); - } - break; - - case '+': - case '*': - if (version_compare(VERSION, '6', 'ge')) { - if ($varargs) { - error("A varargs specifier can only be used once. repeated char at column $i"); - } else { - check_param($params, ++$j, 'zval****', $optional); - check_param($params, ++$j, 'int*', $optional); - $varargs = true; - } - } else { - error("unknown char ('$char') at column $i"); - } - break; - - default: - if (isset($API_params[$char])) { - foreach($API_params[$char] as $exp) { - check_param($params, ++$j, $exp, $optional); - } - } else { - error("unknown char ('$char') at column $i"); - } - } - - $last_last_char = $last_char; - $last_char = $char; - } - } - } -} - - -/** the main recursion function. splits files in functions and calls the other functions */ -function recurse($path) -{ - foreach (scandir($path) as $file) { - if ($file == '.' || $file == '..' || $file == 'CVS') continue; - - $file = "$path/$file"; - if (is_dir($file)) { - recurse($file); - continue; - } - - // parse only .c and .cpp files - if (substr_compare($file, '.c', -2) && substr_compare($file, '.cpp', -4)) continue; - - $txt = file_get_contents($file); - // remove comments (but preserve the number of lines) - $txt = preg_replace(array('@//.*@S', '@/\*.*\*/@SsUe'), array('', 'preg_replace("/[^\r\n]+/S", "", \'$0\')'), $txt); - - - $split = preg_split('/PHP_(?:NAMED_)?(?:FUNCTION|METHOD)\s*\((\w+(?:,\s*\w+)?)\)/S', $txt, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE); - - if (count($split) < 2) continue; // no functions defined on this file - array_shift($split); // the first part isn't relevant - - - // generate the line offsets array - $j = 0; - $lines = preg_split("/(\r\n?|\n)/S", $txt, -1, PREG_SPLIT_DELIM_CAPTURE); - $lines_offset = array(); - - for ($i = 0; $i < count($lines); ++$i) { - $j += strlen($lines[$i]) + strlen(@$lines[++$i]); - $lines_offset[] = $j; - } - - $GLOBALS['lines_offset'] = $lines_offset; - $GLOBALS['current_file'] = $file; - - - for ($i = 0; $i < count($split); $i+=2) { - // if the /* }}} */ comment is found use it to reduce false positives - // TODO: check the other indexes - list($f) = preg_split('@/\*\s*}}}\s*\*/@S', $split[$i+1][0]); - check_function(preg_replace('/\s*,\s*/S', '::', $split[$i][0]), $f, $split[$i][1]); - } - } -} - -$dirs = array(); - -if (isset($argc) && $argc > 1) { - if ($argv[1] == '-h' || $argv[1] == '-help' || $argv[1] == '--help') { - echo <<<HELP -Synopsis: - php check_parameters.php [directories] - -HELP; - exit(0); - } - for ($i = 1; $i < $argc; $i++) { - $dirs[] = $argv[$i]; - } -} else { - $dirs[] = PHPDIR; -} - -foreach($dirs as $dir) { - if (is_dir($dir)) { - if (!is_readable($dir)) { - echo "ERROR: directory '", $dir ,"' is not readable\n"; - exit(1); - } - } else { - echo "ERROR: bogus directory '", $dir ,"'\n"; - exit(1); - } -} - -foreach ($dirs as $dir) { - recurse(realpath($dir)); -} diff --git a/scripts/dev/conv_proto b/scripts/dev/conv_proto deleted file mode 100755 index fad9cfaa83..0000000000 --- a/scripts/dev/conv_proto +++ /dev/null @@ -1,30 +0,0 @@ -#! /bin/sh -# -# do some automatic conversion of prototypes -# - -if test "$1" = "" ; then - echo "usage: $0 list-of-files" - exit 1 -fi - -tmpfile=`mktemp -q /tmp/asd.XXXXXX` - -if test "$?" != "0" ; then - echo "$0: cannot create temporary file" - exit 1 -fi - -for file in ${1+"$@"} ; do - echo "working on $file" - cat $file | \ - sed -e \ - 's/void php3_\(.*\)(INTERNAL_FUNCTION_PARAMETERS)/PHP_FUNCTION(\1)/' \ - -e 's/^extern void /void /' \ - -e 's/^extern PHP_FUNCTION/PHP_FUNCTION/' > $tmpfile - cp $tmpfile $file -done - -rm -f $tmpfile - -exit 0 diff --git a/scripts/dev/conv_z_macros b/scripts/dev/conv_z_macros deleted file mode 100755 index 9da4699eee..0000000000 --- a/scripts/dev/conv_z_macros +++ /dev/null @@ -1,61 +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. | -# +----------------------------------------------------------------------+ -# | Author: Sascha Schumann <sascha@schumann.cx> | -# +----------------------------------------------------------------------+ -# -# $Id$ - -for i in $@; do - echo -n "Processing $i... " - sed \ - -e 's/(\*\([^()]\+\))->type/Z_TYPE_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->type/Z_TYPE_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.type/Z_TYPE(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.dval/Z_DVAL_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.dval/Z_DVAL_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.dval/Z_DVAL(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.lval/Z_LVAL_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.lval/Z_LVAL_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.lval/Z_LVAL(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.ht/Z_ARRVAL_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.ht/Z_ARRVAL_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.ht/Z_ARRVAL(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.str\.val/Z_STRVAL_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.str\.val/Z_STRVAL_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.str\.val/Z_STRVAL(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.str\.len/Z_STRLEN_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.str\.len/Z_STRLEN_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.str\.len/Z_STRLEN(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.obj\.properties/Z_OBJPROP_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.obj\.properties/Z_OBJPROP_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.obj\.properties/Z_OBJPROP(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.obj\.ce/Z_OBJCE_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.obj\.ce/Z_OBJCE_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.obj\.ce/Z_OBJCE(\1)/g' \ - -e 's/(\*\([^()]\+\))->value\.obj/Z_OBJ_PP(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)->value\.obj/Z_OBJ_P(\1)/g' \ - -e 's/\([a-z_][]a-z_0-9\[]*\)\.value\.obj/Z_OBJ(\1)/g' \ - -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)->Z_\([A-Z_]\+\)(/Z_\2(\1->/g' \ - -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)->Z_\([A-Z_]\+\)(/Z_\2(\1->/g' \ - -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)->Z_\([A-Z_]\+\)(/Z_\2(\1->/g' \ - -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)\.Z_\([A-Z_]\+\)(/Z_\2(\1./g' \ - -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)\.Z_\([A-Z_]\+\)(/Z_\2(\1./g' \ - -e 's/\([a-zA-Z_][a-zA-Z_0-9]*\)\.Z_\([A-Z_]\+\)(/Z_\2(\1./g' \ - < $i > tmp && cp tmp $i - echo "DONE" -done - -rm -f tmp diff --git a/scripts/dev/credits b/scripts/dev/credits deleted file mode 100755 index f99c0316aa..0000000000 --- a/scripts/dev/credits +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -awkprog=' -BEGIN { FS = "\n|\r\n|\r"; RS = "" } -{ print "CREDIT_LINE(\""$1"\", \""$2"\");" }' - -for what in ext sapi -do - file=ext/standard/credits_$what.h - cat >$file <<END -/* - DO NOT EDIT THIS FILE! - - it has been automaticaly created by php5/scripts/credits from - the information found in the various php5/ext/.../CREDITS and - php5/sapi/.../CREDITS files - - if you want to change an entry you have to edit the appropriate - CREDITS file instead - -*/ - -END - # Do not process skeleton # - files=`find "$what" -name CREDITS | grep -v "$what"/skeleton/CREDITS` - awk "$awkprog" $files | sort -f | uniq >> $file -done diff --git a/scripts/dev/extern_c.php b/scripts/dev/extern_c.php deleted file mode 100644 index 72c7edcd32..0000000000 --- a/scripts/dev/extern_c.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -function scan_dir($dir) { - if (!is_dir($dir)) return; - - foreach (glob("$dir/*") as $file) { - if (is_dir($file)) { - if (basename($file) != "CVS") { - scan_dir($file); - } - } else if (fnmatch("*.h", $file)) { - scan_file($file); - } - } -} - -function scan_file($file) { - $flag = false; - - foreach (file($file) as $nr => $line) { - if (ereg("^[[:space:]]*BEGIN_EXTERN_C", $line)) { -# echo "$file:".($nr+1)." $line"; - $flag = true; - } else if (ereg("^[[:space:]]*END_EXTERN_C", $line)) { -# echo "$file:".($nr+1)." $line"; - $flag = false; - } else if ( (ereg("^[[:space:]]*PHPAPI[[:space:]]*", $line)) - ||(ereg("^[[:space:]]*ZEND_API[[:space:]]*", $line))) { - if (strstr($line,"(")) { - if (!$flag) echo "$file:".($nr+1)." $line"; - } - } - } -} - -array_shift($_SERVER["argv"]); - -if (count($_SERVER["argv"])) { - foreach ($_SERVER["argv"] as $dir) { - scan_dir($dir); - } -} else { - scan_dir("."); -} -?>
\ No newline at end of file diff --git a/scripts/dev/phpextdist b/scripts/dev/phpextdist deleted file mode 100755 index 97df70020d..0000000000 --- a/scripts/dev/phpextdist +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/sh -if test $# -lt 2; then - echo "usage: phpextdist <extension> <version>"; - exit 1 -fi - -phpize=`php-config --prefix`/bin/phpize -distname="$1-$2" - -if test ! -f Makefile.in || test ! -f config.m4; then - echo "Did not find required files in current directory" - exit 1 -fi - -rm -rf modules *.lo *.o *.la config.status config.cache \ -config.log libtool php_config.h config_vars.mk Makefile - -myname=`basename \`pwd\`` -cd .. -cp -rp $myname $distname -cd $distname -$phpize -cd .. -tar cf $distname.tar $distname -rm -rf $distname $distname.tar.* -gzip --best $distname.tar -mv $distname.tar.gz $myname diff --git a/scripts/dev/search_underscores.php b/scripts/dev/search_underscores.php deleted file mode 100755 index 445228b8c5..0000000000 --- a/scripts/dev/search_underscores.php +++ /dev/null @@ -1,97 +0,0 @@ -#! /usr/local/bin/php -n -<?php - -/* - +----------------------------------------------------------------------+ - | 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: Marcus Boerger <helly@php.net> | - +----------------------------------------------------------------------+ - */ - -/* This script lists extension-, class- and method names that contain any - underscores. It omits magic names (e.g. anything that starts with two - underscores but no more). - */ - -$cnt_modules = 0; -$cnt_classes = 0; -$cnt_methods = 0; -$err = 0; - -$classes = array_merge(get_declared_classes(), get_declared_interfaces()); - -$extensions = array(); - -foreach(get_loaded_extensions() as $ext) { - $cnt_modules++; - if (strpos($ext, "_") !== false) { - $err++; - $extensions[$ext] = array(); - } -} - -$cnt_classes = count($classes); - -foreach($classes as $c) { - if (strpos($c, "_") !== false) { - $err++; - $ref = new ReflectionClass($c); - if (!($ext = $ref->getExtensionName())) {; - $ext = $ref->isInternal() ? "<internal>" : "<user>"; - } - if (!array_key_exists($ext, $extensions)) { - $extensions[$ext] = array(); - } - $extensions[$ext][$c] = array(); - foreach(get_class_methods($c) as $method) { - $cnt_methods++; - if (strpos(substr($method, substr($method, 0, 2) != "__" ? 0 : 2), "_") !== false) { - $err++; - $extensions[$ext][$c][] = $method; - } - } - } - else - { - $cnt_methods += count(get_class_methods($c)); - } -} - -$cnt = $cnt_modules + $cnt_classes + $cnt_methods; - -printf("\n"); -printf("Modules: %5d\n", $cnt_modules); -printf("Classes: %5d\n", $cnt_classes); -printf("Methods: %5d\n", $cnt_methods); -printf("\n"); -printf("Names: %5d\n", $cnt); -printf("Errors: %5d (%.1f%%)\n", $err, round($err * 100 / $cnt, 1)); -printf("\n"); - -ksort($extensions); -foreach($extensions as $ext => &$classes) { - echo "Extension: $ext\n"; - ksort($classes); - foreach($classes as $classname => &$methods) { - echo " Class: $classname\n"; - ksort($methods); - foreach($methods as $method) { - echo " Method: $method\n"; - } - } -} - -printf("\n"); - -?>
\ No newline at end of file |