daeken Posted November 9, 2003 Share Posted November 9, 2003 I\'ve come up with a replacement for ext_skel, based upon my code generator. It generates the header, C source, and config.m4 for you, with or without function definitions. --Edit-- Put up the new code which supports resources, constants, and classes! --Edit-- #!/usr/local/bin/php <?php function Gen($file, $extname) { $defs = array(); $res = array(); $const = array(); foreach($file as $line) { $parts = explode(\' \', trim($line)); $arr = array(); if(!preg_match(\'/^[s]*(#([^s]+)[s]+([^s]+)[s]+(.*)$|(void|int|float|double|bool|resource|array|object|mixed)[s]+([^:]*::)?([^(]+)(([^)]*));[s]*(.*))$/\', trim($line), $matches)) continue; if(!empty($matches[1]) && $matches[1][0] == \'#\') { if($matches[2] == \'resource\') $res[$matches[3]] = $matches[4]; elseif($matches[2] == \'define\') $const[$matches[3]] = $matches[4]; continue; } $arr[\'return\'] = $matches[5]; $arr[\'class\'] = substr($matches[6], 0, -2); $arr[\'name\'] = $matches[7]; $arr[\'params\'] = array(); $arr[\'desc\'] = $matches[9]; $last = 0; $opt = false; preg_match_all(\'/([|])?[s]*(.+?)[s]+$([^s[],=]+)[s]*=?[s]*([^s[]]*)[s]*([|])*,?[s]*/\', $matches[8], $matches); for($i = 0; $i < count($matches[0]); ++$i) { $type = $matches[2][$i]; $name = $matches[3][$i]; $def = $matches[4][$i]; if($matches[1][$i] == \'[\') $opt = $tempopt = true; elseif($matches[5][$i] == \'[\') $tempopt = true; elseif($matches[5][$i] == \']\' || empty($matches[5][$i])) $tempopt = false; $arr[\'params\'][$name] = array($type, $opt, $def); $opt = $tempopt; } $defs[] = $arr; } ob_start(); foreach($defs as $arr) { echo \'PHP_FUNCTION(\', $arr[\'name\']; if(!empty($arr[\'class\'])) echo \'_\'; echo \');\', NL; } $def = ob_get_contents(); ob_end_clean(); ob_start(); $objs = array(); foreach($defs as $arr) { if(!isset($objs[$arr[\'class\']])) $objs[$arr[\'class\']] = array(); $objs[$arr[\'class\']][] = $arr[\'name\']; } $minit = (string) null; foreach($res as $name => $text) { echo \'static int le_\', $name, \'_res;\', NL, \'static void _free_foobar_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)\', NL, \'{\', NL, \'}\', NL, NL; $minit .= \' le_\' . $name . \'_res = zend_register_list_destructors_ex(_free_\' . $name . \'_result, NULL, \' . $text . \', module_number);\' . NL; } foreach($const as $name => $val) { if($val[0] == \'"\') $type = \'STRING\'; elseif(strstr($val, \'.\')) $type = \'DOUBLE\'; else $type = \'LONG\'; $minit .= \' REGISTER_\' . $type . \'_CONSTANT("\' . $name . \'", \' . $val . \', CONST_CS | CONST_PERSISTENT);\' . NL; } echo NL; foreach($objs as $class => $funcs) { if(empty($class)) echo \'function_entry \', $extname, \'_functions[] = {\', NL; else { echo \'zend_class_entry \', $class, \'_class_entry;\', NL; echo \'function_entry \', $class, \'_class_functions[] = {\', NL; $minit .= \' INIT_CLASS_ENTRY(\' . $class . \'_class_entry, "\' . $class . \'", \' . $class . \'_class_functions);\' . NL . \' zend_register_internal_class(&\' . $class . \'_class_entry TSRMLS_CC);\' . NL; } foreach($funcs as $func) { if(empty($class)) echo \' ZEND_FE(\', $func, \', NULL)\', NL; else echo \' ZEND_FALIAS(\', $func, \', \', $func, \'_, NULL)\', NL; } echo \' {NULL, NULL, NULL}\', NL, \'};\', NL, NL, NL; } if(!isset($objs[\'\'])) echo \'function_entry \', $extname, \'_functions[] = {\', NL, \' {NULL, NULL, NULL}\', NL, \'};\', NL, NL, NL; $entry = ob_get_contents(); ob_end_clean(); ob_start(); foreach($defs as $arr) { echo \'/* {{{ proto \', $arr[\'return\'], \' \'; if(!empty($arr[\'class\'])) echo $arr[\'class\'], \'::\'; echo $arr[\'name\'], \'(\'; $i = 0; $optcount = 0; foreach($arr[\'params\'] as $name => $temp) { list($type, $opt, $default) = $temp; if(!$opt) { echo str_repeat(\']\', $optcount); $optcount = 0; } if($opt) { if($i != 0) echo \' \'; echo \'[\'; ++$optcount; } if(++$i > 1) echo \', \'; echo $type, \' \', $name; if($opt && !empty($default)) echo \' = \', $default; } echo str_repeat(\']\', $optcount); echo \')\', NL, \' \', $arr[\'desc\'], \' */\', NL, \'PHP_FUNCTION(\', $arr[\'name\']; if(!empty($arr[\'class\'])) echo \'_\'; echo \')\', NL, \'{\', NL; $format = (string) null; $params = (string) null; $i = 0; foreach($arr[\'params\'] as $name => $temp) { list($type, $opt, $default) = $temp; switch($type) { case \'int\': echo \' int \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = 0\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'l\'; $params .= \'&\' . $name; break; case \'string\': echo \' char *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL, \' int \', $name, \'_len\'; if($opt && !empty($default)) echo \' = \', strlen($default) - 2; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'s\'; $params .= \'&\' . $name . \', &\' . $name . \'_len\'; break; case \'bool\': case \'boolean\': echo \' zend_bool \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = FALSE\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'b\'; $params .= \'&\' . $name; break; case \'array\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'a\'; $params .= \'&\' . $name; break; case \'mixed\': case \'resource\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'z\'; $params .= \'&\' . $name; break; case \'object\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'o\'; $params .= \'&\' . $name; break; case \'double\': case \'float\': echo \' double \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = 0\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'d\'; $params .= \'&\' . $name; break; } if(++$i != count($arr[\'params\'])) $params .= \', \'; } $need = 0; foreach($arr[\'params\'] as $name => $temp) { if(!$temp[1]) ++$need; } if(count($arr[\'params\']) > 0) echo \' if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "\', $format, \'", \', $params, \') == FAILURE)\', NL, \' return;\', NL, \'}\', NL, NL; else echo \'}\', NL, \'/* }}} */\', NL, NL; } $funcs = ob_get_contents(); ob_end_clean(); return array($def, $entry, $funcs, $minit); } function Get() { return trim(fgets(STDIN)); } define(\'NL\', chr(10)); echo \'Welcome to the extension builder.\', NL, \'To get started, type the name of your extension.\', NL; $ext = Get(); $foo = false; echo \'Ok. To get started with making extension `\', $ext, \'\' we will make the directory.\', NL; while(!$foo) { echo \'Please give the path to the ext/ directory of the PHP source tree.\', NL; $dir = Get(); $foo = is_dir($dir); } @mkdir($dir . \'/\' . $ext); echo \'Extension directory created.\', NL, \'What is your name?\', NL; $author = str_pad(Get(), 61, \' \', STR_PAD_RIGHT); echo \'What libraries (if any) are needed by this extension? (space-seperated only please)\', NL; $libs = explode(\' \', Get()); echo \'What includes (if any) are needed by this extension? (space-seperated only please)\', NL; $incs = explode(\' \', Get()); while(true) { echo \'What is the filename of your function definition file? (leave blank if you don\'t have one)\', NL; $def = Get(); if(empty($def)) { $file = array(); break; } if(!empty($def) && !file_exists($def)) echo \'File does not exist.\', NL; else { $file = file($def); break; } } while(true) { echo \'Do you want --with-\', $ext, \' or --enable-\', $ext, \' ? (Enter either with or enable)\', NL; $flag = strtolower(Get()); if($flag == \'with\' || $flag == \'enable\') break; } $head = fopen($dir . \'/\' . $ext . \'/php_\' . $ext . \'.h\', \'w\'); ob_start(); echo \'/*\', NL, \' +----------------------------------------------------------------------+\', NL, \' | PHP Version 4 |\', NL, \' +----------------------------------------------------------------------+\', NL, \' | Copyright (c) 1997-2003 The PHP Group |\', NL, \' +----------------------------------------------------------------------+\', NL, \' | This source file is subject to version 2.02 of the PHP license, |\', NL, \' | that is bundled with this package in the file LICENSE, and is |\', NL, \' | available at through the world-wide-web at |\', NL, \' | http://www.php.net/license/2_02.txt. |\', NL, \' | If you did not receive a copy of the PHP license and are unable to |\', NL, \' | obtain it through the world-wide-web, please send a note to |\', NL, \' | license@php.net so we can mail you a copy immediately. |\', NL, \' +----------------------------------------------------------------------+\', NL, \' | Author: \', $author, \'|\', NL, \' +----------------------------------------------------------------------+\', NL, \' $Id: header,v 1.10.8.1 2003/07/14 15:59:18 sniper Exp $ \', NL, \'*/\', NL, NL; $fileheader = ob_get_contents(); ob_end_clean(); $h = \'#ifndef PHP_\' . strtoupper($ext) . \'_H #define PHP_\' . strtoupper($ext) . \'_H extern zend_module_entry \' . $ext . \'_module_entry; #define phpext_\' . $ext . \'_ptr &\' . $ext . \'_module_entry #ifdef PHP_WIN32 #define PHP_\' . strtoupper($ext) . \'_API __declspec(dllexport) #else #define PHP_\' . strtoupper($ext) . \'_API #endif #ifdef ZTS #include "TSRM.h" #endif \' . NL; foreach($incs as $include) if(!empty($include)) $h .= \'#include <\' . $include . \'>\' . NL; $h .= NL . \'PHP_MINIT_FUNCTION(\' . $ext . \'); PHP_MSHUTDOWN_FUNCTION(\' . $ext . \'); PHP_RINIT_FUNCTION(\' . $ext . \'); PHP_RSHUTDOWN_FUNCTION(\' . $ext . \'); PHP_MINFO_FUNCTION(\' . $ext . \');\' . NL . NL; fwrite($head, $fileheader); fwrite($head, $h); list($defs, $entry, $funcs, $minit) = Gen($file, $ext); fwrite($head, $defs); fwrite($head, \'#endif\' . NL); fclose($head); $source = fopen($dir . \'/\' . $ext . \'/\' . $ext . \'.c\', \'w\'); fwrite($source, $fileheader); $c = \'#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_\' . $ext . \'.h" /* True global resources - no need for thread safety here */ static int le_\' . $ext . \';\' . NL . NL; fwrite($source, $c); fwrite($source, $entry); $c = \'/* {{{ \' . $ext . \'_module_entry */ zend_module_entry \' . $ext . \'_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "\' . $ext . \'", \' . $ext . \'_functions, PHP_MINIT(\' . $ext . \'), PHP_MSHUTDOWN(\' . $ext . \'), PHP_RINIT(\' . $ext . \'), /* Replace with NULL if there\'s nothing to do at request start */ PHP_RSHUTDOWN(\' . $ext . \'), /* Replace with NULL if there\'s nothing to do at request end */ PHP_MINFO(\' . $ext . \'), #if ZEND_MODULE_API_NO >= 20010901 "0.1", /* Replace with version number for your extension */ #endif STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_\' . strtoupper($ext) . \' ZEND_GET_MODULE(\' . $ext . \') #endif /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(\' . $ext . \') { \' . $minit . \' return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(\' . $ext . \') { return SUCCESS; } /* }}} */ /* Remove if there\'s nothing to do at request start */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(\' . $ext . \') { return SUCCESS; } /* }}} */ /* Remove if there\'s nothing to do at request end */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(\' . $ext . \') { return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(\' . $ext . \') { php_info_print_table_start(); php_info_print_table_header(2, "\' . $ext . \' support", "enabled"); php_info_print_table_end(); } /* }}} */\' . NL . NL; fwrite($source, $c); fwrite($source, $funcs); fclose($source); $m4 = fopen($dir . \'/\' . $ext . \'/config.m4\', \'w\'); if($flag == \'enable\') fwrite($m4, \'PHP_ARG_ENABLE(\' . $ext . \', for \' . $ext . \' support,\' . NL . \'[ --enable-\' . $ext . \' Enable \' . $ext . \' support])\' . NL); else fwrite($m4, \'PHP_ARG_WITH(\' . $ext . \', for \' . $ext . \' support,\' . NL . \'[ --with-\' . $ext . \' Include \' . $ext . \' support])\' . NL); fwrite($m4, \'if test "$PHP_\' . strtoupper($ext) . \'" != "no"; then\' . NL); foreach($libs as $lib) { if(!empty($lib)) fwrite($m4, \' PHP_CHECK_LIBRARY(\' . $lib . \',\' . $lib . \',\' . NL . \' [\' . NL . \' AC_DEFINE(HAVE_\' . strtoupper($ext) . \'LIB,1,[ ])\' . NL . \' ],[\' . NL . \' AC_MSG_ERROR([wrong \' . $lib . \' lib version of lib not found])\' . NL . \' ],[\' . NL . \' -l\' . $lib . NL . \' ])\' . NL . \' PHP_ADD_LIBRARY_WITH_PATH(\' . $ext . \', /usr/lib, \' . strtoupper($ext) . \'_SHARED_LIBADD)\' . NL); } fwrite($m4, \' PHP_NEW_EXTENSION(\' . $ext . \', \' . $ext . \'.c, $ext_shared)\' . NL . \'fi\' . NL); fclose($m4); ?> Example definition file: void SomeClass::Foo(int $bar); Description! #define foo "bar" #resource foobar "Foobar Resource" Have fun! Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious) Quote Link to comment https://forums.phpfreaks.com/topic/1332-replacement-for-ext_skel/ Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.