]> granicus.if.org Git - php/commitdiff
Resource handling fixed and improved:
authorHartmut Holzgraefe <hholzgra@php.net>
Wed, 23 Apr 2003 16:19:08 +0000 (16:19 +0000)
committerHartmut Holzgraefe <hholzgra@php.net>
Wed, 23 Apr 2003 16:19:08 +0000 (16:19 +0000)
- resources may have an additional type specifier in prototypes
- the 'alloc' attribute specifies whether to emalloc/efree
  the resource payload in generated code or not

Example code generation for function return types

Small docbook generation fixes in function documentation

scripts/ext_skel_ng/extension.dtd
scripts/ext_skel_ng/extension_parser.php
scripts/ext_skel_ng/php_function.php
scripts/ext_skel_ng/php_resource.php

index db8045f01e4c8932a0a6b1cf73288381d2becfa9..1c58466d0c2bbe877959b9db0a3ebd435c12645c 100644 (file)
@@ -91,5 +91,6 @@
 <!ATTLIST resource
   name       CDATA #REQUIRED
   payload    CDATA #IMPLIED
+       alloc      (yes|no) "no"
 >
 <!ELEMENT destruct (#PCDATA)>
\ No newline at end of file
index 418f5de90581c5c5bb4b22197047a1a49551bf21..d6fae956b814128f08cb999323d00f49bfeb6830 100644 (file)
 
                $this->resources[] = new php_resource($attr['name'], 
                                                                                                                                                                        @$attr['payload'], 
+                                                                                                                                                                       @$attr['alloc'], 
                                                                                                                                                                        @$this->resource_destruct, 
                                                                                                                                                                        @$this->resource_description);
 
index 33bdfbf038b7fe2b471efacdf0b91e1e1b2868d2..cb6a65ea8fd7e0c3ffdb28931462bfb572ad8c63 100644 (file)
                        $opts=0;
                        $params=array();
                        $return_type = ($this->is_type($tokens[$n])) ? $tokens[$n++] : "void";
-                       if(! $this->is_name($tokens[$n])) return("$tokens[$n] is not a valid function name");
                        $function_name = $tokens[$n++];
-
+                       if($return_type === "resource" && $tokens[$n] !== "(") {
+                               $return_subtype = $function_name;
+                               $function_name = $tokens[$n++];
+                       }
+                       if(! $this->is_name($function_name)) {
+                               return("$function_name is not a valid function name");
+                       }
                        if($function_name != $this->name) {
                                return "proto function name is '$function_name' instead of '{$this->name}'";
                        }
                                                $params[$param]['name']=$tokens[$n];
                                                $n++;
                                        }
+                                       if($params[$param]['type'] === "resource" && $this->is_name($tokens[$n])) {
+                                               $params[$param]['subtype'] = $params[$param]['name'];
+                                               $params[$param]['name'] = $tokens[$n];
+                                               $n++;
+                                       }
                                        if($tokens[$n]=='[') {
                                                $n--;
                                                continue;
                        
                        $this->name     = $function_name;
                        $this->returns  = $return_type;
+                       if(isset($return_subtype)) {
+                               $this->returns .= " $return_subtype";
+                       }
                        $this->params   = $params;
                        $this->optional = $numopts;
 
                        return true;
                }
 
