From f35f45906eac34498c7720326fb9da9fde960871 Mon Sep 17 00:00:00 2001 From: Kalle Sommer Nielsen Date: Sun, 23 Jul 2017 10:36:35 +0200 Subject: [PATCH] Redesigned ext_skel to be written entirely in PHP with no dependencies, this means it will now run on Windows without Cygwin and other nonsense. It no longer includes a way to generate XML documentation (the PHP documentation utilities already got tools for that in svn under phpdoc/doc-base) and it no longer support function stubs. $ php ext_skel.php --help php ext_skel.php --ext= [--experimental] [--author=] [--dir=] [--std] [--onlyunix] [--onlywindows] [--help] --ext= The name of the extension defined as --experimental Passed if this extension is experimental, this creates the EXPERIMENTAL file in the root of the extension --author= Your name, this is used if --header is passed and for the CREDITS file --dir= Path to the directory for where extension should be created. Defaults to the directory of where this script lives --std If passed, the standard header and vim rules footer used in extensions that is included in the core, will be used --onlyunix Only generate configure scripts for Unix --onlywindows Only generate configure scripts for Windows --help This help Example usage: $ php ext_skel.php --ext test --std --experimental $ php ext_skel.php --ext kalle --author "Kalle Sommer Nielsen" $ php ext_skel.php --ext phpfi --dir "/home/kalle/dev/" --onlyunix --- NEWS | 14 +- UPGRADING | 5 + ext/ext_skel | 332 -------------------------------- ext/ext_skel.php | 365 ++++++++++++++++++++++++++++++++++++ ext/ext_skel_win32.php | 52 ----- ext/skeleton/CREDITS | 1 - ext/skeleton/EXPERIMENTAL | 0 ext/skeleton/create_stubs | 289 ---------------------------- ext/skeleton/php_skeleton.h | 49 +---- ext/skeleton/skeleton.c | 173 ++++++----------- ext/skeleton/skeleton.php | 21 --- ext/skeleton/tests/001.phpt | 23 +-- ext/skeleton/tests/002.phpt | 17 ++ ext/skeleton/tests/003.phpt | 16 ++ 14 files changed, 485 insertions(+), 872 deletions(-) delete mode 100755 ext/ext_skel create mode 100644 ext/ext_skel.php delete mode 100644 ext/ext_skel_win32.php delete mode 100644 ext/skeleton/CREDITS delete mode 100644 ext/skeleton/EXPERIMENTAL delete mode 100755 ext/skeleton/create_stubs delete mode 100644 ext/skeleton/skeleton.php create mode 100644 ext/skeleton/tests/002.phpt create mode 100644 ext/skeleton/tests/003.phpt diff --git a/NEWS b/NEWS index fd284f3317..233f7e208c 100644 --- a/NEWS +++ b/NEWS @@ -2,14 +2,20 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 7.3.0alpha1 -- Session: - . Fixed bug #74941 (session fails to start after having headers sent). - (morozov) +- Core: + . Redesigned the old ext_skel program written in PHP, run: + 'php ext_skel.php' for all options. This means there is no dependencies + thrus making it work on Windows out of the box. (Kalle) - LDAP: - . Added ldap_exop_refresh helper for EXOP REFRESH operation with dds overlay + . Added ldap_exop_refresh helper for EXOP REFRESH operation with dds overlay. + (Côme) - ODBC: . Removed support for Birdstep. (Kalle) +- Session: + . Fixed bug #74941 (session fails to start after having headers sent). + (morozov) + <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> diff --git a/UPGRADING b/UPGRADING index 8711371bcf..7f432eacf5 100644 --- a/UPGRADING +++ b/UPGRADING @@ -19,6 +19,11 @@ PHP 7.3 UPGRADE NOTES 1. Backward Incompatible Changes ======================================== +Core: + . The ext_skel utility has been completely redesigned with new options and + some old options removed. This is now written in PHP and have no external + dependencies. + ======================================== 2. New Features ======================================== diff --git a/ext/ext_skel b/ext/ext_skel deleted file mode 100755 index d1b8a2874c..0000000000 --- a/ext/ext_skel +++ /dev/null @@ -1,332 +0,0 @@ -#!/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-svn" -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 < 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/\$PHP_LIBDIR, ${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/\$PHP_LIBDIR -lm - dnl ]) - dnl - dnl PHP_SUBST(${EXTNAME}_SHARED_LIBADD) - - PHP_NEW_EXTENSION($extname, $extname.c, \$ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) -fi -eof - -$ECHO_N " config.w32$ECHO_C" -cat >config.w32 <.gitignore < 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 < | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* {{{ error + */ +function error($message) { + printf('Error: %s%s', $message, PHP_EOL); + exit; +} +/* }}} */ + +/* {{{ print_help + */ +function print_help() { + printf('php ext_skel.php --ext= [--experimental] [--author=]%s', PHP_EOL); + printf(' [--dir=] [--std] [--onlyunix]%s', PHP_EOL); + printf(' [--onlywindows] [--help]%1$s%1$s', PHP_EOL); + printf(' --ext= The name of the extension defined as %s', PHP_EOL); + printf(' --experimental Passed if this extension is experimental, this creates%s', PHP_EOL); + printf(' the EXPERIMENTAL file in the root of the extension%s', PHP_EOL); + printf(' --author= Your name, this is used if --header is passed and%s', PHP_EOL); + printf(' for the CREDITS file%s', PHP_EOL); + printf(' --dir= Path to the directory for where extension should be%s', PHP_EOL); + printf(' created. Defaults to the directory of where this script%s', PHP_EOL); + printf(' lives%s', PHP_EOL); + printf(' --std If passed, the standard header and vim rules footer used%s', PHP_EOL); + printf(' in extensions that is included in the core, will be used%s', PHP_EOL); + printf(' --onlyunix Only generate configure scripts for Unix%s', PHP_EOL); + printf(' --onlywindows Only generate configure scripts for Windows%s', PHP_EOL); + printf(' --help This help%s', PHP_EOL); + + exit; +} +/* }}} */ + +/* {{{ task + */ +function task($label, $callback) { + printf('%s... ', $label); + + $callback(); + + printf('done%s', PHP_EOL); +} +/* }}} */ + +/* {{{ print_success + */ +function print_success() { + global $options; + + if (PHP_OS_FAMILY != 'Windows') { + $file_prefix = './'; + $make_prefix = ''; + } else { + $file_prefix = ''; + $make_prefix = 'n'; + } + + printf('%1$sSuccess. The extension is now ready to be compiled into PHP. To do so, use the%s', PHP_EOL); + printf('following steps:%1$s%1$s', PHP_EOL); + printf('cd /path/to/php-src%s', PHP_EOL); + printf('%sbuildconf%s', $file_prefix, PHP_EOL); + printf('%sconfigure --enable-%s%s', $file_prefix, $options['ext'], PHP_EOL); + printf('%smake%2$s%2$s', $make_prefix, PHP_EOL); + printf('Don\'t forget to run tests once the compilation is done:%s', PHP_EOL); + printf('%smake test TESTS=ext/%s/tests%3$s%3$s', $make_prefix, $options['ext'], PHP_EOL); + printf('Thank you for using PHP!%s', PHP_EOL); +} +/* }}} */ + +/* {{{ process_args + */ +function process_args($argv, $argc) { + $options = [ + 'unix' => true, + 'windows' => true, + 'ext' => '', + 'dir' => __DIR__ . DIRECTORY_SEPARATOR, + 'skel' => __DIR__ . DIRECTORY_SEPARATOR . 'skeleton' . DIRECTORY_SEPARATOR, + 'author' => false, + 'experimental' => false, + 'std' => false + ]; + + for($i = 1; $i < $argc; ++$i) + { + $val = $argv[$i]; + + if($val{0} != '-' || $val{1} != '-') + { + continue; + } + + switch($opt = strtolower(substr($val, 2))) + { + case 'help': { + print_help(); + } + case 'onlyunix': { + $options['windows'] = false; + } + break; + case 'onlywindows': { + $options['unix'] = false; + } + break; + case 'experimental': { + $options['experimental'] = true; + } + break; + case 'std': { + $options['std'] = true; + } + break; + case 'ext': + case 'dir': + case 'author': { + if (!isset($argv[$i + 1]) || ($argv[$i + 1]{0} == '-' && $argv[$i + 1]{1} == '-')) { + error('Argument "' . $val . '" expects a value, none passed'); + } else if ($opt == 'dir' && empty($argv[$i + 1])) { + continue; + } + + $options[$opt] = ($opt == 'dir' ? realpath($argv[$i + 1]) : $argv[$i + 1]); + } + break; + default: { + error('Unsupported argument "' . $val . '" passed'); + } + } + } + + if (empty($options['ext'])) { + error('No extension name passed, use "--ext "'); + } else if (!$options['unix'] && !$options['windows']) { + error('Cannot pass both --onlyunix and --onlywindows'); + } else if (!is_dir($options['skel'])) { + error('The skeleton directory was not found'); + } + + $options['ext'] = str_replace(['\\', '/'], '', strtolower($options['ext'])); + + return $options; +} +/* }}} */ + +/* {{{ process_source_tags + */ +function process_source_tags($file, $short_name) { + global $options; + + $source = file_get_contents($file); + + if ($source === false) { + error('Unable to open file for reading: ' . $short_name); + } + + $source = str_replace('%EXTNAME%', $options['ext'], $source); + $source = str_replace('%EXTNAMECAPS%', strtoupper($options['ext']), $source); + + if (strpos($short_name, '.c') !== false || strpos($short_name, '.h') !== false) { + static $header, $footer; + + if (!$header) { + if ($options['std']) { + $year = date('Y'); + $author_len = strlen($options['author']); + $credits = $options['author'] . ($author_len && $author_len <= 60 ? str_repeat(' ', 60 - $author_len) : ''); + + $header = <<<"HEADER" +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-$year The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: $credits | + +----------------------------------------------------------------------+ +*/ +HEADER; + $footer = <<<'FOOTER' + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ +FOOTER; + } else { + if ($options['author']) { + $header = sprintf('/* %s extension for PHP (c) %d %s */', $options['ext'], date('Y'), $options['author']); + } else { + $header = sprintf('/* %s extension for PHP */', $options['ext']); + } + + $footer = ''; + } + } + + $source = str_replace(['%HEADER%', '%FOOTER%'], [$header, $footer], $source); + } + + if (!file_put_contents($file, $source)) { + error('Unable to save contents to file: ' . $short_name); + } +} +/* }}} */ + +/* {{{ copy_config_scripts + */ +function copy_config_scripts() { + global $options; + + $files = []; + + if ($options['unix']) { + $files[] = 'config.m4'; + } + + if ($options['windows']) { + $files[] = 'config.w32'; + } + + if (!$files) { + return; + } + + foreach($files as $config_script) { + $new_config_script = $options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . $config_script; + + if (!copy($options['skel'] . $config_script . '.in', $new_config_script)) { + error('Unable to copy config script: ' . $config_script); + } + + process_source_tags($new_config_script, $config_script); + } +} +/* }}} */ + +/* {{{ copy_sources + */ +function copy_sources() { + global $options; + + $files = [ + 'skeleton.c' => $options['ext'] . '.c', + 'php_skeleton.h' => 'php_' . $options['ext'] . '.h' + ]; + + foreach ($files as $src_file => $dst_file) { + if (!copy($options['skel'] . $src_file, $options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . $dst_file)) { + error('Unable to copy source file: ' . $src_file); + } + + process_source_tags($options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . $dst_file, $dst_file); + } +} +/* }}} */ + +/* {{{ copy_tests + */ +function copy_tests() { + global $options; + + $test_files = glob($options['skel'] . 'tests/*', GLOB_MARK); + + if (!$test_files) { + return; + } + + foreach ($test_files as $test) { + if (is_dir($test)) { + continue; + } + + $new_test = str_replace([$options['skel'], '/'], ['', DIRECTORY_SEPARATOR], $test); + + if (!copy($test, $options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . $new_test)) { + error('Unable to copy file: ' . $new_test); + } + + process_source_tags($options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . $new_test, $new_test); + } +} +/* }}} */ + + +if (PHP_SAPI != 'cli') { + error('This script is only suited for CLI'); +} + +if ($argc < 1) { + print_help(); + exit; +} + +$options = process_args($argv, $argc); + +if (!$options['dir'] || !is_dir($options['dir'])) { + error('The selected output directory does not exists'); +} else if (is_dir($options['dir'] . $options['ext'])) { + error('There is already a folder named "' . $options['ext'] . '" in the output directory'); +} else if (!mkdir($options['dir'] . $options['ext'])) { + error('Unable to create extension directory in the output directory'); +} else if (!mkdir($options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . 'tests')) { + error('Unable to create the tests directory'); +} + +if ($options['experimental']) { + print('Creating EXPERIMENTAL... '); + + if (file_put_contents($options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . 'EXPERIMENTAL', '') === false) { + error('Unable to create the EXPERIMENTAL file'); + } + + printf('done%s', PHP_EOL); +} + +if (!empty($options['author'])) { + print('Creating CREDITS... '); + + if (!file_put_contents($options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . 'CREDITS', $options['ext'] . PHP_EOL . $options['author'])) { + error('Unable to create the CREDITS file'); + } + + printf('done%s', PHP_EOL); +} + +date_default_timezone_set('UTC'); + +task('Copying config scripts', 'copy_config_scripts'); +task('Copying sources', 'copy_sources'); +task('Copying tests', 'copy_tests'); + +print_success(); + +?> \ No newline at end of file diff --git a/ext/ext_skel_win32.php b/ext/ext_skel_win32.php deleted file mode 100644 index 770c6f48bb..0000000000 --- a/ext/ext_skel_win32.php +++ /dev/null @@ -1,52 +0,0 @@ - - diff --git a/ext/skeleton/CREDITS b/ext/skeleton/CREDITS deleted file mode 100644 index 58fc71019a..0000000000 --- a/ext/skeleton/CREDITS +++ /dev/null @@ -1 +0,0 @@ -extname \ No newline at end of file diff --git a/ext/skeleton/EXPERIMENTAL b/ext/skeleton/EXPERIMENTAL deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ext/skeleton/create_stubs b/ext/skeleton/create_stubs deleted file mode 100755 index fe79d6a29c..0000000000 --- a/ext/skeleton/create_stubs +++ /dev/null @@ -1,289 +0,0 @@ -#!/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 "\tzend_long " 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 "\tsize_t " 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, " 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: - diff --git a/ext/skeleton/php_skeleton.h b/ext/skeleton/php_skeleton.h index 1514563a70..542bc91548 100644 --- a/ext/skeleton/php_skeleton.h +++ b/ext/skeleton/php_skeleton.h @@ -1,45 +1,16 @@ -/* __header_here__ */ +%HEADER% -#ifndef PHP_EXTNAME_H -#define PHP_EXTNAME_H +#ifndef PHP_%EXTNAMECAPS%_H +# define PHP_%EXTNAMECAPS%_H -extern zend_module_entry extname_module_entry; -#define phpext_extname_ptr &extname_module_entry +extern zend_module_entry %EXTNAME%_module_entry; +# define phpext_%EXTNAME%_ptr &%EXTNAME%_module_entry -#define PHP_EXTNAME_VERSION "0.1.0" /* Replace with version number for your extension */ +# define PHP_%EXTNAMECAPS%_VERSION "0.1.0" -#ifdef PHP_WIN32 -# define PHP_EXTNAME_API __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_EXTNAME_API __attribute__ ((visibility("default"))) -#else -# define PHP_EXTNAME_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -/* - Declare any global variables you may need between the BEGIN - and END macros here: - -ZEND_BEGIN_MODULE_GLOBALS(extname) - zend_long global_value; - char *global_string; -ZEND_END_MODULE_GLOBALS(extname) -*/ - -/* 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. -*/ -#define EXTNAME_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(extname, v) - -#if defined(ZTS) && defined(COMPILE_DL_EXTNAME) +# if defined(ZTS) && defined(COMPILE_DL_%EXTNAMECAPS%) ZEND_TSRMLS_CACHE_EXTERN() -#endif - -#endif /* PHP_EXTNAME_H */ +# endif -/* __footer_here__ */ +#endif /* PHP_%EXTNAMECAPS%_H */ +%FOOTER% \ No newline at end of file diff --git a/ext/skeleton/skeleton.c b/ext/skeleton/skeleton.c index 50f3271e20..5e674c15c1 100644 --- a/ext/skeleton/skeleton.c +++ b/ext/skeleton/skeleton.c @@ -1,168 +1,103 @@ -/* __header_here__ */ +%HEADER% #ifdef HAVE_CONFIG_H -#include "config.h" +# include "config.h" #endif #include "php.h" -#include "php_ini.h" #include "ext/standard/info.h" -#include "php_extname.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; - -/* {{{ PHP_INI +/* {{{ void %EXTNAME%_test1() */ -/* 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() -*/ -/* }}} */ - -/* Remove the following function when you have successfully 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) +PHP_FUNCTION(%EXTNAME%_test1) { - char *arg = NULL; - size_t arg_len, len; - zend_string *strg; + ZEND_PARSE_PARAMETERS_NONE(); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) { - return; - } - - strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "extname", arg); - - RETURN_STR(strg); + php_printf("The extension %s is loaded and working!\r\n", "%EXTNAME%"); } /* }}} */ -/* 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__ */ - -/* {{{ php_extname_init_globals +/* {{{ string %EXTNAME%_test2( [ string $var ] ) */ -/* Uncomment this function if you have INI entries -static void php_extname_init_globals(zend_extname_globals *extname_globals) +PHP_FUNCTION(%EXTNAME%_test2) { - extname_globals->global_value = 0; - extname_globals->global_string = NULL; -} -*/ -/* }}} */ + char *var = "World"; + size_t var_len = sizeof("World") - 1; + zend_string *retval; -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(extname) -{ - /* If you have INI entries, uncomment these lines - REGISTER_INI_ENTRIES(); - */ - return SUCCESS; -} -/* }}} */ + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STRING(var, var_len) + ZEND_PARSE_PARAMETERS_END(); -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(extname) -{ - /* uncomment this line if you have INI entries - UNREGISTER_INI_ENTRIES(); - */ - return SUCCESS; + retval = strpprintf(0, "Hello %s", var); + + RETURN_STR(retval); } -/* }}} */ +/* }}}*/ -/* Remove if there's nothing to do at request start */ /* {{{ PHP_RINIT_FUNCTION */ -PHP_RINIT_FUNCTION(extname) +PHP_RINIT_FUNCTION(%EXTNAME%) { -#if defined(COMPILE_DL_EXTNAME) && defined(ZTS) +#if defined(ZTS) && defined(COMPILE_DL_%EXTNAMECAPS%) ZEND_TSRMLS_CACHE_UPDATE(); #endif - 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_MINFO_FUNCTION(%EXTNAME%) { php_info_print_table_start(); - php_info_print_table_header(2, "extname support", "enabled"); + 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(); - */ } /* }}} */ -/* {{{ extname_functions[] - * - * Every user visible function must have an entry in extname_functions[]. +/* {{{ arginfo + */ +ZEND_BEGIN_ARG_INFO(arginfo_%EXTNAME%_test1, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_%EXTNAME%_test2, 0) + ZEND_ARG_INFO(0, str) +ZEND_END_ARG_INFO() +/* }}} */ + +/* {{{ %EXTNAME%_functions[] */ -const zend_function_entry extname_functions[] = { - PHP_FE(confirm_extname_compiled, NULL) /* For testing, remove later. */ - /* __function_entries_here__ */ - PHP_FE_END /* Must be the last line in extname_functions[] */ +const zend_function_entry %EXTNAME%_functions[] = { + PHP_FE(%EXTNAME%_test1, arginfo_%EXTNAME%_test1) + PHP_FE(%EXTNAME%_test2, arginfo_%EXTNAME%_test2) + PHP_FE_END }; /* }}} */ -/* {{{ extname_module_entry +/* {{{ %EXTNAME%_module_entry */ -zend_module_entry extname_module_entry = { +zend_module_entry %EXTNAME%_module_entry = { STANDARD_MODULE_HEADER, - "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), - PHP_EXTNAME_VERSION, + "%EXTNAME%", /* Extension name */ + %EXTNAME%_functions, /* zend_function_entry */ + NULL, /* PHP_MINIT - Module initialization */ + NULL, /* PHP_MSHUTDOWN - Module shutdown */ + PHP_RINIT(%EXTNAME%), /* PHP_RINIT - Request initialization */ + NULL, /* PHP_RSHUTDOWN - Request shutdown */ + PHP_MINFO(%EXTNAME%), /* PHP_MINFO - Module info */ + PHP_%EXTNAMECAPS%_VERSION, /* Version */ STANDARD_MODULE_PROPERTIES }; /* }}} */ -#ifdef COMPILE_DL_EXTNAME -#ifdef ZTS +#ifdef COMPILE_DL_%EXTNAMECAPS% +# ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() +# endif +ZEND_GET_MODULE(%EXTNAME%) #endif -ZEND_GET_MODULE(extname) -#endif - -/* - * 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 - */ +%FOOTER% \ No newline at end of file diff --git a/ext/skeleton/skeleton.php b/ext/skeleton/skeleton.php deleted file mode 100644 index 91db9d5408..0000000000 --- a/ext/skeleton/skeleton.php +++ /dev/null @@ -1,21 +0,0 @@ -"; - -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 index 88f5795650..445a914936 100644 --- a/ext/skeleton/tests/001.phpt +++ b/ext/skeleton/tests/001.phpt @@ -1,21 +1,14 @@ --TEST-- -Check for extname presence +Check if %EXTNAME% is loaded --SKIPIF-- - + --FILE-- --EXPECT-- -extname extension is available +The extension "%EXTNAME%" is available diff --git a/ext/skeleton/tests/002.phpt b/ext/skeleton/tests/002.phpt new file mode 100644 index 0000000000..0147087ace --- /dev/null +++ b/ext/skeleton/tests/002.phpt @@ -0,0 +1,17 @@ +--TEST-- +%EXTNAME%_test1() Basic test +--SKIPIF-- + +--FILE-- + +--EXPECT-- +The extension %EXTNAME% is loaded and working! +NULL diff --git a/ext/skeleton/tests/003.phpt b/ext/skeleton/tests/003.phpt new file mode 100644 index 0000000000..d5a0905fa9 --- /dev/null +++ b/ext/skeleton/tests/003.phpt @@ -0,0 +1,16 @@ +--TEST-- +%EXTNAME%_test2() Basic test +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(11) "Hello World" +string(9) "Hello PHP" -- 2.40.0