/CodeGen/PECL/Extension.php
PHP | 2629 lines | 1774 code | 360 blank | 495 comment | 119 complexity | 6ae65736bf0ee5370005c811716fa686 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * A class that generates PECL extension soure and documenation files
- *
- * PHP versions 5
- *
- * LICENSE: This source file is subject to version 3.0 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category Tools and Utilities
- * @package CodeGen_PECL
- * @author Hartmut Holzgraefe <hartmut@php.net>
- * @copyright 2005-2008 Hartmut Holzgraefe
- * @license http://www.php.net/license/3_0.txt PHP License 3.0
- * @version CVS: $Id: Extension.php,v 1.75 2007/04/16 09:28:03 hholzgra Exp $
- * @version CVS: $Id: Extension.php,v 1.75 2007/04/16 09:28:03 hholzgra Exp $
- * @link http://pear.php.net/package/CodeGen_PECL
- */
- /**
- * includes
- */
- require_once "System.php";
- require_once "CodeGen/Extension.php";
- require_once "CodeGen/PECL/Release.php";
- require_once "CodeGen/PECL/Element.php";
- require_once "CodeGen/PECL/Element/Constant.php";
- require_once "CodeGen/PECL/Element/Function.php";
- require_once "CodeGen/PECL/Element/Resource.php";
- require_once "CodeGen/PECL/Element/Ini.php";
- require_once "CodeGen/PECL/Element/Global.php";
- require_once "CodeGen/PECL/Element/Logo.php";
- require_once "CodeGen/PECL/Element/Test.php";
- require_once "CodeGen/PECL/Element/Class.php";
- require_once "CodeGen/PECL/Element/Interface.php";
- require_once "CodeGen/PECL/Element/Stream.php";
- require_once "CodeGen/PECL/Dependency/With.php";
- require_once "CodeGen/PECL/Dependency/Lib.php";
- require_once "CodeGen/PECL/Dependency/Header.php";
- require_once "CodeGen/PECL/Dependency/Extension.php";
- require_once "CodeGen/PECL/Dependency/Platform.php";
- /**
- * A class that generates PECL extension soure and documenation files
- *
- * @category Tools and Utilities
- * @package CodeGen_PECL
- * @author Hartmut Holzgraefe <hartmut@php.net>
- * @copyright 2005-2008 Hartmut Holzgraefe
- * @license http://www.php.net/license/3_0.txt PHP License 3.0
- * @version Release: 1.1.3
- * @link http://pear.php.net/package/CodeGen_PECL
- */
- class CodeGen_PECL_Extension
- extends CodeGen_Extension
- {
- /**
- * Current CodeGen_PECL version number
- *
- * @return string
- */
- function version()
- {
- return "1.1.3";
- }
- /**
- * CodeGen_PECL Copyright message
- *
- * @return string
- */
- function copyright()
- {
- return "Copyright (c) 2003-2006 Hartmut Holzgraefe";
- }
- // {{{ member variables
- /**
- * The public PHP functions defined by this extension
- *
- * @var array
- */
- protected $functions = array();
- /**
- * The extensions internal functions like MINIT
- *
- * @var array
- */
- protected $internalFunctions = array();
- /**
- * The constants defined by this extension
- *
- * @var array
- */
- protected $constants = array();
- /**
- * The PHP classes defined by this extension
- *
- * @var array
- */
- protected $classes = array();
- /**
- * The PHP interfaces defined by this extension
- *
- * @var array
- */
- protected $interfaces = array();
- /**
- * The extensions php.ini parameters
- *
- * @var array
- */
- protected $phpini = array();
- /**
- * The extensions internal global variables
- *
- * @var array
- */
- protected $globals = array();
- /**
- * The PHP resources defined by this extension
- *
- * @var array
- */
- protected $resources = array();
- /**
- * Custom test cases
- *
- * @var array
- */
- protected $testcases = array();
- /**
- * phpinfo logos
- *
- * @var string
- * @access private
- */
- protected $logos = array();
- /**
- * cross extension dependencies
- *
- * @var array
- */
- protected $otherExtensions = array();
- /**
- * generate #line specs?
- *
- * @var bool
- * @access private
- */
- protected $linespecs = false;
- /**
- * PHP Streams
- *
- * @var array
- * @access private
- */
- protected $streams = array();
- /**
- * --with configure options
- *
- * @var array
- * @access private
- */
- protected $with = array();
- /**
- * pear installer channel name
- *
- * @var string
- * @access private
- */
- protected $channel = "pecl.php.net";
- /**
- * phpdoc reference purpose
- *
- * See http://doc.php.net/php/en/dochowto/x1257.php for details
- *
- * @var string
- * @access private
- */
- protected $docPurpose = "utilspec";
- // }}}
- // {{{ constructor
- /**
- * The constructor
- *
- * @access public
- */
- function __construct()
- {
- $this->release = new CodeGen_PECL_Release;
- $this->platform = new CodeGen_PECL_Dependency_Platform("all");
- parent::__construct();
- }
- // }}}
- // {{{ member adding functions
- /**
- * Add a function to the extension
- *
- * @access public
- * @param object a function object
- */
- function addFunction(CodeGen_PECL_Element_Function $function)
- {
- $name = $function->getName();
- $role = $function->getRole();
- switch ($role) {
- case "public":
- if (isset($this->functions[$name])) {
- return PEAR::raiseError("public function '$name' has been defined before");
- }
- $this->functions[$name] = $function;
- return true;
- case "private":
- return PEAR::raiseError("private functions are no longer supported, use <code> sections instead");
- case "internal":
- if (isset($this->internalFunctions[$name])) {
- return PEAR::raiseError("internal '$name' has been defined before");
- }
- $this->internalFunctions[$name] = $function;
- return true;
- default:
- return PEAR::raiseError("unnokwn function role '$role'");
- }
- }
- /**
- * Set target platform for generated code
- *
- * @access public
- * @param string platform name
- */
- function setPlatform($type)
- {
- $this->platform = new CodeGen_PECL_Dependency_Platform($type);
- if (PEAR::isError($this->platform)) {
- return $this->platform;
- }
- return true;
- }
- /**
- * Add a PHP constant to the extension
- *
- * @access public
- * @param object a constant object
- */
- function addConstant(CodeGen_PECL_Element_Constant $constant)
- {
- $name = $constant->getName();
- if (isset($this->constants[$name])) {
- return PEAR::raiseError("constant '$name' has been defined before");
- }
- $this->constants[$name] = $constant;
- return true;
- }
- /**
- * Add a PHP ini directive
- *
- * @access public
- * @param object a phpini object
- */
- function addPhpIni(CodeGen_PECL_Element_Ini $phpini)
- {
- $name = $phpini->getName();
- if (isset($this->phpini[$name])) {
- return PEAR::raiseError("php.ini directive '$name' has been defined before");
- }
- $this->phpini[$name] = $phpini;
- return true;
- }
- /**
- * Add a internal global variable
- *
- * @access public
- * @param object a global object
- */
- function addGlobal(CodeGen_PECL_Element_Global $global)
- {
- $name = $global->getName();
- if (isset($this->globals[$name])) {
- return PEAR::raiseError("global '{$name}' has been defined before");
- }
- $this->globals[$name] = $global;
- return true;
- }
- /**
- * Add a PHP resource type
- *
- * @access public
- * @param object a resource object
- */
- function addResource(CodeGen_PECL_Element_Resource $resource)
- {
- $name = $resource->getName();
- if (isset($this->resources[$name])) {
- return PEAR::raiseError("resource type '{$name}' has been defined before");
- }
- $this->resources[$name] = $resource;
- return true;
- }
- /**
- * Get PHP resource types
- *
- * @access public
- * @return array
- */
- function getResources()
- {
- return $this->resources;
- }
- /**
- * Get a specific resource by name
- *
- * @access public
- * @param string resource name
- * @return object resource object or false if not found
- */
- function getResource($name)
- {
- if (isset($this->resources[$name])) {
- return $this->resources[$name];
- }
- return false;
- }
- /**
- * Get PHP constants
- *
- * @access public
- * @return array
- */
- function getConstants()
- {
- return $this->constants;
- }
- /**
- * Get a specific constant by name
- *
- * @access public
- * @param string constant name
- * @return object constant object or false if not found
- */
- function getConstant($name)
- {
- if (isset($this->constants[$name])) {
- return $this->constants[$name];
- }
- return false;
- }
- /**
- * Get a specific class by name
- *
- * @access public
- * @param string class name
- * @return object class object or false if not found
- */
- function getClass($name)
- {
- if (isset($this->classes[$name])) {
- return $this->classes[$name];
- }
- return false;
- }
- /**
- * Add a PHP class to the extension
- *
- * @access public
- * @param object a class object
- */
- function addClass(CodeGen_PECL_Element_Class $class)
- {
- if (isset($this->classes[$class->getName()])) {
- return PEAR::raiseError("class '".$class->getName()."' has been defined before");
- }
- $this->classes[$class->getName()] = $class;
- return true;
- }
- /**
- * Add a PHP interface to the extension
- *
- * @access public
- * @param object an interface object
- */
- function addInterface(CodeGen_PECL_Element_Interface $interface)
- {
- if (isset($this->interfaces[$interface->getName()])) {
- return PEAR::raiseError("interface '".$interface->getName()."' has been defined before");
- }
- $this->interfaces[$interface->getName()] = $interface;
- return true;
- }
- /**
- * Add a PHP stream wrapper to the extension
- *
- * @access public
- * @param object a stream wrapper object
- */
- function addStream(CodeGen_PECL_Element_Stream $stream)
- {
- if (isset($this->streams[$stream->getName()])) {
- return PEAR::raiseError("stream '".$stream->getName()."' has been defined before");
- }
- $this->streams[$stream->getName()] = $stream;
- return true;
- }
- /**
- * Add a --with configure option
- *
- * @access public
- * @param object 'With' object
- * @returns bool
- */
- function addWith(CodeGen_PECL_Dependency_With $with)
- {
- $name = $with->getName();
- if (isset($this->with[$name])) {
- return PEAR::raiseError("--with-{$name} declared twice");
- }
- $this->with[$name] = $with;
- return true;
- }
- /**
- * Add phpinfo logo
- *
- * @access public
- * @param object the logo
- */
- function addLogo(CodeGen_PECL_Element_Logo $logo)
- {
- $name = $logo->getName();
- if (isset($this->logos[$name])) {
- return PEAR::raiseError("logo '{$name}' already defined");
- }
- $this->logos[$name] = $logo;
- return true;
- }
- /**
- * Add cross-module dependency
- *
- * @param object extension dependency object
- */
- function addOtherExtension(CodeGen_PECL_Dependency_Extension $ext)
- {
- $name = $ext->getName();
- if (isset($this->otherExtensions[$name])) {
- return PEAR::raiseError("dependency to extension '{$name}' already defined");
- }
- $this->otherExtensions[$name] = $ext;
- return true;
- }
- /**
- * Generate #line specs?
- *
- * @access public
- * @param bool
- */
- function setLinespecs($state)
- {
- $this->linespecs = $state;
- }
- /**
- * linespec getter
- *
- * @access public
- * @return bool
- */
- function getLinespecs()
- {
- return $this->linespecs;
- }
- // }}}
- // {{{ output generation
- /**
- * Create the extensions including
- *
- * @access public
- * @param string Directory to create (default is ./$this->name)
- */
- function createExtension($dirpath = false, $force = false)
- {
- // default: create dir in current working directory,
- // dirname is the extensions base name
- if (!is_string($dirpath) || $dirpath == "") {
- $dirpath = "./" . $this->name;
- }
- // purge and create extension directory
- if ($dirpath !== ".") {
- if (!$force && file_exists($dirpath)) {
- return PEAR::raiseError("'$dirpath' already exists, can't create that directory (use '--force' to override)");
- } else if (!@System::mkdir("-p $dirpath")) {
- return PEAR::raiseError("can't create '$dirpath'");
- }
- }
- // make path absolute to be independant of working directory changes
- $this->dirpath = realpath($dirpath);
- // add "unknown" author if no authors specified
- if (empty($this->authors)) {
- $author = new CodeGen_PECL_Maintainer;
- $author->setUser("unknown");
- $author->setName("Unknown User");
- $author->setEmail("unknown@example.com");
- $author->setRole("lead");
- $this->addAuthor($author);
- }
- if (empty($this->description)) {
- $this->description = "none";
- }
- echo "Creating '{$this->name}' extension in '$dirpath'\n";
- // generate complete source code
- $this->generateSource();
- // copy additional source files
- if (isset($this->packageFiles['copy'])) {
- foreach ($this->packageFiles['copy'] as $targetpath => $sourcepath) {
- $targetpath = $this->dirpath."/".$targetpath;
- if (!is_dir(dirname($targetpath))) {
- mkdir(dirname($targetpath), 0777, true);
- }
- copy($sourcepath, $targetpath);
- }
- }
- // generate README file
- $this->writeReadme();
- // generate DocBook XML documantation for PHP manual
- $manpath = $this->dirpath . "/manual/";
- if (!@System::mkdir("-p $manpath")) {
- return PEAR::raiseError("can't create '$manpath'", E_USER_ERROR);
- }
- $this->generateDocumentation($manpath);
- }
- /**
- * Create the extensions code soure and project files
- *
- * @access public
- */
- function generateSource()
- {
- // generate source and header files
- $this->writeHeaderFile();
- $this->writeCodeFile();
- foreach ($this->logos as $logo) {
- $fp = new CodeGen_Tools_FileReplacer("{$this->dirpath}/".$logo->getName()."_logos.h");
- $fp->puts($logo->hCode());
- $fp->close();
- }
- // generate project files for configure (unices and similar platforms like cygwin)
- if ($this->platform->test("unix")) {
- $this->writeConfigM4();
- }
- // generate project files for Windows platform (VisualStudio/C++ V6)
- if ($this->platform->test("windows")) {
- $this->writeMsDevStudioDsp();
- $this->writeConfigW32();
- }
- // generate .cvsignore file entries
- $this->writeDotCvsignore();
- // generate EXPERIMENTAL file for unstable release states
- $this->writeExperimental();
- // generate CREDITS file
- $this->writeCredits();
- // generate LICENSE file if license given
- if ($this->license) {
- $this->license->writeToFile($this->dirpath."/LICENSE");
- $this->files['doc'][] = "LICENSE";
- }
- // generate test case templates
- $this->writeTestFiles();
- // generate PEAR/PECL package.xml file
- $this->writePackageXml();
- $this->writePackageXml2();
- }
- // {{{ docbook documentation
- /**
- * Create the extension documentation DocBook XML files
- *
- * @access public
- * @param string Directory to write to
- */
- function generateDocumentation($docdir)
- {
- $idName = str_replace('_', '-', $this->name);
- if (!@System::mkdir("-p $docdir/$idName")) {
- return PEAR::raiseError("can't create '$docdir/$idName'", E_USER_ERROR);
- }
- $manual = new CodeGen_Tools_FileReplacer("$docdir/manual.xml.in");
- $manual->puts("<?xml version='1.0' encoding='UTF-8' ?>
- <!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.1.2//EN'
- '@PHPDOC@/dtds/dbxml-4.1.2/docbookx.dtd' [
- <!-- Add translated specific definitions and snippets -->
- <!ENTITY % language-defs SYSTEM '@PHPDOC@/en/language-defs.ent'>
- <!ENTITY % language-snippets SYSTEM '@PHPDOC@/en/language-snippets.ent'>
- %language-defs;
- %language-snippets;
- <!-- Fallback to English definitions and snippets (in case of missing translation) -->
- <!ENTITY % language-defs.default SYSTEM '@PHPDOC@/en/language-defs.ent'>
- <!ENTITY % language-snippets.default SYSTEM '@PHPDOC@/en/language-snippets.ent'>
- <!ENTITY % extensions.default SYSTEM '@PHPDOC@/en/extensions.ent'>
- %language-defs.default;
- %language-snippets.default;
- %extensions.default;
- <!-- All global entities for the XML files -->
- <!ENTITY % global.entities SYSTEM '@PHPDOC@/entities/global.ent'>
- <!ENTITY % file.entities SYSTEM './file-entities.ent'>
- <!-- Include all external DTD parts defined previously -->
- %global.entities;
- %file.entities;
- <!-- Autogenerated missing entites and IDs to make build work -->
- <!ENTITY % missing-entities SYSTEM '@PHPDOC@/entities/missing-entities.ent'>
- %missing-entities;
- ]>
- <book id='manual' lang='en'>
- &reference.$idName.reference;
- </book>
- ");
- $manual->close();
- $makefile = new CodeGen_Tools_FileReplacer("$docdir/Makefile");
- $makefile->puts("#
- all: html
- confcheck:
- \t@if test \"x$(PHPDOC)\" = \"x\"; then echo PHPDOC not set; exit 3; fi
- manual.xml: manual.xml.in
- \tsed -e's:@PHPDOC@:\$(PHPDOC):g' < manual.xml.in > manual.xml
- html: confcheck manual.xml
- \trm -rf html; mkdir html
- \tSP_ENCODING=XML SP_CHARSET_FIXED=YES openjade -D $(PHPDOC) -wno-idref -c $(PHPDOC)/docbook/docbook-dsssl/catalog -c $(PHPDOC)/phpbook/phpbook-dsssl/defaults/catalog -d $(PHPDOC)/phpbook/phpbook-dsssl/html.dsl -V use-output-dir -t sgml $(PHPDOC)/phpbook/phpbook-xml/phpdocxml.dcl manual.xml
- bightml: confcheck manual.xml
- \trm -rf html; mkdir html
- \tSP_ENCODING=XML SP_CHARSET_FIXED=YES openjade -D $(PHPDOC) -wno-idref -c $(PHPDOC)/docbook/docbook-dsssl/catalog -c $(PHPDOC)/phpbook/phpbook-dsssl/defaults/catalog -d $(PHPDOC)/phpbook/phpbook-dsssl/html.dsl -V nochunks -t sgml $(PHPDOC)/phpbook/phpbook-xml/phpdocxml.dcl manual.xml > manual.html
- tex: manual.tex
- manual.tex: confcheck manual.xml
- \tSP_ENCODING=XML SP_CHARSET_FIXED=YES openjade -D $(PHPDOC) -wno-idref -c $(PHPDOC)/docbook/docbook-dsssl/catalog -c $(PHPDOC)/phpbook/phpbook-dsssl/defaults/catalog -d $(PHPDOC)/phpbook/phpbook-dsssl/print.dsl -t tex $(PHPDOC)/phpbook/phpbook-xml/phpdocxml.dcl manual.xml
- pdf: manual.tex
- \tpdfjadetex manual.tex && pdfjadetex manual.tex && pdfjadetex manual.tex
- ");
- $makefile->close();
- $entities = new CodeGen_Tools_FileReplacer("$docdir/file-entities.ent");
- $entities->puts("<!ENTITY reference.$idName.reference SYSTEM './$idName/reference.xml'>\n");
- $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/reference.xml");
- $fp->puts(
- "<?xml version='1.0' encoding='iso-8859-1'?>
- <!-- ".'$'."Revision: 1.1 $ -->
- ");
- // phpdoc comments according to http://doc.php.net/php/de/dochowto/x1257.php
- $fp->puts("<!-- Purpose: ".$this->docPurpose." -->\n");
- $fp->puts("<!-- Membership: pecl");
- if (count($this->with)) {
- $fp->puts(", external");
- }
- $fp->puts(" -->\n");
- if ($this->release->getState() !== 'stable') {
- $fp->puts("<!-- State: experimental -->\n");
- }
- $fp->puts("
- <reference xml:id='ref.$idName' xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>
- <title>{$this->summary}</title>
- <titleabbrev>$idName</titleabbrev>
- <partintro>
- <section id='$idName.intro'>
- &reftitle.intro;
- <para>
- {$this->description}
- </para>
- </section>
- <section xml:id='$idName.requirements'>
- &reftitle.required;
- <para>
- </para>
- </section>
- &reference.$idName.configure;
- &reference.extname.ini;
- <section id='$idName.resources'>
- &reftitle.resources;
- ");
- if (empty($this->resources)) {
- $fp->puts(" &no.resource;\n");
- } else {
- foreach ($this->resources as $resource) {
- $fp->puts($resource->docEntry($idName));
- }
- }
- $fp->puts(
- " </section>
- &reference.extname.constants;
- </partintro>
- &reference.$idName.functions;
- </reference>
- ");
- $fp->puts($this->docEditorSettings());
- $fp->close();
- //
- // constants.xml
- //
- $entities->puts("<!ENTITY reference.$idName.constants SYSTEM './$idName/constants.xml'>\n");
- $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/constants.xml");
- $fp->puts(
- "<?xml version='1.0' encoding='iso-8859-1'?>
- <!-- ".'$'."Revision: 1.1 $ -->
- ");
- $fp->puts("<section id='$idName.constants' xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>\n");
- $fp->puts(" &reftitle.constants;\n");
- $fp->puts(" &extension.constants;\n");
- $fp->puts(" <para>\n");
- if (empty($this->constants)) {
- $fp->puts(" &no.constants;\n");
- } else {
- $const_groups = array();
- foreach ($this->constants as $constant) {
- $const_groups[$constant->getGroup()][] = $constant;
- }
- foreach ($const_groups as $group => $constants) {
- if ($group == "default") {
- $group = $idName;
- }
- $fp->puts(CodeGen_PECL_Element_Constant::docHeader($group));
- foreach ($constants as $constant) {
- $fp->puts($constant->docEntry($group));
- }
- $fp->puts(CodeGen_PECL_Element_Constant::docFooter());
- }
- }
- // TODO: 2nd half missing, see http://doc.php.net/php/de/dochowto/c578.php
- $fp->puts(" </para>\n");
- $fp->puts("</section>\n");
- $fp->puts($this->docEditorSettings());
- $fp->close();
- //
- // ini.xml
- //
- $entities->puts("<!ENTITY reference.$idName.ini SYSTEM './$idName/ini.xml'>\n");
- $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/ini.xml");
- $fp->puts(
- "<?xml version='1.0' encoding='iso-8859-1'?>
- <!-- ".'$'."Revision: 1.1 $ -->
- ");
- $fp->puts("<section id='$idName.configuration' xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>\n");
- $fp->puts(" &reftitle.runtime;\n");
- $fp->puts(" &extension.runtime;\n");
- $fp->puts(" <para>\n");
- if (empty($this->phpini)) {
- $fp->puts(" &no.config;\n");
- } else {
- $fp->puts(CodeGen_PECL_Element_Ini::docHeader($this->name));
- foreach ($this->phpini as $phpini) {
- $fp->puts($phpini->docEntry($idName));
- }
- $fp->puts(CodeGen_PECL_Element_Ini::docFooter());
- }
- $fp->puts(" </para>\n");
- $fp->puts("</section>\n");
- $fp->puts($this->docEditorSettings());
- $fp->close();
- //
- // configure.xml
- //
- // configure options and dependencies have their own file
- $entities->puts("<!ENTITY reference.$idName.configure SYSTEM './$idName/configure.xml'>\n");
- $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/configure.xml");
- $fp->puts(
- "<?xml version='1.0' encoding='iso-8859-1'?>
- <!-- ".'$'."Revision: 1.1 $ -->
- ");
- $fp->puts("\n <section id='$idName.requirements'>\n &reftitle.required;\n");
- // TODO headers and libs are now "hidden" in $with
- if (empty($this->libs) && empty($this->headers)) {
- $fp->puts(" &no.requirement;\n");
- } else {
- // TODO allow custom text
- if (isset($this->libs)) {
- $libs = array();
- foreach ($this->libs as $lib) {
- $libs[] = $lib->getName();
- }
- $ies = count($libs)>1 ? "ies" :"y";
- $fp->puts("<para>This extension requires the following librar$ies: ".join(",", $libs)."</para>\n");
- }
- if (isset($this->headers)) {
- $headers = array();
- foreach ($this->headers as $header) {
- $headers[] = $header->getName();
- }
- $s = count($headers)>1 ? "s" : "";
- $fp->puts("<para>This extension requires the following header$s: ".join(",", $headers)."</para>\n");
- }
- }
- $fp->puts("\n </section>\n\n");
- $fp->puts("\n <section id='$idName.install'>\n &reftitle.install;\n");
- if (empty($this->with)) {
- $fp->puts(" &no.install;\n");
- } else {
- foreach ($this->with as $with) {
- if (isset($with->summary)) {
- if (strstr($with->summary, "<para>")) {
- $fp->puts($with->summary);
- } else {
- $fp->puts(" <para>\n".rtrim($with->summary)."\n </para>\n");
- }
- } else {
- $fp->puts(" <para>Requires <literal>".$with->getName()."</literal></para>\n");
- }
- }
- }
- $fp->puts("\n </section>\n\n");
- $fp->puts($this->docEditorSettings());
- $fp->close();
- //
- $function_entities = array();
- @mkdir("$docdir/$idName/functions");
- foreach ($this->functions as $name => $function) {
- $functionId = strtolower(str_replace("_", "-", $name));
- $filepath = "$idName/functions/$functionId.xml";
- $entity = "reference.$idName.functions.$functionId";
- $function_entities[] = $entity;
- $entities->puts("<!ENTITY $entity SYSTEM './$filepath'>\n");
- $funcfile = new CodeGen_Tools_FileReplacer("$docdir$filepath");
- $funcfile->puts($function->docEntry($idName));
- $funcfile->puts($this->docEditorSettings(4));
- $funcfile->close();
- }
- $entities->puts("<!ENTITY reference.$idName.functions SYSTEM './functions.xml'>\n");
- $entities->close();
- $functionsXml = new CodeGen_Tools_FileReplacer($docdir."/functions.xml");
- sort($function_entities);
- foreach ($function_entities as $entity) {
- $functionsXml->puts(" &$entity;\n");
- }
- $functionsXml->close();
- }
- // }}}
- // {{{ extension entry
- /**
- * Create the module entry code for this extension
- *
- * @access private
- * @return string zend_module_entry code fragment
- */
- function generateExtensionEntry()
- {
- $name = $this->name;
- $upname = strtoupper($this->name);
- $code = "";
- if (empty($this->otherExtensions)) {
- $moduleHeader = " STANDARD_MODULE_HEADER,";
- } else {
- $code.= CodeGen_PECL_Dependency_Extension::cCodeHeader($this);
- foreach ($this->otherExtensions as $ext) {
- $code.= $ext->cCode($this);
- }
- $code.= CodeGen_PECL_Dependency_Extension::cCodeFooter($this);
- $moduleHeader =
- "#if ZEND_EXTENSION_API_NO >= 220050617
- STANDARD_MODULE_HEADER_EX, NULL,
- {$this->name}_deps,
- #else
- STANDARD_MODULE_HEADER,
- #endif
- ";
- }
- $code.= "
- /* {{{ {$name}_module_entry
- */
- zend_module_entry {$name}_module_entry = {
- $moduleHeader
- \"$name\",
- {$name}_functions,
- PHP_MINIT($name), /* Replace with NULL if there is nothing to do at php startup */
- PHP_MSHUTDOWN($name), /* Replace with NULL if there is nothing to do at php shutdown */
- PHP_RINIT($name), /* Replace with NULL if there is nothing to do at request start */
- PHP_RSHUTDOWN($name), /* Replace with NULL if there is nothing to do at request end */
- PHP_MINFO($name),
- PHP_".$upname."_VERSION,
- STANDARD_MODULE_PROPERTIES
- };
- /* }}} */
- ";
- $code .= "#ifdef COMPILE_DL_$upname\n";
- if ($this->language == "cpp") {
- $code .= "extern \"C\" {\n";
- }
- $code .= "ZEND_GET_MODULE($name)\n";
- if ($this->language == "cpp") {
- $code .= "} // extern \"C\"\n";
- }
- $code .= "#endif\n\n";
- return $code;
- }
- // }}}
- // {{{ globals and ini
- /**
- * Create the module globals c code fragment
- *
- * @access private
- * @return string module globals code fragment
- */
- function generateGlobalsC()
- {
- if (empty($this->globals)) return "";
- $code = "\n/* {{{ globals and ini entries */\n";
- $code .= "ZEND_DECLARE_MODULE_GLOBALS({$this->name})\n\n";
- if (!empty($this->phpini)) {
- $code .= CodeGen_PECL_Element_Ini::cCodeHeader($this->name);
- foreach ($this->phpini as $phpini) {
- $code .= $phpini->cCode($this->name);
- }
- $code .= CodeGen_PECL_Element_Ini::cCodeFooter($this->name);
- }
- if (!empty($this->globals)) {
- $code .= CodeGen_PECL_Element_Global::cCodeHeader($this->name);
- foreach ($this->globals as $global) {
- $code .= $global->cCode($this->name);
- }
- $code .= CodeGen_PECL_Element_Global::cCodeFooter($this->name);
- }
- $code .= "/* }}} */\n\n";
- return $code;
- }
- /**
- * Create the module globals c header file fragment
- *
- * @access private
- * @return string module globals code fragment
- */
- function generateGlobalsH()
- {
- if (empty($this->globals)) return "";
- $code = CodeGen_PECL_Element_Global::hCodeHeader($this->name);
- foreach ($this->globals as $global) {
- $code .= $global->hCode($this->name);
- }
- $code .= CodeGen_PECL_Element_Global::hCodeFooter($this->name);
- return $code;
- }
- // }}}
- // {{{
- /**
- * Create global function registration
- *
- * @access private
- * @return string function registration code fragments
- */
- function generateFunctionRegistrations()
- {
- $code = "/* {{{ {$this->name}_functions[] */\n";
- $code .= "function_entry {$this->name}_functions[] = {\n";
- foreach ($this->functions as $function) {
- $code.= $function->functionEntry();
- }
- foreach ($this->classes as $class) {
- $code.= $class->functionAliasEntries();
- }
- $code .= " { NULL, NULL, NULL }\n";
- $code .= "};\n/* }}} */\n\n";
- return $code;
- }
- // }}}
- // {{{
- /**
- * Create global class registration code and functions
- *
- * @access private
- * @return string class registration code fragments
- */
- function generateClassRegistrations()
- {
- if (empty($this->classes)) return "";
- $code = "/* {{{ Class definitions */\n\n";
- foreach ($this->classes as $class) {
- $code .= $class->globalCode($this);
- }
- $code .= "/* }}} Class definitions*/\n\n";
- return $code;
- }
- // }}}
- // {{{
- /**
- * Create global interface registration code
- *
- * @access private
- * @return string interface registration code fragments
- */
- function generateInterfaceRegistrations()
- {
- if (empty($this->interfaces)) return "";
- $code = "/* {{{ Interface definitions */\n\n";
- foreach ($this->interfaces as $interface) {
- $code .= $interface->globalCode($this);
- }
- $code .= "/* }}} Interface definitions*/\n\n";
- return $code;
- }
- // }}}
- // {{{ license and authoers
- /**
- * Set license
- *
- * @access public
- * @param object
- */
- function setLicense($license)
- {
- if (preg_match("|^GPL|", $license->getShortName())) {
- return PEAR::raiseError("The ".$license->getShortName().
- "is not a valid choice for PHP extensions due to license incompatibilities");
- }
- $this->license = $license;
- return true;
- }
- /**
- * Create the license part of the source file header comment
- *
- * @access private
- * @return string code fragment
- */
- function getLicenseComment()
- {
- $code = "/*\n";
- $code.= " +----------------------------------------------------------------------+\n";
- if (is_object($this->license)) {
- $code.= $this->license->getComment();
- } else {
- $code.= sprintf(" | unknown license: %-52s |\n", $this->license);
- }
- $code.= " +----------------------------------------------------------------------+\n";
- foreach ($this->authors as $author) {
- $code.= $author->comment();
- }
- $code.= " +----------------------------------------------------------------------+\n";
- $code.= "*/\n\n";
- $code.= "/* $ Id: $ */ \n\n";
- return $code;
- }
- // }}}
- /**
- * Set pear installer channel
- *
- * @access public
- * @param string
- */
- function setChannel($channel)
- {
- if (! preg_match('/^[a-z\-_\.]+$/i', $channel)) {
- return PEAR::raiseError("'$channel' is not a valid pear installer channel name");
- }
- $this->channel = $channel;
- }
- // {{{ header file
- /**
- * Write the complete C header file
- *
- * @access private
- * @param string directory to write to
- */
- function writeHeaderFile()
- {
- $this->addPackageFile('header', "php_{$this->name}.h");
- $file = new CodeGen_Tools_Outbuf($this->dirpath."/php_{$this->name}.h");
- $upname = strtoupper($this->name);
- echo $this->getLicenseComment();
- echo "#ifndef PHP_{$upname}_H\n";
- echo "#define PHP_{$upname}_H\n\n";
- foreach ($this->headers as $header) {
- echo $header->hCode(true);
- }
- echo "#ifdef __cplusplus\n";
- echo "extern \"C\" {\n";
- echo "#endif\n";
- echo '
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <php.h>
- #ifdef HAVE_'.$upname.'
- ';
- echo '#define PHP_'.$upname.'_VERSION "'.$this->release->getVersion().'"'."\n\n";
- echo '
- #include <php_ini.h>
- #include <SAPI.h>
- #include <ext/standard/info.h>
- #include <Zend/zend_extensions.h>
- ';
- echo "#ifdef __cplusplus\n";
- echo "} // extern \"C\" \n";
- echo "#endif\n";
- foreach ($this->headers as $header) {
- echo $header->hCode(false);
- }
- foreach ($this->with as $with) {
- foreach ($with->getHeaders() as $header) {
- echo $header->hCode(false);
- }
- }
- if (isset($this->code["header"]["top"])) {
- foreach ($this->code["header"]["top"] as $code) {
- echo $this->codegen->block($code, 0);
- }
- }
- echo "#ifdef __cplusplus\n";
- echo "extern \"C\" {\n";
- echo "#endif\n";
- echo "
- extern zend_module_entry {$this->name}_module_entry;
- #define phpext_{$this->name}_ptr &{$this->name}_module_entry
- #ifdef PHP_WIN32
- #define PHP_{$upname}_API __declspec(dllexport)
- #else
- #define PHP_{$upname}_API
- #endif
- PHP_MINIT_FUNCTION({$this->name});
- PHP_MSHUTDOWN_FUNCTION({$this->name});
- PHP_RINIT_FUNCTION({$this->name});
- PHP_RSHUTDOWN_FUNCTION({$this->name});
- PHP_MINFO_FUNCTION({$this->name});
- #ifdef ZTS
- #include \"TSRM.h\"
- #endif
- #define FREE_RESOURCE(resource) zend_list_delete(Z_LVAL_P(resource))
- #define PROP_GET_LONG(name) Z_LVAL_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
- #define PROP_SET_LONG(name, l) zend_update_property_long(_this_ce, _this_zval, #name, strlen(#name), l TSRMLS_CC)
- #define PROP_GET_DOUBLE(name) Z_DVAL_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
- #define PROP_SET_DOUBLE(name, d) zend_update_property_double(_this_ce, _this_zval, #name, strlen(#name), d TSRMLS_CC)
- #define PROP_GET_STRING(name) Z_STRVAL_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
- #define PROP_GET_STRLEN(name) Z_STRLEN_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
- #define PROP_SET_STRING(name, s) zend_update_property_string(_this_ce, _this_zval, #name, strlen(#name), s TSRMLS_CC)
- #define PROP_SET_STRINGL(name, s, l) zend_update_property_stringl(_this_ce, _this_zval, #name, strlen(#name), s, l TSRMLS_CC)
- ";
- echo $this->generateGlobalsH();
- echo "\n";
- foreach ($this->functions as $name => $function) {
- echo $function->hCode($this);
- }
- foreach ($this->classes as $name => $class) {
- echo $class->hCode($this);
- }
- foreach ($this->interfaces as $name => $interface) {
- echo $interface->hCode($this);
- }
- foreach ($this->streams as $name => $stream) {
- echo $this->codegen->block($stream->hCode());
- }
- echo "#ifdef __cplusplus\n";
- echo "} // extern \"C\" \n";
- echo "#endif\n";
- echo "\n";
- // write #defines for <constant>s
- $defines = "";
- foreach ($this->constants as $constant) {
- $defines.= $constant->hCode($this);
- }
- if ($defines !== "") {
- echo "/* mirrored PHP Constants */\n";
- echo $defines;
- echo "\n";
- }
- // add bottom header snippets
- if (isset($this->code["header"]["bottom"])) {
- echo "/* 'bottom' header snippets*/\n";
- foreach ($this->code["header"]["bottom"] as $code) {
- echo $this->codegen->block($code, 0);
- }
- echo "\n";
- }
- echo "#endif /* PHP_HAVE_{$upname} */\n\n";
- echo "#endif /* PHP_{$upname}_H */\n\n";
- echo $this->cCodeEditorSettings();
- return $file->write();
- }
- // }}}
- // {{{ internal functions
- /**
- * Create code for the internal functions like MINIT etc ...
- *
- * @access private
- * @return string code snippet
- */
- function internalFunctionsC()
- {
- $need_block = false;
- $code = "
- /* {{{ PHP_MINIT_FUNCTION */
- PHP_MINIT_FUNCTION({$this->name})
- {
- ";
- if (count($this->globals)) {
- $code .= " ZEND_INIT_MODULE_GLOBALS({$this->name}, php_{$this->name}_init_globals, php_{$this->name}_shutdown_globals)\n";
- $need_block = true;
- }
- if (count($this->phpini)) {
- $code .= " REGISTER_INI_ENTRIES();\n";
- $need_block = true;
- }
- foreach ($this->logos as $logo) {
- $code .= $this->codegen->block($logo->minitCode());
- $need_block = true;
- }
- if (count($this->constants)) {
- foreach ($this->constants as $constant) {
- $code .= $this->codegen->block($constant->cCode($this->name));
- }
- $need_block = true;
- }
- if (count($this->resources)) {
- foreach ($this->resources as $resource) {
- $code .= $this->codegen->block($resource->minitCode());
- }
- $need_block = true;
- }
- if (count($this->interfaces)) {
- foreach ($this->interfaces as $interface) {
- $code .= $this->codegen->block($interface->minitCode($this));
- }
- $need_block = true;
- }
- if (count($this->classes)) {
- foreach ($this->classes as $class) {
- $code .= $this->codegen->block($class->minitCode($this));
- }
- $need_block = true;
- }
- if (count($this->streams)) {
- foreach ($this->streams as $stream) {
- $code .= $this->codegen->block($stream->minitCode($this));
- }
- $need_block = true;
- }
- if (isset($this->internalFunctions['MINIT'])) {
- $code .= $this->codegen->varblock($this->internalFunctions['MINIT']->getCode());
- } else {
- $code .="\n /* add your stuff here */\n";
- }
- $code .= "
- return SUCCESS;
- }
- /* }}} */
- ";
- $code .= "
- /* {{{ PHP_MSHUTDOWN_FUNCTION */
- PHP_MSHUTDOWN_FUNCTION({$this->name})
- {
- ";
- if (count($this->phpini)) {
- $code .= " UNREGISTER_INI_ENTRIES();\n";
- $need_block = true;
- }
- // TODO: need to destruct globals here if in ZTS mode!!111
- if (count($this->logos)) {
- foreach ($this->logos as $logo) {
- $code .= $this->codegen->block($logo->mshutdownCode());
- }
- $need_block = true;
- }
- if (isset($this->internalFunctions['MSHUTDOWN'])) {
- $code .= $this->codegen->varblock($this->internalFunctions['MSHUTDOWN']->getCode());
- } else {
- $code .="\n /* add your stuff here */\n";
- }
- $code .= "
- return SUCCESS;
- }
- /* }}} */
- ";
- $code .= "
- /* {{{ PHP_RINIT_FUNCTION */
- PHP_RINIT_FUNCTION({$this->name})
- {
- ";
- if (isset($this->internalFunctions['RINIT'])) {
- $code .= $this->codegen->block($this->internalFunctions['RINIT']->getCode());
- } else {
- $code .= " /* add your stuff here */\n";
- }
- $code .= "
- return SUCCESS;
- }
- /* }}} */
- ";
- $code .= "
- /* {{{ PHP_RSHUTDOWN_FUNCTION */
- PHP_RSHUTDOWN_FUNCTION({$this->name})
- {
- ";
- if (isset($this->internalFunctions['RSHUTDOWN'])) {
- $code .= $this->codegen->block($this->internalFunctions['RSHUTDOWN']->getCode());
- } else {
- $code .= " /* add your stuff here */\n";
- }
- $code .= "
- return SUCCESS;
- }
- /* }}} */
- ";
- $code .= "
- /* {{{ PHP_MINFO_FUNCTION */
- PHP_MINFO_FUNCTION({$this->name})
- {
- ";
- if (!empty($this->logos)) {
- $code.= " if (!sapi_module.phpinfo_as_text) {\n";
- foreach ($this->logos as $logo) {
- $code.= $logo->phpinfoCode($this->name);
- }
- echo " }\n";
- }
- if (!empty($this->summary)) {
- $summary = strtr(trim($this->summary), array('"'=>'\\"'));
- $code .= " php_printf(\"$summary\\n\");\n";
- }
- $code.= " php_info_print_table_start();\n";
- if (!empty($this->release)) {
- $code .= $this->release->phpinfoCode($this->name);
- }
- if (count($this->authors)) {
- $code.= ' php_info_print_table_row(2, "Authors", "';
- foreach ($this->authors as $author) {
- $code.= $author->phpinfoCode($this->name).'\\n';
- }
- $code.= "\");\n";
- }
- $code.=
- " php_info_print_table_end();
- ";
- // TODO move this decision up?
- if (isset($this->internalFunctions['MINFO'])) {
- $code .= $this->codegen->varblock($this->internalFunctions['MINFO']->getCode());
- } else {
- $code .= " /* add your stuff here */\n";
- }
- if (count($this->phpini)) {
- $code .= "\n DISPLAY_INI_ENTRIES();";
- }
- $code .= "
- }
- /* }}} */
- ";
- return $code;
- }
- // }}}
- // {{{ public functions
- /**
- * Create code for the exported PHP functions
- *
- * @access private
- * @return string code snippet
- */
- function publicFunctionsC()
- {
- $code = "";
- foreach ($this->functions as $function) {
- $code .= $function->cCode($this);
- }
- return $code;
- }
- // }}}
- // {{{ code file
- /**
- * Write the complete C code file
- *
- * @access private
- * @param string directory to write to
- */
- function writeCodeFile()
- {
- $filename = "{$this->name}.{$this->language}"; // todo extension logic
- $upname = strtoupper($this->name);
- $this->addPackageFile('code', $filename);
- $file = new CodeGen_Tools_Outbuf($this->dirpath.'/'.$filename, CodeGen_Tools_Outbuf::OB_TABIFY);
- echo $this->getLicenseComment();
- echo "#include \"php_{$this->name}.h\"\n\n";
- echo "#if HAVE_$upname\n\n";
- if (isset($this->code["code"]["top"])) {
- foreach ($this->code["code"]["top"] as $code) {
- echo $this->codegen->block($code, 0);
- }
- }
- if (!empty($this->logos)) {
- echo CodeGen_PECL_Element_Logo::cCodeHeader($this->name);
- foreach ($this->logos as $logo) {
- echo $logo->cCode($this->name);
- }
- echo CodeGen_PECL_Element_Logo::cCodeFooter($this->name);
- }
- if (!empty($this->resources)) {
- echo CodeGen_PECL_Element_Resource::cCodeHeader($this->name);
- foreach ($this->resources as $resource) {
- echo $resource->cCode($this);
- }
- echo CodeGen_PECL_Element_Resource::cCodeFooter($this->name);
- }
- echo $this->generateInterfaceRegistrations();
- echo $this->generateClassRegistrations();
- echo $this->generateFunctionRegistrations();
- echo $this->generateExtensionEntry();
- echo $this->generateGlobalsC();
- echo $this->internalFunctionsC();
- echo $this->publicFunctionsC();
- if (isset($this->code["code"]["bottom"])) {
- foreach ($this->code["code"]["bottom"] as $code) {
- echo $this->codegen->block($code, 0);
- }
- }
- echo "#endif /* HAVE_$upname */\n\n";
- echo $this->cCodeEditorSettings();
- return $file->write();
- }
- // }}}
- // {{{ config.m4 file
- /**
- * Write config.m4 file for autoconf
- *
- * @access private
- * @param string directory to write to
- */
- function writeConfigM4()
- {
- $upname = strtoupper($this->name);
- $this->addPackageFile("conf", "config.m4");
- $file = new CodeGen_Tools_Outbuf($this->dirpath."/config.m4", CodeGen_Tools_Outbuf::OB_TABIFY);
- echo
- 'dnl
- dnl $ Id: $
- dnl
- ';
- if (isset($this->with[$this->name])) {
- $with = $this->with[$this->name];
- echo "\n".$with->m4Line()."\n";
- } else {
- echo "
- PHP_ARG_ENABLE({$this->name}, whether to enable {$this->name} functions,
- [ --enable-{$this->name} Enable {$this->name} support])
- ";
- }
- echo "\n";
- echo "if test \"\$PHP_$upname\" != \"no\"; then\n";
- if ($this->language === "cpp") {
- echo " PHP_REQUIRE_CXX\n";
- echo " AC_LANG_CPLUSPLUS\n";
- echo " PHP_ADD_LIBRARY(stdc++,,{$upname}_SHARED_LIBADD)\n";
- }
- foreach ($this->configfragments['top'] as $fragment) {
- echo "$fragment\n";
- }
- foreach ($this->with as $with) {
- echo $with->configm4($this);
- }
- $pathes = array();
- foreach ($this->headers as $header) {
- $pathes[$header->getPath()] = true; // TODO WTF???
- }
- foreach (array_keys($pathes) as $path) {
- echo " PHP_ADD_INCLUDE(\$PHP_{$upname}_DIR/$path)\n";
- }
- echo " export OLD_CPPFLAGS=\"\$CPPFLAGS\"\n";
- echo " export CPPFLAGS=\"\$CPPFLAGS \$INCLUDES -DHAVE_".strtoupper($this->name)."\"\n";
- echo "
- AC_MSG_CHECKING(PHP version)
- AC_TRY_COMPILE([#include <php_version.h>], [
- #if PHP_VERSION_ID < ".$this->minPhpVersionId()."
- #error this extension requires at least PHP version ".$this->minPhpVersion()."
- #endif
- ],
- [AC_MSG_RESULT(ok)],
- [AC_MSG_ERROR([need at least PHP ".$this->minPhpVersion()."])])
- ";
- if (count($this->headers)) {
- if (!isset($this->with[$this->name])) {
- $this->terminate("global headers not bound to a --with option found and no --with option by the default name");
- }
- foreach ($this->headers as $header) {
- echo $header->configm4($this->name, $this->name);
- }
- }
- foreach ($this->resources as $resource) {
- echo $resource->configm4($this->name);
- }
- echo " export CPPFLAGS=\"\$OLD_CPPFLAGS\"\n";
- if (count($this->libs)) {
- if (!isset($this->with[$this->name])) {
- $this->terminate("global libs not bound to a --with option found and no --with option by the default name");
- }
- foreach ($this->libs as $lib) {
- echo $lib->configm4($this->name, $this->name);
- }
- }
- echo "\n";
- echo "
- PHP_SUBST({$upname}_SHARED_LIBADD)
- AC_DEFINE(HAVE_$upname, 1, [ ])
- ";
- …
Large files files are truncated, but you can click here to view the full file