-               function c_code() {
+               function c_code(&$extension) {
                        $code = "";
 
+                       $returns = explode(" ", $this->returns);
+
                        switch($this->role) {
                        case "public":
                        $code .= "\n/* {{{ proto {$this->returns} {$this->name}(";
                                        if($key) 
                                                $code.=", ";
                                        $code .= $param['type']." ";
+                                       if(isset($param['subtype'])) {
+                                               $code .= $param['subtype']." ";
+                                       }
                                        if($param['type'] !== 'void') {
                                          $code .= $param['name']; 
           }
                        $code .= " */\n";
                        $code .= "PHP_FUNCTION({$this->name})\n";
                        $code .= "{\n";
+
+                       if($returns[0] === "resource" && isset($returns[1])) {
+                               $resource = $extension->resources[$returns[1]];
+                               if($resource->alloc === "yes") {
+                                       $payload  = $resource->payload;
+                                       $code .= "\t$payload * return_res = ($payload *)emalloc(sizeof($payload));\n";
+                               }
+                       }
+
                        if(isset($this->params) && count($this->params)) {
                                $arg_string="";
                                $arg_pointers=array();
                                $optional=false;
                                $res_fetch="";
-                               foreach($this->params as $param) {
+                               foreach($this->params as $key => $param) {
           if($param["type"] === "void") continue;
                                        $name = $param['name']; 
                                        $arg_pointers[]="&$name";
                                        case "resource":
                                                $arg_string.="r";
                                                $code .= "  zval * $name = NULL;\n";
-                                               $code .= "  int * {$name}_id = -1;\n";
-                                               $arg_pointers[]="&{$name}_id";
-                                               $res_fetch.="  if ($name) {\n"
-                                                       ."    ZEND_FETCH_RESOURCE(???, ???, $name, {$name}_id, \"???\", ???_rsrc_id);\n"
-                                                       ."  }\n";
+                                               $code .= "  int {$name}_id = -1;\n";
+                                               // dummfug?                                             $arg_pointers[]="&{$name}_id";
+                                               if(isset($param['subtype'])) {
+                                                       $resource = $extension->resources[$param['subtype']];
+                                                       $varname = "res_{$name}";
+                                                       $code .= "  {$resource->payload} * $varname;\n";
+
+                                                       $res_fetch.="  if ($name) {\n"
+                                                               ."    ZEND_FETCH_RESOURCE($varname, {$resource->payload} *, &$name, {$name}_id, \"$param[subtype]\", le_$param[subtype]);\n"
+                                                               ."  }\n";
+                                               } else {
+                                                       $res_fetch.="  if ($name) {\n"
+                                                               ."    ZEND_FETCH_RESOURCE(???, ???, $name, {$name}_id, \"???\", ???_rsrc_id);\n"
+                                                               ."  }\n";
+                                               }
                                                break;
                                        case "mixed":
                                        case "callback":
                                $code .= "  if (ZEND_NUM_ARGS()>0) { WRONG_PARAM_COUNT; }\n\n";
                        }
 
-                       $code .= "  php_error(E_WARNING, \"{$this->name}: not yet implemented\");\n";
+                       if($this->code) {
+                               $code .= "\t{\n$this->code\t}\n"; // {...} for local variables ...
+                       } else {
+                               $code .= "  php_error(E_WARNING, \"{$this->name}: not yet implemented\"); RETURN_FALSE;\n\n";
+
+                               switch($returns[0]) {
+                               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":
+                                       if($returns[1]) {
+                                               $code .= "\tZEND_REGISTER_RESOURCE(return_value, return_res, le_$returns[1]);\n";
+                                       } else {
+                                               $code .= "\t/* RETURN_RESOURCE(...); /*\n";
+                                       }
+                                       break;
+                               
+                               case "mixed":
+                                       $code .= "\t/* RETURN_...(...); /*\n";                          
+                                       break;
+
+                               default: 
+                                       $code .= "\t/* UNKNOWN RETURN TYPE '$this->returns' /*\n";
+                                       break;
+                               }
+                       }
+                       
                        $code .= "}\n/* }}} */\n\n";
-                         break;
-                 case "internal":
+                       break;
+                 
+                       case "internal":
                                if(!empty($this->code)) {
                                        $code .= "    {\n";
                                        $code .= $this->code."\n";
                                        $code .= "    }\n";
                                }
                                break;
-               case "private":
+               
+                       case "private":
                                $code .= $this->code."\n";                              
                                break;
                  }
 ';
 
                        $xml .= "      <type>{$this->returns}</type><methodname>{$this->name}</methodname>\n";
-                       if(empty($this->params)) {
+                       if(empty($this->params) || $this->params[0]["type"]==="void") {
                                $xml .= "      <void/>\n";
                        } else {
                                foreach($this->params as $key => $param) {
                                }
                        }
 
+
+                       $desc = $this->desc;
+
+                       if(!strstr($this->desc,"<para>")) {
+                               $desc = "     <para>\n$desc     </para>\n";
+                       }
+
 $xml .= 
 '     </methodsynopsis>
-    <para>
-'.$this->desc.'
-    </para>
+'.$desc.'
    </refsect1>
   </refentry>
 ';
index 92949da5417049fb720eb2156f95176c721d8360..3f4984efaf580fe524a58961988400961fbd1ecb 100644 (file)
@@ -1,18 +1,15 @@
 <?php
 
        class php_resource extends php_element {
-               function php_resource($name, $payload, $destruct, $description) {
+               function php_resource($name, $payload, $alloc, $destruct, $description) {
                        $this->name = $name;
                        $this->payload = $payload;
+      $this->alloc = $alloc;
                        $this->destruct = $destruct;
                        $this->description = $description;
 
-                       if (empty($this->destruct) && strstr($this->payload, "*")) {
-                               $this->destruct = "  free(resource);\n";
-                       }
-
                        if(empty($this->payload)) {
-                               $this->payload = "int";
+                               $this->payload = "void";
                        }
                } 
                
@@ -38,23 +35,30 @@ le_{$this->name} = zend_register_list_destructors_ex({$this->name}_dtor,
                }
 
                function c_code() {
-                       return "
+                       $dtor = "
 int le_{$this->name};
 
 void {$this->name}_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
-  {$this->payload} resource = ({$this->payload})(rsrc->ptr);
+  {$this->payload} * resource = ({$this->payload} *)(rsrc->ptr);
 
   {$this->destruct}
-}
 ";
+
+      if ($this->alloc === "yes") {
+        $dtor .= "  efree(resource);\n";
+      }
+
+                       $dtor .= "}\n";
+
+      return $dtor;
                }
 
                function h_code() {
       $upname = strtoupper($this->name);
 
                        return "
-#define {$upname}_FETCH(r, z)   ZEND_FETCH_RESOURCE(r, {$this->payload}, z, -1, ${$this->name}, le_{$this->name }); \
+#define {$upname}_FETCH(r, z)   ZEND_FETCH_RESOURCE(r, {$this->payload} *, z, -1, ${$this->name}, le_{$this->name }); \
                                     if(!r) { RETURN_FALSE; }
 
 #define {$upname}_REGISTER(r)   ZEND_REGISTER_RESOURCE(return_value, r, le_{$this->name });