PageRenderTime 29ms CodeModel.GetById 17ms RepoModel.GetById 0ms 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
Possible License(s): MPL-2.0-no-copyleft-exception

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

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