#!/usr/bin/awk -f
function gobble(s, x)
{
sub(/^ /, "", line)
match(line, "^" "(" s ")")
x = substr(line, 1, RLENGTH)
line = substr(line, RLENGTH+1)
return x
}
function convert(i, j, t)
{
type = argtypes[i,j]
name = argnames[i,j]
opt = optionals[i,j]
tabs = x = ""
for (i = 0; i < t; i++) { tabs = tabs "\t" }
if (type == "int" || type == "long") {
longs = longs "\tlong " name ";\n"
} else if (type == "bool" || type == "boolean") {
bools = bools "\tzend_bool " name ";\n"
} else if (type == "double" || type == "float") {
doubles = doubles "\tdouble " name ";\n"
} else if (type == "string") {
strings = strings "\tchar *" name " = NULL;\n"
ints = ints "\tint " name "_len;\n"
} else if (type == "array" || type == "object" || type == "mixed") {
zvals = zvals "\tzval *" name " = NULL;\n"
} else if (type == "resource" || type == "handle") {
zvals = zvals "\tzval *" name " = NULL;\n"
resources = resources "\tif (" name ") {\n" \
"\t\tZEND_FETCH_RESOURCE(???, ???, " name ", " name "_id, \"???\", ???_rsrc_id);\n\t}\n"
ints = ints "\tint " name "_id = -1;\n"
}
}
function comment(s)
{
if (i_know_what_to_do_shut_up_i_dont_need_your_help_mode) {
return
} else {
return s
}
}
BEGIN {
name = "[_A-Za-z][_A-Za-z0-9]*"
type = "int|long|double|float|string|bool|boolean|array|object|resource|handle|mixed|void"
spec = "l|l|d|d|s|b|b|a|o|r|r|z|"
num_funcs = 0
# create a map from type name to the spec
split(type, type_array, "\|")
split(spec, spec_array, "\|")
for (i in type_array) {
spec_map[type_array[i]] = spec_array[i]
}
if (xml && xml != "yes") {
xmldoc = xml
} else {
xmldoc = extname "/" extname ".xml"
}
xmlhead = "\n" \
"\n" \
" \n" \
" functions\n" \
" \n\n" \
" \n" \
" &warn.experimental;\n" \
" \n" \
" \n" \
" \n\n";
xmlfoot = " \n\n" \
"\n"
}
{
args_max = args_min = optional = i = spec_opt = 0
line = $0
spec_str = "\""
## php extension must use lower case function names.
## this will translate any capitalized letter to lowercase
## and warn the user
if (match(func_name,"[A-Z]") != 0) {
printf("NOTICE: lower casing function name '%s'\n",func_name)
func_name = tolower(func_name)
}
func_type = gobble(type);
func_name = gobble(name);
if (gobble("\\(")) {
if (gobble("\\[")) optional = 1
while (arg_type = gobble(type)) {
arg_name = gobble(name)
if(arg_type == "void") {
args_max = 0;
args_min = 0;
break;
} else {
argtypes[num_funcs,args_max] = arg_type
argnames[num_funcs,args_max] = arg_name
args_max++
if (optional) {
if (!spec_opt) {
spec_str = spec_str "|"
spec_opt = 1
}
optionals[num_funcs,i] = optional
} else {
args_min++
}
spec_str = spec_str spec_map[arg_type]
if (x = gobble("\\[")) {
optional++
}
y = gobble(",")
if (!x && y && optional) {
grouped_optional_param[num_funcs,i] = 1
}
i++
}
}
}
# if (x = gobble("\\)")) {
gobble("\\]* *\\)")
sub(/^[ \t]+/, "", line)
fcomments[num_funcs] = line
# }
spec_str = spec_str "\""
funcs[num_funcs] = func_name
types[num_funcs] = func_type
maxargs[num_funcs] = args_max
minargs[num_funcs] = args_min
specs[num_funcs] = spec_str
spec_opts[num_funcs] = spec_opt
num_funcs++
}
END {
if (xml) print xmlhead > xmldoc
for (i = 0; i < num_funcs; i++) {
compareargc = maxargs[i] - minargs[i]
closefetch = fetchargs = zvals = xmlparams = funcvals = resources = handleargs = closeopts = ""
ints = longs = doubles = strings = bools = zvals = ""
proto = "/* {{{ proto " types[i] " " funcs[i] "("
refid = funcs[i]
gsub(/_/, "-", refid)
xmlstr = " \n" \
" \n" \
" " funcs[i] "\n" \
" " fcomments[i] "\n" \
" \n" \
" \n" \
" Description\n" \
" \n" \
" \n" \
" " types[i] " " funcs[i] "\n"
if (maxargs[i]>0) {
fetchargs = "\tif (zend_parse_parameters("
ints = ints "\tint argc = ZEND_NUM_ARGS();\n"
fetchargs = fetchargs "argc TSRMLS_CC, " specs[i]
} else {
fetchargs = fetchargs "\tif (zend_parse_parameters_none() == FAILURE) {\n\t\treturn;\n\t}"
xmlparams = xmlparams " \n"
}
for (j = 0; j < maxargs[i]; j++) {
fetchargs = fetchargs ", "
fetchargs = fetchargs "&" argnames[i,j]
if (argtypes[i,j] == "string") {
fetchargs = fetchargs ", &" argnames[i,j] "_len"
}
xmlparams = xmlparams " " argtypes[i,j]
if (j > minargs[i]-1) {
if (!grouped_optional_param[i,j-1]) {
if (j > 0) proto = proto " "
proto = proto "["
closeopts = closeopts "]"
}
xmlparams = xmlparams "\n " \
argnames[i,j] \
"\n \n"
} else {
xmlparams = xmlparams \
" " \
argnames[i,j] \
"\n"
}
if (j > 0) proto = proto ", "
proto = proto argtypes[i,j] " " argnames[i,j]
convert(i, j, 1)
}
proto = proto closeopts ")\n " fcomments[i] " */\nPHP_FUNCTION(" funcs[i] ")\n{"
if (maxargs[i]>0) {
fetchargs = fetchargs ") == FAILURE)" closefetch " \n\t\treturn;\n"
}
funcvals = strings ints longs doubles bools zvals
xmlstr = xmlstr xmlparams \
" \n" \
" \n" \
" &warn.experimental.func;\n" \
" \n" \
" &warn.undocumented.func;\n" \
" \n" \
" \n" \
" \n"
print proto > stubfile
if (funcvals) print funcvals > stubfile
if (fetchargs) print fetchargs > stubfile
if (resources) {
print resources > stubfile
if (!stubs) print "" > extname "/function_warning"
}
if (!i_know_what_to_do_shut_up_i_dont_need_your_help_mode) {
print "\tphp_error(E_WARNING, \"" funcs[i] ": not yet implemented\");" > stubfile
}
print "}\n/* }}} */\n" > stubfile
if (stubs) {
h_stubs = h_stubs "PHP_FUNCTION(" funcs[i] ");\n"
c_stubs = c_stubs "\tPHP_FE(" funcs[i] ",\tNULL)\n"
} else {
print "PHP_FUNCTION(" funcs[i] ");" > extname "/function_declarations"
print "\tPHP_FE(" funcs[i] ",\tNULL)" > extname "/function_entries"
}
if (xml) print xmlstr > xmldoc
}
if (stubs) {
print "\n/* ----------------------------------------------------------- */\n" > stubfile
print c_stubs > stubfile
print "\n/* ----------------------------------------------------------- */\n" > stubfile
print h_stubs > stubfile
}
if (xml) print xmlfoot > xmldoc
}
#
# Local variables:
# tab-width: 2
# c-basic-offset: 2
# End: