1<?php
2/**
3 * Parser for XML based extension desription 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
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: ExtensionParser.php,v 1.19 2007/05/06 08:11:57 hholzgra Exp $
19 * @link       http://pear.php.net/package/CodeGen
20 */
21
22
23/**
24 * includes
25 */
26require_once "CodeGen/XmlParser.php";
27require_once "CodeGen/Tools/Indent.php";
28require_once "CodeGen/Tools/Group.php";
29
30/**
31 * Parser for XML based extension desription files
32 *
33 * @category   Tools and Utilities
34 * @package    CodeGen
35 * @author     Hartmut Holzgraefe <hartmut@php.net>
36 * @copyright  2005-2008 Hartmut Holzgraefe
37 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
38 * @version    Release: @package_version@
39 * @link       http://pear.php.net/package/CodeGen
40 */
41abstract class CodeGen_ExtensionParser
42    extends CodeGen_XmlParser
43{
44    /**
45     * The extension to parse specs into
46     *
47     * @access private
48     * @var    object
49     */
50    protected $extension;
51
52    /**
53     * Group stack
54     *
55     * @var array
56     */
57    protected $groups = array();
58
59    function pushGroup(CodeGen_Tools_Group $group)
60    {
61        $currentGroup = end($this->groups);
62        if ($currentGroup) {
63            $group->setParent($currentGroup);
64        }
65        array_push($this->groups, $group);
66
67        return true;
68    }
69
70    function popGroup()
71    {
72        array_pop($this->groups);
73    }
74
75    function getGroupAttribute($name)
76    {
77        $currentGroup = end($this->groups);
78        if ($currentGroup) {
79            return $currentGroup->getAttribute($name);
80        } else {
81            return false;
82        }
83    }
84
85    function getGroupAttributeStack($name)
86    {
87        $currentGroup = end($this->groups);
88        if ($currentGroup) {
89            return $currentGroup->getAttributeStack($name);
90        } else {
91            return false;
92        }
93    }
94
95    function tagstart_extension_group($attr)
96    {
97        $group = new CodeGen_Tools_Group();
98        $group->setAttributes($attr);
99
100        return $this->pushGroup($group);
101    }
102
103    function tagstart_group_group($attr)
104    {
105        return $this->tagstart_extension_group($attr);
106    }
107
108    function tagend_extension_group($attr, $data)
109    {
110        $this->popGroup();
111
112        return true;
113    }
114
115    function tagend_group_group($attr, $data)
116    {
117        return $this->tagend_extension_group($attr, $data);
118    }
119
120    /**
121     * Constructor
122     *
123     * @access public
124     * @param  object the extension to parse specs into
125     */
126    function __construct($extension)
127    {
128        parent::__construct();
129        $this->extension = $extension;
130    }
131
132    /**
133     * Handle <extension>
134     *
135     * @access private
136     * @param  array    attribute/value pairs
137     * @return bool     success status
138     */
139    function tagstart_extension($attr)
140    {
141        $err = $this->checkAttributes($attr, array("name", "prefix", "version"));
142        if (PEAR::isError($err)) {
143            return $err;
144        }
145
146        if (!isset($attr["name"])) {
147            return PEAR::raiseError("needed attribute 'name' for <extension> not given");
148        }
149        $err = $this->extension->setName(trim($attr["name"]));
150        if (PEAR::isError($err)) {
151            return $err;
152        }
153
154        if (isset($attr["prefix"])) {
155            $err = $this->extension->setPrefix(trim($attr["prefix"]));
156            if (PEAR::isError($err)) {
157                return $err;
158            }
159        }
160
161        if (isset($attr["version"])) {
162            $err = $this->extension->setVersion($attr["version"]);
163            if (PEAR::isError($err)) {
164                return $err;
165            }
166        } else {
167            error_log("Warning: no 'version' attribute given for <extension>, assuming ".$this->extension->version()."\n".
168                      "         this may lead to compile errors if your spec file was created for an older version");
169        }
170
171        return true;
172    }
173
174    /**
175     * Handle <extension><name>
176     *
177     * @access private
178     * @param  array    attribute/value pairs
179     * @return bool     success status
180     */
181    function tagstart_extension_name($attr)
182    {
183        return PEAR::raiseError("extension <name> tag is no longer supported, use <extension>s 'name=...' attribute instead");
184    }
185
186
187    /**
188     * Handle <extension><summary>
189     *
190     * @access private
191     * @param  array    attribute/value pairs
192     * @return bool     success status
193     */
194    function tagstart_extension_summary($attr)
195    {
196        return $this->noAttributes($attr);
197    }
198
199    /**
200     * Handle <extension></summary>
201     *
202     * @access private
203     * @param  array    attribute/value pairs
204     * @param  array    tag data content
205     * @return bool     success status
206     */
207    function tagend_extension_summary($attr, $data)
208    {
209        return $this->extension->setSummary(CodeGen_Tools_Indent::linetrim($data));
210    }
211
212    /**
213     * Handle <extension><description>
214     *
215     * @access private
216     * @param  array    attribute/value pairs
217     * @return bool     success status
218     */
219    function tagstart_extension_description($attr)
220    {
221        return $this->noAttributes($attr);
222    }
223
224    /**
225     * Handle <extension></description>
226     *
227     * @access private
228     * @param  array    attribute/value pairs
229     * @param  array    tag data content
230     * @return bool     success status
231     */
232    function tagend_extension_description($attr, $data)
233    {
234        return $this->extension->setDescription(CodeGen_Tools_Indent::linetrim($data));
235    }
236
237    function tagstart_extension_maintainer($attr)
238    {
239        $this->pushHelper(new CodeGen_Maintainer);
240        return $this->noAttributes($attr);;
241    }
242
243    function tagstart_maintainers_maintainer($attr)
244    {
245        return $this->tagstart_extension_maintainer($attr);
246    }
247
248    function tagstart_group_maintainer($attr)
249    {
250        return $this->tagstart_extension_maintainer($attr);
251    }
252
253    function tagstart_maintainer_user($attr)
254    {
255        return $this->noAttributes($attr);;
256    }
257
258    function tagend_maintainer_user($attr, $data)
259    {
260        return $this->helper->setUser(trim($data));
261    }
262
263    function tagstart_maintainer_name($attr)
264    {
265        return $this->noAttributes($attr);;
266    }
267
268    function tagend_maintainer_name($attr, $data)
269    {
270        return $this->helper->setName(trim($data));
271    }
272
273    function tagstart_maintainer_email($attr)
274    {
275        return $this->noAttributes($attr);;
276    }
277
278    function tagend_maintainer_email($attr, $data)
279    {
280        return $this->helper->setEmail(trim($data));
281    }
282
283    function tagstart_maintainer_role($attr)
284    {
285        return $this->noAttributes($attr);;
286    }
287
288    function tagend_maintainer_role($attr, $data)
289    {
290        return $this->helper->setRole(trim($data));
291    }
292
293    function tagend_maintainer($attr, $data)
294    {
295        $err = $this->extension->addAuthor($this->helper);
296        $this->popHelper();
297        return $err;
298    }
299
300    function tagend_maintainers($attr, $data)
301    {
302        return true;
303    }
304
305    function tagstart_extension_release($attr)
306    {
307        $this->pushHelper(new CodeGen_Release);
308        return $this->noAttributes($attr);;
309    }
310
311    function tagstart_group_release($attr)
312    {
313        $this->tagstart_extension_release($attr);
314    }
315
316    function tagstart_release_version($attr)
317    {
318        return $this->noAttributes($attr);;
319    }
320
321    function tagend_release_version($attr, $data)
322    {
323        return $this->helper->setVersion(trim($data));
324    }
325
326    function tagstart_release_date($attr)
327    {
328        return $this->noAttributes($attr);;
329    }
330
331    function tagend_release_date($attr, $data)
332    {
333        return $this->helper->setDate(trim($data));
334    }
335
336    function tagstart_release_state($attr)
337    {
338        return $this->noAttributes($attr);;
339    }
340
341    function tagend_release_state($attr, $data)
342    {
343        return $this->helper->setState(trim($data));
344    }
345
346    function tagstart_release_notes($attr)
347    {
348        return $this->noAttributes($attr);;
349    }
350
351    function tagend_release_notes($attr, $data)
352    {
353        return $this->helper->setNotes(CodeGen_Tools_Indent::linetrim($data));
354    }
355
356    function tagend_release($attr, $data)
357    {
358        $err = $this->extension->setRelease($this->helper);
359        $this->popHelper(new CodeGen_Release);
360        return $err;
361    }
362
363    function tagstart_extension_changelog($attr)
364    {
365        $this->verbatim();
366        return $this->noAttributes($attr);;
367    }
368
369    function tagstart_group_changelog($attr)
370    {
371        $this->tagstart_extension_changelog($attr);
372    }
373
374    function tagend_changelog($attr, $data)
375    {
376        return $this->extension->setChangelog(CodeGen_Tools_Indent::linetrim($data));
377    }
378
379
380    function tagend_extension_license($attr, $data)
381    {
382        $license = CodeGen_License::factory(trim($data));
383
384        if (PEAR::isError($license)) {
385            return $license;
386        }
387
388        return $this->extension->setLicense($license);
389    }
390
391    function tagend_group_license($attr, $data)
392    {
393        return $this->tagend_extension_license($attr, $data);
394    }
395
396    function tagend_extension_code($attr, $data)
397    {
398        $err = $this->checkAttributes($attr, array("role", "position"));
399        if (PEAR::isError($err)) {
400            return $err;
401        }
402
403        $role     = isset($attr["role"])     ? $attr["role"]     : "code";
404        $position = isset($attr["position"]) ? $attr["position"] : "bottom";
405
406        if (isset($attr["src"])) {
407            return $this->extension->addCode($role, $position, CodeGen_Tools_Indent::linetrim(file_get_contents($attr["src"])));
408        } else {
409            return $this->extension->addCode($role, $position, CodeGen_Tools_Indent::linetrim($data));
410        }
411    }
412
413    function tagend_group_code($attr, $data)
414    {
415        return $this->tagend_extension_code($attr, $data);
416    }
417
418    function tagstart_extension_deps($attr)
419    {
420        $err = $this->checkAttributes($attr, array("platform", "language"));
421        if (PEAR::isError($err)) {
422            return $err;
423        }
424
425        if (isset($attr["platform"])) {
426            $err = $this->extension->setPlatform($attr["platform"]);
427            if (PEAR::isError($err)) {
428                return $err;
429            }
430        }
431
432        if (isset($attr["language"])) {
433            $err = $this->extension->setLanguage($attr["language"]);
434            if (PEAR::isError($err)) {
435                return $err;
436            }
437        }
438
439    }
440
441    function tagstart_group_deps($attr)
442    {
443        return $this->tagstart_extension_deps($attr);
444    }
445
446    function tagstart_deps_file($attr)
447    {
448        $err = $this->checkAttributes($attr, array("name", "dir"));
449        if (PEAR::isError($err)) {
450            return $err;
451        }
452
453        if (!isset($attr['name'])) {
454            return PEAR::raiseError("name attribut for file missing");
455        }
456
457        if (isset($attr["dir"])) {
458            return $this->extension->addSourceFile($attr['name'], $attr['dir']);
459        } else {
460            return $this->extension->addSourceFile($attr['name']);
461        }
462    }
463
464    function tagstart_deps_lib($attr)
465    {
466        $err = $this->checkAttributes($attr, array("name", "platform", "function"));
467        if (PEAR::isError($err)) {
468            return $err;
469        }
470
471        if (!isset($attr['name'])) {
472            return PEAR::raiseError("name attribut for lib missing");
473        }
474
475        // TODO need to use addLibs(), libs[] is protected
476        $this->extension->libs[$attr['name']] = $attr;
477        if (isset($attr['platform'])) {
478            $platform = new CodeGen_Tools_Platform($attr["platform"]);
479        } else {
480            $platform = new CodeGen_Tools_Platform("all");
481        }
482
483        if (PEAR::isError($platform)) {
484            return $platform;
485        }
486
487        $this->extension->libs[$attr['name']]['platform'] = $platform;
488        return true;
489    }
490
491    function tagstart_deps_header($attr)
492    {
493        $err = $this->checkAttributes($attr, array("name", "prepend", "path"));
494        if (PEAR::isError($err)) {
495            return $err;
496        }
497
498        // TODO check name
499        $header = new CodeGen_Dependency_Header($attr["name"]);
500
501        if (isset($attr['path'])) {
502            $header->setPath($attr["path"]);
503        }
504
505        if (isset($attr['prepend'])) {
506            $header->setPrepend($attr["prepend"]);
507        }
508
509        $this->extension->addHeader($header);
510    }
511
512    function tagstart_deps_define($attr) {
513        if (!isset($attr["name"])) {
514            return PEAR::raiseError("name attribut for define missing");
515        }
516
517        return $this->extension->addDefine($attr['name'], @$attr['value'], @$attr['comment']);
518    }
519
520    function tagend_extension_makefile($attr, $data) {
521        return $this->extension->addMakeFragment(CodeGen_Tools_IndentC::linetrim($data));
522    }
523
524    function tagend_group_makefile($attr, $data)
525    {
526        return $this->tagend_extension_makefile($attr, $data);
527    }
528
529    function tagend_extension_acinclude($attr, $data) {
530        $position = isset($attr["position"]) ? $attr["position"] : "bottom";
531        return $this->extension->addAcIncludeFragment($data, $position);
532    }
533
534    function tagend_group_acinclude($attr, $data)
535    {
536        return $this->tagend_extension_acinclude($attr, $data);
537    }
538
539    function tagend_deps_configm4($attr, $data) {
540        return $this->extension->addConfigFragment(CodeGen_Tools_IndentC::linetrim($data),
541                                                   isset($attr['position']) ? $attr['position'] : "top");
542    }
543
544    function tagend_group_configm4($attr, $data)
545    {
546        return $this->tagend_extension_configm4($attr, $data);
547    }
548}
549
550
551/*
552 * Local variables:
553 * tab-width: 4
554 * c-basic-offset: 4
555 * indent-tabs-mode:nil
556 * End:
557 */
558?>
559