php/sigfiles/generate.php
author Tomas Mysik <tmysik@netbeans.org>
Mon, 24 Apr 2017 12:39:46 +0200
changeset 6385 1763913f11f4
parent 6325 9e44b44935db
child 6386 4c814dea6449
permissions -rw-r--r--
Use some PHP 7.1 features
tmysik@6020
     1
<?php
tmysik@6020
     2
/**
tmysik@6020
     3
 * This script can be used for generating PHP model for PDT.
tmysik@6020
     4
 * It builds PHP functions according to the loaded extensions in running PHP,
tmysik@6020
     5
 * using complementary information gathered from PHP.net documentation
tmysik@6020
     6
 *
tmysik@6020
     7
 * @author Michael Spector <michael@zend.com>
tmysik@6020
     8
 */
tmysik@6020
     9
tmysik@6020
    10
define("BRANCH_DIR", ""); // can be e.g. "/trunk" (do not forget slash!)
tmysik@6020
    11
define("DOC_URL", "./html/");      // PHP documentation, separate HTML files
tmysik@6020
    12
if (!is_dir(DOC_URL)) {
tmysik@6020
    13
    die('Incorrect directory for separated HTML files ("./html/" expected)!');
tmysik@6020
    14
}
tmysik@6020
    15
tmysik@6020
    16
if (version_compare(phpversion(), "5.0.0") < 0) {
tmysik@6020
    17
	die ("This script requires PHP 5.0.0 or higher!\n");
tmysik@6020
    18
}
tmysik@6020
    19
tmysik@6020
    20
$splitFiles = true;
tmysik@6020
    21
$phpdocDir = null;
tmysik@6020
    22
tmysik@6325
    23
$phpDir = "php";
tmysik@6020
    24
tmysik@6020
    25
// Parse arguments:
tmysik@6020
    26
$argv = $_SERVER["argv"];
tmysik@6020
    27
$argv0 = array_shift ($argv);
tmysik@6020
    28
for ($i = 0; $i < count($argv); ++$i) {
tmysik@6020
    29
	switch ($argv[$i]) {
tmysik@6020
    30
		case "-nosplit":
tmysik@6020
    31
			$splitFiles = false;
tmysik@6020
    32
			break;
tmysik@6020
    33
tmysik@6020
    34
		case "-help":
tmysik@6020
    35
			show_help();
tmysik@6020
    36
			break;
tmysik@6020
    37
tmysik@6020
    38
		default:
tmysik@6020
    39
			$phpdocDir = $argv[$i];
tmysik@6020
    40
	}
tmysik@6020
    41
}
tmysik@6020
    42
tmysik@6020
    43
if (!$phpdocDir) {
tmysik@6020
    44
	show_help();
tmysik@6020
    45
}
tmysik@6020
    46
tmysik@6020
    47
/***************** REMOVED FUNCTIONS (START) *************************/
tmysik@6020
    48
tmysik@6020
    49
// add these functions to $removedFunctions!
tmysik@6020
    50
tmysik@6020
    51
if (!function_exists('ob_iconv_handler')) {
tmysik@6020
    52
    function ob_iconv_handler($contents, $status) {}
tmysik@6020
    53
}
tmysik@6020
    54
if (!function_exists('ob_tidyhandler')) {
tmysik@6020
    55
    function ob_tidyhandler($input, $mode = 0) {}
tmysik@6020
    56
}
tmysik@6020
    57
if (!function_exists('session_register')) {
tmysik@6020
    58
    function session_register($name, $_ = null) {}
tmysik@6020
    59
}
tmysik@6020
    60
if (!function_exists('session_unregister')) {
tmysik@6020
    61
    function session_unregister($name) {}
tmysik@6020
    62
}
tmysik@6020
    63
if (!function_exists('session_is_registered')) {
tmysik@6020
    64
    function session_is_registered($name) {}
tmysik@6020
    65
}
tmysik@6020
    66
if (!function_exists('chroot')) {
tmysik@6020
    67
    function chroot($directory) {}
tmysik@6020
    68
}
tmysik@6020
    69
tmysik@6020
    70
/***************** REMOVED FUNCTIONS (END) *************************/
tmysik@6020
    71
tmysik@6020
    72
$entities = parse_entities($phpdocDir);
tmysik@6020
    73
$extensions = get_loaded_extensions();
tmysik@6020
    74
$functionsDoc = parse_phpdoc_functions ($phpdocDir, $extensions);
tmysik@6020
    75
$fieldsDoc = parse_phpdoc_fields ($phpdocDir, $extensions);
tmysik@6020
    76
$classesDoc = parse_phpdoc_classes ($phpdocDir, $extensions);
tmysik@6020
    77
$constantsDoc = parse_phpdoc_constants ($phpdocDir);
tmysik@6020
    78
$removedFunctions = array(
tmysik@6020
    79
    'ob_iconv_handler',
tmysik@6020
    80
    'ob_tidyhandler',
tmysik@6020
    81
    'session_register',
tmysik@6020
    82
    'session_unregister',
tmysik@6020
    83
    'session_is_registered',
tmysik@6020
    84
    'chroot',
tmysik@6020
    85
);
tmysik@6020
    86
$functionBlackList = array(
tmysik@6020
    87
    'oci_lob_save' => 1,
tmysik@6020
    88
    'oci_lob_import' => 1,
tmysik@6020
    89
    'oci_lob_size' => 1,
tmysik@6020
    90
    'oci_lob_load' => 1,
tmysik@6020
    91
    'oci_lob_read' => 1,
tmysik@6020
    92
    'oci_lob_eof' => 1,
tmysik@6020
    93
    'oci_lob_tell' => 1,
tmysik@6020
    94
    'oci_lob_truncate' => 1,
tmysik@6020
    95
    'oci_lob_erase' => 1,
tmysik@6020
    96
    'oci_lob_flush' => 1,
tmysik@6020
    97
    'ocisetbufferinglob' => 1,
tmysik@6020
    98
    'ocigetbufferinglob' => 1,
tmysik@6020
    99
    'oci_lob_rewind' => 1,
tmysik@6020
   100
    'oci_lob_write' => 1,
tmysik@6020
   101
    'oci_lob_append' => 1,
tmysik@6020
   102
    'oci_lob_export' => 1,
tmysik@6020
   103
    'oci_lob_seek' => 1,
tmysik@6020
   104
    'oci_free_collection' => 1,
tmysik@6020
   105
    'oci_collection_append' => 1,
tmysik@6020
   106
    'oci_collection_element_get' => 1,
tmysik@6020
   107
    'oci_collection_element_assign' => 1,
tmysik@6020
   108
    'oci_collection_size' => 1,
tmysik@6020
   109
    'oci_collection_max' => 1,
tmysik@6020
   110
    'oci_collection_trim' => 1,
tmysik@6020
   111
    'oci_collection_assign' => 1,
tmysik@6020
   112
);
tmysik@6111
   113
$methodBlackList = array(
tmysik@6111
   114
    'clone',
tmysik@6111
   115
    'throw',
tmysik@6111
   116
    'isset',
tmysik@6127
   117
    'echo',
tmysik@6127
   118
    'eval',
tmysik@6111
   119
);
tmysik@6100
   120
$preferHtmlProperties = array(
tmysik@6100
   121
    'mysqli',
tmysik@6100
   122
);
tmysik@6020
   123
tmysik@6020
   124
$processedFunctions = $functionBlackList;
tmysik@6020
   125
$processedClasses = array();
tmysik@6020
   126
$processedConstants = array();
tmysik@6020
   127
tmysik@6020
   128
@mkdir ($phpDir);
tmysik@6020
   129
tmysik@6020
   130
if (!$splitFiles) {
tmysik@6020
   131
	begin_file_output();
tmysik@6020
   132
}
tmysik@6020
   133
foreach ($extensions as $extName) {
tmysik@6020
   134
	if ($splitFiles) {
tmysik@6020
   135
		begin_file_output();
tmysik@6020
   136
	}
tmysik@6020
   137
	print_extension (new ReflectionExtension ($extName));
tmysik@6020
   138
	if ($splitFiles) {
tmysik@6020
   139
		finish_file_output("{$phpDir}/{$extName}.php");
tmysik@6020
   140
	}
tmysik@6020
   141
}
tmysik@6020
   142
tmysik@6020
   143
if ($splitFiles) {
tmysik@6020
   144
	begin_file_output();
tmysik@6020
   145
}
tmysik@6020
   146
$intFunctions = get_defined_functions();
tmysik@6020
   147
foreach ($intFunctions["internal"] as $intFunction) {
tmysik@6020
   148
	if (!@$processedFunctions[strtolower($intFunction)]) {
tmysik@6020
   149
		print_function (new ReflectionFunction ($intFunction));
tmysik@6020
   150
	}
tmysik@6020
   151
}
tmysik@6020
   152
tmysik@6020
   153
$intClasses = array_merge (get_declared_classes(), get_declared_interfaces(), get_declared_traits());
tmysik@6020
   154
foreach ($intClasses as $intClass) {
tmysik@6060
   155
    if (strpos($intClass, 'NetBeans_') === 0) {
tmysik@6060
   156
        continue;
tmysik@6060
   157
    }
tmysik@6020
   158
	if (!@$processedClasses[strtolower($intClass)]) {
tmysik@6020
   159
		print_class (new ReflectionClass ($intClass));
tmysik@6020
   160
	}
tmysik@6020
   161
}
tmysik@6020
   162
tmysik@6020
   163
print "\n";
tmysik@6020
   164
$constants = get_defined_constants(true);
tmysik@6020
   165
$intConstants = isset($constants["internal"]) ? $constants["internal"] : array();
tmysik@6020
   166
// add magic constants:
tmysik@6020
   167
$intConstants['__FILE__'] = null;
tmysik@6020
   168
$intConstants['__LINE__'] = null;
tmysik@6020
   169
$intConstants['__CLASS__'] = null;
tmysik@6020
   170
$intConstants['__FUNCTION__'] = null;
tmysik@6020
   171
$intConstants['__METHOD__'] = null;
tmysik@6048
   172
$intConstants['__TRAIT__'] = null;
tmysik@6020
   173
if (version_compare(phpversion(), "5.3.0") >= 0) {
tmysik@6020
   174
	$intConstants['__DIR__'] = null;
tmysik@6020
   175
	$intConstants['__NAMESPACE__'] = null;
tmysik@6020
   176
}
tmysik@6020
   177
foreach ($intConstants as $name => $value) {
tmysik@6020
   178
	if (!@$processedConstants[$name]) {
tmysik@6020
   179
		print_constant ($name, $value);
tmysik@6020
   180
	}
tmysik@6020
   181
}
tmysik@6020
   182
tmysik@6020
   183
finish_file_output("{$phpDir}/basic.php");
tmysik@6020
   184
tmysik@6020
   185
// removed functions
tmysik@6020
   186
if ($splitFiles) {
tmysik@6020
   187
    begin_file_output();
tmysik@6020
   188
}
tmysik@6020
   189
foreach ($removedFunctions as $removedFunction) {
tmysik@6020
   190
	if (!@$processedFunctions[strtolower($removedFunction)]) {
tmysik@6020
   191
		print_function (new ReflectionFunction ($removedFunction));
tmysik@6020
   192
	}
tmysik@6020
   193
}
tmysik@6020
   194
if ($splitFiles) {
tmysik@6020
   195
    finish_file_output("{$phpDir}/removed.php");
tmysik@6020
   196
}
tmysik@6020
   197
tmysik@6020
   198
tmysik@6020
   199
// Create .list file
tmysik@6020
   200
$fp = fopen ("{$phpDir}/.list", "w");
tmysik@6020
   201
foreach (glob("{$phpDir}/*.php") as $f) {
tmysik@6020
   202
	fwrite ($fp, basename($f));
tmysik@6020
   203
	fwrite ($fp, "\n");
tmysik@6020
   204
}
tmysik@6020
   205
fclose($fp);
tmysik@6020
   206
tmysik@6020
   207
tmysik@6020
   208
function findVerInfo($file)
tmysik@6020
   209
 {
tmysik@6020
   210
    $url = DOC_URL.$file.".html";
tmysik@6020
   211
    $search_for = '<p class="verinfo">';
tmysik@6020
   212
    //echo "Reading $url :\n";
tmysik@6020
   213
tmysik@6020
   214
    if (!is_file($url)) {
tmysik@6020
   215
        return;
tmysik@6020
   216
    }
tmysik@6020
   217
tmysik@6020
   218
    $file_contents = file_get_contents($url);
tmysik@6020
   219
tmysik@6020
   220
    $start_pos = strpos($file_contents, $search_for);
tmysik@6020
   221
tmysik@6020
   222
    if ($start_pos !== 0) {
tmysik@6020
   223
       $start_pos += strlen($search_for);
tmysik@6020
   224
       $end_pos = strpos($file_contents, '</p>', $start_pos);
tmysik@6020
   225
tmysik@6020
   226
       if ($end_pos !== 0) {
tmysik@6020
   227
          $verinfo = substr($file_contents, $start_pos, $end_pos - $start_pos);
tmysik@6020
   228
          //echo "Ver. info: $verinfo\n";
tmysik@6020
   229
          return $verinfo;
tmysik@6020
   230
       }
tmysik@6020
   231
    }
tmysik@6020
   232
 }
tmysik@6020
   233
tmysik@6020
   234
// === Functions ===
tmysik@6020
   235
/**
tmysik@6020
   236
 * Makes generic key from given function name
tmysik@6020
   237
 * @param name string Function name
tmysik@6020
   238
 * @return string generic key
tmysik@6020
   239
 */
tmysik@6020
   240
function make_funckey_from_str ($name) {
tmysik@6020
   241
	$name = str_replace ("->", "::", $name);
tmysik@6020
   242
	$name = str_replace ("()", "", $name);
tmysik@6020
   243
	$name = strtolower ($name);
tmysik@6020
   244
	return $name;
tmysik@6020
   245
}
tmysik@6020
   246
tmysik@6020
   247
/**
tmysik@6020
   248
 * Replaces all invalid charaters with '_' in PHP identifier
tmysik@6020
   249
 * @param name PHP identifier
tmysik@6020
   250
 * @return string PHP identifier with stripped invalid characters
tmysik@6020
   251
 */
tmysik@6020
   252
function clean_php_identifier ($name) {
tmysik@6020
   253
	$name = preg_replace('/[^\$\w\_]+/', '_', $name);
tmysik@6020
   254
	return $name;
tmysik@6020
   255
}
tmysik@6020
   256
tmysik@6020
   257
function clean_php_value($type) {
tmysik@6020
   258
    $type = trim($type);
tmysik@6020
   259
    $type = str_replace("&null;", "null", $type);
tmysik@6202
   260
    $type = str_replace("&true;", "true", $type);
tmysik@6202
   261
    $type = str_replace("&false;", "false", $type);
tmysik@6202
   262
    $type = str_replace("&quot;", "", $type);
tmysik@6020
   263
    $type = strip_tags($type);
tmysik@6020
   264
    return $type;
tmysik@6020
   265
}
tmysik@6020
   266
tmysik@6020
   267
/**
tmysik@6020
   268
 * Makes generic key from given function reference
tmysik@6020
   269
 * @param name ReflectionMethod function reference
tmysik@6020
   270
 * @return string generic key
tmysik@6020
   271
 */
tmysik@6020
   272
function make_funckey_from_ref ($ref) {
tmysik@6020
   273
	if ($ref instanceof ReflectionMethod) {
tmysik@6020
   274
		$funckey = make_classmember_ref($ref->getDeclaringClass()->getName(), $ref->getName());
tmysik@6020
   275
	} else {
tmysik@6020
   276
		$funckey = strtolower($ref->getName());
tmysik@6020
   277
	}
tmysik@6020
   278
	return $funckey;
tmysik@6020
   279
}
tmysik@6020
   280
function make_property_from_ref ($ref) {
tmysik@6020
   281
	if ($ref instanceof ReflectionProperty) {
tmysik@6020
   282
		$funckey = make_classmember_ref($ref->getDeclaringClass()->getName(), $ref->getName());
tmysik@6020
   283
	} else {
tmysik@6020
   284
		throw new Exception("Unexpected type: ".gettype($ref));
tmysik@6020
   285
	}
tmysik@6020
   286
	return $funckey;
tmysik@6020
   287
}
tmysik@6020
   288
tmysik@6020
   289
function make_classmember_ref ($className, $memberName) {
tmysik@6020
   290
	return strtolower($className)."::".strtolower($memberName);
tmysik@6020
   291
}
tmysik@6020
   292
tmysik@6020
   293
tmysik@6020
   294
/**
tmysik@6020
   295
 * Parses PHP documentation
tmysik@6020
   296
 * @param phpdocDir string PHP.net documentation directory
tmysik@6020
   297
 * @return array Function information gathered from the PHP.net documentation by parsing XML files
tmysik@6020
   298
 */
tmysik@6020
   299
function parse_phpdoc_functions ($phpdocDir, $extensions) {
tmysik@6020
   300
	$xml_files = array_merge (
tmysik@6020
   301
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/reference/*/functions/*.xml"),
tmysik@6020
   302
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/language/predefined/*/*.xml"),
tmysik@6020
   303
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/reference/*/functions/*/*.xml")
tmysik@6020
   304
	);
tmysik@6020
   305
	foreach ($extensions as $extName) {
tmysik@6020
   306
		$extName = strtolower($extName);
tmysik@6020
   307
		$globPattern = "{$phpdocDir}/en" . BRANCH_DIR . "/reference/{$extName}/*/*.xml";
tmysik@6020
   308
		$xml_files = array_merge (
tmysik@6020
   309
			$xml_files,
tmysik@6020
   310
			glob ($globPattern)
tmysik@6020
   311
		);
tmysik@6020
   312
	}
tmysik@6020
   313
    $functionsDoc = array();
tmysik@6020
   314
	foreach ($xml_files as $xml_file) {
tmysik@6020
   315
		$xml = file_get_contents ($xml_file);
tmysik@6020
   316
tmysik@6058
   317
		if (preg_match ('@<refentry.*?xml:id=["\'](.*?)["\'].*?>.*?<refname>(.*?)</refname>\s*(?:<refname>(.*?)</refname>)?.*?<refpurpose>(.*?)</refpurpose>@s', $xml, $match)) {
tmysik@6058
   318
            $id = $match[1];
tmysik@6058
   319
            $refnames = array($match[2], $match[3]);
tmysik@6058
   320
            $phpdoc = $match[4];
tmysik@6058
   321
            foreach ($refnames as $refname) {
tmysik@6058
   322
                $refname = trim($refname);
tmysik@6058
   323
                if ($refname == '') {
tmysik@6058
   324
                    continue;
tmysik@6058
   325
                }
tmysik@6058
   326
                $refname = make_funckey_from_str ($refname);
tmysik@6058
   327
                if (array_key_exists($refname, $functionsDoc)) {
tmysik@6058
   328
                    // already there
tmysik@6058
   329
                    continue;
tmysik@6058
   330
                }
tmysik@6058
   331
                $functionsDoc[$refname] = array();
tmysik@6058
   332
                $functionsDoc[$refname]['id'] = $id;
tmysik@6058
   333
                $functionsDoc[$refname]['quickref'] = xml_to_phpdoc($phpdoc);
tmysik@6058
   334
                $functionsDoc[$refname]['deprecated'] = strpos($xml_file, "/oldaliases/") !== false;
tmysik@6020
   335
tmysik@6058
   336
                if (preg_match ('@<refsect1\s+role=["\']description["\']>(.*?)</refsect1>@s', $xml, $match)) {
tmysik@6058
   337
                    $description = $match[1];
tmysik@6058
   338
                    $function_alias = null;
tmysik@6058
   339
                    $parameters = null;
tmysik@6058
   340
                    $has_object_style = false;
tmysik@6058
   341
                    if (preg_match ('@^(.*?)<classsynopsis>.*?<classname>(.*)</classname>.*?<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>.*?</classsynopsis>(.*)$@s', $description, $match)) {
tmysik@6058
   342
                        $functionsDoc[$refname]['classname'] = trim($match[2]);
tmysik@6058
   343
                        $functionsDoc[$refname]['returntype'] = trim($match[3]);
tmysik@6058
   344
                        $functionsDoc[$refname]['methodname'] = trim($match[4]);
tmysik@6058
   345
                        $parameters = $match[5];
tmysik@6058
   346
                        $description = $match[1].$match[6];
tmysik@6058
   347
                        $has_object_style = true;
tmysik@6058
   348
                    }
tmysik@6058
   349
                    $methodsynopsis = null;
tmysik@6058
   350
                    if ($refname == 'number_format') {
tmysik@6058
   351
                        $methodsynopsis = preg_match_all ('@<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>@s', $description, $tmp);
tmysik@6058
   352
                        $match = array();
tmysik@6058
   353
                        foreach ($tmp as $key => $val) {
tmysik@6058
   354
                            $match[$key] = $val[count($val) - 1];
tmysik@6058
   355
                        }
tmysik@6058
   356
                    } else {
tmysik@6058
   357
                        if (strpos($refname, '::') !== false) {
tmysik@6058
   358
                            $methodsynopsis = preg_match ('@<methodsynopsis role="oop">.*?(?:<type>(.*?)</type>.*?)?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>@s', $description, $match);
tmysik@6058
   359
                        }
tmysik@6058
   360
                        if (!$methodsynopsis) {
tmysik@6198
   361
                            $methodsynopsis = preg_match ('@<methodsynopsis>.*?(?:<type>(.*?)</type>.*?)?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>@s', $description, $match);
tmysik@6197
   362
                        }
tmysik@6197
   363
                        if (!$methodsynopsis) {
tmysik@6198
   364
                            $methodsynopsis = preg_match ('@<constructorsynopsis>.*?(?:<type>(.*?)</type>.*?)?<methodname>(.*?)</methodname>(.*?)</constructorsynopsis>@s', $description, $match);
tmysik@6058
   365
                        }
tmysik@6058
   366
                    }
tmysik@6058
   367
                    if ($methodsynopsis) {
tmysik@6058
   368
                        if ($has_object_style && make_funckey_from_str($match[2]) != $refname) {
tmysik@6058
   369
                            $function_alias = trim($match[2]);
tmysik@6058
   370
                        } else {
tmysik@6058
   371
                            $functionsDoc[$refname]['returntype'] = trim(str_replace('-', '_', $match[1])); // e.g. OCI-Collection -> OCI_Collection
tmysik@6058
   372
                            $functionsDoc[$refname]['methodname'] = trim($match[2]);
tmysik@6058
   373
                                                    $parameters = $match[3];
tmysik@6058
   374
                        }
tmysik@6058
   375
                    }
tmysik@6058
   376
                    if ($parameters) {
tmysik@6058
   377
                        if (preg_match_all ('@<methodparam\s*(.*?)>.*?<type>(.*?)</type>.*?<parameter\s*(.*?)>(.*?)</parameter>(?:<initializer>(.+?)</initializer>)?.*?</methodparam>@s', $parameters, $match)) {
tmysik@6058
   378
                            for ($i = 0; $i < count($match[0]); ++$i) {
tmysik@6058
   379
                                $parameter = array (
tmysik@6058
   380
                                    'type' => trim(str_replace('-', '_', $match[2][$i])), // e.g. OCI-Collection -> OCI_Collection
tmysik@6058
   381
                                    'name' => clean_php_identifier(trim($match[4][$i])),
tmysik@6058
   382
                                );
tmysik@6058
   383
                                if (preg_match ('@choice=[\'"]opt[\'"]@', $match[1][$i])) {
tmysik@6058
   384
                                    $parameter['isoptional'] = true;
tmysik@6020
   385
                                }
tmysik@6058
   386
                                if (preg_match ('@role=[\'"]reference[\'"]@', $match[3][$i])) {
tmysik@6058
   387
                                    $parameter['isreference'] = true;
tmysik@6058
   388
                                }
tmysik@6058
   389
                                if (@strlen(trim($match[5][$i]))) {
tmysik@6198
   390
                                    $def = $match[5][$i];
tmysik@6198
   391
                                    if ($def == '"\"') {
tmysik@6198
   392
                                        $def = '"\\\\"';
tmysik@6198
   393
                                    }
tmysik@6198
   394
                                    $parameter['defaultvalue'] = clean_php_value($def);
tmysik@6058
   395
                                                                    $parameter['isoptional'] = true;
tmysik@6058
   396
                                }
tmysik@6058
   397
                                $functionsDoc[$refname]['parameters'][] = $parameter;
tmysik@6020
   398
                            }
tmysik@6020
   399
                        }
tmysik@6020
   400
                    }
tmysik@6020
   401
                }
tmysik@6058
   402
                if (preg_match ('@<refsect1\s+role=["\']parameters["\']>(.*?)</refsect1>@s', $xml, $match)) {
tmysik@6058
   403
                    $parameters = $match[1];
tmysik@6058
   404
                    if (preg_match_all('@<varlistentry\s*.*?>.*?<parameter>(.*?)</parameter>.*?<listitem\s*.*?>(.*?)</listitem>.*?</varlistentry>@s', $parameters, $match)) {
tmysik@6058
   405
                        for ($i = 0; $i < count($match[0]); $i++) {
tmysik@6058
   406
                            for ($j = 0; $j < count(@$functionsDoc[$refname]['parameters']); $j++) {
tmysik@6058
   407
                                if (clean_php_identifier(trim($match[1][$i])) == $functionsDoc[$refname]['parameters'][$j]['name']) {
tmysik@6058
   408
                                    $functionsDoc[$refname]['parameters'][$j]['paramdoc'] = xml_to_phpdoc ($match[2][$i]);
tmysik@6058
   409
                                    break;
tmysik@6058
   410
                                }
tmysik@6058
   411
                            }
tmysik@6058
   412
                        }
tmysik@6058
   413
                    }
tmysik@6058
   414
                }
tmysik@6058
   415
                if (preg_match ('@<refsect1\s+role=["\']returnvalues["\']>(.*?)</refsect1>@s', $xml, $match)) {
tmysik@6058
   416
                    $returnvalues = $match[1];
tmysik@6058
   417
                    if (preg_match ('@<para>\s*(.*)</para>?@s', $returnvalues, $match)) {
tmysik@6058
   418
                        $functionsDoc[$refname]['returndoc'] = preg_replace("@^Returns @", "", xml_to_phpdoc ($match[1]));
tmysik@6058
   419
                    }
tmysik@6058
   420
                }
tmysik@6020
   421
tmysik@6058
   422
                // Create information for function alias
tmysik@6058
   423
                if ($function_alias) {
tmysik@6058
   424
                    $functionsDoc[$function_alias] = $functionsDoc[$refname];
tmysik@6058
   425
                }
tmysik@6058
   426
            }
tmysik@6020
   427
		}
tmysik@6020
   428
	}
tmysik@6020
   429
	return $functionsDoc;
tmysik@6020
   430
}
tmysik@6020
   431
