Jump to content

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)

Link to comment
https://forums.phpfreaks.com/topic/1332-replacement-for-ext_skel/
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

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.