2003-02-19 10:07:22 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
class php_function extends php_element {
|
|
|
|
// all known php types
|
2003-02-19 16:02:45 +00:00
|
|
|
function php_function($name, $summary, $proto, $desc="", $code="", $role="") {
|
2003-02-19 10:07:22 +00:00
|
|
|
$this->name = $name;
|
|
|
|
$this->summary = $summary;
|
|
|
|
$this->desc = empty($desc) ? "&warn.undocumented.func;" : $desc;
|
|
|
|
$this->code = $code;
|
2003-02-19 16:02:45 +00:00
|
|
|
$this->role = empty($role) ? "public" : $role;
|
2003-02-28 06:37:05 +00:00
|
|
|
if($this->role === "public") $this->status = $this->parse_proto($proto);
|
2003-02-19 10:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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";
|
2003-02-28 06:37:05 +00:00
|
|
|
if(! $this->is_name($tokens[$n])) return("$tokens[$n] is not a valid function name");
|
2003-02-19 10:07:22 +00:00
|
|
|
$function_name = $tokens[$n++];
|
2003-03-15 22:34:32 +00:00
|
|
|
|
|
|
|
if($function_name != $this->name) {
|
|
|
|
return "proto function name is '$function_name' instead of '{$this->name}'";
|
|
|
|
}
|
|
|
|
|
2003-02-28 06:37:05 +00:00
|
|
|
if($tokens[$n]!='(') return("'(' expected instead of '$tokens[$n]'");
|
2003-02-19 10:07:22 +00:00
|
|
|
if($tokens[++$n]!=')') {
|
|
|
|
for($param=0;$tokens[$n];$n++,$param++) {
|
|
|
|
if($tokens[$n]=='[') {
|
|
|
|
$params[$param]['optional']=true;
|
|
|
|
$opts++;
|
|
|
|
$n++;
|
|
|
|
if($param>0) {
|
2003-02-28 06:37:05 +00:00
|
|
|
if ($tokens[$n]!=',') return("',' expected after '[' instead of '$token[$n]'");
|
2003-02-19 10:07:22 +00:00
|
|
|
$n++;
|
|
|
|
}
|
|
|
|
}
|
2003-02-28 06:37:05 +00:00
|
|
|
if(!$this->is_type($tokens[$n])) return("type name expected instead of '$tokens[$n]'");
|
2003-02-19 10:07:22 +00:00
|
|
|
$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--;
|
|
|
|
}
|
2003-02-28 06:37:05 +00:00
|
|
|
if($opts!=0) return ("'[' / ']' count mismatch");
|
|
|
|
if($tokens[$n] != ')') return("')' expected instead of '$tokens[$n]'");
|
2003-02-19 10:07:22 +00:00
|
|
|
|
|
|
|
$this->name = $function_name;
|
|
|
|
$this->returns = $return_type;
|
|
|
|
$this->params = $params;
|
|
|
|
$this->optional = $numopts;
|
2003-02-28 06:37:05 +00:00
|
|
|
|
|
|
|
return true;
|
2003-02-19 10:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function c_code() {
|
2003-02-19 16:02:45 +00:00
|
|
|
$code = "";
|
|
|
|
|
|
|
|
switch($this->role) {
|
|
|
|
case "public":
|
2003-02-19 10:07:22 +00:00
|
|
|
$code .= "\n/* {{{ proto {$this->returns} {$this->name}(";
|
|
|
|
if(isset($this->params)) {
|
2003-02-24 10:57:48 +00:00
|
|
|
foreach($this->params as $key => $param) {
|
2003-02-19 10:07:22 +00:00
|
|
|
if(!empty($param['optional']))
|
|
|
|
$code.=" [";
|
|
|
|
if($key)
|
|
|
|
$code.=", ";
|
|
|
|
$code .= $param['type']." ";
|
2003-02-24 10:57:48 +00:00
|
|
|
if($param['type'] !== 'void') {
|
|
|
|
$code .= $param['name'];
|
|
|
|
}
|
2003-02-19 10:07:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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";
|
2003-02-24 10:57:48 +00:00
|
|
|
if(isset($this->params) && count($this->params)) {
|
2003-02-19 10:07:22 +00:00
|
|
|
$arg_string="";
|
|
|
|
$arg_pointers=array();
|
|
|
|
$optional=false;
|
|
|
|
$res_fetch="";
|
|
|
|
foreach($this->params as $param) {
|
2003-02-24 10:57:48 +00:00
|
|
|
if($param["type"] === "void") continue;
|
2003-02-19 10:07:22 +00:00
|
|
|
$name = $param['name'];
|
|
|
|
$arg_pointers[]="&$name";
|
|
|
|
if(isset($param['optional'])&&!$optional) {
|
|
|
|
$optional=true;
|
|
|
|
$arg_string.="|";
|
|
|
|
}
|
|
|
|
switch($param['type']) {
|
|
|
|
case "bool":
|
|
|
|
$arg_string.="b";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " zend_bool $name = 0;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
case "int":
|
|
|
|
$arg_string.="l";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " long $name = 0;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
case "float":
|
|
|
|
$arg_string.="d";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " double $name = 0.0;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
case "string":
|
|
|
|
$arg_string.="s";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " char * $name = NULL;\n";
|
|
|
|
$code .= " int {$name}_len = 0;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
$arg_pointers[]="&{$name}_len";
|
|
|
|
break;
|
|
|
|
case "array":
|
|
|
|
$arg_string.="a";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " zval * $name = NULL;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
case "object":
|
|
|
|
$arg_string.="o";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " zval * $name = NULL;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
case "resource":
|
|
|
|
$arg_string.="r";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " zval * $name = NULL;\n";
|
|
|
|
$code .= " int * {$name}_id = -1;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
$arg_pointers[]="&{$name}_id";
|
2003-02-24 10:57:48 +00:00
|
|
|
$res_fetch.=" if ($name) {\n"
|
|
|
|
." ZEND_FETCH_RESOURCE(???, ???, $name, {$name}_id, \"???\", ???_rsrc_id);\n"
|
|
|
|
." }\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
case "mixed":
|
2003-02-28 06:37:05 +00:00
|
|
|
case "callback":
|
2003-02-19 10:07:22 +00:00
|
|
|
$arg_string.="z";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " zval * $name = NULL;\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-02-24 10:57:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(isset($arg_string) && strlen($arg_string)) {
|
|
|
|
$code .= " int argc = ZEND_NUM_ARGS();\n\n";
|
|
|
|
$code .= "\n if (zend_parse_parameters(argc TSRMLS_CC, \"$arg_string\", ".join(", ",$arg_pointers).") == FAILURE) return;\n";
|
|
|
|
if($res_fetch) $code.="\n$res_fetch\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
} else {
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " if (ZEND_NUM_ARGS()>0) { WRONG_PARAM_COUNT; }\n\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
}
|
2003-02-24 10:57:48 +00:00
|
|
|
|
|
|
|
$code .= " php_error(E_WARNING, \"{$this->name}: not yet implemented\");\n";
|
2003-02-19 10:07:22 +00:00
|
|
|
$code .= "}\n/* }}} */\n\n";
|
2003-02-19 16:02:45 +00:00
|
|
|
break;
|
|
|
|
case "internal":
|
|
|
|
if(!empty($this->code)) {
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " {\n";
|
2003-02-19 16:02:45 +00:00
|
|
|
$code .= $this->code."\n";
|
2003-02-24 10:57:48 +00:00
|
|
|
$code .= " }\n";
|
2003-02-19 16:02:45 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "private":
|
|
|
|
$code .= $this->code."\n";
|
|
|
|
break;
|
|
|
|
}
|
2003-02-19 10:07:22 +00:00
|
|
|
return $code;
|
|
|
|
}
|
|
|
|
|
|
|
|
function docbook_xml() {
|
|
|
|
$xml =
|
|
|
|
'<?xml version="1.0" encoding="iso-8859-1"?>
|
|
|
|
<!-- $Revision$ -->
|
|
|
|
<refentry id="function.'.strtolower(str_replace("_","-",$this->name)).'">
|
|
|
|
<refnamediv>
|
|
|
|
<refname>'.$this->name.'</refname>
|
|
|
|
<refpurpose>'.$this->summary.'</refpurpose>
|
|
|
|
</refnamediv>
|
|
|
|
<refsect1>
|
|
|
|
<title>Description</title>
|
|
|
|
<methodsynopsis>
|
|
|
|
';
|
|
|
|
|
|
|
|
$xml .= " <type>{$this->returns}</type><methodname>{$this->name}</methodname>\n";
|
|
|
|
if(empty($this->params)) {
|
|
|
|
$xml .= " <void/>\n";
|
|
|
|
} else {
|
|
|
|
foreach($this->params as $key => $param) {
|
|
|
|
if(isset($param['optional'])) {
|
|
|
|
$xml .= " <methodparam choice='opt'>";
|
|
|
|
} else {
|
|
|
|
$xml .= " <methodparam>";
|
|
|
|
}
|
|
|
|
$xml .= "<type>$param[type]</type><parameter>$param[name]</parameter>";
|
|
|
|
$xml .= "</methodparam>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$xml .=
|
|
|
|
' </methodsynopsis>
|
|
|
|
<para>
|
|
|
|
'.$this->desc.'
|
|
|
|
</para>
|
|
|
|
</refsect1>
|
|
|
|
</refentry>
|
|
|
|
';
|
|
|
|
$xml .= $this->docbook_editor_footer(4);
|
|
|
|
|
|
|
|
return $xml;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
?>
|