]> granicus.if.org Git - php/commitdiff
- Automatically generate C code to handle arguments passed to a PHP function
authorJouni Ahto <jah@php.net>
Sat, 10 Jun 2000 03:53:11 +0000 (03:53 +0000)
committerJouni Ahto <jah@php.net>
Sat, 10 Jun 2000 03:53:11 +0000 (03:53 +0000)
  based on function proto.
# Very cool! Try yourself, put for example the following line in file funcs:
# bool drawtext(string text, resource font, int x, int y [, resource color])
# and then run ./ext_skel foobar /full/path/to/funcs and then look at
# foobar.c...

ext/ext_skel
ext/skeleton/create_stubs [new file with mode: 0755]

index 3204ea57f3cd1a66b7f5ade4495b37174574a6c7..3fc90dc12a0b85b5d749f9f0297ebe590e9e939d 100755 (executable)
@@ -3,7 +3,8 @@
 extname="$1"
 EXTNAME=`echo $1|tr a-z A-Z`
 if [ ! -z $2 -a -r $2 ]; then
-    functions=`cat $2`
+    functions=$2
+    echo=$2
 fi
 
 givup() {
@@ -12,7 +13,7 @@ givup() {
 }
 
 if test "$extname" = ""; then
-       givup "usage: $0 extension-name [function-names]"
+       givup "usage: $0 extension-name [/full/path/to/function-list]"
 fi
 
 if test -d "$extname" ; then
@@ -20,6 +21,7 @@ if test -d "$extname" ; then
 fi
 
 test -f ext_skel || givup "ext_skel must be in the current directory"
+test -d skeleton || givup "subdirectory skeleton does not exist or is not directory"
 
 if echo '\c' | grep -s c >/dev/null 2>&1
 then
@@ -39,33 +41,8 @@ mkdir $extname || givup "Cannot create directory $extname"
 cd $extname
 chmod 755 .
 
-touch function_entries
-touch function_declarations
-touch function_stubs
-
-if [ $2 ] ; then
-    cat > function_stubs <<EOF
-/* Don't forget to remove the '#'-mark before protos when you have finished
-   with your function, so PHP's documentation system recognizes it. And
-   you really documented your function, didn't you?
-*/
-
-EOF
-    for f in $functions; do
-       $ECHO_E "\tPHP_FE($f,\tNULL)" >> function_entries
-       $ECHO_E "PHP_FUNCTION($f);" >> function_declarations
-       cat >> function_stubs <<EOF
-
-/* {{{ #proto $f()
-   */
-PHP_FUNCTION($f)
-{
-    php_error(E_WARNING, "$f: not yet implemented");
-}
-/* }}} */
-
-EOF
-    done
+if [ ! -z $functions ]; then
+    cat $functions | awk -f ../skeleton/create_stubs
 fi
 
 $ECHO_N "Creating basic files:$ECHO_C"
@@ -148,9 +125,11 @@ cat ../skeleton/skeleton.php | sed \
 -e "s/extname/$extname/g" \
 > $extname.php
 
-rm function_entries
-rm function_declarations
-rm function_stubs
+if [ ! -z $functions ]; then
+    rm function_entries
+    rm function_declarations
+    rm function_stubs
+fi
 
 chmod 644 *
 
diff --git a/ext/skeleton/create_stubs b/ext/skeleton/create_stubs
new file mode 100755 (executable)
index 0000000..986bdfb
--- /dev/null
@@ -0,0 +1,137 @@
+#!/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(t, n)
+{
+       if (t == "int") x = "convert_to_long_ex(" n ");\n"
+       else if (t == "double") x = "convert_to_double_ex(" n ");\n"
+       else if (t == "string") x = "convert_to_string_ex(" n ");\n"
+       else if (t == "array") x = "convert_to_array_ex(" n ");\n"
+       else if (t == "resource") {
+               x = "/* " n ": fetching resources already handled. */\n"
+               resources = resources "\tZEND_FETCH_RESOURCE(???, ???, " n ", " n "_id, \"???\", ???G());\n"
+               funcvals = funcvals "\tint " n "_id = -1;\n"
+       }
+       else x = "/* You must write your own code here to handle argument " n ". */\n"
+       return x
+}
+
+BEGIN {
+       name = "[_A-Za-z][_A-Za-z0-9]*"
+       type = "int|double|string|bool|array|object|resource|mixed|void"
+       num_funcs = 0
+}
+
+{
+       args_max = args_min = optional = 0
+       line = $0
+
+       func_type = gobble(type);
+       func_name = gobble(name);
+
+       if (gobble("\\(")) {
+               if (gobble("\\[")) optional = 1
+               while (arg_type = gobble(type)) {
+                       arg_name = gobble(name)
+                       argtypes[num_funcs,args_max] = arg_type
+                       argnames[num_funcs,args_max] = arg_name
+
+                       args_max++
+                       if (!optional) args_min++
+
+                       if (gobble("\\[")) optional = 1
+                       gobble(",")
+               }
+       }
+
+       funcs[num_funcs]   = func_name
+       types[num_funcs]   = func_type
+       maxargs[num_funcs] = args_max
+       minargs[num_funcs] = args_min
+
+       num_funcs++
+}
+
+END {
+       for (i = 0; i < num_funcs; i++) {
+               
+               useswitch = maxargs[i] - minargs[i]
+               funcvals = resources = handleargs = ""
+
+               proto = "/* {{{ #proto " types[i] " " funcs[i] "("
+
+               if (maxargs[i]) {
+                       zvals = "\tzval "
+                       if (useswitch) {
+                               funcvals = "\tint argc;\n"
+                               fetchargs = "\targc = ZEND_NUM_ARGS();\n\tif (argc < " minargs[i] " || argc > " maxargs[i] " || zend_get_parameters_ex(argc, "
+                       } else {
+                               fetchargs = "\tif (ZEND_NUM_ARGS() != " maxargs[i] " || zend_get_parameters_ex(" maxargs[i] ", "
+                       }
+               }
+
+               for (j = 0; j < maxargs[i]; j++) {
+
+                       if (j) {
+                               zvals = zvals ", "
+                               fetchargs = fetchargs ", "
+                       }
+
+                       zvals = zvals "**" argnames[i,j]
+                       fetchargs = fetchargs "&" argnames[i,j]
+
+                       if (j > minargs[i]-1) {
+                               proto = proto "["
+                               closeopts = closeopts "]"
+                       }
+
+                       if (j) proto = proto ", "
+                       proto = proto argtypes[i,j] " " argnames[i,j]
+
+                       if (useswitch) {
+                               if (j > minargs[i]-1) {
+                                       handleargs = "\t\tcase " j+1 ";\n\t\t\t" convert(argtypes[i,j], argnames[i,j]) "\t\t\t/* Fall-through. */\n" handleargs
+                               } else if (j >= minargs[i]-1) {
+                                       handleargs = "\t\tcase " j+1 ";\n\t\t\t" convert(argtypes[i,j], argnames[i,j]) handleargs
+                               } else {
+                                       handleargs = "\t\t\t" convert(argtypes[i,j], argnames[i,j]) handleargs
+                               }
+                       } else {
+                               handleargs = handleargs "\t" convert(argtypes[i,j], argnames[i,j])
+                       }
+               }
+
+               proto = proto closeopts ")\n    */\nPHP_FUNCTION(" funcs[i] ")\n{"
+               if (maxargs[i]) {
+                       zvals = zvals ";"
+                       fetchargs = fetchargs ") == FAILURE) {\n\t\tWRONG_PARAM_COUNT();\n\t}\n"
+               }
+               if (resources ) funcvals = funcvals "\t???LS_FETCH();\n"
+               if (useswitch) handleargs = "\tswitch (argc) {\n" handleargs "\t\t\tbreak;\n\t}"
+
+               print proto > "function_stubs"
+               if (zvals) print zvals > "function_stubs"
+       if (funcvals) print funcvals > "function_stubs"
+               if (fetchargs) print fetchargs > "function_stubs"
+               if (resources) print resources > "function_stubs"
+               if (handleargs) print handleargs > "function_stubs"
+               print "\n\tphp_error(E_WARNING, \"" funcs[i] ": not yet implemented\");" > "function_stubs"
+               print "}\n/* }}} */\n" > "function_stubs"
+               print "PHP_FUNCTION(" funcs[i] ");" > "function_declarations"
+               print "\tPHP_FE(" funcs[i] ",\tNULL)" > "function_entries"
+       }
+}
+
+#
+# Local variables:
+# tab-width: 2
+# End:
+#