diff options
author | Hartmut Holzgraefe <hholzgra@php.net> | 2003-06-29 16:07:18 +0000 |
---|---|---|
committer | Hartmut Holzgraefe <hholzgra@php.net> | 2003-06-29 16:07:18 +0000 |
commit | f355c4c5bbd0d02b838a056c8e081ee6fcd1e0d0 (patch) | |
tree | cb7e62d66cdea0d59b6e8be2a0223c1d7c219a52 | |
parent | 913cec65517f11ebd972f920d1d320b853a175dd (diff) | |
download | php-git-f355c4c5bbd0d02b838a056c8e081ee6fcd1e0d0.tar.gz |
ok, re-adding this mostly un-maintained awk/sed/sh nightmare for now ...
-rw-r--r-- | README.EXT_SKEL | 196 | ||||
-rwxr-xr-x | ext/ext_skel | 284 | ||||
-rw-r--r-- | ext/ext_skel_win32.php | 52 | ||||
-rw-r--r-- | ext/skeleton/CREDITS | 1 | ||||
-rw-r--r-- | ext/skeleton/EXPERIMENTAL | 0 | ||||
-rwxr-xr-x | ext/skeleton/create_stubs | 289 | ||||
-rw-r--r-- | ext/skeleton/php_skeleton.h | 56 | ||||
-rw-r--r-- | ext/skeleton/skeleton.c | 167 | ||||
-rw-r--r-- | ext/skeleton/skeleton.dsp | 113 | ||||
-rw-r--r-- | ext/skeleton/skeleton.php | 19 | ||||
-rw-r--r-- | ext/skeleton/tests/001.phpt | 24 |
11 files changed, 1199 insertions, 2 deletions
diff --git a/README.EXT_SKEL b/README.EXT_SKEL index 261f72caf7..599e6997c4 100644 --- a/README.EXT_SKEL +++ b/README.EXT_SKEL @@ -1,2 +1,194 @@ -NOTE: ext_skel does no longer exist, it has been replaced - by the PEAR package PECL_Gen +(NOTE: you may also want to take a look at the pear package + PECL_Gen, a PHP-only alternative for this script that + supports way more extension writing tasks and is + supposed to replace ext_skel completely in the long run ...) + +WHAT IT IS + + It's a tool for automatically creating the basic framework for a PHP module + and writing C code handling arguments passed to your functions from a simple + configuration file. See an example at the end of this file. + +HOW TO USE IT + + Very simple. First, change to the ext/ directory of the PHP 4 sources. If + you just need the basic framework and will be writing all the code in your + functions yourself, you can now do + + ./ext_skel --extname=module_name + + and everything you need is placed in directory module_name. + + [ Note that GNU awk is likely required for this script to work. Debian + systems seem to default to using mawk, so you may need to change the + #! line in skeleton/create_stubs and the cat $proto | awk line in + ext_skel to use gawk explicitly. ] + + If you don't need to test the existence of any external header files, + libraries or functions in them, the module is already almost ready to be + compiled in PHP. Just remove 3 comments in your_module_name/config.m4, + change back up to PHP sources top directory, and do + + ./buildconf; ./configure --enable-module_name; make + + But if you already have planned the overall scheme of your module, what + functions it will contain, their return types and the arguments they take + (a very good idea) and don't want to bother yourself with creating function + definitions and handling arguments passed yourself, it's time to create a + function definitions file, which you will give as an argument to ext_skel + with option + + --proto=filename. + +FORMAT OF FUNCTION DEFINITIONS FILE + + All the definitions must be on one line. In it's simplest form, it's just + the function name, e.g. + + my_function + + but then you'll be left with an almost empty function body without any + argument handling. + + Arguments are given in parenthesis after the function name, and are of + the form 'argument_type argument_name'. Arguments are separated from each + other with a comma and optional space. Argument_type can be one of int, + bool, double, float, string, array, object or mixed. + + An optional argument is separated from the previous by an optional space, + then '[' and of course comma and optional space, like all the other + arguments. You should close a row of optional arguments with same amount of + ']'s as there where '['s. Currently, it does not harm if you forget to do it + or there is a wrong amount of ']'s, but this may change in the future. + + An additional short description may be added after the parameters. + If present it will be filled into the 'proto' header comments in the stubs + code and the <refpurpose> tag in the XML documentation. + + An example: + + my_function(int arg1, int arg2 [, int arg3 [, int arg4]]) this is my 1st + + Arguments arg3 and arg4 are optional. + + If possible, the function definition should also contain it's return type + in front of the definition. It's not actually used for any C code generating + purposes but PHP in-source documentation instead, and as such, very useful. + It can be any of int, double, string, bool, array, object, resource, mixed + or void. + + The file must contain nothing else but function definitions, no comments or + empty lines. + +OTHER OPTIONS + + --no-help + + By default, ext_skel creates both comments in the source code and a test + function to help first time module writers to get started and testing + configuring and compiling their module. This option turns off all such things + which may just annoy experienced PHP module coders. Especially useful with + + --stubs=file + + which will leave out also all module specific stuff and write just function + stubs with function value declarations and passed argument handling, and + function entries and definitions at the end of the file, for copying and + pasting into an already existing module. + + --assign-params + --string-lens + + By default, function proto 'void foo(string bar)' creates the following: + ... + zval **bar; + ... (zend_get_parameters_ex() called in the middle...) + convert_to_string_ex(bar); + + Specifying both of these options changes the generated code to: + ... + zval **bar_arg; + int bar_len; + char *bar = NULL; + ... (zend_get_parameters_ex() called in the middle...) + convert_to_string_ex(bar_arg); + bar = Z_STRVAL_PP(bar_arg); + bar_len = Z_STRLEN_PP(bar_arg); + + You shouldn't have to ask what happens if you leave --string-lens out. If you + have to, it's questionable whether you should be reading this document. + + --with-xml[=file] + + Creates the basics for phpdoc .xml file. + + --full-xml + + Not implemented yet. When or if there will ever be created a framework for + self-contained extensions to use phpdoc system for their documentation, this + option enables it on the created xml file. + +CURRENT LIMITATIONS, BUGS AND OTHER ODDITIES + + Only arguments of types int, bool, double, float, string and array are + handled. For other types you must write the code yourself. And for type + mixed, it wouldn't even be possible to write anything, because only you + know what to expect. + + It can't handle correctly, and probably never will, variable list of + of arguments. (void foo(int bar [, ...]) + + Don't trust the generated code too much. It tries to be useful in most of + the situations you might encounter, but automatic code generation will never + beat a programmer who knows the real situation at hand. ext_skel is generally + best suited for quickly generating a wrapper for c-library functions you + might want to have available in PHP too. + + This program doesn't have a --help option. It has --no-help instead. + +EXAMPLE + + The following _one_ line + + bool my_drawtext(resource image, string text, resource font, int x, int y [, int color]) + + will create this function definition for you (note that there are a few + question marks to be replaced by you, and you must of course add your own + value definitions too): + +/* {{{ proto bool my_drawtext(resource image, string text, resource font, int x, int y[, int color]) + */ +PHP_FUNCTION(my_drawtext) +{ + zval **image, **text, **font, **x, **y, **color; + int argc; + int image_id = -1; + int font_id = -1; + + argc = ZEND_NUM_ARGS(); + if (argc < 5 || argc > 6 || zend_get_parameters_ex(argc, &image, &text, &font, &x, &y, &color) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(???, ???, image, image_id, "???", ???_rsrc_id); + ZEND_FETCH_RESOURCE(???, ???, font, font_id, "???", ???_rsrc_id); + + switch (argc) { + case 6: + convert_to_long_ex(color); + /* Fall-through. */ + case 5: + convert_to_long_ex(y); + convert_to_long_ex(x); + /* font: fetching resources already handled. */ + convert_to_string_ex(text); + /* image: fetching resources already handled. */ + break; + default: + WRONG_PARAM_COUNT; + } + + php_error(E_WARNING, "my_drawtext: not yet implemented"); +} +/* }}} */ + diff --git a/ext/ext_skel b/ext/ext_skel new file mode 100755 index 0000000000..3abf341bdf --- /dev/null +++ b/ext/ext_skel @@ -0,0 +1,284 @@ +#!/bin/sh + +givup() { + echo $* + exit 1 +} + +usage() { +echo "$0 --extname=module [--proto=file] [--stubs=file] [--xml[=file]]" +echo " [--skel=dir] [--full-xml] [--no-help]" +echo "" +echo " --extname=module module is the name of your extension" +echo " --proto=file file contains prototypes of functions to create" +echo " --stubs=file generate only function stubs in file" +echo " --xml generate xml documentation to be added to phpdoc-cvs" +echo " --skel=dir path to the skeleton directory" +echo " --full-xml generate xml documentation for a self-contained extension" +echo " (not yet implemented)" +echo " --no-help don't try to be nice and create comments in the code" +echo " and helper functions to test if the module compiled" +exit 1 +} + +if test $# = 0; then + usage +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --extname=?*) + extname=$optarg + EXTNAME=`echo $extname | tr "[:lower:]" "[:upper:]"` + ;; + --proto=?*) + proto=$optarg + ;; + --stubs=*) + stubs=yes + stubfile=$optarg + ;; + --xml) + xml="yes" + ;; + --xml=?*) + xml=$optarg + ;; + --full-xml) + full_xml="yes" + ;; + --no-help) + no_help="yes" + ;; + --skel=?*) + skel_dir=$optarg + ;; + *) + usage + ;; + esac + shift +done + +if test -d "$extname" ; then + givup "Directory $extname already exists." +fi + +if test -z "$skel_dir"; then + skel_dir="skeleton" +fi + +## convert skel_dir to full path +skel_dir=`cd $skel_dir && pwd` + +test -d $skel_dir || givup "directory $skel_dir does not exist or is not directory" + +if echo '\c' | grep -s c >/dev/null 2>&1 +then + ECHO_N="echo -n" + ECHO_C="" +else + ECHO_N="echo" + ECHO_C='\c' +fi + +if test -z "$stubs"; then + echo "Creating directory $extname" + stubfile=$extname"/function_stubs" + mkdir $extname || givup "Cannot create directory $extname" +fi + +if test -n "$proto"; then + cat $proto | awk -v extname=$extname -v stubs=$stubs -v stubfile=$stubfile -v xml=$xml -v full_xml=$full_xml -v i_know_what_to_do_shut_up_i_dont_need_your_help_mode=$no_help -f $skel_dir/create_stubs +fi + +if test -z "$stubs"; then + cd $extname + chmod 755 . + +$ECHO_N "Creating basic files:$ECHO_C" + +$ECHO_N " config.m4$ECHO_C" +cat >config.m4 <<eof +dnl \$Id\$ +dnl config.m4 for extension $extname + +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl If your extension references something external, use with: + +dnl PHP_ARG_WITH($extname, for $extname support, +dnl Make sure that the comment is aligned: +dnl [ --with-$extname Include $extname support]) + +dnl Otherwise use enable: + +dnl PHP_ARG_ENABLE($extname, whether to enable $extname support, +dnl Make sure that the comment is aligned: +dnl [ --enable-$extname Enable $extname support]) + +if test "\$PHP_$EXTNAME" != "no"; then + dnl Write more examples of tests here... + + dnl # --with-$extname -> check with-path + dnl SEARCH_PATH="/usr/local /usr" # you might want to change this + dnl SEARCH_FOR="/include/$extname.h" # you most likely want to change this + dnl if test -r \$PHP_$EXTNAME/\$SEARCH_FOR; then # path given as parameter + dnl ${EXTNAME}_DIR=\$PHP_$EXTNAME + dnl else # search default path list + dnl AC_MSG_CHECKING([for $extname files in default path]) + dnl for i in \$SEARCH_PATH ; do + dnl if test -r \$i/\$SEARCH_FOR; then + dnl ${EXTNAME}_DIR=\$i + dnl AC_MSG_RESULT(found in \$i) + dnl fi + dnl done + dnl fi + dnl + dnl if test -z "\$${EXTNAME}_DIR"; then + dnl AC_MSG_RESULT([not found]) + dnl AC_MSG_ERROR([Please reinstall the $extname distribution]) + dnl fi + + dnl # --with-$extname -> add include path + dnl PHP_ADD_INCLUDE(\$${EXTNAME}_DIR/include) + + dnl # --with-$extname -> check for lib and symbol presence + dnl LIBNAME=$extname # you may want to change this + dnl LIBSYMBOL=$extname # you most likely want to change this + + dnl PHP_CHECK_LIBRARY(\$LIBNAME,\$LIBSYMBOL, + dnl [ + dnl PHP_ADD_LIBRARY_WITH_PATH(\$LIBNAME, \$${EXTNAME}_DIR/lib, ${EXTNAME}_SHARED_LIBADD) + dnl AC_DEFINE(HAVE_${EXTNAME}LIB,1,[ ]) + dnl ],[ + dnl AC_MSG_ERROR([wrong $extname lib version or lib not found]) + dnl ],[ + dnl -L\$${EXTNAME}_DIR/lib -lm -ldl + dnl ]) + dnl + dnl PHP_SUBST(${EXTNAME}_SHARED_LIBADD) + + PHP_NEW_EXTENSION($extname, $extname.c, \$ext_shared) +fi +eof + + +$ECHO_N " .cvsignore$ECHO_C" +cat >.cvsignore <<eof +.deps +*.lo +*.la +eof + +$ECHO_N " $extname.c$ECHO_C" +echo "s/extname/$extname/g" > sedscript +echo "s/EXTNAME/$EXTNAME/g" >> sedscript +echo '/__function_entries_here__/r function_entries' >> sedscript +echo '/__function_stubs_here__/r function_stubs' >> sedscript +echo '/__header_here__/r ../../header' >> sedscript +echo '/__footer_here__/r ../../footer' >> sedscript +echo '/__function_entries_here__/D' >> sedscript +echo '/__function_stubs_here__/D' >> sedscript +echo '/__header_here__/D' >> sedscript +echo '/__footer_here__/D' >> sedscript +if [ ! -z "$no_help" ]; then + echo "/confirm_$extname_compiled/D" >> sedscript + echo '/Remove the following/,/^\*\//D' >> sedscript + echo 's/[[:space:]]\/\*.\+\*\///' >> sedscript + echo 's/^\/\*.*\*\/$//' >> sedscript + echo '/^[[:space:]]*\/\*/,/^[[:space:]]*\*\//D' >> sedscript +fi + +sed -f sedscript < $skel_dir/skeleton.c > $extname.c + + +$ECHO_N " php_$extname.h$ECHO_C" +echo "s/extname/$extname/g" > sedscript +echo "s/EXTNAME/$EXTNAME/g" >> sedscript +echo '/__function_declarations_here__/r function_declarations' >> sedscript +echo '/__header_here__/r ../../header' >> sedscript +echo '/__footer_here__/r ../../footer' >> sedscript +echo '/__function_declarations_here__/D' >> sedscript +echo '/__header_here__/D' >> sedscript +echo '/__footer_here__/D' >> sedscript +if [ ! -z "$no_help" ]; then + echo "/confirm_$extname_compiled/D" >> sedscript + echo 's/[[:space:]]\/\*.\+\*\///' >> sedscript + echo 's/^\/\*.*\*\/$//' >> sedscript + echo '/^[[:space:]]*\/\*/,/^[[:space:]]*\*\//D' >> sedscript +fi +sed -f sedscript <$skel_dir/php_skeleton.h > php_$extname.h + +$ECHO_N " CREDITS$ECHO_C" +echo "s/extname/$extname/g" > sedscript +sed -f sedscript <$skel_dir/CREDITS > CREDITS + +$ECHO_N " EXPERIMENTAL$ECHO_C" +echo "s/extname/$extname/g" > sedscript +sed -f sedscript <$skel_dir/EXPERIMENTAL > EXPERIMENTAL + +$ECHO_N " tests/001.phpt$ECHO_C" +mkdir tests || givup "Cannot create tests directory" +chmod 755 tests +sed -f sedscript <$skel_dir/tests/001.phpt > tests/001.phpt + +if test -z "$stubs" && test -z "$no_help"; then + $ECHO_N " $extname.php$ECHO_C" + sed \ + -e "s/extname/$extname/g" \ + <$skel_dir/skeleton.php \ + > $extname.php +fi + +rm sedscript + +if test -n "$proto"; then + if test -z "$stubs"; then + rm function_entries + rm function_declarations + rm function_stubs + fi + if test -f function_warning; then + rm function_warning + warning=" +NOTE! Because some arguments to functions were resources, the code generated +cannot yet be compiled without editing. Please consider this to be step 4.5 +in the instructions above. +" + fi +fi + +find . -type f | xargs chmod 644 +find . -type d | xargs chmod 755 +fi + +echo " [done]." + +if test -z "$no_help" && test -z "$stubs"; then + cat <<eof + +To use your new extension, you will have to execute the following steps: + +1. $ cd .. +2. $ vi ext/$extname/config.m4 +3. $ ./buildconf +4. $ ./configure --[with|enable]-$extname +5. $ make +6. $ ./php -f ext/$extname/$extname.php +7. $ vi ext/$extname/$extname.c +8. $ make + +Repeat steps 3-6 until you are satisfied with ext/$extname/config.m4 and +step 6 confirms that your module is compiled into PHP. Then, start writing +code and repeat the last two steps as often as necessary. +$warning +eof +fi diff --git a/ext/ext_skel_win32.php b/ext/ext_skel_win32.php new file mode 100644 index 0000000000..5036ad21d8 --- /dev/null +++ b/ext/ext_skel_win32.php @@ -0,0 +1,52 @@ +<?php +/* $Id$ */ + +if (php_sapi_name() != "cli") { + echo "Please run this script using the CLI version of PHP\n"; + exit; +} +/* + This script can be used on Win32 systems + + 1) Make sure you have CygWin installed + 2) Adjust the $cygwin_path to match your installation + 3) Change the environment cariable PATHEXT to include .PHP + 4) run ext_skel --ext_name=... + the first time you run this script you will be asked to + associate it with a program. chooses the CLI version of php. +*/ + +$cygwin_path = 'c:\cygwin\bin'; + +$path = getenv("PATH"); +putenv("PATH=$cygwin_path;$path"); + +array_shift($argv); +system("sh ext_skel " . implode(" ", $argv)); + +$extname = ""; +$skel = "skeleton"; +foreach($argv as $arg) { + if (strtolower(substr($arg, 0, 9)) == "--extname") { + $extname = substr($arg, 10); + } + if (strtolower(substr($arg, 0, 6)) == "--skel") { + $skel = substr($arg, 7); + } +} + +$fp = fopen("$skel/skeleton.dsp", "rb"); +if ($fp) { + $dsp_file = fread($fp, filesize("$skel/skeleton.dsp")); + fclose($fp); + + $dsp_file = str_replace("extname", $extname, $dsp_file); + $dsp_file = str_replace("EXTNAME", strtoupper($extname), $dsp_file); + $fp = fopen("$extname/$extname.dsp", "wb"); + if ($fp) { + fwrite($fp, $dsp_file); + fclose($fp); + } +} + +?>
\ No newline at end of file diff --git a/ext/skeleton/CREDITS b/ext/skeleton/CREDITS new file mode 100644 index 0000000000..58fc71019a --- /dev/null +++ b/ext/skeleton/CREDITS @@ -0,0 +1 @@ +extname
\ No newline at end of file diff --git a/ext/skeleton/EXPERIMENTAL b/ext/skeleton/EXPERIMENTAL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/ext/skeleton/EXPERIMENTAL diff --git a/ext/skeleton/create_stubs b/ext/skeleton/create_stubs new file mode 100755 index 0000000000..61957289d0 --- /dev/null +++ b/ext/skeleton/create_stubs @@ -0,0 +1,289 @@ +#!/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 = "<?xml version='1.0' encoding='iso-8859-1'?>\n" \ + "<!-- $Revision$ -->\n" \ + " <reference id=\"ref." extname "\">\n" \ + " <title> functions</title>\n" \ + " <titleabbrev></titleabbrev>\n\n" \ + " <partintro>\n" \ + " &warn.experimental;\n" \ + " <para>\n" \ + " </para>\n" \ + " </partintro>\n\n"; + + xmlfoot = " </reference>\n\n" \ + "<!-- Keep this comment at the end of the file\n" \ + "Local variables:\n" \ + "mode: sgml\n" \ + "sgml-omittag:t\n" \ + "sgml-shorttag:t\n" \ + "sgml-minimize-attributes:nil\n" \ + "sgml-always-quote-attributes:t\n" \ + "sgml-indent-step:1\n" \ + "sgml-indent-data:t\n" \ + "indent-tabs-mode:nil\n" \ + "sgml-parent-document:nil\n" \ + "sgml-default-dtd-file:\"../../manual.ced\"\n" \ + "sgml-exposed-tags:nil\n" \ + "sgml-local-catalogs:nil\n" \ + "sgml-local-ecat-files:nil\n" \ + "End:\n" \ + "vim600: syn=xml fen fdm=syntax fdl=2 si\n" \ + "vim: et tw=78 syn=sgml\n" \ + "vi: ts=1 sw=1\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 = " <refentry id=\"function." refid "\">\n" \ + " <refnamediv>\n" \ + " <refname>" funcs[i] "</refname>\n" \ + " <refpurpose>" fcomments[i] "</refpurpose>\n" \ + " </refnamediv>\n" \ + " <refsect1>\n" \ + " <title>Description</title>\n" \ + " <funcsynopsis>\n" \ + " <funcprototype>\n" \ + " <funcdef>" types[i] " <function>" funcs[i] "</function></funcdef>\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_NUM_ARGS() != 0) {\n\t\tWRONG_PARAM_COUNT;\n\t}" + xmlparams = xmlparams " <void/>\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 " <paramdef>" 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 <parameter><optional>" \ + argnames[i,j] \ + "</optional></parameter>\n </paramdef>\n" + } else { + xmlparams = xmlparams \ + " <parameter>" \ + argnames[i,j] \ + "</parameter></paramdef>\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 \ + " </funcprototype>\n" \ + " </funcsynopsis>\n" \ + " &warn.experimental.func;\n" \ + " <para>\n" \ + " &warn.undocumented.func;\n" \ + " </para>\n" \ + " </refsect1>\n" \ + " </refentry>\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: + diff --git a/ext/skeleton/php_skeleton.h b/ext/skeleton/php_skeleton.h new file mode 100644 index 0000000000..76ad225754 --- /dev/null +++ b/ext/skeleton/php_skeleton.h @@ -0,0 +1,56 @@ +/* __header_here__ */ + +#ifndef PHP_EXTNAME_H +#define PHP_EXTNAME_H + +extern zend_module_entry extname_module_entry; +#define phpext_extname_ptr &extname_module_entry + +#ifdef PHP_WIN32 +#define PHP_EXTNAME_API __declspec(dllexport) +#else +#define PHP_EXTNAME_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +PHP_MINIT_FUNCTION(extname); +PHP_MSHUTDOWN_FUNCTION(extname); +PHP_RINIT_FUNCTION(extname); +PHP_RSHUTDOWN_FUNCTION(extname); +PHP_MINFO_FUNCTION(extname); + +PHP_FUNCTION(confirm_extname_compiled); /* For testing, remove later. */ +/* __function_declarations_here__ */ + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + +ZEND_BEGIN_MODULE_GLOBALS(extname) + long global_value; + char *global_string; +ZEND_END_MODULE_GLOBALS(extname) +*/ + +/* In every utility function you add that needs to use variables + in php_extname_globals, call TSRM_FETCH(); after declaring other + variables used by that function, or better yet, pass in TSRMLS_CC + after the last function argument and declare your utility function + with TSRMLS_DC after the last declared argument. Always refer to + the globals in your function as EXTNAME_G(variable). You are + encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ + +#ifdef ZTS +#define EXTNAME_G(v) TSRMG(extname_globals_id, zend_extname_globals *, v) +#else +#define EXTNAME_G(v) (extname_globals.v) +#endif + +#endif /* PHP_EXTNAME_H */ + +/* __footer_here__ */ diff --git a/ext/skeleton/skeleton.c b/ext/skeleton/skeleton.c new file mode 100644 index 0000000000..021b76e789 --- /dev/null +++ b/ext/skeleton/skeleton.c @@ -0,0 +1,167 @@ +/* __header_here__ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_extname.h" + +/* If you declare any globals in php_extname.h uncomment this: +ZEND_DECLARE_MODULE_GLOBALS(extname) +*/ + +/* True global resources - no need for thread safety here */ +static int le_extname; + +/* {{{ extname_functions[] + * + * Every user visible function must have an entry in extname_functions[]. + */ +function_entry extname_functions[] = { + PHP_FE(confirm_extname_compiled, NULL) /* For testing, remove later. */ + /* __function_entries_here__ */ + {NULL, NULL, NULL} /* Must be the last line in extname_functions[] */ +}; +/* }}} */ + +/* {{{ extname_module_entry + */ +zend_module_entry extname_module_entry = { +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif + "extname", + extname_functions, + PHP_MINIT(extname), + PHP_MSHUTDOWN(extname), + PHP_RINIT(extname), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(extname), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(extname), +#if ZEND_MODULE_API_NO >= 20010901 + "0.1", /* Replace with version number for your extension */ +#endif + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_EXTNAME +ZEND_GET_MODULE(extname) +#endif + +/* {{{ PHP_INI + */ +/* Remove comments and fill if you need to have entries in php.ini +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("extname.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_extname_globals, extname_globals) + STD_PHP_INI_ENTRY("extname.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_extname_globals, extname_globals) +PHP_INI_END() +*/ +/* }}} */ + +/* {{{ php_extname_init_globals + */ +/* Uncomment this function if you have INI entries +static void php_extname_init_globals(zend_extname_globals *extname_globals) +{ + extname_globals->global_value = 0; + extname_globals->global_string = NULL; +} +*/ +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(extname) +{ + /* If you have INI entries, uncomment these lines + ZEND_INIT_MODULE_GLOBALS(extname, php_extname_init_globals, NULL); + REGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(extname) +{ + /* uncomment this line if you have INI entries + UNREGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request start */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(extname) +{ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request end */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(extname) +{ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(extname) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "extname support", "enabled"); + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} +/* }}} */ + + +/* Remove the following function when you have succesfully modified config.m4 + so that your module can be compiled into PHP, it exists only for testing + purposes. */ + +/* Every user-visible function in PHP should document itself in the source */ +/* {{{ proto string confirm_extname_compiled(string arg) + Return a string to confirm that the module is compiled in */ +PHP_FUNCTION(confirm_extname_compiled) +{ + char *arg = NULL; + int arg_len, len; + char string[256]; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { + return; + } + + len = sprintf(string, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "extname", arg); + RETURN_STRINGL(string, len, 1); +} +/* }}} */ +/* The previous line is meant for vim and emacs, so it can correctly fold and + unfold functions in source code. See the corresponding marks just before + function definition, where the functions purpose is also documented. Please + follow this convention for the convenience of others editing your code. +*/ + +/* __function_stubs_here__ */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/skeleton/skeleton.dsp b/ext/skeleton/skeleton.dsp new file mode 100644 index 0000000000..5f84019f21 --- /dev/null +++ b/ext/skeleton/skeleton.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="extname" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=extname - Win32 Release_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "extname.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "extname.mak" CFG="extname - Win32 Release_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "extname - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "extname - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "extname - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_EXTNAME" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXTNAME_EXPORTS" /D "COMPILE_DL_EXTNAME" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_EXTNAME=1 /D "LIBZEND_EXPORTS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/extname.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"
+
+!ELSEIF "$(CFG)" == "extname - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_EXTNAME" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXTNAME_EXPORTS" /D "COMPILE_DL_EXTNAME" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_EXTNAME=1 /D "LIBZEND_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts_debug.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/extname.dll" /libpath:"..\..\Debug_TS"
+
+!ENDIF
+
+# Begin Target
+
+# Name "extname - Win32 Release_TS"
+# Name "extname - Win32 Debug_TS"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\extname.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_extname.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/ext/skeleton/skeleton.php b/ext/skeleton/skeleton.php new file mode 100644 index 0000000000..12e1e64bb4 --- /dev/null +++ b/ext/skeleton/skeleton.php @@ -0,0 +1,19 @@ +<? +if(!extension_loaded('extname')) { + dl('extname.' . PHP_SHLIB_SUFFIX); +} +$module = 'extname'; +$functions = get_extension_funcs($module); +echo "Functions available in the test extension:<br>\n"; +foreach($functions as $func) { + echo $func."<br>\n"; +} +echo "<br>\n"; +$function = 'confirm_' . $module . '_compiled'; +if (extension_loaded($module)) { + $str = $function($module); +} else { + $str = "Module $module is not compiled into PHP"; +} +echo "$str\n"; +?> diff --git a/ext/skeleton/tests/001.phpt b/ext/skeleton/tests/001.phpt new file mode 100644 index 0000000000..7ef8472db3 --- /dev/null +++ b/ext/skeleton/tests/001.phpt @@ -0,0 +1,24 @@ +--TEST-- +Check for extname presence +--SKIPIF-- +<?php if (!extension_loaded("extname")) print "skip"; ?> +--POST-- +--GET-- +--INI-- +--FILE-- +<?php +echo "extname extension is available"; +/* + you can add regression tests for your extension here + + the output of your test code has to be equal to the + text in the --EXPECT-- section below for the tests + to pass, differences between the output and the + expected text are interpreted as failure + + see php4/README.TESTING for further information on + writing regression tests +*/ +?> +--EXPECT-- +extname extension is available |