hholzgra Wed Feb 19 05:07:22 2003 EDT
Added files:
/php4/scripts/ext_skel_ng README ext_skel_ng.php extension.dtd
extension.xml extension_parser.php
php_constant.php php_element.php
php_function.php
xml_stream_callback_parser.php
xml_stream_parser.php
Log:
next generation ext_skel script - initial checkin
Index: php4/scripts/ext_skel_ng/ext_skel_ng.php
+++ php4/scripts/ext_skel_ng/ext_skel_ng.php
<?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();
?>
Index: php4/scripts/ext_skel_ng/extension.dtd
+++ php4/scripts/ext_skel_ng/extension.dtd
<!--
-->
<!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
>
Index: php4/scripts/ext_skel_ng/extension.xml
+++ php4/scripts/ext_skel_ng/extension.xml
<?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>[EMAIL PROTECTED]</email>
<role>lead</role>
</maintainer>
<maintainer>
<user>dummy</user>
<name>Crashtest Dummy</name>
<email>[EMAIL PROTECTED]</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>
Index: php4/scripts/ext_skel_ng/extension_parser.php
+++ php4/scripts/ext_skel_ng/extension_parser.php
<?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: 1.1 $ -->
<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 |
| [EMAIL PROTECTED] 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);
}
// }}}
}
?>
Index: php4/scripts/ext_skel_ng/php_constant.php
+++ php4/scripts/ext_skel_ng/php_constant.php
<?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";
}
}
?>
Index: php4/scripts/ext_skel_ng/php_element.php
+++ php4/scripts/ext_skel_ng/php_element.php
<?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
-->
';
}
}
?>
Index: php4/scripts/ext_skel_ng/php_function.php
+++ php4/scripts/ext_skel_ng/php_function.php
<?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: 1.1 $ -->
<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;
}
}
?>
Index: php4/scripts/ext_skel_ng/xml_stream_callback_parser.php
+++ php4/scripts/ext_skel_ng/xml_stream_callback_parser.php
<?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);
}
}
?>
Index: php4/scripts/ext_skel_ng/xml_stream_parser.php
+++ php4/scripts/ext_skel_ng/xml_stream_parser.php
<?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
?>
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php