Jump to content

Archived

This topic is now archived and is closed to further replies.

daeken

Replacement for ext_skel.

Recommended Posts

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)

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.