$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>
';
<?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";
}
}
}
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 });