10 changed files with 1399 additions and 0 deletions
-
36scripts/ext_skel_ng/README
-
13scripts/ext_skel_ng/ext_skel_ng.php
-
80scripts/ext_skel_ng/extension.dtd
-
82scripts/ext_skel_ng/extension.xml
-
789scripts/ext_skel_ng/extension_parser.php
-
38scripts/ext_skel_ng/php_constant.php
-
74scripts/ext_skel_ng/php_element.php
-
210scripts/ext_skel_ng/php_function.php
-
35scripts/ext_skel_ng/xml_stream_callback_parser.php
-
42scripts/ext_skel_ng/xml_stream_parser.php
@ -0,0 +1,36 @@ |
|||
sorry, no real documentation yet ... |
|||
just a short look at what is going on |
|||
|
|||
ext_skel_ng.php gets an extension description |
|||
from an "extension.xml" file and generates working |
|||
code and documentation stubs from that |
|||
|
|||
call "php ext_skel_ng.php" to see it at work, |
|||
it will create a dummy extension including |
|||
|
|||
- module globals and ini paramter setup |
|||
- function registration and stubbs |
|||
- documentation framework |
|||
- config.m4 (only minimal for now) |
|||
- ... |
|||
|
|||
almost every aspect of an extension may now be |
|||
configured using one xml description file instead |
|||
of the old mixture of command line parameters |
|||
and a proto file |
|||
|
|||
it is even possible to embed function code into |
|||
the xml description right away, so it should be |
|||
possible to create complete working extensions |
|||
from just the xml description without further |
|||
editing in a not to distant future |
|||
|
|||
for now almost all the 'helpfull comments' have |
|||
been removed from the generated code. some of |
|||
them (like 'uncomment this if you have ini params) |
|||
just don't make sense anymore, others will come |
|||
back (configurable) at a later state |
|||
|
|||
... have fun! |
|||
|
|||
Hartmut Holzgraefe <hholzgra@php.net> |
|||
@ -0,0 +1,13 @@ |
|||
<?php |
|||
require_once "extension_parser.php"; |
|||
|
|||
$ext = &new extension_parser(fopen("extension.xml", "r")); |
|||
|
|||
system("rm -rf {$ext->name}"); |
|||
mkdir($ext->name); |
|||
|
|||
$ext->write_config_m4(); |
|||
$ext->write_header_file(); |
|||
$ext->write_code_file(); |
|||
$ext->generate_documentation(); |
|||
?>
|
|||
@ -0,0 +1,80 @@ |
|||
<!-- |
|||
--> |
|||
|
|||
<!ELEMENT extension (name|summary|description|license|maintainers|release|changelog|functions|constants|globals|deps)*> |
|||
<!ATTLIST extension type (source|binary|empty) "empty" |
|||
version CDATA #REQUIRED> |
|||
|
|||
<!ELEMENT name (#PCDATA)> |
|||
|
|||
<!ELEMENT summary (#PCDATA)> |
|||
|
|||
<!ELEMENT description (#PCDATA)> |
|||
|
|||
<!ELEMENT maintainers (maintainer)+> |
|||
|
|||
<!ELEMENT maintainer (user|role|name|email)*> |
|||
|
|||
<!ELEMENT user (#PCDATA)> |
|||
|
|||
<!ELEMENT role (#PCDATA)> |
|||
|
|||
<!ELEMENT email (#PCDATA)> |
|||
|
|||
<!ELEMENT changelog (release)*> |
|||
|
|||
<!ELEMENT release (version|license|state|date|notes|filelist|deps)*> |
|||
|
|||
<!ELEMENT version (#PCDATA)> |
|||
|
|||
<!ELEMENT state (#PCDATA)> |
|||
|
|||
<!ELEMENT license (#PCDATA)> |
|||
|
|||
<!ELEMENT date (#PCDATA)> |
|||
|
|||
<!ELEMENT notes (#PCDATA)> |
|||
|
|||
<!ELEMENT functions (function)*> |
|||
<!ELEMENT function (summary,proto,description*)> |
|||
<!ATTLIST function |
|||
name CDATA #REQUIRED |
|||
> |
|||
<!ELEMENT proto (#PCDATA)> |
|||
|
|||
<!ELEMENT constants (constant)*> |
|||
<!ELEMENT constant (#PCDATA)> |
|||
<!ATTLIST constant |
|||
name CDATA #REQUIRED |
|||
value CDATA #REQUIRED |
|||
type (string|int|float) "string" |
|||
> |
|||
|
|||
<!ELEMENT globals (phpini|global)*> |
|||
<!ELEMENT phpini (#PCDATA)> |
|||
<!ATTLIST phpini |
|||
name CDATA #REQUIRED |
|||
type CDATA #REQUIRED |
|||
value CDATA #REQUIRED |
|||
access (system|perdir|user|all) "all" |
|||
onupdate CDATA #IMPLIED |
|||
> |
|||
<!ELEMENT global (#PCDATA)> |
|||
<!ATTLIST global |
|||
name CDATA #REQUIRED |
|||
type CDATA #REQUIRED |
|||
> |
|||
|
|||
<!ELEMENT deps (with|lib|header|file|program)*> |
|||
<!ELEMENT with (#PCDATA)> |
|||
<!ATTLIST with |
|||
defaults CDATA #REQUIRED |
|||
testfile CDATA #REQUIRED |
|||
name CDATA #IMPLIED |
|||
> |
|||
<!ELEMENT lib (#PCDATA)> |
|||
<!ATTLIST lib |
|||
name CDATA #REQUIRED |
|||
function CDATA #REQUIRED |
|||
searchpath CDATA #IMPLIED |
|||
> |
|||
@ -0,0 +1,82 @@ |
|||
<?xml version="1.0" encoding="ISO-8859-1" ?> |
|||
<!DOCTYPE extension SYSTEM "extension.dtd"> |
|||
<extension version="0.1"> |
|||
<name>dummy</name> |
|||
<summary>experimental dummy extension</summary> |
|||
<description> |
|||
this is used for testing of the extension generater only |
|||
</description> |
|||
|
|||
<maintainers> |
|||
<maintainer> |
|||
<user>hholzgra</user> |
|||
<name>Hartmut Holzgraefe</name> |
|||
<email>hholzgra@php.net</email> |
|||
<role>lead</role> |
|||
</maintainer> |
|||
<maintainer> |
|||
<user>dummy</user> |
|||
<name>Crashtest Dummy</name> |
|||
<email>dummy@example.com</email> |
|||
<role>dummy</role> |
|||
</maintainer> |
|||
</maintainers> |
|||
|
|||
<release> |
|||
<version>0.1</version> |
|||
<date>2002-02-16</date> |
|||
<state>alpha</state> |
|||
<license>other</license> |
|||
<notes> |
|||
- first experimental draft |
|||
</notes> |
|||
</release> |
|||
|
|||
<changelog> |
|||
</changelog> |
|||
|
|||
|
|||
<deps> |
|||
<!-- these are not yet used in any way :( --> |
|||
<with defaults='/usr:/usr/local' testfile='include/dummy.h'></with> |
|||
<lib name='dummy' function='dummy' searchpath='/usr/lib:/lib'></lib> |
|||
</deps> |
|||
|
|||
<constants> |
|||
<constant name="DUMMY_OK" type="int" value="1">dummy ok status</constant> |
|||
<constant name="DUMMY_ERR" type="int" value="0">dummy fault status</constant> |
|||
</constants> |
|||
|
|||
<globals> |
|||
<global name="foobar" type="int"></global> |
|||
<phpini name="foo_int" type="int" value="42" access="system"></phpini> |
|||
<phpini name="foo_bool" type="int" value="on" access="all" onupdate="OnUpdateBool"></phpini> |
|||
<phpini name="foo_string" type="string" value="foobar" access="all" ></phpini> |
|||
</globals> |
|||
|
|||
<functions> |
|||
|
|||
<function name='dummy_int'> |
|||
<summary>dummy integer conversion</summary> |
|||
<proto>int dummy_int(int bar)</proto> |
|||
<description> |
|||
some funcy longer description |
|||
|
|||
foo |
|||
bar |
|||
</description> |
|||
</function> |
|||
|
|||
<function name='dummy_string'> |
|||
<summary>dummy string conversion</summary> |
|||
<proto>string dummy_string(string bar) foobar</proto> |
|||
<code> |
|||
<![CDATA[ |
|||
RETURN_STRINGL(bar, bar_len, 1); |
|||
]]> |
|||
</code> |
|||
</function> |
|||
|
|||
</functions> |
|||
|
|||
</extension> |
|||
@ -0,0 +1,789 @@ |
|||
<?php |
|||
// {{{ includes
|
|||
|
|||
require_once "php_element.php"; |
|||
require_once "php_constant.php"; |
|||
require_once "php_function.php"; |
|||
|
|||
require_once "xml_stream_parser.php"; |
|||
require_once "xml_stream_callback_parser.php"; |
|||
|
|||
// }}}
|
|||
|
|||
class extension_parser extends xml_stream_callback_parser { |
|||
|
|||
// {{{ constructor
|
|||
|
|||
function extension_parser($stream) { |
|||
$this->template_dir = dirname(realpath(__FILE__))."/templates"; |
|||
|
|||
$this->name = "foobar"; |
|||
|
|||
$this->license = "php"; |
|||
|
|||
$this->constants = array(); |
|||
$this->functions = array(); |
|||
$this->globals = array(); |
|||
$this->phpini = array(); |
|||
$this->users = array(); |
|||
$this->dependson = array(); |
|||
|
|||
parent::xml_stream_callback_parser($stream); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ parsing
|
|||
|
|||
// {{{ general infos
|
|||
|
|||
function handle_extension_name($attr) { |
|||
$this->name = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_extension_summary($attr) { |
|||
$this->summary = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_extension_description($attr) { |
|||
$this->description = $this->cdata; |
|||
} |
|||
|
|||
function handle_release_version($attr) { |
|||
$this->version = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_maintainers_maintainer_user($attr) { |
|||
$this->user["user"] = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_maintainers_maintainer_name($attr) { |
|||
$this->user["name"] = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_maintainers_maintainer_email($attr) { |
|||
$this->user["email"] = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_maintainers_maintainer_role($attr) { |
|||
$this->user["role"] = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_maintainers_maintainer($attr) { |
|||
$this->users[$this->user["name"]] = $this->user; |
|||
unset($this->user); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ constants
|
|||
|
|||
function handle_constants_constant($attr) { |
|||
$name = $attr["name"]; |
|||
$value= $attr["value"]; |
|||
$type = isset($attr["type"]) ? $attr["type"] : "string"; |
|||
|
|||
switch($type) { |
|||
case "int": |
|||
case "integer": |
|||
if (!is_numeric($value)) $this->error("invalid value for integer constant: '$value'"); |
|||
if ((int)$value != $value) $this->error("invalid value for integer constant: '$value'"); |
|||
$this->constants[] = &new php_constant($name, (int)$value, "integer", trim($this->cdata)); |
|||
break; |
|||
|
|||
case "float": |
|||
case "double": |
|||
case "real": |
|||
if (!is_numeric($value)) $this->error("invalid value for integer constant: '$value'"); |
|||
$this->constants[] = &new php_constant($name, $value, "float", trim($this->cdata)); |
|||
break; |
|||
|
|||
case "string": |
|||
default: |
|||
$this->constants[] = &new php_constant($name, $value, "string", trim($this->cdata)); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ functions
|
|||
|
|||
function handle_functions_function_summary($attr) { |
|||
$this->func_summary = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_functions_function_proto($attr) { |
|||
$this->func_proto = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_functions_function_description($attr) { |
|||
$this->func_desc = trim($this->cdata); |
|||
} |
|||
|
|||
function handle_functions_function_code($attr) { |
|||
$this->func_code = $this->cdata; |
|||
} |
|||
|
|||
function handle_functions_function($attr) { |
|||
$this->functions[$attr['name']] = new php_function($attr['name'], $this->func_summary, $this->func_proto, @$this->func_desc, @$this->func_code); |
|||
unset($this->func_summary); |
|||
unset($this->func_proto); |
|||
unset($this->func_desc); |
|||
unset($this->func_code); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ globals and php.ini
|
|||
|
|||
function handle_globals_global($attr) { |
|||
if($attr["type"] == "string") $attr["type"] = "char*"; |
|||
$this->globals[$attr["name"]] = $attr; |
|||
} |
|||
|
|||
function handle_globals_phpini($attr) { |
|||
$ini = array("name" => $attr["name"], |
|||
"type" => $attr["type"], |
|||
"value"=> $attr["value"] |
|||
); |
|||
switch($attr["access"]) { |
|||
case "system": |
|||
$ini["access"] = "PHP_INI_SYSTEM"; |
|||
break; |
|||
case "perdir": |
|||
$ini["access"] = "PHP_INI_PERDIR"; |
|||
break; |
|||
case "user": |
|||
$ini["access"] = "PHP_INI_USER"; |
|||
break; |
|||
case "all": |
|||
default: |
|||
$ini["access"] = "PHP_INI_ALL"; |
|||
break; |
|||
} |
|||
if(isset($attr["onupdate"])) { |
|||
$ini["onupdate"] = $attr["onupdate"]; |
|||
} else { |
|||
switch($attr["type"]) { |
|||
case "int": |
|||
case "long": |
|||
$ini["onupdate"] = "OnUpdateInt"; |
|||
break; |
|||
case "float": |
|||
case "double": |
|||
$ini["onupdate"] = "OnUpdateFloat"; |
|||
break; |
|||
case "string": |
|||
$ini["type"] = "char*"; |
|||
// fallthru
|
|||
case "char*": |
|||
$ini["onupdate"] = "OnUpdateString"; |
|||
break; |
|||
} |
|||
} |
|||
$this->phpini[$attr["name"]] = $ini; |
|||
$this->handle_globals_global($attr); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// }}}
|
|||
|
|||
// {{{ output generation
|
|||
|
|||
// {{{ docbook documentation
|
|||
|
|||
function generate_documentation() { |
|||
system("rm -rf {$this->name}/manual"); |
|||
mkdir("{$this->name}/manual"); |
|||
|
|||
$docdir = "{$this->name}/manual/".$this->name; |
|||
mkdir($docdir); |
|||
|
|||
$fp = fopen("$docdir/reference.xml", "w"); |
|||
fputs($fp, |
|||
"<?xml version='1.0' encoding='iso-8859-1'?>
|
|||
<!-- \$Revision$ --> |
|||
<reference id='ref.{$this->name}'> |
|||
<title>{$this->summary}</title> |
|||
<titleabbrev>{$this->name}</titleabbrev> |
|||
|
|||
<partintro> |
|||
<section id='{$this->name}.intro'> |
|||
&reftitle.intro; |
|||
<para> |
|||
{$this->description} |
|||
</para> |
|||
</section> |
|||
|
|||
<section id='{$this->name}.requirements'> |
|||
&reftitle.required; |
|||
<para> |
|||
</para> |
|||
</section> |
|||
|
|||
&reference.{$this->name}.configure; |
|||
|
|||
<section id='{$this->name}.configuration'> |
|||
&reftitle.runtime; |
|||
&no.config; |
|||
</section> |
|||
|
|||
<section id='{$this->name}.resources'> |
|||
&reftitle.resources; |
|||
&no.resource; |
|||
</section> |
|||
|
|||
<section id='{$this->name}.constants'> |
|||
&reftitle.constants; |
|||
&no.constants; |
|||
</section> |
|||
|
|||
</partintro> |
|||
|
|||
&reference.{$this->name}.functions; |
|||
|
|||
</reference> |
|||
");
|
|||
fputs($fp, php_element::docbook_editor_footer()); |
|||
|
|||
fclose($fp); |
|||
|
|||
mkdir("$docdir/functions"); |
|||
foreach($this->functions as $name => $function) { |
|||
$filename = $docdir . "/functions/" . strtolower(str_replace("_", "-", $name)) . ".xml"; |
|||
$funcfile = fopen($filename, "w"); |
|||
fputs($funcfile, $function->docbook_xml()); |
|||
fclose($funcfile); |
|||
} |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ extension entry
|
|||
|
|||
function generate_extension_entry() { |
|||
return ' |
|||
/* {{{ '.$this->name.'_module_entry |
|||
*/ |
|||
zend_module_entry '.$this->name.'_module_entry = { |
|||
STANDARD_MODULE_HEADER, |
|||
"'.$this->name.'", |
|||
'.$this->name.'_functions, |
|||
PHP_MINIT('.$this->name.'), /* Replace with NULL if there is nothing to do at php startup */ |
|||
PHP_MSHUTDOWN('.$this->name.'), /* Replace with NULL if there is nothing to do at php shutdown */ |
|||
PHP_RINIT('.$this->name.'), /* Replace with NULL if there is nothing to do at request start */ |
|||
PHP_RSHUTDOWN('.$this->name.'), /* Replace with NULL if there is nothing to do at request end */ |
|||
PHP_MINFO('.$this->name.'), |
|||
"'.$this->version.'", |
|||
STANDARD_MODULE_PROPERTIES |
|||
}; |
|||
/* }}} */ |
|||
|
|||
#ifdef COMPILE_DL_'.strtoupper($this->name).'
|
|||
ZEND_GET_MODULE('.$this->name.') |
|||
#endif
|
|||
'; |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ globals and ini
|
|||
|
|||
function generate_globals_c() { |
|||
if (empty($this->globals)) return ""; |
|||
|
|||
$code = "ZEND_DECLARE_MODULE_GLOBALS({$this->name})\n\n"; |
|||
|
|||
if (!empty($this->phpini)) { |
|||
$code .= "PHP_INI_BEGIN()\n"; |
|||
foreach ($this->phpini as $name => $ini) { |
|||
$code .= " STD_PHP_INI_ENTRY(\"{$this->name}.$name\", \"$ini[value]\", $ini[access], $ini[onupdate], $name, zend_{$this->name}_globals, {$this->name}_globals)\n"; |
|||
} |
|||
$code .= "PHP_INI_END()\n\n"; |
|||
$code .= "static void php_{$this->name}_init_globals(zend_{$this->name}_globals *{$this->name}_globals)\n"; |
|||
$code .= "{\n"; |
|||
foreach ($this->globals as $name => $ini) { |
|||
$code .= " {$this->name}_globals->$name = "; |
|||
if (strstr($ini["type"],"*")) { |
|||
$code .= "NULL;\n"; |
|||
} else { |
|||
$code .= "0;\n"; |
|||
} |
|||
} |
|||
$code .= "}\n\n"; |
|||
return $code; |
|||
} |
|||
} |
|||
|
|||
function generate_globals_h() { |
|||
if (empty($this->globals)) return ""; |
|||
|
|||
$code = "ZEND_BEGIN_MODULE_GLOBALS({$this->name})\n"; |
|||
foreach($this->globals as $name => $global) { |
|||
$code .= " $global[type] $name;\n"; |
|||
} |
|||
$code.= "ZEND_END_MODULE_GLOBALS({$this->name})\n"; |
|||
|
|||
$upname = strtoupper($this->name); |
|||
|
|||
$code.= "
|
|||
|
|||
#ifdef ZTS
|
|||
#define {$upname}_G(v) TSRMG({$this->name}_globals_id, zend_{$this->name}_globals *, v)
|
|||
#else
|
|||
#define {$upname}_G(v) ({$this->name}_globals.v)
|
|||
#endif
|
|||
|
|||
";
|
|||
|
|||
return $code; |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ license and authoers
|
|||
|
|||
function get_license() { |
|||
$code = "/*\n"; |
|||
switch($this->license) { |
|||
case "php": |
|||
$code.= |
|||
' +----------------------------------------------------------------------+ |
|||
| PHP Version 4 | |
|||
+----------------------------------------------------------------------+ |
|||
| Copyright (c) 1997-2002 The PHP Group | |
|||
+----------------------------------------------------------------------+ |
|||
| This source file is subject to version 2.02 of the PHP license, | |
|||
| that is bundled with this package in the file LICENSE, and is | |
|||
| available at through the world-wide-web at | |
|||
| http://www.php.net/license/2_02.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. | |
|||
'; |
|||
break; |
|||
|
|||
default: |
|||
$code.= |
|||
" +----------------------------------------------------------------------+
|
|||
| unkown license: '{$this->license}' | |
|||
+----------------------------------------------------------------------+ |
|||
";
|
|||
break; |
|||
} |
|||
|
|||
$code.= " +----------------------------------------------------------------------+\n"; |
|||
$prefix = "Authors: "; |
|||
foreach($this->users as $name => $user) { |
|||
$code .= sprintf(" | $prefix %-58s |\n", "$user[name] <$user[email]>"); |
|||
$prefix = str_repeat(" ",strlen($prefix)); |
|||
} |
|||
$code.= " +----------------------------------------------------------------------+\n"; |
|||
$code.= "*/\n\n"; |
|||
|
|||
$code.= "/* $ Id: $ */ \n\n"; |
|||
|
|||
return $code; |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ editor config footer
|
|||
|
|||
function editor_config_c() { |
|||
return ' |
|||
/* |
|||
* Local variables: |
|||
* tab-width: 4 |
|||
* c-basic-offset: 4 |
|||
* End: |
|||
* vim600: noet sw=4 ts=4 fdm=marker |
|||
* vim<600: noet sw=4 ts=4 |
|||
*/ |
|||
'; |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ header file
|
|||
|
|||
function write_header_file() { |
|||
$fp = fopen("{$this->name}/php_{$this->name}.h", "w"); |
|||
|
|||
$upname = strtoupper($this->name); |
|||
|
|||
fputs($fp, $this->get_license()); |
|||
fputs($fp, "#ifndef PHP_{$upname}_H\n"); |
|||
fputs($fp, "#define PHP_{$upname}_H\n\n"); |
|||
|
|||
fputs($fp, "#ifndef PHP_HAVE_{$upname}\n\n"); |
|||
|
|||
fputs($fp, "
|
|||
extern zend_module_entry {$this->name}_module_entry; |
|||
#define phpext_{$this->name}_ptr &{$this->name}_module_entry
|
|||
|
|||
#ifdef PHP_WIN32
|
|||
#define PHP_{$upname}_API __declspec(dllexport)
|
|||
#else
|
|||
#define PHP_{$upname}_API
|
|||
#endif
|
|||
|
|||
PHP_MINIT_FUNCTION({$this->name}); |
|||
PHP_MSHUTDOWN_FUNCTION({$this->name}); |
|||
PHP_RINIT_FUNCTION({$this->name}); |
|||
PHP_RSHUTDOWN_FUNCTION({$this->name}); |
|||
PHP_MINFO_FUNCTION({$this->name}); |
|||
|
|||
#ifdef ZTS
|
|||
#include \"TSRM.h\"
|
|||
#endif
|
|||
|
|||
");
|
|||
|
|||
fputs($fp, $this->generate_globals_h()); |
|||
|
|||
fputs($fp, "\n"); |
|||
|
|||
foreach($this->functions as $name => $function) { |
|||
fputs($fp, "PHP_FUNCTION($name);\n"); |
|||
} |
|||
|
|||
fputs($fp, "\n"); |
|||
|
|||
fputs($fp, "#endif /* PHP_HAVE_{$upname} */\n\n"); |
|||
fputs($fp, "#endif /* PHP_{$upname}_H */\n\n"); |
|||
|
|||
fputs($fp, $this->editor_config_c()); |
|||
|
|||
fclose($fp); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
// {{{ internal functions
|
|||
|
|||
function internal_functions_c() { |
|||
$code = "
|
|||
/* {{{ PHP_MINIT_FUNCTION */ |
|||
PHP_MINIT_FUNCTION({$this->name}) |
|||
{ |
|||
";
|
|||
|
|||
if(count($this->globals)) { |
|||
$code .= " ZEND_INIT_MODULE_GLOBALS({$this->name}, php_{$this->name}_init_globals, NULL)\n"; |
|||
} |
|||
|
|||
if(count($this->phpini)) { |
|||
$code .= " REGISTER_INI_ENTRIES();\n"; |
|||
} |
|||
|
|||
$code .="\n /* add your stuff here */\n"; |
|||
|
|||
$code .= "
|
|||
return SUCCESS; |
|||
} |
|||
/* }}} */ |
|||
|
|||
";
|
|||
|
|||
$code .= "
|
|||
/* {{{ PHP_MSHUTDOWN_FUNCTION */ |
|||
PHP_MSHUTDOWN_FUNCTION({$this->name}) |
|||
{ |
|||
";
|
|||
|
|||
if(count($this->phpini)) { |
|||
$code .= " UNREGISTER_INI_ENTRIES();\n"; |
|||
} |
|||
|
|||
$code .="\n /* add your stuff here */\n"; |
|||
|
|||
$code .= "
|
|||
return SUCCESS; |
|||
} |
|||
/* }}} */ |
|||
|
|||
";
|
|||
|
|||
$code .= "
|
|||
/* {{{ PHP_RINIT_FUNCTION */ |
|||
PHP_RINIT_FUNCTION({$this->name}) |
|||
{ |
|||
/* add your stuff here */ |
|||
|
|||
return SUCCESS; |
|||
} |
|||
/* }}} */ |
|||
|
|||
";
|
|||
|
|||
$code .= "
|
|||
/* {{{ PHP_RSHUTDOWN_FUNCTION */ |
|||
PHP_RSHUTDOWN_FUNCTION({$this->name}) |
|||
{ |
|||
/* add your stuff here */ |
|||
|
|||
return SUCCESS; |
|||
} |
|||
/* }}} */ |
|||
|
|||
";
|
|||
|
|||
$code .= "
|
|||
/* {{{ PHP_MINFO_FUNCTION */ |
|||
PHP_MINFO_FUNCTION({$this->name}) |
|||
{ |
|||
php_info_print_table_start(); |
|||
php_info_print_table_header(2, \"{$this->name} support\", \"enabled\");
|
|||
php_info_print_table_end(); |
|||
|
|||
/* add your stuff here */ |
|||
";
|
|||
|
|||
if(count($this->phpini)) { |
|||
$code .= "\n DISPLAY_INI_ENTRIES();"; |
|||
} |
|||
$code .= "
|
|||
} |
|||
/* }}} */ |
|||
|
|||
";
|
|||
|
|||
return $code; |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
|
|||
// {{{ public functions
|
|||
|
|||
function public_functions_c() { |
|||
$code = ""; |
|||
|
|||
foreach ($this->functions as $name => $func) { |
|||
|
|||
$code .= "\n/* {{{ func {$func->returns} {$func->name}("; |
|||
if (isset($func->params)) { |
|||
foreach ($func->params as $key => $param) { |
|||
if (!empty($param['optional'])) $code.=" ["; |
|||
if ($key) $code.=", "; |
|||
$code .= $param['type']." "; |
|||
$code .= isset($param['name']) ? $param['name'] : "par_$key"; |
|||
} |
|||
} |
|||
for ($n=$func->optional; $n>0; $n--) { |
|||
$code .= "]"; |
|||
} |
|||
$code .= ")\n "; |
|||
if(!empty($func->summary)) $code .= $func->summary; |
|||
$code .= " */\n"; |
|||
|
|||
$code .= "PHP_FUNCTION({$func->name})\n"; |
|||
$code .= "{\n"; |
|||
$code .= "\tint argc = ZEND_NUM_ARGS();\n\n"; |
|||
|
|||
if (isset($func->params)) { |
|||
$arg_string=""; |
|||
$arg_pointers=array(); |
|||
$optional=false; |
|||
$res_fetch=""; |
|||
|
|||
foreach ($func->params as $key => $param) { |
|||
$name = isset($param['name']) ? $param['name'] : "par_$key"; |
|||
$arg_pointers[]="&$name"; |
|||
if(isset($param['optional'])&&!$optional) { |
|||
$optional=true; |
|||
$arg_string.="|"; |
|||
} |
|||
|
|||
switch($param['type']) { |
|||
case "void": |
|||
break; |
|||
|
|||
case "bool": |
|||
$arg_string.="b"; |
|||
$code .= "\tzend_bool $name = 0;\n"; |
|||
break; |
|||
|
|||
case "int": |
|||
$arg_string.="l"; |
|||
$code .= "\tlong $name = 0;\n"; |
|||
break; |
|||
|
|||
case "float": |
|||
$arg_string.="d"; |
|||
$code .= "\tdouble $name = 0.0;\n"; |
|||
break; |
|||
|
|||
case "string": |
|||
$arg_string.="s"; |
|||
$code .= "\tchar * $name = NULL;\n"; |
|||
$code .= "\tint {$name}_len = 0;\n"; |
|||
$arg_pointers[]="&{$name}_len"; |
|||
break; |
|||
|
|||
case "array": |
|||
$arg_string.="a"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
break; |
|||
|
|||
case "object": |
|||
$arg_string.="o"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
break; |
|||
|
|||
case "resource": |
|||
$arg_string.="r"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
$code .= "\tint * {$name}_id = -1;\n"; |
|||
$arg_pointers[]="&{$name}_id"; |
|||
$res_fetch.="\tif ($name) {\n" |
|||
."\t\tZEND_FETCH_RESOURCE(???, ???, $name, {$name}_id, \"???\", ???_rsrc_id);\n" |
|||
."\t}\n"; |
|||
break; |
|||
|
|||
case "mixed": |
|||
$arg_string.="z"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
$code .= "\n\tif (zend_parse_parameters(argc TSRMLS_CC, \"$arg_string\", ".join(", ",$arg_pointers).") == FAILURE) return;\n";
|
|||
if($res_fetch) $code.="\n$res_fetch\n"; |
|||
} else { |
|||
$code .= "\tif(argc>0) { WRONG_PARAM_COUNT; }\n"; |
|||
} |
|||
|
|||
$code .= "\n"; |
|||
|
|||
if (!empty($func->code)) { |
|||
$code .= $func->code."\n"; |
|||
} else { |
|||
$code .= "\tphp_error(E_WARNING, \"{$func->name}: not yet implemented\");\n\n"; |
|||
|
|||
switch($func->returns) { |
|||
case "void": |
|||
break; |
|||
|
|||
case "bool": |
|||
$code .= "\tRETURN_FALSE;\n"; |
|||
break; |
|||
|
|||
case "int": |
|||
$code .= "\tRETURN_LONG(0);\n"; |
|||
break; |
|||
|
|||
case "float": |
|||
$code .= "\tRETURN_DOUBLE(0.0);\n"; |
|||
break; |
|||
|
|||
case "string": |
|||
$code .= "\tRETURN_STRINGL(\"\", 0, 1);\n"; |
|||
break; |
|||
|
|||
case "array": |
|||
$code .= "\tarray_init(return_value);\n"; |
|||
break; |
|||
|
|||
case "object": |
|||
$code .= "\tobject_init(return_value)\n"; |
|||
break; |
|||
|
|||
case "resource": |
|||
$code .= "\t/* RETURN_RESOURCE(...); /*\n"; |
|||
break; |
|||
|
|||
case "mixed": |
|||
$code .= "\t/* RETURN_...(...); /*\n"; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
$code .= "}\n/* }}} */\n\n"; |
|||
} |
|||
|
|||
|
|||
return $code; |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
|
|||
// {{{ code file
|
|||
|
|||
function write_code_file() { |
|||
$fp = fopen("{$this->name}/{$this->name}.c", "w"); |
|||
|
|||
$upname = strtoupper($this->name); |
|||
|
|||
fputs($fp, $this->get_license()); |
|||
|
|||
fputs($fp, ' |
|||
#ifdef HAVE_CONFIG_H
|
|||
#include "config.h"
|
|||
#endif
|
|||
|
|||
#include <php.h>
|
|||
#include <php_ini.h>
|
|||
#include <ext/standard/info.h>
|
|||
|
|||
'); |
|||
fputs($fp, "#include \"php_{$this->name}.h\"\n\n"); |
|||
|
|||
if (!empty($this->globals)) { |
|||
fputs($fp, "ZEND_DECLARE_MODULE_GLOBALS({$this->name})\n\n"); |
|||
} |
|||
|
|||
fputs($fp, "/* {{{ {$this->name}_functions[] */\n"); |
|||
fputs($fp, "function_entry {$this->name}_functions[] = {\n"); |
|||
foreach($this->functions as $name => $function) { |
|||
fputs($fp, sprintf(" PHP_FE(%-20s, NULL)\n",$name)); |
|||
} |
|||
fputs($fp, "};\n/* }}} */\n\n"); |
|||
|
|||
fputs($fp, $this->generate_extension_entry()); |
|||
|
|||
fputs($fp, "\n/* {{{ globals and ini entries */\n"); |
|||
fputs($fp, $this->generate_globals_c()); |
|||
fputs($fp, "/* }}} */\n\n"); |
|||
|
|||
fputs($fp, $this->internal_functions_c()); |
|||
|
|||
fputs($fp, $this->public_functions_c()); |
|||
|
|||
fputs($fp, $this->editor_config_c()); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
|
|||
function write_config_m4() { |
|||
|
|||
$upname = $this->name; |
|||
|
|||
$fp = fopen("{$this->name}/config.m4", "w"); |
|||
fputs($fp, |
|||
"dnl
|
|||
dnl \$ Id: \$ |
|||
dnl |
|||
|
|||
PHP_ARG_ENABLE({$this->name} , whether to enable {$this->name} functions, |
|||
[ --disable-{$this->name} Disable {$this->name} functions], yes) |
|||
|
|||
if test \"\$PHP_$upname\" != \"no\"; then
|
|||
AC_DEFINE(HAVE_$upname, 1, [ ]) |
|||
PHP_NEW_EXTENSION({$this->name}, {$this->name}.c, \$ext_shared) |
|||
fi |
|||
");
|
|||
fclose($fp); |
|||
} |
|||
|
|||
// }}}
|
|||
|
|||
} |
|||
|
|||
?>
|
|||
@ -0,0 +1,38 @@ |
|||
<?php |
|||
|
|||
class php_constant extends php_element { |
|||
function php_constant($name, $value, $type="string", $desc="") { |
|||
$this->name = $name; |
|||
$this->value= $value; |
|||
$this->type = $type; |
|||
$this->desc = $desc; |
|||
} |
|||
|
|||
function c_code() { |
|||
switch($this->type) { |
|||
case "integer": |
|||
return "REGISTER_LONG_CONSTANT(\"{$this->name}\", {$this->value}, 0);\n"; |
|||
|
|||
case "float": |
|||
return "REGISTER_DOUBLE_CONSTANT(\"{$this->name}\", {$this->value}, 0);\n"; |
|||
|
|||
case "string": |
|||
return "REGISTER_STRING_CONSTANT(\"{$this->name}\", \"$value\", ".strlen($this->value).", 0);\n";
|
|||
} |
|||
} |
|||
|
|||
function docbook_xml() { |
|||
return trim("
|
|||
<row> |
|||
<entry> |
|||
<constant id='constant".strtolower(str_replace("_","-",$this->name))."'>$name</constant> |
|||
(<link linkend='language.types.integer'>integer</link>) |
|||
</entry> |
|||
<entry>{$this->value}</entry> |
|||
<entry>{$this->desc}</entry> |
|||
</row> |
|||
")."\n";
|
|||
} |
|||
} |
|||
|
|||
?>
|
|||
@ -0,0 +1,74 @@ |
|||
<?php |
|||
|
|||
class php_element { |
|||
function is_type($name) { |
|||
$types = array("void" => "void", |
|||
"bool" => "bool", |
|||
"boolean" => "bool", |
|||
"int" => "int", |
|||
"integer" => "int", |
|||
"float" => "float", |
|||
"double" => "float", |
|||
"real" => "float", |
|||
"string" => "string", |
|||
"array" => "array", |
|||
"object" => "object", |
|||
"resource" => "resource", |
|||
"mixed" => "mixes", |
|||
); |
|||
|
|||
if(isset($types[$name])) { |
|||
return $types[$name]; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
function is_name($name) { |
|||
if(ereg("[a-zA-Z0-9_]",$name)) { |
|||
// TODO reserved words
|
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
|
|||
function c_code() { |
|||
return ""; |
|||
} |
|||
|
|||
function h_code() { |
|||
return ""; |
|||
} |
|||
|
|||
function docbook_xml() { |
|||
return ""; |
|||
} |
|||
|
|||
function docbook_editor_footer($level=3) { |
|||
return ' |
|||
<!-- Keep this comment at the end of the file |
|||
Local variables: |
|||
mode: sgml |
|||
sgml-omittag:t |
|||
sgml-shorttag:t |
|||
sgml-minimize-attributes:nil |
|||
sgml-always-quote-attributes:t |
|||
sgml-indent-step:1 |
|||
sgml-indent-data:t |
|||
indent-tabs-mode:nil |
|||
sgml-parent-document:nil |
|||
sgml-default-dtd-file:"'.str_repeat("../",$level).'manual.ced" |
|||
sgml-exposed-tags:nil |
|||
sgml-local-catalogs:nil |
|||
sgml-local-ecat-files:nil |
|||
End: |
|||
vim600: syn=xml fen fdm=syntax fdl=2 si |
|||
vim: et tw=78 syn=sgml |
|||
vi: ts=1 sw=1 |
|||
--> |
|||
'; |
|||
} |
|||
} |
|||
|
|||
?>
|
|||
@ -0,0 +1,210 @@ |
|||
<?php |
|||
|
|||
class php_function extends php_element { |
|||
// all known php types
|
|||
function php_function($name, $summary, $proto, $desc="", $code="") { |
|||
$this->name = $name; |
|||
$this->summary = $summary; |
|||
$this->parse_proto($proto); |
|||
$this->desc = empty($desc) ? "&warn.undocumented.func;" : $desc; |
|||
$this->code = $code; |
|||
} |
|||
|
|||
function parse_proto($proto) { |
|||
// 'tokenize' it
|
|||
$len=strlen($proto); |
|||
$name=""; |
|||
$tokens=array(); |
|||
for($n=0;$n<$len;$n++) { |
|||
$char = $proto{$n}; |
|||
if(ereg("[a-zA-Z0-9_]",$char)) { |
|||
$name.=$char; |
|||
} else { |
|||
if($name) $tokens[]=$name; |
|||
$name=""; |
|||
if(trim($char)) $tokens[]=$char; |
|||
} |
|||
} |
|||
if($name) $tokens[]=$name; |
|||
|
|||
$n=0; |
|||
$opts=0; |
|||
$params=array(); |
|||
$return_type = ($this->is_type($tokens[$n])) ? $tokens[$n++] : "void"; |
|||
if(! $this->is_name($tokens[$n])) die("$tokens[$n] is not a valid function name"); |
|||
$function_name = $tokens[$n++]; |
|||
if($tokens[$n]!='(') die("'(' expected instead of '$tokens[$n]'"); |
|||
if($tokens[++$n]!=')') { |
|||
for($param=0;$tokens[$n];$n++,$param++) { |
|||
if($tokens[$n]=='[') { |
|||
$params[$param]['optional']=true; |
|||
$opts++; |
|||
$n++; |
|||
if($param>0) { |
|||
if ($tokens[$n]!=',') die("',' expected after '[' instead of $token[$n]"); |
|||
$n++; |
|||
} |
|||
} |
|||
if(!$this->is_type($tokens[$n])) die("type name expected instead of $tokens[$n]"); |
|||
$params[$param]['type']=$tokens[$n]; |
|||
$n++; |
|||
if($this->is_name($tokens[$n])) { |
|||
$params[$param]['name']=$tokens[$n]; |
|||
$n++; |
|||
} |
|||
if($tokens[$n]=='[') { |
|||
$n--; |
|||
continue; |
|||
} |
|||
if($tokens[$n]==',') continue; |
|||
if($tokens[$n]==']') break; |
|||
if($tokens[$n]==')') break; |
|||
} |
|||
} |
|||
$numopts=$opts; |
|||
while($tokens[$n]==']') { |
|||
$n++; |
|||
$opts--; |
|||
} |
|||
if($opts!=0) die ("'[' / ']' count mismatch"); |
|||
if($tokens[$n] != ')') die ("')' expected instead of $tokens[$n]"); |
|||
|
|||
$this->name = $function_name; |
|||
$this->returns = $return_type; |
|||
$this->params = $params; |
|||
$this->optional = $numopts; |
|||
} |
|||
|
|||
function c_code() { |
|||
$code .= "\n/* {{{ proto {$this->returns} {$this->name}("; |
|||
if(isset($this->params)) { |
|||
foreach($this->params as $param) { |
|||
if(!empty($param['optional'])) |
|||
$code.=" ["; |
|||
if($key) |
|||
$code.=", "; |
|||
$code .= $param['type']." "; |
|||
$code .= $param['name']; |
|||
} |
|||
} |
|||
for($n=$this->optional; $n>0; $n--) { |
|||
$code .= "]"; |
|||
} |
|||
$code .= ")\n "; |
|||
if(!empty($this->summary)) { |
|||
$code .= $this->summary; |
|||
} |
|||
$code .= " */\n"; |
|||
$code .= "PHP_FUNCTION({$this->name})\n"; |
|||
$code .= "{\n"; |
|||
$code .= "\tint argc = ZEND_NUM_ARGS();\n\n"; |
|||
if(isset($this->params)) { |
|||
$arg_string=""; |
|||
$arg_pointers=array(); |
|||
$optional=false; |
|||
$res_fetch=""; |
|||
foreach($this->params as $param) { |
|||
$name = $param['name']; |
|||
$arg_pointers[]="&$name"; |
|||
if(isset($param['optional'])&&!$optional) { |
|||
$optional=true; |
|||
$arg_string.="|"; |
|||
} |
|||
switch($param['type']) { |
|||
//case "void":
|
|||
case "bool": |
|||
$arg_string.="b"; |
|||
$code .= "\tzend_bool $name = 0;\n"; |
|||
break; |
|||
case "int": |
|||
$arg_string.="l"; |
|||
$code .= "\tlong $name = 0;\n"; |
|||
break; |
|||
case "float": |
|||
$arg_string.="d"; |
|||
$code .= "\tdouble $name = 0.0;\n"; |
|||
break; |
|||
case "string": |
|||
$arg_string.="s"; |
|||
$code .= "\tchar * $name = NULL;\n"; |
|||
$code .= "\tint {$name}_len = 0;\n"; |
|||
$arg_pointers[]="&{$name}_len"; |
|||
break; |
|||
case "array": |
|||
$arg_string.="a"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
break; |
|||
case "object": |
|||
$arg_string.="o"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
break; |
|||
case "resource": |
|||
$arg_string.="r"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
$code .= "\tint * {$name}_id = -1;\n"; |
|||
$arg_pointers[]="&{$name}_id"; |
|||
$res_fetch.="\tif ($name) {\n" |
|||
."\t\tZEND_FETCH_RESOURCE(???, ???, $name, {$name}_id, \"???\", ???_rsrc_id);\n" |
|||
."\t}\n"; |
|||
break; |
|||
case "mixed": |
|||
$arg_string.="z"; |
|||
$code .= "\tzval * $name = NULL;\n"; |
|||
break; |
|||
} |
|||
} |
|||
$code .= "\n\tif (zend_parse_parameters(argc TSRMLS_CC, \"$arg_string\", ".join(", ",$arg_pointers).") == FAILURE) return;\n";
|
|||
if($res_fetch) $code.="\n$res_fetch\n"; |
|||
} else { |
|||
$code .= "\tif(argc>0) { WRONG_PARAM_COUNT; }\n\n"; |
|||
} |
|||
$code .= "\tphp_error(E_WARNING, \"{$this->name}: not yet implemented\");\n"; |
|||
$code .= "}\n/* }}} */\n\n"; |
|||
|
|||
return $code; |
|||
} |
|||
|
|||
function docbook_xml() { |
|||
$xml = |
|||
'<?xml version="1.0" encoding="iso-8859-1"?>
|
|||
<!-- $Revision$ --> |
|||
<refentry id="function.'.strtolower(str_replace("_","-",$this->name)).'"> |
|||
<refnamediv> |
|||
<refname>'.$this->name.'</refname> |
|||
<refpurpose>'.$this->summary.'</refpurpose> |
|||
</refnamediv> |
|||
<refsect1> |
|||
<title>Description</title> |
|||
<methodsynopsis> |
|||
'; |
|||
|
|||
$xml .= " <type>{$this->returns}</type><methodname>{$this->name}</methodname>\n"; |
|||
if(empty($this->params)) { |
|||
$xml .= " <void/>\n"; |
|||
} else { |
|||
foreach($this->params as $key => $param) { |
|||
if(isset($param['optional'])) { |
|||
$xml .= " <methodparam choice='opt'>"; |
|||
} else { |
|||
$xml .= " <methodparam>"; |
|||
} |
|||
$xml .= "<type>$param[type]</type><parameter>$param[name]</parameter>"; |
|||
$xml .= "</methodparam>\n"; |
|||
} |
|||
} |
|||
|
|||
$xml .= |
|||
' </methodsynopsis> |
|||
<para> |
|||
'.$this->desc.' |
|||
</para> |
|||
</refsect1> |
|||
</refentry> |
|||
'; |
|||
$xml .= $this->docbook_editor_footer(4); |
|||
|
|||
return $xml; |
|||
} |
|||
} |
|||
|
|||
?>
|
|||
@ -0,0 +1,35 @@ |
|||
<?php |
|||
class xml_stream_callback_parser extends xml_stream_parser { |
|||
function xml_stream_callback_parser ($stream) { |
|||
$this->cdata = ""; |
|||
$this->tags = array(); |
|||
$this->attrs = array(); |
|||
|
|||
parent::xml_stream_parser($stream); |
|||
} |
|||
|
|||
function cdata($parser, $cdata) { |
|||
$this->cdata .= $cdata; |
|||
} |
|||
|
|||
function tag_open($parser, $tag, $attributes) { |
|||
array_push($this->tags, $tag); |
|||
array_push($this->attrs, $attributes); |
|||
} |
|||
|
|||
function tag_close($parser, $tag) { |
|||
$attributes = array_pop($this->attrs); |
|||
|
|||
for ($tags = $this->tags; count($tags); array_shift($tags)) { |
|||
$method = "handle_".join("_", $tags); |
|||
if(method_exists($this, $method)) { |
|||
$this->$method($attributes); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
$this->cdata = ""; |
|||
array_pop($this->tags); |
|||
} |
|||
} |
|||
?>
|
|||
@ -0,0 +1,42 @@ |
|||
<?php |
|||
class xml_stream_parser { |
|||
var $parser; |
|||
|
|||
function xml_stream_parser($stream) |
|||
{ |
|||
if(!is_resource($stream)) die("not a stream"); |
|||
if(get_resource_type($stream) != "stream") die("not a stream"); |
|||
|
|||
$this->parser = xml_parser_create(); |
|||
|
|||
xml_set_object($this->parser, $this); |
|||
xml_set_element_handler($this->parser, "tag_open", "tag_close"); |
|||
xml_set_character_data_handler($this->parser, "cdata"); |
|||
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); |
|||
|
|||
while(!feof($stream)) { |
|||
xml_parse($this->parser, fgets($stream), feof($stream)); |
|||
} |
|||
xml_parser_free($this->parser); |
|||
} |
|||
|
|||
function tag_open($parser, $tag, $attributes) |
|||
{ |
|||
var_dump($parser, $tag, $attributes); |
|||
} |
|||
|
|||
function cdata($parser, $cdata) |
|||
{ |
|||
var_dump($parser, $cdata); |
|||
} |
|||
|
|||
function tag_close($parser, $tag) |
|||
{ |
|||
var_dump($parser, $tag); |
|||
} |
|||
|
|||
function error($msg) { |
|||
die("$msg in line ".xml_get_current_line_number($this->parser)); |
|||
} |
|||
} // end of class xml
|
|||
?>
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue