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, \' | [email protected] 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) Link to comment https://forums.phpfreaks.com/topic/1332-replacement-for-ext_skel/ Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.