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

Reply via email to