tmysik@6020
   432
/**
tmysik@6020
   433
 * Parses PHP documentation
tmysik@6020
   434
 * @param phpdocDir string PHP.net documentation directory
tmysik@6020
   435
 * @return array Function information gathered from the PHP.net documentation by parsing XML files
tmysik@6020
   436
 */
tmysik@6020
   437
function parse_phpdoc_fields ($phpdocDir, $extensions) {
tmysik@6020
   438
	$xml_files = array();
tmysik@6020
   439
	foreach ($extensions as $extName) {
tmysik@6020
   440
		$extName = strtolower($extName);
tmysik@6020
   441
tmysik@6020
   442
		$xml_files = array_merge (
tmysik@6020
   443
			$xml_files,
tmysik@6020
   444
			glob ("{$phpdocDir}/en" . BRANCH_DIR . "/reference/{$extName}/*.xml"),
tmysik@6020
   445
                        glob ("{$phpdocDir}/en" . BRANCH_DIR . "/reference/{$extName}/*/*.xml")
tmysik@6020
   446
		);
tmysik@6020
   447
	}
tmysik@6020
   448
        foreach ($xml_files as $xml_file) {
tmysik@6020
   449
            $xml = file_get_contents($xml_file);
tmysik@6020
   450
            if (preg_match('@<classsynopsisinfo>.*?<classname>(.*)</classname>.*?</classsynopsisinfo>@s', $xml, $matchOffset, PREG_OFFSET_CAPTURE)) {
tmysik@6020
   451
                $classname = $matchOffset[1][0];
tmysik@6020
   452
                if (preg_match_all("@<fieldsynopsis>.*?<type>(.*?)</type>.*?<varname.*?>(.*?)</varname>@s", $xml, $matchOffset,null,$matchOffset[1][1])) {
tmysik@6020
   453
                    for ($index = 0; $index < count($matchOffset[2]); $index++) {
tmysik@6020
   454
                        $name = $matchOffset[2][$index];
tmysik@6020
   455
                        $type= $matchOffset[1][$index];
tmysik@6020
   456
                        $exploded = explode("::", $name);
tmysik@6020
   457
                        if (count($exploded) > 1) {
tmysik@6020
   458
                            $name = $exploded[1];
tmysik@6020
   459
                        }
tmysik@6020
   460
                        $reference = make_classmember_ref($classname, $name);
tmysik@6020
   461
                        $fieldsDoc[$reference]['field'] = $name;
tmysik@6020
   462
                        $fieldsDoc[$reference]['type'] = $type;
tmysik@6020
   463
                    }
tmysik@6020
   464
                }
tmysik@6020
   465
            } else {
tmysik@6020
   466
                if (preg_match('@<classsynopsis>.*?<classname>(.*)</classname>.*?<fieldsynopsis>.*?<type>(.*?)</type>.*?<varname.*?>(.*?)</varname>.*?</classsynopsis>@s', $xml, $match)) {
tmysik@6020
   467
                    $reference = make_classmember_ref($match[1], $match[3]);
tmysik@6020
   468
                    $fieldsDoc[$reference]['field'] = $match[3];
tmysik@6020
   469
                    $fieldsDoc[$reference]['type'] = $match[2];
tmysik@6020
   470
                    //$fieldsDoc[$refname]['quickref'] = trim($match[3]);
tmysik@6020
   471
                }
tmysik@6020
   472
            }
tmysik@6020
   473
tmysik@6020
   474
        }
tmysik@6020
   475
        if (isset($fieldsDoc)) {
tmysik@6020
   476
            return $fieldsDoc;
tmysik@6020
   477
        }
tmysik@6020
   478
        return array();
tmysik@6020
   479
}
tmysik@6020
   480
tmysik@6020
   481
/**
tmysik@6020
   482
 * Parses PHP documentation
tmysik@6020
   483
 * @param phpdocDir string PHP.net documentation directory
tmysik@6020
   484
 * @return array Class information gathered from the PHP.net documentation by parsing XML files
tmysik@6020
   485
 */
tmysik@6020
   486
function parse_phpdoc_classes ($phpdocDir, $extensions) {
tmysik@6020
   487
	$xml_files = array_merge (
tmysik@6020
   488
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/reference/*/reference.xml"),
tmysik@6020
   489
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/reference/*/classes.xml"),
tmysik@6020
   490
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/language/*/*.xml"),
tmysik@6020
   491
		glob ("{$phpdocDir}/en" . BRANCH_DIR . "/language/*.xml")
tmysik@6020
   492
	);
tmysik@6020
   493
	foreach ($extensions as $extName) {
tmysik@6020
   494
		$extName = strtolower($extName);
tmysik@6020
   495
		$globPattern = "{$phpdocDir}/en" . BRANCH_DIR . "/reference/{$extName}/*.xml";
tmysik@6020
   496
		$xml_files = array_merge (
tmysik@6020
   497
			$xml_files,
tmysik@6020
   498
			glob ($globPattern)
tmysik@6020
   499
		);
tmysik@6020
   500
	}
tmysik@6020
   501
tmysik@6020
   502
    $classesDoc = array();
tmysik@6020
   503
	foreach ($xml_files as $xml_file) {
tmysik@6020
   504
		$xml = file_get_contents ($xml_file);
tmysik@6020
   505
		if (preg_match ('@xml:id=["\'](.*?)["\']@', $xml, $match)) {
tmysik@6020
   506
			$id = $match[1];
tmysik@6020
   507
			$prefixId = substr($id, 0, strlen("class."));
tmysik@6020
   508
			$clsNamePattern = ($prefixId === "class.") ?
tmysik@6020
   509
			'@<ooclass><classname>(.*?)</classname></ooclass>@' :
tmysik@6020
   510
			'@<title><classname>(.*?)</classname></title>@';
tmysik@6020
   511
			if (preg_match_all ($clsNamePattern, $xml, $match)) {
tmysik@6020
   512
				for ($i = 0; $i < count($match[0]); ++$i) {
tmysik@6020
   513
					$class = $match[1][$i];
tmysik@6020
   514
					$refname = strtolower ($class);
tmysik@6020
   515
					$classesDoc[$refname]['id'] = $id;
tmysik@6020
   516
					$classesDoc[$refname]['name'] = $class;
tmysik@6020
   517
					$offsetPattern = ($prefixId === "class.") ?
tmysik@6020
   518
						"@xml:id=[\"'](.*?)\.intro[\"']@i" :
tmysik@6020
   519
						"@<title><classname>{$class}</classname></title>@";
tmysik@6020
   520
					if (preg_match ($offsetPattern , $xml, $matchOffset,PREG_OFFSET_CAPTURE)) {
tmysik@6020
   521
						$docPattern = '@<para>(.*?)</para>@s';
tmysik@6020
   522
						if (preg_match ($docPattern, $xml, $match2,null,$matchOffset[0][1])) {
tmysik@6020
   523
							$doc = xml_to_phpdoc($match2[1]);
tmysik@6020
   524
							$classesDoc[$refname]['doc'] = $doc;
tmysik@6020
   525
						}
tmysik@6020
   526
					}
tmysik@6020
   527
				}
tmysik@6020
   528
			}
tmysik@6020
   529
		}
tmysik@6020
   530
	}
tmysik@6020
   531
	return $classesDoc;
tmysik@6020
   532
}
tmysik@6020
   533
tmysik@6020
   534
/**
tmysik@6020
   535
 * Parses PHP documentation
tmysik@6020
   536
 * @param phpdocDir string PHP.net documentation directory
tmysik@6020
   537
 * @return array Constant information gathered from the PHP.net documentation by parsing XML files
tmysik@6020
   538
 */
tmysik@6020
   539
function parse_phpdoc_constants ($phpdocDir) {
tmysik@6020
   540
	exec ("find ".addslashes($phpdocDir)." -name \"*constants.xml\"", $xml_files);
tmysik@6020
   541
	foreach ($xml_files as $xml_file) {
tmysik@6020
   542
		$xml = file_get_contents ($xml_file);
tmysik@6020
   543
tmysik@6020
   544
		if (preg_match ('@xml:id=["\'](.*?)["\']@', $xml, $match)) {
tmysik@6020
   545
			$id = $match[1];
tmysik@6020
   546
			if (preg_match_all ('@<term>\s*<constant>([a-zA-Z_:][a-zA-Z0-9_:]*)</constant>.*?</term>.*?<listitem>(.*?)</listitem>@s', $xml, $match)) {
tmysik@6020
   547
				for ($i = 0; $i < count($match[0]); ++$i) {
tmysik@6020
   548
					$constant = $match[1][$i];
tmysik@6020
   549
					$constantsDoc[$constant]['id'] = $id;
tmysik@6020
   550
					$constantsDoc[$constant]['doc'] = xml_to_phpdoc($match[2][$i]);
tmysik@6020
   551
				}
tmysik@6020
   552
			}
tmysik@6020
   553
			if (preg_match_all (
tmysik@6020
   554
				'@<entry>\s*<constant>([a-zA-Z_][a-zA-Z0-9_]*)</constant>.*?</entry>\s*<entry>\d+</entry>\s*<entry>(.*?)</entry>@s', $xml, $match)
tmysik@6020
   555
				|| preg_match_all ('@<entry>\s*<constant>([a-zA-Z_][a-zA-Z0-9_]*)</constant>.*?</entry>\s*<entry>(.*?)</entry>@s', $xml, $match)) {
tmysik@6020
   556
tmysik@6020
   557
				for ($i = 0; $i < count($match[0]); ++$i) {
tmysik@6020
   558
					$constant = $match[1][$i];
tmysik@6020
   559
					$constantsDoc[$constant]['id'] = $id;
tmysik@6020
   560
					$constantsDoc[$constant]['doc'] = xml_to_phpdoc($match[2][$i]);
tmysik@6020
   561
				}
tmysik@6020
   562
			}
tmysik@6020
   563
		}
tmysik@6020
   564
	}
tmysik@6020
   565
	return $constantsDoc;
tmysik@6020
   566
}
tmysik@6020
   567
tmysik@6020
   568
/**
tmysik@6020
   569
 * Prints ReflectionExtension in format of PHP code
tmysik@6020
   570
 * @param extRef ReflectionExtension object
tmysik@6020
   571
 */
tmysik@6020
   572
function print_extension ($extRef) {
tmysik@6020
   573
    global $functionBlackList;
tmysik@6020
   574
tmysik@6020
   575
	print "\n// Start of {$extRef->getName()} v.{$extRef->getVersion()}\n";
tmysik@6020
   576
tmysik@6020
   577
	// process classes:
tmysik@6020
   578
	$classesRef = $extRef->getClasses();
tmysik@6020
   579
	if (count ($classesRef) > 0) {
tmysik@6020
   580
		foreach ($classesRef as $classRef) {
tmysik@6020
   581
			print_class ($classRef);
tmysik@6020
   582
		}
tmysik@6020
   583
	}
tmysik@6020
   584
tmysik@6020
   585
	// process functions
tmysik@6020
   586
	$funcsRef = $extRef->getFunctions();
tmysik@6020
   587
	if (count ($funcsRef) > 0) {
tmysik@6020
   588
		foreach ($funcsRef as $funcName => $funcRef) {
tmysik@6020
   589
                    if (array_key_exists($funcName, $functionBlackList)) {
tmysik@6020
   590
                        continue;
tmysik@6020
   591
                    }
tmysik@6020
   592
			print_function ($funcRef);
tmysik@6020
   593
		}
tmysik@6020
   594
		print "\n";
tmysik@6020
   595
	}
tmysik@6020
   596
tmysik@6020
   597
	// process constants
tmysik@6020
   598
	$constsRef = $extRef->getConstants();
tmysik@6020
   599
	if (count ($constsRef) > 0) {
tmysik@6020
   600
		print_constants ($constsRef);
tmysik@6020
   601
		print "\n";
tmysik@6020
   602
	}
tmysik@6020
   603
tmysik@6020
   604
	print "// End of {$extRef->getName()} v.{$extRef->getVersion()}\n";
tmysik@6020
   605
}
tmysik@6020
   606
tmysik@6020
   607
/**
tmysik@6020
   608
 * Prints ReflectionClass in format of PHP code
tmysik@6020
   609
 * @param classRef ReflectionClass object
tmysik@6020
   610
 * @param tabs integer[optional] number of tabs for indentation
tmysik@6020
   611
 */
tmysik@6020
   612
function print_class (ReflectionClass $classRef, $tabs = 0) {
tmysik@6111
   613
	global $processedClasses, $preferHtmlProperties, $methodBlackList;
tmysik@6020
   614
	$processedClasses [strtolower($classRef->getName())] = true;
tmysik@6020
   615
tmysik@6020
   616
	print "\n";
tmysik@6020
   617
	print_doccomment ($classRef, $tabs);
tmysik@6020
   618
	print_tabs ($tabs);
tmysik@6020
   619
	if ($classRef->isFinal()) print "final ";
tmysik@6020
   620
tmysik@6020
   621
        if ($classRef->isInterface()) {
tmysik@6020
   622
            print "interface ";
tmysik@6020
   623
        } elseif ($classRef->isTrait()) {
tmysik@6020
   624
            print "trait ";
tmysik@6020
   625
        } else {
tmysik@6020
   626
            print "class ";
tmysik@6020
   627
        }
tmysik@6020
   628
	print clean_php_identifier($classRef->getName())." ";
tmysik@6020
   629
tmysik@6020
   630
	// print out parent class
tmysik@6020
   631
	$parentClassRef = $classRef->getParentClass();
tmysik@6020
   632
	if ($parentClassRef) {
tmysik@6020
   633
		print "extends {$parentClassRef->getName()} ";
tmysik@6020
   634
	}
tmysik@6020
   635
tmysik@6020
   636
	// print out interfaces
tmysik@6020
   637
	$interfacesRef = $classRef->getInterfaces();
tmysik@6020
   638
	if (count ($interfacesRef) > 0) {
tmysik@6020
   639
		print $classRef->isInterface() ? "extends " : "implements ";
tmysik@6020
   640
		$i = 0;
tmysik@6020
   641
		foreach ($interfacesRef as $interfaceRef) {
tmysik@6020
   642
			if ($i++ > 0) {
tmysik@6020
   643
				print ", ";
tmysik@6020
   644
			}
tmysik@6020
   645
			print "{$interfaceRef->getName()}";
tmysik@6020
   646
		}
tmysik@6020
   647
	}
tmysik@6020
   648
	print " {\n";
tmysik@6020
   649
tmysik@6020
   650
	// print out traits
tmysik@6020
   651
        $traits = $classRef->getTraits();
tmysik@6020
   652
        if (count($traits)) {
tmysik@6020
   653
            foreach ($traits as $trait => $traitInfo) {
tmysik@6020
   654
                print_tabs($tabs + 1);
tmysik@6020
   655
                print 'use ' . $trait . ';';
tmysik@6020
   656
		print "\n";
tmysik@6020
   657
            }
tmysik@6020
   658
            print "\n";
tmysik@6020
   659
        }
tmysik@6020
   660
tmysik@6020
   661
	// process constants
tmysik@6020
   662
	$constsRef = $classRef->getConstants();
tmysik@6020
   663
	if (count ($constsRef) > 0) {
tmysik@6020
   664
		print_class_constants ($classRef, $constsRef, $tabs + 1);
tmysik@6020
   665
		print "\n";
tmysik@6020
   666
	}
tmysik@6020
   667
tmysik@6020
   668
	// process properties
tmysik@6020
   669
	$propertiesRef = $classRef->getProperties();
tmysik@6100
   670
	if (!in_array(strtolower($classRef->getName()), $preferHtmlProperties)
tmysik@6100
   671
                && count ($propertiesRef) > 0) {
tmysik@6020
   672
		foreach ($propertiesRef as $propertyRef) {
tmysik@6020
   673
			print_property ($propertyRef, $tabs + 1);
tmysik@6020
   674
		}
tmysik@6020
   675
		print "\n";
tmysik@6060
   676
	} else {
tmysik@6060
   677
        // #188245 - try to find them directly in HTML
tmysik@6060
   678
        $properties = parse_properties_from_html_file('class.' . strtolower($classRef->getName()) . '.html', $classRef->getName());
tmysik@6060
   679
        if (count($properties)) {
tmysik@6060
   680
            foreach ($properties as $property) {
tmysik@6060
   681
                print_field($property, $tabs + 1);
tmysik@6060
   682
            }
tmysik@6060
   683
            print "\n";
tmysik@6060
   684
        }
tmysik@6060
   685
    }
tmysik@6020
   686
tmysik@6020
   687
	// process methods
tmysik@6020
   688
	/* @var $classRef ReflectionClass */
tmysik@6020
   689
	$methodsRef = $classRef->getMethods();
tmysik@6020
   690
	if (count ($methodsRef) > 0) {
tmysik@6020
   691
		foreach ($methodsRef as $methodRef) {
tmysik@6020
   692
            /* @var $methodRef ReflectionMethod */
tmysik@6111
   693
            if (in_array(strtolower($methodRef->getName()), $methodBlackList)) {
tmysik@6020
   694
                continue;
tmysik@6020
   695
            }
tmysik@6020
   696
			print_method($classRef, $methodRef, $tabs + 1);
tmysik@6020
   697
		}
tmysik@6020
   698
		print "\n";
tmysik@6020
   699
	}
tmysik@6020
   700
	print_tabs ($tabs);
tmysik@6020
   701
	print "}\n";
tmysik@6020
   702
}
tmysik@6020
   703
tmysik@6020
   704
/**
tmysik@6020
   705
 * Prints ReflectionProperty in format of PHP code
tmysik@6020
   706
 * @param ReflectionProperty $propertyRef  object
tmysik@6020
   707
 * @param integer[optional] tabs  number of tabs for indentation
tmysik@6020
   708
 */
tmysik@6020
   709
function print_property ($propertyRef, $tabs = 0) {
tmysik@6020
   710
	print_doccomment ($propertyRef, $tabs);
tmysik@6020
   711
	print_tabs ($tabs);
tmysik@6020
   712
	print_modifiers ($propertyRef, true);
tmysik@6057
   713
        $name = $propertyRef->getName();
tmysik@6057
   714
        if (substr($name, 0, 1) !== '$') {
tmysik@6057
   715
            $name = '$' . $name;
tmysik@6057
   716
        }
tmysik@6057
   717
        print $name . ";\n";
tmysik@6020
   718
}
tmysik@6020
   719
tmysik@6060
   720
/**
tmysik@6060
   721
 * Prints Field in format of PHP code
tmysik@6060
   722
 * @param NetBeans_Field $field  object
tmysik@6060
   723
 * @param integer[optional] tabs  number of tabs for indentation
tmysik@6060
   724
 */
tmysik@6060
   725
function print_field (NetBeans_Field $field, $tabs = 0) {
tmysik@6060
   726
    // documentation
tmysik@6060
   727
    $fieldType = $field->getType();
tmysik@6060
   728
    $fieldDoc = $field->getDocumentation();
tmysik@6060
   729
    $fieldDoc = trim(strip_tags($fieldDoc, '<p>,<strong>,<code>,<a>'));
tmysik@6060
   730
    // replace hyperlinks
tmysik@6060
   731
    $fieldDoc = preg_replace('%<(a|strong)[^>]*>%', '<b>', $fieldDoc);
tmysik@6060
   732
    $fieldDoc = preg_replace('%<p[^>]+>%', '<p>', $fieldDoc);
tmysik@6060
   733
    $fieldDoc = str_replace('</a>', '</b>', $fieldDoc);
tmysik@6060
   734
    $fieldDoc = str_replace('</strong>', '</b>', $fieldDoc);
tmysik@6060
   735
    $fieldDoc = preg_replace('%^<p>(.+)</p>$%s', '<p style="margin-top:0;">\\1</p>', $fieldDoc);
tmysik@6060
   736
tmysik@6060
   737
    print_tabs ($tabs);
tmysik@6060
   738
    print "/**\n";
tmysik@6060
   739
    foreach (preg_split('%\n|\r%', $fieldDoc) as $line) {
tmysik@6060
   740
        $line = trim($line);
tmysik@6060
   741
        if (!$line) {
tmysik@6060
   742
            continue;
tmysik@6060
   743
        }
tmysik@6060
   744
        print_tabs($tabs);
tmysik@6060
   745
        print " * $line\n";
tmysik@6060
   746
    }
tmysik@6060
   747
    print_tabs($tabs);
tmysik@6060
   748
    print " * @var $fieldType\n";
tmysik@6060
   749
    print_tabs($tabs);
tmysik@6060
   750
    print " */\n";
tmysik@6060
   751
    // tabs
tmysik@6060
   752
	print_tabs($tabs);
tmysik@6060
   753
    // modifiers
tmysik@6060
   754
    $print = implode(' ', $field->getModifiers());
tmysik@6060
   755
    $print = str_replace("final", "", $print);
tmysik@6060
   756
    $print = str_replace("abstract", "", $print);
tmysik@6060
   757
    $print = str_replace("readonly", "", $print);
tmysik@6100
   758
    $print = trim($print);
tmysik@6100
   759
    if (!$print) {
tmysik@6100
   760
        // no modifiers
tmysik@6100
   761
        $print = 'public';
tmysik@6100
   762
    }
tmysik@6100
   763
    print $print;
tmysik@6060
   764
    print " ";
tmysik@6060
   765
    $name = $field->getName();
tmysik@6060
   766
    if (substr($name, 0, 1) !== '$') {
tmysik@6060
   767
        $name = '$' . $name;
tmysik@6060
   768
    }
tmysik@6060
   769
    print $name . ";\n";
tmysik@6060
   770
}
tmysik@6060
   771
tmysik@6020
   772
function print_function ($functionRef, $tabs = 0) {
tmysik@6020
   773
    print_method(null, $functionRef, $tabs);
tmysik@6020
   774
}
tmysik@6020
   775
tmysik@6020
   776
function print_method ($classRef, $functionRef, $tabs = 0) {
tmysik@6020
   777
	global $functionsDoc;
tmysik@6020
   778
	global $processedFunctions;
tmysik@6020
   779
tmysik@6020
   780
	$funckey = make_funckey_from_ref ($functionRef);
tmysik@6020
   781
	$processedFunctions[$funckey] = true;
tmysik@6020
   782
tmysik@6020
   783
	print "\n";
tmysik@6020
   784
        $modifiers = null;
tmysik@6020
   785
	print_doccomment ($functionRef, $tabs);
tmysik@6020
   786
	print_tabs ($tabs);
tmysik@6020
   787
	if (!($functionRef instanceof ReflectionFunction)) {
tmysik@6020
   788
		print_modifiers ($functionRef);
tmysik@6020
   789
                $modifiers = Reflection::getModifierNames($functionRef->getModifiers());
tmysik@6020
   790
	}
tmysik@6020
   791
tmysik@6020
   792
	print "function ";
tmysik@6020
   793
	if ($functionRef->returnsReference()) {
tmysik@6020
   794
		print "&";
tmysik@6020
   795
	}
tmysik@6325
   796
	$functionName = $functionRef->getName();
tmysik@6325
   797
	print "$functionName(";
tmysik@6020
   798
	$parameters = @$functionsDoc[$funckey]['parameters'];
tmysik@6020
   799
	if ($parameters) {
tmysik@6020
   800
		print_parameters ($parameters);
tmysik@6020
   801
	} else {
tmysik@6020
   802
		print_parameters_ref ($functionRef->getParameters());
tmysik@6020
   803
	}
tmysik@6020
   804
	print ")";
tmysik@6325
   805
        $returntype = sanitizeType(@$functionsDoc[$funckey]['returntype']);
tmysik@6325
   806
        if ($returntype
tmysik@6325
   807
                && $functionName !== '__construct') {
tmysik@6325
   808
            print ': ' . $returntype;
tmysik@6325
   809
        }
tmysik@6020
   810
        $body = true;
tmysik@6020
   811
        if ($classRef != null && $classRef->isInterface()) {
tmysik@6020
   812
            $body = false;
tmysik@6020
   813
        } elseif (is_array($modifiers)) {
tmysik@6020
   814
            foreach ($modifiers as $modifier) {
tmysik@6020
   815
                if ($modifier == "abstract") {
tmysik@6020
   816
                    $body = false;
tmysik@6020
   817
                    break;
tmysik@6020
   818
                }
tmysik@6020
   819
            }
tmysik@6020
   820
        }
tmysik@6020
   821
        if ($body) {
tmysik@6020
   822
            print " {}";
tmysik@6020
   823
        } else {
tmysik@6020
   824
            print ";";
tmysik@6020
   825
        }
tmysik@6020
   826
	print "\n";
tmysik@6020
   827
}
tmysik@6020
   828
tmysik@6020
   829
tmysik@6020
   830
/**
tmysik@6020
   831
 * Prints ReflectionParameter in format of PHP code
tmysik@6020
   832
 * @param parameters array information from PHP.net documentation
tmysik@6020
   833
 */
tmysik@6020
   834
function print_parameters ($parameters) {
tmysik@6020
   835
	$i = 0;
tmysik@6020
   836
	foreach ($parameters as $parameter) {
tmysik@6020
   837
		if ($parameter['name'] != "...") {
tmysik@6385
   838
                        $type = sanitizeType($parameter['type']);
tmysik@6385
   839
                        $nullable = false;
tmysik@6385
   840
                        $param_value = '';
tmysik@6020
   841
			if (@$parameter['isoptional']) {
tmysik@6202
   842
				if (array_key_exists('defaultvalue', $parameter)) {
tmysik@6020
   843
					$value = $parameter['defaultvalue'];
tmysik@6325
   844
                                        if ((is_numeric ($value) && $type != 'string')
tmysik@6325
   845
                                                || in_array(strtolower($value), array('true', 'false', 'null', 'array()'))
tmysik@6020
   846
                                                || (substr($value, 0, 1) == '\'' && substr($value, -1) == '\'')
tmysik@6325
   847
                                                || (substr($value, 0, 1) == '"' && substr($value, -1) == '"')
tmysik@6325
   848
                                                || (substr($value, 0, 2) == '__' && substr($value, -2) == '__')
tmysik@6325
   849
                                                || isConstant($value)) {
tmysik@6020
   850
                                            // no apostrophes
tmysik@6020
   851
                                        } else {
tmysik@6020
   852
                                            $value = "'{$value}'";
tmysik@6020
   853
                                        }
tmysik@6385
   854
                                        $param_value = " = {$value}";
tmysik@6020
   855
				} else {
tmysik@6385
   856
                                        $nullable = true;
tmysik@6385
   857
                                        if (!$type) {
tmysik@6385
   858
                                            $param_value = " = null";
tmysik@6385
   859
                                        }
tmysik@6020
   860
				}
tmysik@6020
   861
			}
tmysik@6385
   862
                    
tmysik@6385
   863
			if ($i++ > 0) {
tmysik@6385
   864
				print ", ";
tmysik@6385
   865
			}
tmysik@6385
   866
			if ($type) {
tmysik@6385
   867
                                if ($nullable) {
tmysik@6385
   868
                                    print "?";
tmysik@6385
   869
                                }
tmysik@6385
   870
				print "{$type} ";
tmysik@6385
   871
			}
tmysik@6385
   872
			if (@$parameter['isreference']) {
tmysik@6385
   873
				print "&";
tmysik@6385
   874
			}
tmysik@6385
   875
                        print "\${$parameter['name']}";
tmysik@6385
   876
                        
tmysik@6385
   877
                        if ($param_value) {
tmysik@6385
   878
                            print $param_value;
tmysik@6385
   879
                        }
tmysik@6385
   880
tmysik@6020
   881
		}
tmysik@6020
   882
	}
tmysik@6020
   883
}
tmysik@6020
   884
tmysik@6020
   885
/**
tmysik@6020
   886
 * Prints ReflectionParameter in format of PHP code
tmysik@6020
   887
 * @param paramsRef ReflectionParameter[] array of objects
tmysik@6020
   888
 */
tmysik@6020
   889
function print_parameters_ref ($paramsRef) {
tmysik@6020
   890
	$i = 0;
tmysik@6020
   891
	foreach ($paramsRef as $paramRef) {
tmysik@6385
   892
            /* @var $paramRef ReflectionParameter */
tmysik@6385
   893
            if ($paramRef->allowsNull()) {
tmysik@6385
   894
                echo '?';
tmysik@6385
   895
            }
tmysik@6020
   896
		if ($paramRef->isArray()) {
tmysik@6020
   897
			print "array ";
tmysik@6020
   898
		} else {
tmysik@6020
   899
			if ($className = get_parameter_classname($paramRef)) {
tmysik@6020
   900
				print "{$className} ";
tmysik@6020
   901
			}
tmysik@6020
   902
		}
tmysik@6020
   903
		$name = $paramRef->getName() ? $paramRef->getName() : "var".($i+1);
tmysik@6020
   904
		if ($name != "...") {
tmysik@6020
   905
			if ($i++ > 0) {
tmysik@6020
   906
				print ", ";
tmysik@6020
   907
			}
tmysik@6020
   908
			if ($paramRef->isPassedByReference()) {
tmysik@6020
   909
				print "&";
tmysik@6020
   910
			}
tmysik@6020
   911
			print "\${$name}";
tmysik@6020
   912
			if ($paramRef->allowsNull()) {
tmysik@6020
   913
				print " = null";
tmysik@6020
   914
			} else if ($paramRef->isDefaultValueAvailable()) {
tmysik@6020
   915
				$value = $paramRef->getDefaultValue();
tmysik@6020
   916
				if (!is_numeric ($value)) {
tmysik@6020
   917
					$value = "'{$value}'";
tmysik@6020
   918
				}
tmysik@6020
   919
				print " = {$value}";
tmysik@6020
   920
			}
tmysik@6020
   921
		}
tmysik@6020
   922
	}
tmysik@6020
   923
}
tmysik@6020
   924
tmysik@6020
   925
/**
tmysik@6020
   926
 * Prints constants in format of PHP code
tmysik@6020
   927
 * @param constants array containing constants, where key is a name of constant
tmysik@6020
   928
 * @param tabs integer[optional] number of tabs for indentation
tmysik@6020
   929
 */
tmysik@6020
   930
function print_constants ($constants, $tabs = 0) {
tmysik@6020
   931
	foreach ($constants as $name => $value) {
tmysik@6020
   932
		print_constant ($name, $value, $tabs);
tmysik@6020
   933
	}
tmysik@6020
   934
}
tmysik@6020
   935
tmysik@6020
   936
function print_constant ($name, $value = null, $tabs = 0) {
tmysik@6020
   937
	global $constantsDoc;
tmysik@6020
   938
	global $processedConstants;
tmysik@6020
   939
	$processedConstants [$name] = true;
tmysik@6020
   940
tmysik@6020
   941
	if ($value === null) {
tmysik@6020
   942
		$value = @constant ($name);
tmysik@6020
   943
	}
tmysik@6020
   944
	$value = escape_const_value ($value);
tmysik@6020
   945
tmysik@6020
   946
	$doc = @$constantsDoc[$name]['doc'];
tmysik@6020
   947
	if ($doc) {
tmysik@6020
   948
		print "\n";
tmysik@6020
   949
		print_tabs ($tabs);
tmysik@6020
   950
		print "/**\n";
tmysik@6020
   951
		print_tabs ($tabs);
tmysik@6020
   952
		print " * ".newline_to_phpdoc($doc, $tabs)."\n";
tmysik@6020
   953
		print_tabs ($tabs);
tmysik@6020
   954
		print " * @link ".make_url($constantsDoc[$name]['id'])."\n";
tmysik@6020
   955
		print_tabs ($tabs);
tmysik@6020
   956
		print " */\n";
tmysik@6020
   957
	}
tmysik@6020
   958
	print_tabs ($tabs);
tmysik@6020
   959
	print "define ('{$name}', {$value});\n";
tmysik@6020
   960
}
tmysik@6020
   961
tmysik@6020
   962
function escape_const_value ($value) {
tmysik@6020
   963
	if (is_resource($value)) {
tmysik@6020
   964
		$value = "\"${value}\"";
tmysik@6020
   965
	} else if (!is_numeric ($value) && !is_bool ($value) && $value !== null) {
tmysik@6020
   966
		$value = '"'.addcslashes ($value, "\"\r\n\t").'"';
tmysik@6020
   967
	} else if ($value === null) {
tmysik@6020
   968
		$value = "null";
tmysik@6020
   969
	} else if ($value === false) {
tmysik@6020
   970
		$value = "false";
tmysik@6020
   971
	} else if ($value === true) {
tmysik@6020
   972
		$value = "true";
tmysik@6020
   973
	}
tmysik@6020
   974
	return $value;
tmysik@6020
   975
}
tmysik@6020
   976
tmysik@6020
   977
/**
tmysik@6020
   978
 * Prints class constants in format of PHP code
tmysik@6020
   979
 * @param constants array containing constants, where key is a name of constant
tmysik@6020
   980
 * @param tabs integer[optional] number of tabs for indentation
tmysik@6020
   981
 */
tmysik@6020
   982
function print_class_constants ($classRef, $constants, $tabs = 0) {
tmysik@6020
   983
    global $constantsDoc;
tmysik@6020
   984
    global $processedConstants;
tmysik@6020
   985
tmysik@6020
   986
tmysik@6020
   987
    //$doc = @$constantsDoc[$name]['doc'];
tmysik@6020
   988
    foreach ($constants as $name => $value) {
tmysik@6020
   989
        $value = escape_const_value ($value);
tmysik@6020
   990
        $clsName = $classRef->getName();
tmysik@6020
   991
        $idx = "$clsName::$name";
tmysik@6020
   992
        $doc = @$constantsDoc[$idx]['doc'];
tmysik@6020
   993
        if ($doc) {
tmysik@6020
   994
            print "\n";
tmysik@6020
   995
            print_tabs ($tabs);
tmysik@6020
   996
            print "/**\n";
tmysik@6020
   997
            print_tabs ($tabs);
tmysik@6020
   998
            print " * ".newline_to_phpdoc($doc, $tabs)."\n";
tmysik@6020
   999
            print_tabs ($tabs);
tmysik@6020
  1000
            print " * @link ".make_url($constantsDoc[$idx]['id'])."\n";
tmysik@6020
  1001
            print_tabs ($tabs);
tmysik@6020
  1002
            print " */\n";
tmysik@6020
  1003
        }
tmysik@6020
  1004
        print_tabs ($tabs);
tmysik@6020
  1005
        print "const {$name} = {$value};\n";
tmysik@6020
  1006
    }
tmysik@6020
  1007
}
tmysik@6020
  1008
tmysik@6020
  1009
/**
tmysik@6020
  1010
 * Prints modifiers of reflection object in format of PHP code
tmysik@6020
  1011
 * @param ref Reflection some reflection object
tmysik@6020
  1012
 */
tmysik@6020
  1013
function print_modifiers ($ref, $forFields = false) {
tmysik@6020
  1014
	$modifiers = Reflection::getModifierNames ($ref->getModifiers());
tmysik@6020
  1015
	if (count ($modifiers) > 0) {
tmysik@6020
  1016
                $print = implode(' ', $modifiers);
tmysik@6020
  1017
                if ($forFields) {
tmysik@6020
  1018
                    $print = str_replace("final", "", $print);
tmysik@6020
  1019
                    $print = str_replace("abstract", "", $print);
tmysik@6060
  1020
                    $print = str_replace("readonly", "", $print);
tmysik@6020
  1021
                }
tmysik@6020
  1022
		print trim($print);
tmysik@6020
  1023
		print " ";
tmysik@6020
  1024
	}
tmysik@6020
  1025
}
tmysik@6020
  1026
tmysik@6020
  1027
/**
tmysik@6020
  1028
 * Makes PHP Manual URL from the given ID
tmysik@6020
  1029
 * @param id PHP Element ID
tmysik@6020
  1030
 * @return URL
tmysik@6020
  1031
 */
tmysik@6020
  1032
function make_url ($id) {
tmysik@6020
  1033
	return "http://php.net/manual/en/{$id}.php";
tmysik@6020
  1034
}
tmysik@6020
  1035
tmysik@6020
  1036
/**
tmysik@6020
  1037
 * Prints PHPDOC comment before specified reflection object
tmysik@6020
  1038
 * @param ref Reflection some reflection object
tmysik@6020
  1039
 * @param tabs integer[optional] number of tabs for indentation
tmysik@6020
  1040
 */
tmysik@6020
  1041
function print_doccomment ($ref, $tabs = 0) {
tmysik@6020
  1042
	global $functionsDoc;
tmysik@6020
  1043
	global $classesDoc;
tmysik@6020
  1044
        global $fieldsDoc;
tmysik@6111
  1045
        global $methodBlackList;
tmysik@6020
  1046
tmysik@6020
  1047
	$docComment = $ref->getDocComment();
tmysik@6020
  1048
	if ($docComment) {
tmysik@6020
  1049
		print_tabs ($tabs);
tmysik@6020
  1050
		print "{$docComment}\n";
tmysik@6020
  1051
	}
tmysik@6020
  1052
	else if ($ref instanceof ReflectionClass) {
tmysik@6020
  1053
		$refname = strtolower($ref->getName());
tmysik@6020
  1054
		if (@$classesDoc[$refname]) {
tmysik@6020
  1055
			print_tabs ($tabs);
tmysik@6020
  1056
			print "/**\n";
tmysik@6020
  1057
			$doc = @$classesDoc[$refname]['doc'];
tmysik@6020
  1058
			if ($doc) {
tmysik@6020
  1059
				$doc = newline_to_phpdoc ($doc, $tabs);
tmysik@6020
  1060
				print_tabs ($tabs);
tmysik@6020
  1061
				print " * {$doc}\n";
tmysik@6020
  1062
			}
tmysik@6111
  1063
                        // @method
tmysik@6111
  1064
                        foreach ($ref->getMethods() as $method) {
tmysik@6111
  1065
                            if (in_array(strtolower($method->getName()), $methodBlackList)) {
tmysik@6111
  1066
                                print_magic_method($ref, $method, $tabs);
tmysik@6111
  1067
                            }
tmysik@6111
  1068
                        }
tmysik@6020
  1069
			if (@$classesDoc[$refname]['id']) {
tmysik@6020
  1070
				print_Tabs ($tabs);
tmysik@6020
  1071
				$url = make_url ($classesDoc[$refname]['id']);
tmysik@6020
  1072
				print " * @link {$url}\n";
tmysik@6020
  1073
			}
tmysik@6020
  1074
			print_tabs ($tabs);
tmysik@6020
  1075
			print " */\n";
tmysik@6020
  1076
		}
tmysik@6020
  1077
	}
tmysik@6020
  1078
	else if ($ref instanceof ReflectionFunctionAbstract) {
tmysik@6020
  1079
		$funckey = make_funckey_from_ref ($ref);
tmysik@6020
  1080
                $id = @$functionsDoc[$funckey]['id'];
tmysik@6020
  1081
                $ver_info = findVerInfo($id);
tmysik@6020
  1082
                $desc = @$functionsDoc[$funckey]['quickref'];
tmysik@6020
  1083
		$returntype = "";
tmysik@6020
  1084
                $returndoc = "";
tmysik@6020
  1085
                if (strpos($funckey, "::__construct") === false) {
tmysik@6020
  1086
                    $returntype = @$functionsDoc[$funckey]['returntype'];
tmysik@6020
  1087
                    $returndoc = newline_to_phpdoc (@$functionsDoc[$funckey]['returndoc'], $tabs);
tmysik@6020
  1088
                }
tmysik@6020
  1089
tmysik@6020
  1090
		$paramsRef = $ref->getParameters();
tmysik@6020
  1091
		$parameters = @$functionsDoc[$funckey]['parameters'];
tmysik@6020
  1092
tmysik@6020
  1093
		if ($desc || count ($paramsRef) > 0 || $parameters || $returntype) {
tmysik@6020
  1094
			print_tabs ($tabs);
tmysik@6020
  1095
			print "/**\n";
tmysik@6020
  1096
                        if($ver_info) {
tmysik@6020
  1097
                            print_tabs ($tabs);
tmysik@6020
  1098
                            print " * {$ver_info}<br/>\n";
tmysik@6020
  1099
                        }
tmysik@6020
  1100
                        if ($desc) {
tmysik@6020
  1101
				print_tabs ($tabs);
tmysik@6020
  1102
				print " * {$desc}\n";
tmysik@6020
  1103
			}
tmysik@6020
  1104
			if (@$functionsDoc[$funckey]['id']) {
tmysik@6020
  1105
				print_tabs ($tabs);
tmysik@6020
  1106
				$url = make_url ($functionsDoc[$funckey]['id']);
tmysik@6020
  1107
				print " * @link {$url}\n";
tmysik@6020
  1108
			}
tmysik@6020
  1109
                        if (!@$functionsDoc[$funckey]['deprecated']) {
tmysik@6020
  1110
                            if($parameters) {
tmysik@6020
  1111
                                foreach ($parameters as $parameter) {
tmysik@6020
  1112
                                    print_tabs($tabs);
tmysik@6020
  1113
                                    print " * @param {$parameter['type']} \${$parameter['name']}";
tmysik@6020
  1114
                                    if (@$parameter['isoptional']) {
tmysik@6020
  1115
                                        print " [optional]";
tmysik@6020
  1116
                                    }
tmysik@6020
  1117
                                    $paramdoc = @$parameter['paramdoc'];
tmysik@6020
  1118
                                    if ($paramdoc && $paramdoc != "<p>\n</p>") {
tmysik@6020
  1119
                                        $paramdoc = newline_to_phpdoc(@$parameter['paramdoc'], $tabs);
tmysik@6020
  1120
                                        print " {$paramdoc}";
tmysik@6020
  1121
                                    }
tmysik@6020
  1122
                                    print "\n";
tmysik@6020
  1123
                                }
tmysik@6020
  1124
                            } else {
tmysik@6020
  1125
                                $i = 0;
tmysik@6020
  1126
                                foreach ($paramsRef as $paramRef) {
tmysik@6020
  1127
                                    print_tabs($tabs);
tmysik@6020
  1128
                                    $name = $paramRef->getName() ? $paramRef->getName() : "var".++$i;
tmysik@6020
  1129
                                    print " * @param";
tmysik@6020
  1130
                                    if($className = get_parameter_classname($paramRef)) {
tmysik@6020
  1131
                                        print " {$className}";
tmysik@6020
  1132
                                        if($paramRef->isArray()) {
tmysik@6020
  1133
                                            print "[]";
tmysik@6020
  1134
                                        }
tmysik@6020
  1135
                                    }
tmysik@6020
  1136
                                    print " \${$name}";
tmysik@6020
  1137
                                    if($paramRef->isOptional()) {
tmysik@6020
  1138
                                        print " [optional]";
tmysik@6020
  1139
                                    }
tmysik@6020
  1140
                                    print "\n";
tmysik@6020
  1141
                                }
tmysik@6020
  1142
                            }
tmysik@6020
  1143
                            if ($returntype || $returndoc) {
tmysik@6020
  1144
                                if (!$returntype) {
tmysik@6020
  1145
                                    $returntype = 'mixed';
tmysik@6020
  1146
                                }
tmysik@6020
  1147
                                    print_tabs ($tabs);
tmysik@6020
  1148
                                    print " * @return " . trim("{$returntype} {$returndoc}") . "\n";
tmysik@6020
  1149
                            }
tmysik@6020
  1150
                        }
tmysik@6020
  1151
			print_tabs ($tabs);
tmysik@6020
  1152
			print " */\n";
tmysik@6020
  1153
		}
tmysik@6020
  1154
	}else if ($ref instanceof ReflectionProperty) {
tmysik@6020
  1155
            $property_from_ref = make_property_from_ref($ref);
tmysik@6020
  1156
            $fieldName = @$fieldsDoc[$property_from_ref]['field'];
tmysik@6020
  1157
            $fieldType = @$fieldsDoc[$property_from_ref]['type'];
tmysik@6020
  1158
            if (isset ($fieldName) && isset ($fieldType)) {
tmysik@6020
  1159
                print_tabs ($tabs);
tmysik@6020
  1160
                print "/**\n";
tmysik@6020
  1161
                print_tabs ($tabs);
tmysik@6020
  1162
                print " * @var $fieldType\n";
tmysik@6020
  1163
                print_tabs ($tabs);
tmysik@6020
  1164
                print " */\n";
tmysik@6020
  1165
            }
tmysik@6020
  1166
        }
tmysik@6020
  1167
}
tmysik@6020
  1168
tmysik@6111
  1169
function print_magic_method(ReflectionClass $classRef, ReflectionMethod $methodRef, $tabs = 0) {
tmysik@6111
  1170
    global $functionsDoc;
tmysik@6111
  1171
    global $processedFunctions;
tmysik@6111
  1172
tmysik@6111
  1173
    $funckey = make_funckey_from_ref($methodRef);
tmysik@6111
  1174
    $processedFunctions[$funckey] = true;
tmysik@6111
  1175
tmysik@6111
  1176
    print_tabs($tabs);
tmysik@6111
  1177
    print " * @method ";
tmysik@6111
  1178
    $returntype = @$functionsDoc[$funckey]['returntype'];
tmysik@6111
  1179
    $returndoc = @$functionsDoc[$funckey]['returndoc'];
tmysik@6111
  1180
    if ($returntype
tmysik@6111
  1181
            || $returndoc) {
tmysik@6111
  1182
        if (!$returntype) {
tmysik@6111
  1183
            $returntype = 'mixed';
tmysik@6111
  1184
        }
tmysik@6111
  1185
        print $returntype . " ";
tmysik@6111
  1186
    }
tmysik@6111
  1187
    print $methodRef->getName() . "(";
tmysik@6111
  1188
    $parameters = @$functionsDoc[$funckey]['parameters'];
tmysik@6111
  1189
    if ($parameters) {
tmysik@6111
  1190
        print_parameters($parameters);
tmysik@6111
  1191
    } else {
tmysik@6111
  1192
        print_parameters_ref($methodRef->getParameters());
tmysik@6111
  1193
    }
tmysik@6111
  1194
    print ")";
tmysik@6111
  1195
    $id = @$functionsDoc[$funckey]['id'];
tmysik@6111
  1196
    $ver_info = findVerInfo($id);
tmysik@6111
  1197
    $docComment = @$functionsDoc[$funckey]['quickref'];
tmysik@6111
  1198
    if ($ver_info
tmysik@6111
  1199
            || $docComment) {
tmysik@6111
  1200
        print " ";
tmysik@6111
  1201
        if ($ver_info) {
tmysik@6111
  1202
            print $ver_info;
tmysik@6111
  1203
        }
tmysik@6111
  1204
        if ($docComment) {
tmysik@6111
  1205
            if ($ver_info) {
tmysik@6111
  1206
                print "<br/>";
tmysik@6111
  1207
            }
tmysik@6111
  1208
            print $docComment;
tmysik@6111
  1209
        }
tmysik@6111
  1210
    }
tmysik@6111
  1211
    print "\n";
tmysik@6111
  1212
}
tmysik@6111
  1213
tmysik@6020
  1214
/**
tmysik@6020
  1215
 * Converts XML entities to human readable string for PHPDOC
tmysik@6020
  1216
 * @param str string
tmysik@6020
  1217
 * @return string
tmysik@6020
  1218
 */
tmysik@6020
  1219
function xml_to_phpdoc ($str) {
tmysik@6020
  1220
    $str = str_replace ("&php.ini;", "###(i)###php.ini###(/i)###", $str); // XXX will be replaced in strip_tags_special()
tmysik@6020
  1221
    $str = replace_entities($str);
tmysik@6020
  1222
        $str = strip_tags_special ($str);
tmysik@6020
  1223
	$str = preg_replace ("/  */", " ", $str);
tmysik@6020
  1224
	$str = str_replace ("*/", "* /", $str);
tmysik@6112
  1225
	$str = str_replace ("“", "&quot;", $str);
tmysik@6112
  1226
	$str = str_replace ("”", "&quot;", $str);
tmysik@6020
  1227
	$str = preg_replace ("/[\r\n][\t ]/", "\n", $str);
tmysik@6020
  1228
        $str = trim($str);
tmysik@6020
  1229
	return $str;
tmysik@6020
  1230
}
tmysik@6020
  1231
tmysik@6020
  1232
/**
tmysik@6020
  1233
 * Converts newlines to PHPDOC prefixes in the given string
tmysik@6020
  1234
 * @param str string
tmysik@6020
  1235
 * @param tabs integer[optional] number of tabs for indentation
tmysik@6020
  1236
 * @return string PHPDOC string
tmysik@6020
  1237
 */
tmysik@6020
  1238
function newline_to_phpdoc ($str, $tabs = 0) {
tmysik@6020
  1239
	$str = preg_replace ("@\s*[\r\n]+@", "\n".str_repeat("\t", $tabs)." * ", $str);
tmysik@6020
  1240
	return $str;
tmysik@6020
  1241
}
tmysik@6020
  1242
tmysik@6020
  1243
/**
tmysik@6020
  1244
 * Prints specified number of tabs
tmysik@6020
  1245
 * @param tabs integer number of tabs to print
tmysik@6020
  1246
 */
tmysik@6020
  1247
function print_tabs ($tabs) {
tmysik@6020
  1248
	print str_repeat("\t", $tabs);
tmysik@6020
  1249
}
tmysik@6020
  1250
tmysik@6020
  1251
/**
tmysik@6020
  1252
 * Returns class name from given parameter reference, this method is a workaround
tmysik@6020
  1253
 * for the case when exception is thrown from getClass() when such classname does not exist.
tmysik@6020
  1254
 */
tmysik@6020
  1255
function get_parameter_classname(ReflectionParameter $paramRef) {
tmysik@6020
  1256
	try {
tmysik@6020
  1257
		if ($classRef = $paramRef->getClass()) {
tmysik@6020
  1258
			return $classRef->getName();
tmysik@6020
  1259
		}
tmysik@6020
  1260
	} catch (Exception $e) {
tmysik@6020
  1261
		if (preg_match('/Class (\w+) does not exist/', $e->getMessage(), $matches)) {
tmysik@6020
  1262
			return $matches[1];
tmysik@6020
  1263
		}
tmysik@6020
  1264
	}
tmysik@6020
  1265
	return null;
tmysik@6020
  1266
}
tmysik@6020
  1267
tmysik@6020
  1268
/**
tmysik@6020
  1269
 * Starts outputing to the new file
tmysik@6020
  1270
 */
tmysik@6020
  1271
function begin_file_output() {
tmysik@6020
  1272
	ob_start();
tmysik@6020
  1273
	print "<?php\n";
tmysik@6020
  1274
}
tmysik@6020
  1275
tmysik@6020
  1276
/**
tmysik@6020
  1277
 * Ends outputing, and dumps the output to the specified file
tmysik@6020
  1278
 * @param filename File to dump the output
tmysik@6020
  1279
 */
tmysik@6020
  1280
function finish_file_output($filename) {
tmysik@6020
  1281
	//if (file_exists ($filename)) {
tmysik@6020
  1282
	//	rename ($filename, "{$filename}.bak");
tmysik@6020
  1283
	//}
tmysik@6020
  1284
	print "?>\n";
tmysik@6111
  1285
	file_put_contents (str_replace(" ", "-", $filename), ob_get_contents());
tmysik@6020
  1286
	ob_end_clean();
tmysik@6020
  1287
}
tmysik@6020
  1288
tmysik@6020
  1289
/**
tmysik@6020
  1290
 * Strips xml tags from the string like the standard strip_tags() function
tmysik@6020
  1291
 * would do, but also translates some of the docbook tags (such as tables
tmysik@6020
  1292
 * an paragraphs) to proper html tags
tmysik@6020
  1293
 * @param str string
tmysik@6020
  1294
 * @return string
tmysik@6020
  1295
 */
tmysik@6020
  1296
function strip_tags_special ($str) {
tmysik@6020
  1297
    // methodsynopsis
tmysik@6020
  1298
//    $str = method_to_phpdoc($str);
tmysik@6020
  1299
    // first mask and translate the tags to preseve
tmysik@6020
  1300
    $str = preg_replace ("/<(\/?)table>/", "###($1table)###", $str);
tmysik@6020
  1301
    $str = str_replace ("<row>", "###(tr valign=\"top\")###", $str);
tmysik@6020
  1302
    $str = str_replace ("</row>", "###(/tr)###", $str);
tmysik@6020
  1303
    $str = preg_replace ("/<(\/?)entry>/", "###($1td)###", $str);
tmysik@6020
  1304
    $str = preg_replace ("/<(\/?)para>/", "###($1p)###", $str);
tmysik@6020
  1305
    $str = preg_replace ("/<(\/?)p>/", "###($1p)###", $str);
tmysik@6020
  1306
    // remove cdata
tmysik@6020
  1307
    $str = str_replace ("<![CDATA[", "###(pre)###", $str);
tmysik@6020
  1308
    $str = str_replace ("]]>", "###(/pre)###", $str);
tmysik@6020
  1309
    // preserve php samples; XXX sample for preg_match_all
tmysik@6020
  1310
    $str = str_replace ("<?php", "###(code)###", $str);
tmysik@6020
  1311
    $str = str_replace ("?>", "###(/code)###", $str);
tmysik@6020
  1312
    // handle "<pre><code>"
tmysik@6020
  1313
    $str = preg_replace ("/###\(pre\)###\s*\n\s*###\(code\)###/", "###(code)###", $str);
tmysik@6020
  1314
    $str = preg_replace ("/###\(\/code\)###\s*\n\s*###\(\/pre\)###/", "###(/code)###", $str);
tmysik@6020
  1315
    // constant & function etc.
tmysik@6020
  1316
    $str = preg_replace ("%<(/)?(constant|function|classname|methodname|methodparam)[^>]*>%", "###(\\1b)###", $str);
tmysik@6020
  1317
    $str = preg_replace ("%<(/)?(parameter)[^>]*>%", "###(\\1i)###", $str);
tmysik@6020
  1318
    // now strip the remaining tags
tmysik@6020
  1319
    $str = strip_tags ($str);
tmysik@6020
  1320
    // and restore the translated ones
tmysik@6020
  1321
    $str = str_replace ("###(", "<", $str);
tmysik@6020
  1322
    $str = str_replace (")###", ">", $str);
tmysik@6020
  1323
    return $str;
tmysik@6020
  1324
}
tmysik@6020
  1325
tmysik@6020
  1326
// XXX, see set_error_handler
tmysik@6020
  1327
function method_to_phpdoc($str) {
tmysik@6020
  1328
    $tmp = array();
tmysik@6020
  1329
    $methodsynopsis = preg_match_all ('@<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>@s', $str, $tmp);
tmysik@6020
  1330
    if (!$methodsynopsis) {
tmysik@6020
  1331
        return $str;
tmysik@6020
  1332
    }
tmysik@6020
  1333
    $functionsDoc = array();
tmysik@6020
  1334
    $parameters = null;
tmysik@6020
  1335
    for ($i = 0; $i < count($tmp); ++$i) {
tmysik@6020
  1336
        $refname = trim($tmp[2][$i]);
tmysik@6020
  1337
        $functionsDoc[$refname]['methodname'] = $refname;
tmysik@6020
  1338
        $parameters = $tmp[3][$i];
tmysik@6020
  1339
        if ($parameters) {
tmysik@6020
  1340
                if (preg_match_all ('@<methodparam\s*(.*?)>.*?<type>(.*?)</type>.*?<parameter\s*(.*?)>(.*?)</parameter>(?:<initializer>(.+?)</initializer>)?.*?</methodparam>@s', $parameters, $match)) {
tmysik@6020
  1341
                        for ($i = 0; $i < count($match[0]); ++$i) {
tmysik@6020
  1342
                                $parameter = array (
tmysik@6020
  1343
                                        'type' => trim(str_replace('-', '_', $match[2][$i])), // e.g. OCI-Collection -> OCI_Collection
tmysik@6020
  1344
                                        'name' => clean_php_identifier(trim($match[4][$i])),
tmysik@6020
  1345
                                );
tmysik@6020
  1346
                                if (preg_match ('@choice=[\'"]opt[\'"]@', $match[1][$i])) {
tmysik@6020
  1347
                                        $parameter['isoptional'] = true;
tmysik@6020
  1348
                                }
tmysik@6020
  1349
                                if (preg_match ('@role=[\'"]reference[\'"]@', $match[3][$i])) {
tmysik@6020
  1350
                                        $parameter['isreference'] = true;
tmysik@6020
  1351
                                }
tmysik@6020
  1352
                                if (@strlen(trim($match[5][$i]))) {
tmysik@6020
  1353
                                        $parameter['defaultvalue'] = clean_php_value($match[5][$i]);
tmysik@6020
  1354
                                        $parameter['isoptional'] = true;
tmysik@6020
  1355
                                }
tmysik@6020
  1356
                                $functionsDoc[$refname]['parameters'][] = $parameter;
tmysik@6020
  1357
                        }
tmysik@6020
  1358
                }
tmysik@6020
  1359
                if (preg_match_all('@<varlistentry\s*.*?>.*?<parameter>(.*?)</parameter>.*?<listitem\s*.*?>(.*?)</listitem>.*?</varlistentry>@s', $parameters, $match)) {
tmysik@6020
  1360
                    for ($i = 0; $i < count($match[0]); $i++) {
tmysik@6020
  1361
                        for ($j = 0; $j < count(@$functionsDoc[$refname]['parameters']); $j++) {
tmysik@6020
  1362
                            if (clean_php_identifier(trim($match[1][$i])) == $functionsDoc[$refname]['parameters'][$j]['name']) {
tmysik@6020
  1363
                                $functionsDoc[$refname]['parameters'][$j]['paramdoc'] = xml_to_phpdoc ($match[2][$i]);
tmysik@6020
  1364
                                break;
tmysik@6020
  1365
                            }
tmysik@6020
  1366
                        }
tmysik@6020
  1367
                    }
tmysik@6020
  1368
                }
tmysik@6020
  1369
        }
tmysik@6020
  1370
    }
tmysik@6020
  1371
    return $str;
tmysik@6020
  1372
}
tmysik@6020
  1373
tmysik@6020
  1374
function parse_entities($phpdocDir) {
tmysik@6020
  1375
    $entities = array();
tmysik@6020
  1376
    parse_entities_from_file($entities, $phpdocDir, '/en/language-defs.ent');
tmysik@6020
  1377
    parse_entities_from_file($entities, $phpdocDir, '/en/language-snippets.ent');
tmysik@6020
  1378
    parse_entities_from_file($entities, $phpdocDir, '/doc-base/docbook/docbook-xml/ent/isonum.ent');
tmysik@6020
  1379
    parse_entities_from_file($entities, $phpdocDir, '/doc-base/entities/global.ent');
tmysik@6020
  1380
    return $entities;
tmysik@6020
  1381
}
tmysik@6020
  1382
function parse_entities_from_file(array &$entities, $phpdocDir, $filepath) {
tmysik@6020
  1383
    $content = file_get_contents($phpdocDir . $filepath);
tmysik@6020
  1384
    $matches = array();
tmysik@6020
  1385
    preg_match_all('%\!ENTITY\s+(\S+)\s+([\'"])([^\\2]+?)\\2\s*>%m', $content, $matches);
tmysik@6020
  1386
    if (array_key_exists(1, $matches) && count($matches[1])) {
tmysik@6020
  1387
        for ($i = 0; $i < count($matches[2]); $i++) {
tmysik@6020
  1388
            $entities['&' . $matches[1][$i] . ';'] = $matches[3][$i];
tmysik@6020
  1389
        }
tmysik@6020
  1390
    }
tmysik@6020
  1391
}
tmysik@6020
  1392
function replace_entities($text) {
tmysik@6020
  1393
    global $entities;
tmysik@6020
  1394
    $matches = array();
tmysik@6020
  1395
    while (preg_match_all('%(\&(?!#)\S+?\;)%', $text, $matches)) {
tmysik@6020
  1396
        if (count($matches[1])) {
tmysik@6020
  1397
            foreach ($matches[1] as $e) {
tmysik@6020
  1398
                $replace = null;
tmysik@6020
  1399
                if (array_key_exists($e, $entities)) {
tmysik@6020
  1400
                    $replace = $entities[$e];
tmysik@6020
  1401
                }
tmysik@6020
  1402
                if ($replace === null) {
tmysik@6020
  1403
                    switch ($e) {
tmysik@6020
  1404
                        case '&$a));':
tmysik@6020
  1405
                            // code sample
tmysik@6020
  1406
                        case '&reference.strings.charsets;':
tmysik@6100
  1407
                        case '&reference.intl.inctimezoneparam;':
tmysik@6100
  1408
                        case '&reference.intl.incfieldparam;':
tmysik@6020
  1409
                            // entity not found
tmysik@6020
  1410
                            break;
tmysik@6020
  1411
                        default:
tmysik@6020
  1412
                            die('Entity "' . $e . '" not found' . "\n");
tmysik@6020
  1413
                    }
tmysik@6020
  1414
                }
tmysik@6020
  1415
                $text = str_replace($e, $replace, $text);
tmysik@6020
  1416
            }
tmysik@6020
  1417
        }
tmysik@6020
  1418
    }
tmysik@6020
  1419
    // return back &lt; and &gt;
tmysik@6020
  1420
    $keep = array(
tmysik@6020
  1421
        '&#38;#60;' => '&lt;',
tmysik@6020
  1422
        '&#x0003E;' => '&gt;',
tmysik@6020
  1423
    );
tmysik@6020
  1424
    return str_replace(array_keys($keep), $keep, $text);
tmysik@6020
  1425
}
tmysik@6020
  1426
tmysik@6060
  1427
function parse_properties_from_html_file($filepath, $classname) {
tmysik@6060
  1428
    $file = DOC_URL . $filepath;
tmysik@6060
  1429
    if (!is_file($file)) {
tmysik@6060
  1430
        return array();
tmysik@6060
  1431
        //die('Cannot parse properties from non-existing file: ' . $file);
tmysik@6060
  1432
    }
tmysik@6060
  1433
    $fields = array();
tmysik@6060
  1434
    $html = new DOMDocument();
tmysik@6060
  1435
    $html->preserveWhiteSpace = false;
tmysik@6060
  1436
    @$html->loadHtmlFile($file);
tmysik@6060
  1437
    $xpath = new DOMXPath($html);
tmysik@6060
  1438
    // documentation
tmysik@6060
  1439
    $doc = array();
tmysik@6060
  1440
    $docNodes = $xpath->query('//div[@id="' . strtolower($classname) . '.props"]/dl');
tmysik@6060
  1441
    if (!$docNodes->length) {
tmysik@6060
  1442
        //die('Documentation not found for properties in file: ' . $file);
tmysik@6060
  1443
    } elseif ($docNodes->length > 1) {
tmysik@6060
  1444
        die('More documentations found for properties in file: ' . $file);
tmysik@6060
  1445
    }
tmysik@6060
  1446
    if ($docNodes->length) {
tmysik@6060
  1447
        $fieldname = null;
tmysik@6060
  1448
        foreach ($docNodes->item(0)->childNodes as $node) {
tmysik@6060
  1449
            if ($node->nodeName == 'dt') {
tmysik@6060
  1450
                $fieldname = trim($node->nodeValue);
tmysik@6060
  1451
            } elseif ($node->nodeName == 'dd') {
tmysik@6060
  1452
                $tmp = new DOMDocument();
tmysik@6060
  1453
                foreach ($node->childNodes as $child) {
tmysik@6060
  1454
                    $tmp->appendChild($tmp->importNode($child, true));
tmysik@6060
  1455
                }
tmysik@6060
  1456
                $doc[$fieldname] = $tmp->saveHTML();
tmysik@6060
  1457
            } else {
tmysik@6060
  1458
                //die('Unknown node name: ' . $node->nodeName);
tmysik@6060
  1459
            }
tmysik@6060
  1460
        }
tmysik@6060
  1461
    }
tmysik@6060
  1462
tmysik@6060
  1463
    // fields
tmysik@6060
  1464
    $fieldNodes = $xpath->query('//div[@class="classsynopsis"]//div[@class="fieldsynopsis"]');
tmysik@6060
  1465
    foreach ($fieldNodes as $fieldNode) {
tmysik@6060
  1466
        $field = new NetBeans_Field();
tmysik@6060
  1467
        // name
tmysik@6060
  1468
        $varnameNodes = $xpath->query('var//var[@class="varname"]', $fieldNode);
tmysik@6060
  1469
        if (!$varnameNodes->length) {
tmysik@6060
  1470
            die('Varname not found for property in file: ' . $file);
tmysik@6060
  1471
        } elseif ($varnameNodes->length > 1) {
tmysik@6060
  1472
            die('More varnames found for property in file: ' . $file);
tmysik@6060
  1473
        }
tmysik@6060
  1474
        $field->setName($varnameNodes->item(0)->nodeValue);
tmysik@6060
  1475
        // modifiers
tmysik@6060
  1476
        $modifierNodes = $xpath->query('span[@class="modifier"]', $fieldNode);
tmysik@6060
  1477
        foreach ($modifierNodes as $modifierNode) {
tmysik@6060
  1478
            $modifier = $modifierNode->nodeValue;
tmysik@6060
  1479
            // XXX
tmysik@6060
  1480
            if ($modifier == 'const') {
tmysik@6060
  1481
                // constant => do nothing
tmysik@6060
  1482
                return array();
tmysik@6060
  1483
            }
tmysik@6060
  1484
            $field->addModifier($modifier);
tmysik@6060
  1485
        }
tmysik@6060
  1486
        // type
tmysik@6060
  1487
        $typeNodes = $xpath->query('span[@class="type"]', $fieldNode);
tmysik@6060
  1488
        if ($typeNodes->length > 1) {
tmysik@6060
  1489
            die('More types found for property ' . $field->getName() . ' in file: ' . $file);
tmysik@6060
  1490
        }
tmysik@6060
  1491
        $field->setType($typeNodes->item(0)->nodeValue);
tmysik@6060
  1492
        // documentation
tmysik@6060
  1493
        if (array_key_exists($field->getName(), $doc)) {
tmysik@6060
  1494
            $field->setDocumentation($doc[$field->getName()]);
tmysik@6060
  1495
        }
tmysik@6060
  1496
        // all ok
tmysik@6060
  1497
        $fields[] = $field;
tmysik@6060
  1498
    }
tmysik@6060
  1499
    return $fields;
tmysik@6060
  1500
}
tmysik@6060
  1501
tmysik@6060
  1502
class NetBeans_Field {
tmysik@6060
  1503
tmysik@6060
  1504
    private $modifiers = array();
tmysik@6060
  1505
    private $type;
tmysik@6060
  1506
    private $name;
tmysik@6060
  1507
    private $value;
tmysik@6060
  1508
    private $documentation;
tmysik@6060
  1509
tmysik@6060
  1510
tmysik@6060
  1511
    public function getModifiers() {
tmysik@6060
  1512
        return $this->modifiers;
tmysik@6060
  1513
    }
tmysik@6060
  1514
tmysik@6060
  1515
    /**
tmysik@6060
  1516
     * @return \NetBeans_Field
tmysik@6060
  1517
     */
tmysik@6060
  1518
    public function addModifier($modifier) {
tmysik@6060
  1519
        $this->modifiers[] = $modifier;
tmysik@6060
  1520
        return $this;
tmysik@6060
  1521
    }
tmysik@6060
  1522
tmysik@6060
  1523
    /**
tmysik@6060
  1524
     * @return \NetBeans_Field
tmysik@6060
  1525
     */
tmysik@6060
  1526
    public function setModifiers($modifiers) {
tmysik@6060
  1527
        $this->modifiers = $modifiers;
tmysik@6060
  1528
        return $this;
tmysik@6060
  1529
    }
tmysik@6060
  1530
tmysik@6060
  1531
    public function getType() {
tmysik@6060
  1532
        return $this->type;
tmysik@6060
  1533
    }
tmysik@6060
  1534
tmysik@6060
  1535
    /**
tmysik@6060
  1536
     * @return \NetBeans_Field
tmysik@6060
  1537
     */
tmysik@6060
  1538
    public function setType($type) {
tmysik@6060
  1539
        $this->type = $type;
tmysik@6060
  1540
        return $this;
tmysik@6060
  1541
    }
tmysik@6060
  1542
tmysik@6060
  1543
    public function getName() {
tmysik@6060
  1544
        return $this->name;
tmysik@6060
  1545
    }
tmysik@6060
  1546
tmysik@6060
  1547
    /**
tmysik@6060
  1548
     * @return \NetBeans_Field
tmysik@6060
  1549
     */
tmysik@6060
  1550
    public function setName($name) {
tmysik@6060
  1551
        $this->name = $name;
tmysik@6060
  1552
        return $this;
tmysik@6060
  1553
    }
tmysik@6060
  1554
tmysik@6060
  1555
    public function getValue() {
tmysik@6060
  1556
        return $this->value;
tmysik@6060
  1557
    }
tmysik@6060
  1558
tmysik@6060
  1559
    /**
tmysik@6060
  1560
     * @return \NetBeans_Field
tmysik@6060
  1561
     */
tmysik@6060
  1562
    public function setValue($value) {
tmysik@6060
  1563
        $this->value = $value;
tmysik@6060
  1564
        return $this;
tmysik@6060
  1565
    }
tmysik@6060
  1566
tmysik@6060
  1567
    public function getDocumentation() {
tmysik@6060
  1568
        return $this->documentation;
tmysik@6060
  1569
    }
tmysik@6060
  1570
tmysik@6060
  1571
    /**
tmysik@6060
  1572
     * @return \NetBeans_Field
tmysik@6060
  1573
     */
tmysik@6060
  1574
    public function setDocumentation($documentation) {
tmysik@6060
  1575
        $this->documentation = trim($documentation);
tmysik@6060
  1576
        return $this;
tmysik@6060
  1577
    }
tmysik@6060
  1578
tmysik@6060
  1579
}
tmysik@6060
  1580
tmysik@6325
  1581
function sanitizeType($type) {
tmysik@6325
  1582
    if (!trim($type)) {
tmysik@6325
  1583
        return '';
tmysik@6325
  1584
    }
tmysik@6325
  1585
    if (strpos($type, '|') !== false) {
tmysik@6325
  1586
        // ignore 'MyClass|YourClass' cases
tmysik@6325
  1587
        return '';
tmysik@6325
  1588
    }
tmysik@6325
  1589
    if (in_array($type, [
tmysik@6325
  1590
        'mixed',
tmysik@6325
  1591
        'object',
tmysik@6325
  1592
        'callback',
tmysik@6325
  1593
        'resource',
tmysik@6325
  1594
        'bitmask',
tmysik@6325
  1595
        'name',
tmysik@6325
  1596
        'number',
tmysik@6325
  1597
        'scalar',
tmysik@6325
  1598
    ])) {
tmysik@6325
  1599
        return '';
tmysik@6325
  1600
    }
tmysik@6325
  1601
    $convert = [
tmysik@6325
  1602
        'boolean' => 'bool',
tmysik@6325
  1603
    ];
tmysik@6325
  1604
    return str_replace(array_keys($convert), $convert, $type);
tmysik@6325
  1605
}
tmysik@6325
  1606
tmysik@6325
  1607
function isConstant($value) {
tmysik@6325
  1608
    $values = explode(' | ', $value);
tmysik@6325
  1609
    foreach ($values as $v) {
tmysik@6325
  1610
        if (!preg_match('/^(\\w+\\:\\:)?[A-Z0-9_]+$/', $v)) {
tmysik@6325
  1611
            return false;
tmysik@6325
  1612
        }
tmysik@6325
  1613
    }
tmysik@6325
  1614
    return true;
tmysik@6325
  1615
}
tmysik@6325
  1616
tmysik@6020
  1617
/**
tmysik@6020
  1618
 * Prints usage help to the screen, and exits from program
tmysik@6020
  1619
 */
tmysik@6020
  1620
function show_help() {
tmysik@6020
  1621
	global $argv0;
tmysik@6020
  1622
tmysik@6020
  1623
	die (<<<EOF
tmysik@6020
  1624
USAGE: {$argv0} [options] <PHP.net documentation directory>
tmysik@6020
  1625
tmysik@6020
  1626
Where options are:
tmysik@6020
  1627
tmysik@6020
  1628
-help	Show this help.
tmysik@6020
  1629
-split	Split output to different files (one file per PHP extension).
tmysik@6020
  1630
tmysik@6020
  1631
EOF
tmysik@6020
  1632
	);
tmysik@6020
  1633
}
tmysik@6020
  1634
tmysik@6020
  1635
?>