PageRenderTime 10ms CodeModel.GetById 5ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 1ms

/CodeGen/PECL/Extension.php

https://github.com/lucciano/CodeGen_PECL
PHP | 2629 lines | 1774 code | 360 blank | 495 comment | 119 complexity | 6ae65736bf0ee5370005c811716fa686 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * A class that generates PECL extension soure and documenation files
   4 *
   5 * PHP versions 5
   6 *
   7 * LICENSE: This source file is subject to version 3.0 of the PHP license
   8 * that is available through the world-wide-web at the following URI:
   9 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10 * the PHP License and are unable to obtain it through the web, please
  11 * send a note to license@php.net so we can mail you a copy immediately.
  12 *
  13 * @category   Tools and Utilities
  14 * @package    CodeGen_PECL
  15 * @author     Hartmut Holzgraefe <hartmut@php.net>
  16 * @copyright  2005-2008 Hartmut Holzgraefe
  17 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18 * @version    CVS: $Id: Extension.php,v 1.75 2007/04/16 09:28:03 hholzgra Exp $
  19 * @version    CVS: $Id: Extension.php,v 1.75 2007/04/16 09:28:03 hholzgra Exp $
  20 * @link       http://pear.php.net/package/CodeGen_PECL
  21 */
  22
  23/**
  24 * includes
  25 */
  26require_once "System.php";
  27
  28require_once "CodeGen/Extension.php";
  29
  30require_once "CodeGen/PECL/Release.php";
  31
  32require_once "CodeGen/PECL/Element.php";
  33require_once "CodeGen/PECL/Element/Constant.php";
  34require_once "CodeGen/PECL/Element/Function.php";
  35require_once "CodeGen/PECL/Element/Resource.php";
  36require_once "CodeGen/PECL/Element/Ini.php";
  37require_once "CodeGen/PECL/Element/Global.php";
  38require_once "CodeGen/PECL/Element/Logo.php";
  39require_once "CodeGen/PECL/Element/Test.php";
  40require_once "CodeGen/PECL/Element/Class.php";
  41require_once "CodeGen/PECL/Element/Interface.php";
  42require_once "CodeGen/PECL/Element/Stream.php";
  43
  44require_once "CodeGen/PECL/Dependency/With.php";
  45require_once "CodeGen/PECL/Dependency/Lib.php";
  46require_once "CodeGen/PECL/Dependency/Header.php";
  47require_once "CodeGen/PECL/Dependency/Extension.php";
  48require_once "CodeGen/PECL/Dependency/Platform.php";
  49
  50/**
  51 * A class that generates PECL extension soure and documenation files
  52 *
  53 * @category   Tools and Utilities
  54 * @package    CodeGen_PECL
  55 * @author     Hartmut Holzgraefe <hartmut@php.net>
  56 * @copyright  2005-2008 Hartmut Holzgraefe
  57 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  58 * @version    Release: 1.1.3
  59 * @link       http://pear.php.net/package/CodeGen_PECL
  60 */
  61class CodeGen_PECL_Extension
  62    extends CodeGen_Extension
  63{
  64    /**
  65    * Current CodeGen_PECL version number
  66    *
  67    * @return string
  68    */
  69    function version()
  70    {
  71        return "1.1.3";
  72    }
  73
  74    /**
  75    * CodeGen_PECL Copyright message
  76    *
  77    * @return string
  78    */
  79    function copyright()
  80    {
  81        return "Copyright (c) 2003-2006 Hartmut Holzgraefe";
  82    }
  83
  84    // {{{ member variables
  85
  86    /**
  87     * The public PHP functions defined by this extension
  88     *
  89     * @var array
  90     */
  91    protected $functions = array();
  92
  93    /**
  94     * The extensions internal functions like MINIT
  95     *
  96     * @var array
  97     */
  98    protected $internalFunctions = array();
  99
 100    /**
 101     * The constants defined by this extension
 102     *
 103     * @var array
 104     */
 105    protected $constants = array();
 106
 107    /**
 108     * The PHP classes defined by this extension
 109     *
 110     * @var array
 111     */
 112    protected $classes = array();
 113
 114    /**
 115     * The PHP interfaces defined by this extension
 116     *
 117     * @var array
 118     */
 119    protected $interfaces = array();
 120
 121    /**
 122     * The extensions php.ini parameters
 123     *
 124     * @var array
 125     */
 126    protected $phpini    = array();
 127
 128    /**
 129     * The extensions internal global variables
 130     *
 131     * @var array
 132     */
 133    protected $globals    = array();
 134
 135    /**
 136     * The PHP resources defined by this extension
 137     *
 138     * @var array
 139     */
 140    protected $resources = array();
 141
 142    /**
 143     * Custom test cases
 144     *
 145     * @var array
 146     */
 147    protected $testcases = array();
 148
 149    /**
 150     * phpinfo logos
 151     *
 152     * @var    string
 153     * @access private
 154     */
 155    protected $logos = array();
 156
 157    /**
 158     * cross extension dependencies
 159     *
 160     * @var  array
 161     */
 162    protected $otherExtensions = array();
 163
 164    /**
 165     * generate #line specs?
 166     *
 167     * @var     bool
 168     * @access  private
 169     */
 170    protected $linespecs = false;
 171
 172    /**
 173     * PHP Streams
 174     *
 175     * @var    array
 176     * @access private
 177     */
 178    protected $streams = array();
 179
 180    /**
 181     * --with configure options
 182     *
 183     * @var    array
 184     * @access private
 185     */
 186    protected $with = array();
 187
 188    /**
 189     * pear installer channel name
 190     *
 191     * @var    string
 192     * @access private
 193     */
 194    protected $channel = "pecl.php.net";
 195
 196    /**
 197     * phpdoc reference purpose
 198     *
 199     * See http://doc.php.net/php/en/dochowto/x1257.php for details
 200     *
 201     * @var    string
 202     * @access private
 203     */
 204    protected $docPurpose = "utilspec";
 205
 206    // }}}
 207
 208    // {{{ constructor
 209
 210    /**
 211     * The constructor
 212     *
 213     * @access public
 214     */
 215    function __construct()
 216    {
 217        $this->release = new CodeGen_PECL_Release;
 218
 219        $this->platform = new CodeGen_PECL_Dependency_Platform("all");
 220
 221        parent::__construct();
 222    }
 223
 224    // }}}
 225
 226    // {{{ member adding functions
 227
 228    /**
 229     * Add a function to the extension
 230     *
 231     * @access public
 232     * @param  object   a function object
 233     */
 234    function addFunction(CodeGen_PECL_Element_Function $function)
 235    {
 236        $name = $function->getName();
 237        $role = $function->getRole();
 238
 239        switch ($role) {
 240        case "public":
 241            if (isset($this->functions[$name])) {
 242                return PEAR::raiseError("public function '$name' has been defined before");
 243            }
 244            $this->functions[$name] = $function;
 245            return true;
 246
 247        case "private":
 248            return PEAR::raiseError("private functions are no longer supported, use <code> sections instead");
 249
 250        case "internal":
 251            if (isset($this->internalFunctions[$name])) {
 252                return PEAR::raiseError("internal '$name' has been defined before");
 253            }
 254            $this->internalFunctions[$name] = $function;
 255            return true;
 256
 257        default:
 258            return PEAR::raiseError("unnokwn function role '$role'");
 259        }
 260    }
 261
 262    /**
 263     * Set target platform for generated code
 264     *
 265     * @access public
 266     * @param  string  platform name
 267     */
 268    function setPlatform($type)
 269    {
 270        $this->platform = new CodeGen_PECL_Dependency_Platform($type);
 271        if (PEAR::isError($this->platform)) {
 272            return $this->platform;
 273        }
 274
 275        return true;
 276    }
 277
 278    /**
 279     * Add a PHP constant to the extension
 280     *
 281     * @access public
 282     * @param  object   a constant object
 283     */
 284    function addConstant(CodeGen_PECL_Element_Constant $constant)
 285    {
 286        $name = $constant->getName();
 287
 288        if (isset($this->constants[$name])) {
 289            return PEAR::raiseError("constant '$name' has been defined before");
 290        }
 291        $this->constants[$name] = $constant;
 292
 293        return true;
 294    }
 295
 296    /**
 297     * Add a PHP ini directive
 298     *
 299     * @access public
 300     * @param  object   a phpini object
 301     */
 302    function addPhpIni(CodeGen_PECL_Element_Ini $phpini)
 303    {
 304        $name = $phpini->getName();
 305
 306        if (isset($this->phpini[$name])) {
 307            return PEAR::raiseError("php.ini directive '$name' has been defined before");
 308        }
 309        $this->phpini[$name] = $phpini;
 310
 311        return true;
 312    }
 313
 314    /**
 315     * Add a internal global variable
 316     *
 317     * @access public
 318     * @param  object   a global object
 319     */
 320    function addGlobal(CodeGen_PECL_Element_Global $global)
 321    {
 322        $name = $global->getName();
 323        if (isset($this->globals[$name])) {
 324            return PEAR::raiseError("global '{$name}' has been defined before");
 325        }
 326        $this->globals[$name] = $global;
 327
 328        return true;
 329    }
 330
 331    /**
 332     * Add a PHP resource type
 333     *
 334     * @access public
 335     * @param  object   a resource object
 336     */
 337    function addResource(CodeGen_PECL_Element_Resource $resource)
 338    {
 339        $name = $resource->getName();
 340        if (isset($this->resources[$name])) {
 341            return PEAR::raiseError("resource type '{$name}' has been defined before");
 342        }
 343        $this->resources[$name] = $resource;
 344
 345        return true;
 346    }
 347
 348    /**
 349     * Get PHP resource types
 350     *
 351     * @access public
 352     * @return array
 353     */
 354    function getResources()
 355    {
 356        return $this->resources;
 357    }
 358
 359    /**
 360     * Get a specific resource by name
 361     *
 362     * @access public
 363     * @param  string  resource name
 364     * @return object  resource object or false if not found
 365     */
 366    function getResource($name)
 367    {
 368        if (isset($this->resources[$name])) {
 369            return $this->resources[$name];
 370        }
 371
 372        return false;
 373    }
 374
 375    /**
 376     * Get PHP constants
 377     *
 378     * @access public
 379     * @return array
 380     */
 381    function getConstants()
 382    {
 383        return $this->constants;
 384    }
 385
 386    /**
 387     * Get a specific constant by name
 388     *
 389     * @access public
 390     * @param  string  constant name
 391     * @return object  constant object or false if not found
 392     */
 393    function getConstant($name)
 394    {
 395        if (isset($this->constants[$name])) {
 396            return $this->constants[$name];
 397        }
 398
 399        return false;
 400    }
 401
 402    /**
 403     * Get a specific class by name
 404     *
 405     * @access public
 406     * @param  string  class name
 407     * @return object  class object or false if not found
 408     */
 409    function getClass($name)
 410    {
 411        if (isset($this->classes[$name])) {
 412            return $this->classes[$name];
 413        }
 414
 415        return false;
 416    }
 417
 418    /**
 419     * Add a PHP class to the extension
 420     *
 421     * @access public
 422     * @param  object   a class object
 423     */
 424    function addClass(CodeGen_PECL_Element_Class $class)
 425    {
 426        if (isset($this->classes[$class->getName()])) {
 427            return PEAR::raiseError("class '".$class->getName()."' has been defined before");
 428        }
 429        $this->classes[$class->getName()] = $class;
 430
 431        return true;
 432    }
 433
 434    /**
 435     * Add a PHP interface to the extension
 436     *
 437     * @access public
 438     * @param  object   an interface object
 439     */
 440    function addInterface(CodeGen_PECL_Element_Interface $interface)
 441    {
 442        if (isset($this->interfaces[$interface->getName()])) {
 443            return PEAR::raiseError("interface '".$interface->getName()."' has been defined before");
 444        }
 445        $this->interfaces[$interface->getName()] = $interface;
 446
 447        return true;
 448    }
 449
 450    /**
 451     * Add a PHP stream wrapper to the extension
 452     *
 453     * @access public
 454     * @param  object   a stream wrapper object
 455     */
 456    function addStream(CodeGen_PECL_Element_Stream $stream)
 457    {
 458        if (isset($this->streams[$stream->getName()])) {
 459            return PEAR::raiseError("stream '".$stream->getName()."' has been defined before");
 460        }
 461        $this->streams[$stream->getName()] = $stream;
 462
 463        return true;
 464    }
 465
 466    /**
 467     * Add a --with configure option
 468     *
 469     * @access  public
 470     * @param   object 'With' object
 471     * @returns bool
 472     */
 473    function addWith(CodeGen_PECL_Dependency_With $with)
 474    {
 475        $name = $with->getName();
 476
 477        if (isset($this->with[$name])) {
 478            return PEAR::raiseError("--with-{$name} declared twice");
 479        }
 480
 481        $this->with[$name] = $with;
 482
 483        return true;
 484    }
 485
 486    /**
 487     * Add phpinfo logo
 488     *
 489     * @access public
 490     * @param  object  the logo
 491     */
 492    function addLogo(CodeGen_PECL_Element_Logo $logo)
 493    {
 494        $name = $logo->getName();
 495
 496        if (isset($this->logos[$name])) {
 497            return PEAR::raiseError("logo '{$name}' already defined");
 498        }
 499
 500        $this->logos[$name] = $logo;
 501
 502        return true;
 503    }
 504
 505    /**
 506     * Add cross-module dependency
 507     *
 508     * @param  object  extension dependency object
 509     */
 510    function addOtherExtension(CodeGen_PECL_Dependency_Extension $ext)
 511    {
 512        $name = $ext->getName();
 513
 514        if (isset($this->otherExtensions[$name])) {
 515            return PEAR::raiseError("dependency to extension '{$name}' already defined");
 516        }
 517
 518        $this->otherExtensions[$name] = $ext;
 519
 520        return true;
 521    }
 522
 523    /**
 524     * Generate #line specs?
 525     *
 526     * @access public
 527     * @param  bool
 528     */
 529    function setLinespecs($state)
 530    {
 531        $this->linespecs = $state;
 532    }
 533
 534    /**
 535     * linespec getter
 536     *
 537     * @access public
 538     * @return bool
 539     */
 540    function getLinespecs()
 541    {
 542        return $this->linespecs;
 543    }
 544
 545    // }}}
 546
 547    // {{{ output generation
 548
 549    /**
 550     * Create the extensions including
 551     *
 552     * @access public
 553     * @param  string Directory to create (default is ./$this->name)
 554     */
 555    function createExtension($dirpath = false, $force = false)
 556    {
 557        // default: create dir in current working directory,
 558        // dirname is the extensions base name
 559        if (!is_string($dirpath) || $dirpath == "") {
 560            $dirpath = "./" . $this->name;
 561        }
 562
 563        // purge and create extension directory
 564        if ($dirpath !== ".") {
 565            if (!$force && file_exists($dirpath)) {
 566                return PEAR::raiseError("'$dirpath' already exists, can't create that directory (use '--force' to override)");
 567            } else if (!@System::mkdir("-p $dirpath")) {
 568                return PEAR::raiseError("can't create '$dirpath'");
 569            }
 570        }
 571
 572        // make path absolute to be independant of working directory changes
 573        $this->dirpath = realpath($dirpath);
 574
 575        // add "unknown" author if no authors specified
 576        if (empty($this->authors)) {
 577            $author = new CodeGen_PECL_Maintainer;
 578            $author->setUser("unknown");
 579            $author->setName("Unknown User");
 580            $author->setEmail("unknown@example.com");
 581            $author->setRole("lead");
 582
 583            $this->addAuthor($author);
 584        }
 585
 586        if (empty($this->description)) {
 587            $this->description = "none";
 588        }
 589
 590        echo "Creating '{$this->name}' extension in '$dirpath'\n";
 591
 592        // generate complete source code
 593        $this->generateSource();
 594
 595        // copy additional source files
 596        if (isset($this->packageFiles['copy'])) {
 597            foreach ($this->packageFiles['copy'] as $targetpath => $sourcepath) {
 598                $targetpath = $this->dirpath."/".$targetpath;
 599                if (!is_dir(dirname($targetpath))) {
 600                    mkdir(dirname($targetpath), 0777, true);
 601                }
 602                copy($sourcepath, $targetpath);
 603            }
 604        }
 605
 606        // generate README file
 607        $this->writeReadme();
 608
 609        // generate DocBook XML documantation for PHP manual
 610        $manpath = $this->dirpath . "/manual/";
 611        if (!@System::mkdir("-p $manpath")) {
 612            return PEAR::raiseError("can't create '$manpath'", E_USER_ERROR);
 613        }
 614        $this->generateDocumentation($manpath);
 615    }
 616
 617    /**
 618     * Create the extensions code soure and project files
 619     *
 620     * @access public
 621     */
 622    function generateSource()
 623    {
 624        // generate source and header files
 625        $this->writeHeaderFile();
 626        $this->writeCodeFile();
 627
 628        foreach ($this->logos as $logo) {
 629            $fp = new CodeGen_Tools_FileReplacer("{$this->dirpath}/".$logo->getName()."_logos.h");
 630            $fp->puts($logo->hCode());
 631            $fp->close();
 632        }
 633
 634        // generate project files for configure (unices and similar platforms like cygwin)
 635        if ($this->platform->test("unix")) {
 636            $this->writeConfigM4();
 637        }
 638
 639        // generate project files for Windows platform (VisualStudio/C++ V6)
 640        if ($this->platform->test("windows")) {
 641            $this->writeMsDevStudioDsp();
 642            $this->writeConfigW32();
 643        }
 644
 645        // generate .cvsignore file entries
 646        $this->writeDotCvsignore();
 647
 648        // generate EXPERIMENTAL file for unstable release states
 649        $this->writeExperimental();
 650
 651        // generate CREDITS file
 652        $this->writeCredits();
 653
 654        // generate LICENSE file if license given
 655        if ($this->license) {
 656            $this->license->writeToFile($this->dirpath."/LICENSE");
 657            $this->files['doc'][] = "LICENSE";
 658        }
 659
 660        // generate test case templates
 661        $this->writeTestFiles();
 662
 663        // generate PEAR/PECL package.xml file
 664        $this->writePackageXml();
 665        $this->writePackageXml2();
 666    }
 667
 668    // {{{   docbook documentation
 669
 670    /**
 671     * Create the extension documentation DocBook XML files
 672     *
 673     * @access public
 674     * @param  string Directory to write to
 675     */
 676    function generateDocumentation($docdir)
 677    {
 678        $idName = str_replace('_', '-', $this->name);
 679
 680        if (!@System::mkdir("-p $docdir/$idName")) {
 681            return PEAR::raiseError("can't create '$docdir/$idName'", E_USER_ERROR);
 682        }
 683
 684        $manual = new CodeGen_Tools_FileReplacer("$docdir/manual.xml.in");
 685        $manual->puts("<?xml version='1.0' encoding='UTF-8' ?>
 686<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.1.2//EN'
 687          '@PHPDOC@/dtds/dbxml-4.1.2/docbookx.dtd' [
 688
 689<!-- Add translated specific definitions and snippets -->
 690<!ENTITY % language-defs     SYSTEM '@PHPDOC@/en/language-defs.ent'>
 691<!ENTITY % language-snippets SYSTEM '@PHPDOC@/en/language-snippets.ent'>
 692
 693%language-defs;
 694%language-snippets;
 695
 696<!-- Fallback to English definitions and snippets (in case of missing translation) -->
 697<!ENTITY % language-defs.default     SYSTEM '@PHPDOC@/en/language-defs.ent'>
 698<!ENTITY % language-snippets.default SYSTEM '@PHPDOC@/en/language-snippets.ent'>
 699<!ENTITY % extensions.default        SYSTEM '@PHPDOC@/en/extensions.ent'>
 700
 701%language-defs.default;
 702%language-snippets.default;
 703%extensions.default;
 704
 705<!-- All global entities for the XML files -->
 706<!ENTITY % global.entities  SYSTEM '@PHPDOC@/entities/global.ent'>
 707
 708<!ENTITY % file.entities      SYSTEM './file-entities.ent'>
 709
 710<!-- Include all external DTD parts defined previously -->
 711%global.entities;
 712%file.entities;
 713
 714<!-- Autogenerated missing entites and IDs to make build work -->
 715<!ENTITY % missing-entities  SYSTEM '@PHPDOC@/entities/missing-entities.ent'>
 716%missing-entities;
 717]>
 718
 719<book id='manual' lang='en'>
 720   &reference.$idName.reference;
 721</book>
 722");
 723        $manual->close();
 724
 725        $makefile = new CodeGen_Tools_FileReplacer("$docdir/Makefile");
 726        $makefile->puts("#
 727all: html
 728
 729confcheck:
 730\t@if test \"x$(PHPDOC)\" = \"x\"; then echo PHPDOC not set; exit 3; fi
 731
 732manual.xml: manual.xml.in
 733\tsed -e's:@PHPDOC@:\$(PHPDOC):g' < manual.xml.in > manual.xml
 734
 735html: confcheck manual.xml
 736\trm -rf html; mkdir html
 737\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
 738
 739bightml: confcheck manual.xml
 740\trm -rf html; mkdir html
 741\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
 742
 743tex: manual.tex
 744
 745manual.tex: confcheck manual.xml
 746\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
 747
 748pdf: manual.tex
 749\tpdfjadetex manual.tex && pdfjadetex manual.tex && pdfjadetex manual.tex
 750");
 751
 752        $makefile->close();
 753
 754        $entities = new CodeGen_Tools_FileReplacer("$docdir/file-entities.ent");
 755
 756        $entities->puts("<!ENTITY reference.$idName.reference SYSTEM './$idName/reference.xml'>\n");
 757        $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/reference.xml");
 758        $fp->puts(
 759"<?xml version='1.0' encoding='iso-8859-1'?>
 760<!-- ".'$'."Revision: 1.1 $ -->
 761");
 762
 763        // phpdoc comments according to http://doc.php.net/php/de/dochowto/x1257.php
 764        $fp->puts("<!-- Purpose: ".$this->docPurpose." -->\n");
 765
 766        $fp->puts("<!-- Membership: pecl");
 767        if (count($this->with)) {
 768            $fp->puts(", external");
 769        }
 770        $fp->puts(" -->\n");
 771
 772        if ($this->release->getState() !== 'stable') {
 773            $fp->puts("<!-- State: experimental -->\n");
 774        }
 775
 776        $fp->puts("
 777 <reference xml:id='ref.$idName' xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>
 778  <title>{$this->summary}</title>
 779  <titleabbrev>$idName</titleabbrev>
 780
 781  <partintro>
 782   <section id='$idName.intro'>
 783    &reftitle.intro;
 784    <para>
 785{$this->description}
 786    </para>
 787   </section>
 788
 789   <section xml:id='$idName.requirements'>
 790    &reftitle.required;
 791    <para>
 792
 793    </para>
 794   </section>
 795
 796   &reference.$idName.configure;
 797   &reference.extname.ini;
 798
 799   <section id='$idName.resources'>
 800    &reftitle.resources;
 801");
 802
 803        if (empty($this->resources)) {
 804            $fp->puts("   &no.resource;\n");
 805        } else {
 806            foreach ($this->resources as $resource) {
 807                $fp->puts($resource->docEntry($idName));
 808            }
 809        }
 810
 811        $fp->puts(
 812"   </section>
 813
 814   &reference.extname.constants;
 815  </partintro>
 816
 817&reference.$idName.functions;
 818
 819 </reference>
 820");
 821
 822        $fp->puts($this->docEditorSettings());
 823
 824        $fp->close();
 825
 826        //
 827        // constants.xml
 828        //
 829
 830        $entities->puts("<!ENTITY reference.$idName.constants SYSTEM './$idName/constants.xml'>\n");
 831
 832        $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/constants.xml");
 833
 834        $fp->puts(
 835"<?xml version='1.0' encoding='iso-8859-1'?>
 836<!-- ".'$'."Revision: 1.1 $ -->
 837");
 838
 839        $fp->puts("<section id='$idName.constants' xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>\n");
 840
 841        $fp->puts(" &reftitle.constants;\n");
 842        $fp->puts(" &extension.constants;\n");
 843
 844        $fp->puts(" <para>\n");
 845
 846        if (empty($this->constants)) {
 847            $fp->puts("    &no.constants;\n");
 848        } else {
 849            $const_groups = array();
 850            foreach ($this->constants as $constant) {
 851                $const_groups[$constant->getGroup()][] = $constant;
 852            }
 853            foreach ($const_groups as $group => $constants) {
 854                if ($group == "default") {
 855                    $group = $idName;
 856                }
 857                $fp->puts(CodeGen_PECL_Element_Constant::docHeader($group));
 858                foreach ($constants as $constant) {
 859                    $fp->puts($constant->docEntry($group));
 860                }
 861                $fp->puts(CodeGen_PECL_Element_Constant::docFooter());
 862            }
 863        }
 864
 865        // TODO: 2nd half missing, see http://doc.php.net/php/de/dochowto/c578.php
 866
 867        $fp->puts(" </para>\n");
 868        $fp->puts("</section>\n");
 869
 870        $fp->puts($this->docEditorSettings());
 871        $fp->close();
 872
 873        //
 874        // ini.xml
 875        //
 876
 877        $entities->puts("<!ENTITY reference.$idName.ini SYSTEM './$idName/ini.xml'>\n");
 878
 879        $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/ini.xml");
 880
 881        $fp->puts(
 882"<?xml version='1.0' encoding='iso-8859-1'?>
 883<!-- ".'$'."Revision: 1.1 $ -->
 884");
 885
 886        $fp->puts("<section id='$idName.configuration' xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>\n");
 887
 888        $fp->puts(" &reftitle.runtime;\n");
 889        $fp->puts(" &extension.runtime;\n");
 890
 891        $fp->puts(" <para>\n");
 892
 893        if (empty($this->phpini)) {
 894            $fp->puts("    &no.config;\n");
 895        } else {
 896            $fp->puts(CodeGen_PECL_Element_Ini::docHeader($this->name));
 897            foreach ($this->phpini as $phpini) {
 898                $fp->puts($phpini->docEntry($idName));
 899            }
 900            $fp->puts(CodeGen_PECL_Element_Ini::docFooter());
 901        }
 902
 903        $fp->puts(" </para>\n");
 904        $fp->puts("</section>\n");
 905
 906        $fp->puts($this->docEditorSettings());
 907        $fp->close();
 908
 909        //
 910        // configure.xml
 911        //
 912
 913        // configure options and dependencies have their own file
 914        $entities->puts("<!ENTITY reference.$idName.configure SYSTEM './$idName/configure.xml'>\n");
 915
 916        $fp = new CodeGen_Tools_FileReplacer("$docdir/$idName/configure.xml");
 917
 918        $fp->puts(
 919"<?xml version='1.0' encoding='iso-8859-1'?>
 920<!-- ".'$'."Revision: 1.1 $ -->
 921");
 922
 923        $fp->puts("\n   <section id='$idName.requirements'>\n    &reftitle.required;\n");
 924
 925        // TODO headers and libs are now "hidden" in $with
 926
 927        if (empty($this->libs) && empty($this->headers)) {
 928            $fp->puts("    &no.requirement;\n");
 929        } else {
 930            // TODO allow custom text
 931            if (isset($this->libs)) {
 932                $libs = array();
 933                foreach ($this->libs as $lib) {
 934                    $libs[] = $lib->getName();
 935                }
 936                $ies = count($libs)>1 ? "ies" :"y";
 937                $fp->puts("<para>This extension requires the following librar$ies: ".join(",", $libs)."</para>\n");
 938            }
 939            if (isset($this->headers)) {
 940                $headers = array();
 941                foreach ($this->headers as $header) {
 942                    $headers[] = $header->getName();
 943                }
 944                $s = count($headers)>1 ? "s" : "";
 945                $fp->puts("<para>This extension requires the following header$s: ".join(",", $headers)."</para>\n");
 946            }
 947        }
 948        $fp->puts("\n   </section>\n\n");
 949
 950        $fp->puts("\n   <section id='$idName.install'>\n    &reftitle.install;\n");
 951        if (empty($this->with)) {
 952            $fp->puts("    &no.install;\n");
 953        } else {
 954            foreach ($this->with as $with) {
 955                if (isset($with->summary)) {
 956                    if (strstr($with->summary, "<para>")) {
 957                        $fp->puts($with->summary);
 958                    } else {
 959                        $fp->puts("    <para>\n".rtrim($with->summary)."\n    </para>\n");
 960                    }
 961                } else {
 962                    $fp->puts("    <para>Requires <literal>".$with->getName()."</literal></para>\n");
 963                }
 964            }
 965        }
 966        $fp->puts("\n   </section>\n\n");
 967
 968        $fp->puts($this->docEditorSettings());
 969        $fp->close();
 970
 971        //
 972
 973        $function_entities = array();
 974        @mkdir("$docdir/$idName/functions");
 975        foreach ($this->functions as $name => $function) {
 976            $functionId = strtolower(str_replace("_", "-", $name));
 977            $filepath   = "$idName/functions/$functionId.xml";
 978
 979            $entity = "reference.$idName.functions.$functionId";
 980
 981            $function_entities[] = $entity;
 982            $entities->puts("<!ENTITY $entity SYSTEM './$filepath'>\n");
 983
 984            $funcfile = new CodeGen_Tools_FileReplacer("$docdir$filepath");
 985            $funcfile->puts($function->docEntry($idName));
 986            $funcfile->puts($this->docEditorSettings(4));
 987            $funcfile->close();
 988        }
 989
 990        $entities->puts("<!ENTITY reference.$idName.functions SYSTEM './functions.xml'>\n");
 991        $entities->close();
 992
 993        $functionsXml = new CodeGen_Tools_FileReplacer($docdir."/functions.xml");
 994        sort($function_entities);
 995        foreach ($function_entities as $entity) {
 996            $functionsXml->puts(" &$entity;\n");
 997        }
 998        $functionsXml->close();
 999    }
1000
1001    // }}}
1002
1003    // {{{   extension entry
1004    /**
1005     * Create the module entry code for this extension
1006     *
1007     * @access private
1008     * @return string  zend_module_entry code fragment
1009     */
1010    function generateExtensionEntry()
1011    {
1012        $name   = $this->name;
1013        $upname = strtoupper($this->name);
1014        $code   = "";
1015
1016        if (empty($this->otherExtensions)) {
1017            $moduleHeader = "    STANDARD_MODULE_HEADER,";
1018        } else {
1019            $code.= CodeGen_PECL_Dependency_Extension::cCodeHeader($this);
1020            foreach ($this->otherExtensions as $ext) {
1021                $code.= $ext->cCode($this);
1022            }
1023            $code.= CodeGen_PECL_Dependency_Extension::cCodeFooter($this);
1024
1025            $moduleHeader =
1026"#if ZEND_EXTENSION_API_NO >= 220050617
1027        STANDARD_MODULE_HEADER_EX, NULL,
1028        {$this->name}_deps,
1029#else
1030        STANDARD_MODULE_HEADER,
1031#endif
1032";
1033        }
1034
1035        $code.= "
1036/* {{{ {$name}_module_entry
1037 */
1038zend_module_entry {$name}_module_entry = {
1039$moduleHeader
1040    \"$name\",
1041    {$name}_functions,
1042    PHP_MINIT($name),     /* Replace with NULL if there is nothing to do at php startup   */
1043    PHP_MSHUTDOWN($name), /* Replace with NULL if there is nothing to do at php shutdown  */
1044    PHP_RINIT($name),     /* Replace with NULL if there is nothing to do at request start */
1045    PHP_RSHUTDOWN($name), /* Replace with NULL if there is nothing to do at request end   */
1046    PHP_MINFO($name),
1047    PHP_".$upname."_VERSION,
1048    STANDARD_MODULE_PROPERTIES
1049};
1050/* }}} */
1051
1052";
1053
1054        $code .= "#ifdef COMPILE_DL_$upname\n";
1055        if ($this->language == "cpp") {
1056            $code .= "extern \"C\" {\n";
1057        }
1058        $code .= "ZEND_GET_MODULE($name)\n";
1059        if ($this->language == "cpp") {
1060            $code .= "} // extern \"C\"\n";
1061        }
1062        $code .= "#endif\n\n";
1063
1064        return $code;
1065    }
1066
1067    // }}}
1068
1069    // {{{ globals and ini
1070    /**
1071     * Create the module globals c code fragment
1072     *
1073     * @access private
1074     * @return string  module globals code fragment
1075     */
1076
1077    function generateGlobalsC()
1078    {
1079        if (empty($this->globals)) return "";
1080
1081        $code  = "\n/* {{{ globals and ini entries */\n";
1082        $code .= "ZEND_DECLARE_MODULE_GLOBALS({$this->name})\n\n";
1083
1084        if (!empty($this->phpini)) {
1085            $code .= CodeGen_PECL_Element_Ini::cCodeHeader($this->name);
1086            foreach ($this->phpini as $phpini) {
1087                $code .= $phpini->cCode($this->name);
1088            }
1089            $code .= CodeGen_PECL_Element_Ini::cCodeFooter($this->name);
1090        }
1091
1092        if (!empty($this->globals)) {
1093            $code .= CodeGen_PECL_Element_Global::cCodeHeader($this->name);
1094            foreach ($this->globals as $global) {
1095                $code .= $global->cCode($this->name);
1096            }
1097            $code .= CodeGen_PECL_Element_Global::cCodeFooter($this->name);
1098        }
1099
1100        $code .= "/* }}} */\n\n";
1101        return $code;
1102    }
1103
1104    /**
1105     * Create the module globals c header file fragment
1106     *
1107     * @access private
1108     * @return string  module globals code fragment
1109     */
1110    function generateGlobalsH()
1111    {
1112        if (empty($this->globals)) return "";
1113
1114        $code = CodeGen_PECL_Element_Global::hCodeHeader($this->name);
1115        foreach ($this->globals as $global) {
1116            $code .= $global->hCode($this->name);
1117        }
1118        $code .= CodeGen_PECL_Element_Global::hCodeFooter($this->name);
1119
1120        return $code;
1121    }
1122
1123    // }}}
1124
1125    // {{{
1126    /**
1127     * Create global function registration
1128     *
1129     * @access private
1130     * @return string  function registration code fragments
1131     */
1132    function generateFunctionRegistrations()
1133    {
1134        $code  = "/* {{{ {$this->name}_functions[] */\n";
1135        $code .= "function_entry {$this->name}_functions[] = {\n";
1136        foreach ($this->functions as $function) {
1137            $code.= $function->functionEntry();
1138        }
1139        foreach ($this->classes as $class) {
1140            $code.= $class->functionAliasEntries();
1141        }
1142        $code .=  "    { NULL, NULL, NULL }\n";
1143        $code .=  "};\n/* }}} */\n\n";
1144
1145        return $code;
1146    }
1147    // }}}
1148
1149    // {{{
1150    /**
1151     * Create global class registration code and functions
1152     *
1153     * @access private
1154     * @return string  class registration code fragments
1155     */
1156    function generateClassRegistrations()
1157    {
1158        if (empty($this->classes)) return "";
1159
1160        $code = "/* {{{ Class definitions */\n\n";
1161
1162        foreach ($this->classes as $class) {
1163            $code .= $class->globalCode($this);
1164        }
1165
1166        $code .= "/* }}} Class definitions*/\n\n";
1167
1168        return $code;
1169    }
1170    // }}}
1171
1172    // {{{
1173    /**
1174     * Create global interface registration code
1175     *
1176     * @access private
1177     * @return string  interface registration code fragments
1178     */
1179    function generateInterfaceRegistrations()
1180    {
1181        if (empty($this->interfaces)) return "";
1182
1183        $code = "/* {{{ Interface definitions */\n\n";
1184
1185        foreach ($this->interfaces as $interface) {
1186            $code .= $interface->globalCode($this);
1187        }
1188
1189        $code .= "/* }}} Interface definitions*/\n\n";
1190
1191        return $code;
1192    }
1193    // }}}
1194
1195    // {{{ license and authoers
1196    /**
1197     * Set license
1198     *
1199     * @access public
1200     * @param  object
1201     */
1202    function setLicense($license)
1203    {
1204        if (preg_match("|^GPL|", $license->getShortName())) {
1205            return PEAR::raiseError("The ".$license->getShortName().
1206                                    "is not a valid choice for PHP extensions due to license incompatibilities");
1207        }
1208
1209        $this->license = $license;
1210
1211        return true;
1212    }
1213
1214    /**
1215     * Create the license part of the source file header comment
1216     *
1217     * @access private
1218     * @return string  code fragment
1219     */
1220    function getLicenseComment()
1221    {
1222        $code = "/*\n";
1223        $code.= "   +----------------------------------------------------------------------+\n";
1224
1225        if (is_object($this->license)) {
1226            $code.= $this->license->getComment();
1227        } else {
1228            $code.= sprintf("   | unknown license: %-52s |\n", $this->license);
1229        }
1230
1231        $code.= "   +----------------------------------------------------------------------+\n";
1232
1233        foreach ($this->authors as $author) {
1234            $code.= $author->comment();
1235        }
1236
1237        $code.= "   +----------------------------------------------------------------------+\n";
1238        $code.= "*/\n\n";
1239
1240        $code.= "/* $ Id: $ */ \n\n";
1241
1242        return $code;
1243    }
1244
1245    // }}}
1246
1247    /**
1248     * Set pear installer channel
1249     *
1250     * @access public
1251     * @param  string
1252     */
1253    function setChannel($channel)
1254    {
1255        if (! preg_match('/^[a-z\-_\.]+$/i', $channel)) {
1256            return PEAR::raiseError("'$channel' is not a valid pear installer channel name");
1257        }
1258
1259        $this->channel = $channel;
1260    }
1261
1262    // {{{ header file
1263
1264    /**
1265     * Write the complete C header file
1266     *
1267     * @access private
1268     * @param  string  directory to write to
1269     */
1270    function writeHeaderFile()
1271    {
1272        $this->addPackageFile('header', "php_{$this->name}.h");
1273
1274        $file =  new CodeGen_Tools_Outbuf($this->dirpath."/php_{$this->name}.h");
1275
1276        $upname = strtoupper($this->name);
1277
1278        echo $this->getLicenseComment();
1279        echo "#ifndef PHP_{$upname}_H\n";
1280        echo "#define PHP_{$upname}_H\n\n";
1281
1282        foreach ($this->headers as $header) {
1283            echo $header->hCode(true);
1284        }
1285
1286        echo "#ifdef  __cplusplus\n";
1287        echo "extern \"C\" {\n";
1288        echo "#endif\n";
1289
1290        echo '
1291#ifdef HAVE_CONFIG_H
1292#include "config.h"
1293#endif
1294
1295#include <php.h>
1296
1297#ifdef HAVE_'.$upname.'
1298';
1299
1300       echo '#define PHP_'.$upname.'_VERSION "'.$this->release->getVersion().'"'."\n\n";
1301
1302       echo '
1303#include <php_ini.h>
1304#include <SAPI.h>
1305#include <ext/standard/info.h>
1306#include <Zend/zend_extensions.h>
1307';
1308
1309        echo "#ifdef  __cplusplus\n";
1310        echo "} // extern \"C\" \n";
1311        echo "#endif\n";
1312
1313        foreach ($this->headers as $header) {
1314            echo $header->hCode(false);
1315        }
1316
1317        foreach ($this->with as $with) {
1318            foreach ($with->getHeaders() as $header) {
1319                echo $header->hCode(false);
1320            }
1321        }
1322
1323        if (isset($this->code["header"]["top"])) {
1324            foreach ($this->code["header"]["top"] as $code) {
1325                echo $this->codegen->block($code, 0);
1326            }
1327        }
1328
1329        echo "#ifdef  __cplusplus\n";
1330        echo "extern \"C\" {\n";
1331        echo "#endif\n";
1332
1333        echo "
1334extern zend_module_entry {$this->name}_module_entry;
1335#define phpext_{$this->name}_ptr &{$this->name}_module_entry
1336
1337#ifdef PHP_WIN32
1338#define PHP_{$upname}_API __declspec(dllexport)
1339#else
1340#define PHP_{$upname}_API
1341#endif
1342
1343PHP_MINIT_FUNCTION({$this->name});
1344PHP_MSHUTDOWN_FUNCTION({$this->name});
1345PHP_RINIT_FUNCTION({$this->name});
1346PHP_RSHUTDOWN_FUNCTION({$this->name});
1347PHP_MINFO_FUNCTION({$this->name});
1348
1349#ifdef ZTS
1350#include \"TSRM.h\"
1351#endif
1352
1353#define FREE_RESOURCE(resource) zend_list_delete(Z_LVAL_P(resource))
1354
1355#define PROP_GET_LONG(name)    Z_LVAL_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
1356#define PROP_SET_LONG(name, l) zend_update_property_long(_this_ce, _this_zval, #name, strlen(#name), l TSRMLS_CC)
1357
1358#define PROP_GET_DOUBLE(name)    Z_DVAL_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
1359#define PROP_SET_DOUBLE(name, d) zend_update_property_double(_this_ce, _this_zval, #name, strlen(#name), d TSRMLS_CC)
1360
1361#define PROP_GET_STRING(name)    Z_STRVAL_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
1362#define PROP_GET_STRLEN(name)    Z_STRLEN_P(zend_read_property(_this_ce, _this_zval, #name, strlen(#name), 1 TSRMLS_CC))
1363#define PROP_SET_STRING(name, s) zend_update_property_string(_this_ce, _this_zval, #name, strlen(#name), s TSRMLS_CC)
1364#define PROP_SET_STRINGL(name, s, l) zend_update_property_stringl(_this_ce, _this_zval, #name, strlen(#name), s, l TSRMLS_CC)
1365
1366";
1367
1368        echo $this->generateGlobalsH();
1369
1370        echo "\n";
1371
1372        foreach ($this->functions as $name => $function) {
1373            echo $function->hCode($this);
1374        }
1375
1376        foreach ($this->classes as $name => $class) {
1377            echo $class->hCode($this);
1378        }
1379
1380        foreach ($this->interfaces as $name => $interface) {
1381            echo $interface->hCode($this);
1382        }
1383
1384        foreach ($this->streams as $name => $stream) {
1385            echo $this->codegen->block($stream->hCode());
1386        }
1387
1388        echo "#ifdef  __cplusplus\n";
1389        echo "} // extern \"C\" \n";
1390        echo "#endif\n";
1391        echo "\n";
1392
1393        // write #defines for <constant>s
1394        $defines = "";
1395        foreach ($this->constants as $constant) {
1396            $defines.= $constant->hCode($this);
1397        }
1398        if ($defines !== "") {
1399            echo "/* mirrored PHP Constants */\n";
1400            echo $defines;
1401            echo "\n";
1402        }
1403
1404        // add bottom header snippets
1405        if (isset($this->code["header"]["bottom"])) {
1406            echo "/* 'bottom' header snippets*/\n";
1407            foreach ($this->code["header"]["bottom"] as $code) {
1408                echo $this->codegen->block($code, 0);
1409            }
1410            echo "\n";
1411        }
1412
1413        echo "#endif /* PHP_HAVE_{$upname} */\n\n";
1414        echo "#endif /* PHP_{$upname}_H */\n\n";
1415
1416        echo $this->cCodeEditorSettings();
1417
1418        return $file->write();
1419    }
1420
1421    // }}}
1422
1423    // {{{ internal functions
1424
1425    /**
1426     * Create code for the internal functions like MINIT etc ...
1427     *
1428     * @access private
1429     * @return string  code snippet
1430     */
1431
1432    function internalFunctionsC()
1433    {
1434        $need_block = false;
1435
1436        $code = "
1437/* {{{ PHP_MINIT_FUNCTION */
1438PHP_MINIT_FUNCTION({$this->name})
1439{
1440";
1441
1442        if (count($this->globals)) {
1443            $code      .= "    ZEND_INIT_MODULE_GLOBALS({$this->name}, php_{$this->name}_init_globals, php_{$this->name}_shutdown_globals)\n";
1444            $need_block = true;
1445        }
1446
1447        if (count($this->phpini)) {
1448            $code      .= "    REGISTER_INI_ENTRIES();\n";
1449            $need_block = true;
1450        }
1451
1452        foreach ($this->logos as $logo) {
1453            $code      .= $this->codegen->block($logo->minitCode());
1454            $need_block = true;
1455        }
1456
1457        if (count($this->constants)) {
1458            foreach ($this->constants as $constant) {
1459                $code .= $this->codegen->block($constant->cCode($this->name));
1460            }
1461            $need_block = true;
1462        }
1463
1464        if (count($this->resources)) {
1465            foreach ($this->resources as $resource) {
1466                $code .= $this->codegen->block($resource->minitCode());
1467            }
1468            $need_block = true;
1469        }
1470
1471        if (count($this->interfaces)) {
1472            foreach ($this->interfaces as $interface) {
1473                $code .= $this->codegen->block($interface->minitCode($this));
1474            }
1475            $need_block = true;
1476        }
1477
1478        if (count($this->classes)) {
1479            foreach ($this->classes as $class) {
1480                $code .= $this->codegen->block($class->minitCode($this));
1481            }
1482            $need_block = true;
1483        }
1484
1485        if (count($this->streams)) {
1486            foreach ($this->streams as $stream) {
1487                $code .= $this->codegen->block($stream->minitCode($this));
1488            }
1489            $need_block = true;
1490        }
1491
1492        if (isset($this->internalFunctions['MINIT'])) {
1493            $code .= $this->codegen->varblock($this->internalFunctions['MINIT']->getCode());
1494        } else {
1495            $code .="\n    /* add your stuff here */\n";
1496        }
1497        $code .= "
1498    return SUCCESS;
1499}
1500/* }}} */
1501
1502";
1503
1504        $code .= "
1505/* {{{ PHP_MSHUTDOWN_FUNCTION */
1506PHP_MSHUTDOWN_FUNCTION({$this->name})
1507{
1508";
1509
1510        if (count($this->phpini)) {
1511            $code      .= "    UNREGISTER_INI_ENTRIES();\n";
1512            $need_block = true;
1513        }
1514
1515        // TODO: need to destruct globals here if in ZTS mode!!111
1516
1517        if (count($this->logos)) {
1518            foreach ($this->logos as $logo) {
1519                $code .= $this->codegen->block($logo->mshutdownCode());
1520            }
1521            $need_block = true;
1522        }
1523
1524        if (isset($this->internalFunctions['MSHUTDOWN'])) {
1525            $code .= $this->codegen->varblock($this->internalFunctions['MSHUTDOWN']->getCode());
1526        } else {
1527            $code .="\n    /* add your stuff here */\n";
1528        }
1529
1530        $code .= "
1531    return SUCCESS;
1532}
1533/* }}} */
1534
1535";
1536
1537        $code .= "
1538/* {{{ PHP_RINIT_FUNCTION */
1539PHP_RINIT_FUNCTION({$this->name})
1540{
1541";
1542
1543        if (isset($this->internalFunctions['RINIT'])) {
1544            $code .= $this->codegen->block($this->internalFunctions['RINIT']->getCode());
1545        } else {
1546            $code .= "    /* add your stuff here */\n";
1547        }
1548
1549        $code .= "
1550    return SUCCESS;
1551}
1552/* }}} */
1553
1554";
1555
1556        $code .= "
1557/* {{{ PHP_RSHUTDOWN_FUNCTION */
1558PHP_RSHUTDOWN_FUNCTION({$this->name})
1559{
1560";
1561
1562        if (isset($this->internalFunctions['RSHUTDOWN'])) {
1563            $code .= $this->codegen->block($this->internalFunctions['RSHUTDOWN']->getCode());
1564        } else {
1565            $code .= "    /* add your stuff here */\n";
1566        }
1567
1568        $code .= "
1569    return SUCCESS;
1570}
1571/* }}} */
1572
1573";
1574
1575        $code .= "
1576/* {{{ PHP_MINFO_FUNCTION */
1577PHP_MINFO_FUNCTION({$this->name})
1578{
1579";
1580
1581        if (!empty($this->logos)) {
1582            $code.= "    if (!sapi_module.phpinfo_as_text) {\n";
1583            foreach ($this->logos as $logo) {
1584                $code.= $logo->phpinfoCode($this->name);
1585            }
1586            echo "    }\n";
1587        }
1588
1589        if (!empty($this->summary)) {
1590            $summary = strtr(trim($this->summary), array('"'=>'\\"'));
1591            $code .= "    php_printf(\"$summary\\n\");\n";
1592        }
1593
1594        $code.= "    php_info_print_table_start();\n";
1595
1596        if (!empty($this->release)) {
1597            $code .= $this->release->phpinfoCode($this->name);
1598        }
1599
1600        if (count($this->authors)) {
1601            $code.= '    php_info_print_table_row(2, "Authors", "';
1602
1603            foreach ($this->authors as $author) {
1604                $code.= $author->phpinfoCode($this->name).'\\n';
1605            }
1606
1607            $code.= "\");\n";
1608        }
1609
1610        $code.=
1611"    php_info_print_table_end();
1612";
1613
1614        // TODO move this decision up?
1615        if (isset($this->internalFunctions['MINFO'])) {
1616            $code .= $this->codegen->varblock($this->internalFunctions['MINFO']->getCode());
1617        } else {
1618            $code .= "    /* add your stuff here */\n";
1619        }
1620
1621        if (count($this->phpini)) {
1622            $code .= "\n    DISPLAY_INI_ENTRIES();";
1623        }
1624        $code .= "
1625}
1626/* }}} */
1627
1628";
1629
1630        return $code;
1631    }
1632
1633    // }}}
1634
1635    // {{{ public functions
1636    /**
1637     * Create code for the exported PHP functions
1638     *
1639     * @access private
1640     * @return string  code snippet
1641     */
1642    function publicFunctionsC()
1643    {
1644        $code = "";
1645
1646        foreach ($this->functions as $function) {
1647            $code .= $function->cCode($this);
1648        }
1649
1650        return $code;
1651    }
1652
1653    // }}}
1654
1655    // {{{ code file
1656
1657    /**
1658     * Write the complete C code file
1659     *
1660     * @access private
1661     * @param  string  directory to write to
1662     */
1663    function writeCodeFile()
1664    {
1665        $filename = "{$this->name}.{$this->language}";  // todo extension logic
1666
1667        $upname = strtoupper($this->name);
1668
1669        $this->addPackageFile('code', $filename);
1670
1671        $file = new CodeGen_Tools_Outbuf($this->dirpath.'/'.$filename, CodeGen_Tools_Outbuf::OB_TABIFY);
1672
1673        echo $this->getLicenseComment();
1674
1675        echo "#include \"php_{$this->name}.h\"\n\n";
1676
1677        echo "#if HAVE_$upname\n\n";
1678
1679        if (isset($this->code["code"]["top"])) {
1680            foreach ($this->code["code"]["top"] as $code) {
1681                echo $this->codegen->block($code, 0);
1682            }
1683        }
1684
1685        if (!empty($this->logos)) {
1686            echo CodeGen_PECL_Element_Logo::cCodeHeader($this->name);
1687            foreach ($this->logos as $logo) {
1688                echo $logo->cCode($this->name);
1689            }
1690            echo CodeGen_PECL_Element_Logo::cCodeFooter($this->name);
1691        }
1692
1693        if (!empty($this->resources)) {
1694            echo CodeGen_PECL_Element_Resource::cCodeHeader($this->name);
1695            foreach ($this->resources as $resource) {
1696                echo $resource->cCode($this);
1697            }
1698            echo CodeGen_PECL_Element_Resource::cCodeFooter($this->name);
1699        }
1700
1701        echo $this->generateInterfaceRegistrations();
1702
1703        echo $this->generateClassRegistrations();
1704
1705        echo $this->generateFunctionRegistrations();
1706
1707        echo $this->generateExtensionEntry();
1708
1709        echo $this->generateGlobalsC();
1710
1711        echo $this->internalFunctionsC();
1712
1713        echo $this->publicFunctionsC();
1714
1715        if (isset($this->code["code"]["bottom"])) {
1716            foreach ($this->code["code"]["bottom"] as $code) {
1717                echo $this->codegen->block($code, 0);
1718            }
1719        }
1720
1721        echo "#endif /* HAVE_$upname */\n\n";
1722
1723        echo $this->cCodeEditorSettings();
1724
1725        return $file->write();
1726    }
1727
1728    // }}}
1729
1730    // {{{ config.m4 file
1731
1732    /**
1733     * Write config.m4 file for autoconf
1734     *
1735     * @access private
1736     * @param  string  directory to write to
1737     */
1738    function writeConfigM4()
1739    {
1740        $upname = strtoupper($this->name);
1741
1742        $this->addPackageFile("conf", "config.m4");
1743
1744        $file = new CodeGen_Tools_Outbuf($this->dirpath."/config.m4", CodeGen_Tools_Outbuf::OB_TABIFY);
1745
1746        echo
1747'dnl
1748dnl $ Id: $
1749dnl
1750';
1751
1752        if (isset($this->with[$this->name])) {
1753            $with = $this->with[$this->name];
1754            echo "\n".$with->m4Line()."\n";
1755        } else {
1756            echo "
1757PHP_ARG_ENABLE({$this->name}, whether to enable {$this->name} functions,
1758[  --enable-{$this->name}         Enable {$this->name} support])
1759";
1760        }
1761
1762        echo "\n";
1763
1764        echo "if test \"\$PHP_$upname\" != \"no\"; then\n";
1765
1766        if ($this->language === "cpp") {
1767            echo "  PHP_REQUIRE_CXX\n";
1768            echo "  AC_LANG_CPLUSPLUS\n";
1769            echo "  PHP_ADD_LIBRARY(stdc++,,{$upname}_SHARED_LIBADD)\n";
1770        }
1771
1772        foreach ($this->configfragments['top'] as $fragment) {
1773            echo "$fragment\n";
1774        }
1775
1776        foreach ($this->with as $with) {
1777            echo $with->configm4($this);
1778        }
1779
1780        $pathes = array();
1781        foreach ($this->headers as $header) {
1782            $pathes[$header->getPath()] = true; // TODO WTF???
1783        }
1784
1785        foreach (array_keys($pathes) as $path) {
1786            echo "  PHP_ADD_INCLUDE(\$PHP_{$upname}_DIR/$path)\n";
1787        }
1788
1789        echo "  export OLD_CPPFLAGS=\"\$CPPFLAGS\"\n";
1790        echo "  export CPPFLAGS=\"\$CPPFLAGS \$INCLUDES -DHAVE_".strtoupper($this->name)."\"\n";
1791
1792        echo "
1793  AC_MSG_CHECKING(PHP version)
1794  AC_TRY_COMPILE([#include <php_version.h>], [
1795#if PHP_VERSION_ID < ".$this->minPhpVersionId()."
1796#error  this extension requires at least PHP version ".$this->minPhpVersion()."
1797#endif
1798],
1799[AC_MSG_RESULT(ok)],
1800[AC_MSG_ERROR([need at least PHP ".$this->minPhpVersion()."])])
1801
1802";
1803
1804        if (count($this->headers)) {
1805            if (!isset($this->with[$this->name])) {
1806                $this->terminate("global headers not bound to a --with option found and no --with option by the default name");
1807            }
1808
1809            foreach ($this->headers as $header) {
1810                echo $header->configm4($this->name, $this->name);
1811            }
1812        }
1813
1814        foreach ($this->resources as $resource) {
1815            echo $resource->configm4($this->name);
1816        }
1817
1818        echo "  export CPPFLAGS=\"\$OLD_CPPFLAGS\"\n";
1819
1820        if (count($this->libs)) {
1821            if (!isset($this->with[$this->name])) {
1822                $this->terminate("global libs not bound to a --with option found and no --with option by the default name");
1823            }
1824            foreach ($this->libs as $lib) {
1825                echo $lib->configm4($this->name, $this->name);
1826            }
1827        }
1828
1829        echo "\n";
1830
1831        echo "
1832  PHP_SUBST({$upname}_SHARED_LIBADD)
1833  AC_DEFINE(HAVE_$upname, 1, [ ])
1834";
1835
1836

Large files files are truncated, but you can click here to view the full file