/[suikacvs]/messaging/manakai/bin/dis2pm.pl
Suika

Contents of /messaging/manakai/bin/dis2pm.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Sun Oct 10 06:09:47 2004 UTC (20 years, 1 month ago) by wakaba
Branch: MAIN
Changes since 1.1: +10 -2 lines
File MIME type: text/plain
domtest2perl.pl: New

1 wakaba 1.1 #!/usr/bin/perl -w
2    
3     =head1 NAME
4    
5     dis2pm.pl - Manakai DOM Perl Module Generator
6    
7     =head1 SYNOPSIS
8    
9     perl dis2pm.pl Foo.dis > Foo.pm
10    
11     =head1 DESCRIPTION
12    
13     B<dis2pm> generates a Perl module file (*.pm) that implements
14     DOM (Document Object Model) interfaces from a "dis"
15     (DOM implementation source) file.
16    
17     This script is part of manakai.
18    
19     =cut
20    
21     use strict;
22     use lib qw<lib ../lib>;
23     use Message::Markup::SuikaWikiConfig20::Parser;
24     use Message::Markup::XML::QName qw/DEFAULT_PFX/;
25     use Message::Util::QName::General [qw/ExpandedURI/], {
26     DOMCore => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/dom-core#>,
27     DOMMain => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/dom-core#>,
28     infoset => q<http://www.w3.org/2001/04/infoset#>,
29     lang => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#>,
30     Perl => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#Perl-->,
31     license => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/license#>,
32     ManakaiDOM => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/manakai-dom#>,
33     MDOM_EXCEPTION => q<http://suika.fam.cx/~wakaba/archive/2004/8/4/manakai-dom-exception#>,
34     xml => q<http://www.w3.org/XML/1998/namespace>,
35     xmlns => q<http://www.w3.org/2000/xmlns/>,
36     };
37     my $ManakaiDOMModulePrefix = q<Message::DOM>;
38     my $MAX_DOM_LEVEL = 3;
39    
40     my $s;
41     {
42     local $/ = undef;
43     $s = <>;
44     }
45     my $source = Message::Markup::SuikaWikiConfig20::Parser->parse_text ($s);
46     my $Info = {};
47     my $Status = {package => 'main', depth => 0, generated_fragment => 0};
48     our $result = '';
49    
50     BEGIN {
51     require 'manakai/genlib.pl';
52     }
53    
54     sub perl_package_name (%) {
55     my %opt = @_;
56     my $r;
57     if ($opt{if}) {
58     $r = $ManakaiDOMModulePrefix . q<::IF::> . perl_name $opt{if};
59     } elsif ($opt{iif}) {
60     $r = $ManakaiDOMModulePrefix . q<::IIF::> . perl_name $opt{iif};
61     } elsif ($opt{name} or $opt{name_with_condition}) {
62     if ($opt{name_with_condition}) {
63     if ($opt{name_with_condition} =~ /^([^:]+)::([^:]+)$/) {
64     $opt{name} = $1;
65     $opt{condition} = $2;
66     } else {
67     $opt{name} = $opt{name_with_condition};
68     }
69     }
70     $opt{name} = perl_name $opt{name};
71     $opt{name} = $opt{prefix} . '::' . $opt{name} if $opt{prefix};
72     $r = $ManakaiDOMModulePrefix . q<::> . $opt{name};
73     } elsif ($opt{qname} or $opt{qname_with_condition}) {
74     if ($opt{qname_with_condition}) {
75     if ($opt{qname_with_condition} =~ /^(.+)::([^:]*)$/) {
76     $opt{qname} = $1;
77     $opt{condition} = $2;
78     } else {
79     $opt{qname} = $opt{qname_with_condition};
80     }
81     }
82     if ($opt{qname} =~ /^([^:]*):(.*)$/) {
83     $opt{ns_prefix} = $1;
84     $opt{name} = $2;
85     } else {
86     $opt{ns_prefix} = DEFAULT_PFX;
87     $opt{name} = $opt{qname};
88     }
89     ## ISSUE: Prefix to ...
90     #$r = ns_uri_to_perl_package_name (ns_prefix_to_uri ($opt{ns_prefix})) .
91     # '::' . $opt{name};
92     $r = $ManakaiDOMModulePrefix . '::' . $opt{name};
93     } elsif ($opt{if_qname} or $opt{if_qname_with_condition}) {
94     if ($opt{if_qname_with_condition}) {
95     if ($opt{if_qname_with_condition} =~ /^(.+)::([^:]*)$/) {
96     $opt{if_qname} = $1;
97     $opt{condition} = $2;
98     } else {
99     $opt{if_qname} = $opt{if_qname_with_condition};
100     }
101     }
102     if ($opt{if_qname} =~ /^([^:]*):(.*)$/) {
103     $opt{ns_prefix} = $1;
104     $opt{name} = $2;
105     } else {
106     $opt{ns_prefix} = DEFAULT_PFX;
107     $opt{name} = $opt{if_qname};
108     }
109     ## ISSUE: Prefix to ...
110     #$r = ns_uri_to_perl_package_name (ns_prefix_to_uri ($opt{ns_prefix})) .
111     # '::' . $opt{name};
112     $r = $ManakaiDOMModulePrefix . '::IF::' . $opt{name};
113     } elsif ($opt{full_name}) {
114     $r = $opt{full_name};
115     } else {
116     valid_err q<$opt{name} is false>;
117     }
118     if ($opt{condition}) {
119     $r = $r . '::' . perl_name $opt{condition};
120     }
121     if ($opt{is_internal}) {
122     $r .= '::_internal';
123     $r .= '_inherit' if $opt{is_for_inheriting};
124     }
125     $r;
126     }
127    
128     sub perl_package (%) {
129     my $fn = perl_package_name @_;
130     unless ($fn eq $Status->{package}) {
131     $Status->{package} = $fn;
132     return perl_statement qq<package $fn>;
133     } else {
134     return '';
135     }
136     }
137    
138     sub perl_exception (@) {
139     my %opt = @_;
140     if ($opt{class} !~ /:/) {
141     $opt{class} = perl_package_name name => $opt{class};
142     } else {
143     $opt{class} = perl_package_name full_name => $opt{class};
144     }
145     my @param = (-type => $opt{type},
146     -object => perl_code_literal ('$self'));
147     if (ref $opt{param}) {
148     push @param, %{$opt{param}};
149     } elsif ($opt{param}) {
150     push @param, perl_code_literal ($opt{param});
151     }
152     if ($opt{subtype} or $opt{subtype_uri}) {
153     my $uri = $opt{subtype_uri} || expanded_uri ($opt{subtype});
154     push @param, ExpandedURI q<MDOM_EXCEPTION:subtype> => $uri;
155     }
156     q<report > . $opt{class} . q< > . perl_list @param;
157     }
158    
159    
160     {
161     use re 'eval';
162     my $RegBlockContent;
163     $RegBlockContent = qr/(?>[^{}\\]*)(?>(?>[^{}\\]+|\\.|\{(??{$RegBlockContent})\})*)/s;
164     ## Defined by genlib.pl but overridden.
165     sub perl_code ($;%) {
166     my ($s, %opt) = @_;
167     valid_err q<Uninitialized value in perl_code>,
168     node => $opt{node} unless defined $s;
169     $s =~ s[<Q:([^<>]+)>|\b(null|true|false)\b][
170     my ($q, $l) = ($1, $2);
171     if (defined $q) {
172     if ($q =~ /\}/) {
173     valid_warn qq<Possible typo in the QName: "$q">;
174     }
175     perl_literal (expanded_uri ($q));
176     } else {
177     {true => 1, false => 0, null => 'undef'}->{$l};
178     }
179     ]ge;
180     ## TODO: Ensure Message::Util::Error imported if try.
181     ## ISSUE: __FILE__ & __LINE__ will break if multiline substition happens.
182     $s =~ s{
183     \b__([A-Z]+)
184     (?:\{($RegBlockContent)\})?
185     __\b
186     }{
187     my ($name, $data) = ($1, $2);
188     my $r;
189     if ($name eq 'CLASS' or ## Manakai DOM Class
190     $name eq 'SUPER' or ## Manakai DOM Class (internal)
191     $name eq 'IIF' or ## DOM Interface + Internal interface & prop
192     $name eq 'IF') { ## DOM Interface
193     local $Status->{condition} = $Status->{condition};
194     if ($data =~ s/::([^:]*)$//) {
195     $Status->{condition} = $1;
196     }
197     $r = perl_package_name {qw/CLASS name SUPER name IIF iif IF if/}->{$name}
198     => $data,
199     is_internal => {qw/SUPER 1/}->{$name},
200     condition => $Status->{condition};
201     } elsif ($name eq 'INT') { ## Internal Method / Attr Name
202     if (defined $data) {
203     if ($data =~ /^{($RegBlockContent)}$/o) {
204     $data = $1;
205     my $name = $1 if $data =~ s/^\s*(\w+)\s*(?:$|:\s*)// or
206     valid_err qq<Syntax of preprocessing macro "INT" is invalid>,
207     node => $opt{node};
208     local $Status->{preprocess_variable}
209     = {%{$Status->{preprocess_variable}||{}}};
210     while ($data =~ /\G(\S+)\s*(?:=>\s*(\S+)\s*)?(?:,\s*|$)/g) {
211     my ($n, $v) = ($1, defined $2 ? $2 : 1);
212     for ($n, $v) {
213     s/^'([^']+)'$/$1/; ## ISSUE: Doesn't support quoted-'
214     }
215     $Status->{preprocess_variable}->{$n} = $v;
216     }
217     valid_err q<Preprocessing macro INT{} cannot be used here>
218     unless $opt{internal};
219     $r = perl_comment ("INT: $name").
220     $opt{internal}->($name);
221     } elsif ($data =~ s/^SP://) {
222     $r = '___'.$data;
223     } else {
224     $r = perl_internal_name $data;
225     }
226     } else {
227     valid_err q<Preprocessing macro INT cannot be used here>
228     unless $opt{internal};
229     $r = $opt{internal}->();
230     }
231     } elsif ($name eq 'DEEP') { ## Deep Method Call
232     $r = 'do { local $Error::Depth = $Error::Depth + 1;' . perl_code ($data) .
233     '}';
234     } elsif ($name eq 'EXCEPTION' or $name eq 'WARNING') {
235     ## Raising an Exception or Warning
236     if ($data =~ s/^\s*(\w+)\s*\.\s*(\w+)\s*(?:\.\s*([\w:]+)\s*)?(?:::\s*|$)//) {
237     $r = perl_exception (level => $name,
238     class => $1,
239     type => $2,
240     subtype => $3,
241     param => perl_code $data);
242     } else {
243     valid_err qq<Exception type and name required: "$data">,
244     node => $opt{node};
245     }
246     } elsif ($name eq 'CODE') { # Built-in code
247     my ($nm, %param);
248     if ($data =~ s/^(\w+)\s*(?::\s*|$)//) {
249     $nm = $1;
250     } elsif ($data =~ s/^<([^<>]+)>\s*(?::\s*|$)//) {
251     $nm = $1;
252     } else {
253     valid_err q<Built-in code name required>;
254     }
255     while ($data =~ /\G(\S+)\s*=>\s*(\S+)\s*(?:,\s*|$)/g) {
256     $param{$1} = $2;
257     }
258     $r = perl_builtin_code ($nm, condition => $opt{condition}, %param);
259     } elsif ($name eq 'PACKAGE' and $data) {
260     if ($data eq 'Global') {
261     $r = $ManakaiDOMModulePrefix;
262     } else {
263     valid_err qq<PACKAGE "$data" not supported>;
264     }
265     } elsif ($name eq 'REQUIRE') {
266     $r = perl_statement (q<require >. perl_package_name name => $data);
267     } elsif ($name eq 'WHEN') {
268     if ($data =~ s/^\s*IS\s*\{($RegBlockContent)\}::\s*//o) {
269     my $v = $1;
270     if ($v =~ /^\s*'([^']+)'\s*$/) { ## ISSUE: Doesn't support quoted-'
271     if ($Status->{preprocess_variable}->{$1}) {
272     $r = perl_code ($data, %opt);
273     } else {
274     $r = perl_comment ($data);
275     }
276     } else {
277     valid_err qq<WHEN-IS condition "$v" is invalid>,
278     node => $opt{node};
279     }
280     } else {
281     valid_err qq<Syntax for preprocessing macro "WHEN" is invalid>,
282     node => $opt{node};
283     }
284     } elsif ($name eq 'FILE' or $name eq 'LINE' or $name eq 'PACKAGE') {
285     $r = qq<__${name}__>;
286     } else {
287     valid_err qq<Preprocessing macro "$name" not supported>;
288     }
289     $r;
290     }goex;
291     $s;
292     }
293     }
294    
295     ## Defined in genlib.pl but overridden.
296     sub perl_code_source ($%) {
297     my ($s, %opt) = @_;
298     sprintf qq<\n#line %d "File <%s> Node <%s>"\n%s\n> .
299     qq<#line 1 "File <%s> Chunk #%d"\n>,
300     $opt{line} || 1, $opt{file} || $Info->{source_filename},
301     $opt{path} || 'x:unknown ()', $s,
302     $opt{file} || $Info->{source_filename}, ++$Status->{generated_fragment};
303     }
304    
305     sub perl_builtin_code ($;%);
306     sub perl_builtin_code ($;%) {
307     my ($name, %opt) = @_;
308     $opt{condition} ||= $Status->{condition};
309     my $r;
310     if ($name eq 'DOMString') {
311     $name = $1 if $name =~ /(\w+)$/;
312     $r = q{
313     if (defined $arg) {
314     if (ref $arg) {
315     if (ref $arg eq 'SCALAR') {
316     $r = bless {value => $$arg}, $self;
317     } elsif ($arg->isa ('IF')) {
318     $r = $arg;
319     } else {
320     $r = bless {value => ''.$arg}, $self;
321     }
322     } else {
323     $r = bless {value => $arg}, $self;
324     }
325     } else {
326     $r = undef; # null
327     }
328     };
329     $r =~ s/'IF'/perl_literal (perl_package_name (if => $name))/ge;
330     $r =~ s/\$self\b/perl_literal (perl_package_name (name => $name))/ge;
331     $opt{s} or valid_err q<Built-in code parameter "s" required>;
332     $r =~ s/\$arg\b/\$$opt{s}/g;
333     $opt{r} or valid_err q<Built-in code parameter "r" required>;
334     $r =~ s/\$r\b/\$$opt{r}/g;
335     $r =~ s/\$$opt{r} = \$$opt{s};/#/g if $opt{r} eq $opt{s};
336     } elsif (type_isa ($name, ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>)) {
337     $r = perl_statement perl_exception
338     (level => 'WARNING',
339     class => 'ManakaiDOMImplementationWarning',
340     type => 'MDOM_NS_EMPTY_URI',
341     param => {
342     ExpandedURI q<MDOM_EXCEPTION:param-name> => $opt{s},
343     });
344     if ($opt{condition} and $opt{condition} ne 'DOM2') {
345     $r .= perl_statement q<$out = undef>;
346     }
347     $r = perl_if (q<defined $in and $in eq ''>, $r);
348     $opt{s} or valid_err q<Built-in code parameter "s" required>;
349     $r =~ s/\$in\b/\$$opt{s}/g;
350     $opt{r} or valid_err q<Built-in code parameter "r" required>;
351     $r =~ s/\$out\b/\$$opt{r}/g;
352     } elsif ($name eq 'UniqueID') {
353     $r = q{(
354     sprintf 'mid:%d.%d.%s.dom.manakai@suika.fam.cx',
355     time, $$,
356     ['A'..'Z', 'a'..'z', '0'..'9']->[rand 62] .
357     ['A'..'Z', 'a'..'z', '0'..'9']->[rand 62] .
358     ['A'..'Z', 'a'..'z', '0'..'9']->[rand 62] .
359     ['A'..'Z', 'a'..'z', '0'..'9']->[rand 62] .
360     ['A'..'Z', 'a'..'z', '0'..'9']->[rand 62]
361     )};
362     ## TODO: Check as HTML Name if not XML.
363     } elsif ($name eq 'CheckQName') {
364     $opt{version} = '1.0' if $opt{condition} and $opt{condition} eq 'DOM2';
365     my $chk = perl_if
366     (qq<##CHKNAME##>, undef,
367     (perl_statement
368     perl_exception
369     (class => 'DOMException',
370     type => 'INVALID_CHARACTER_ERR',
371     subtype_uri =>
372     ExpandedURI q<MDOM_EXCEPTION:MDOM_BAD_NAME>,
373     param => {
374     ExpandedURI q<DOMCore:name>
375     => perl_code_literal
376     (perl_var type => '$', local_name => 'qname'),
377     }))) .
378     perl_if
379     (qq<##CHKQNAME##>, undef,
380     (perl_statement
381     perl_exception
382     (class => 'DOMException',
383     type => 'NAMESPACE_ERR',
384     subtype_uri =>
385     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_MALFORMED_QNAME>,
386     param => {
387     ExpandedURI q<DOMCore:qualifiedName>
388     => perl_code_literal
389     (perl_var type => '$', local_name => 'qname'),
390     })));
391     my $chk10 = $chk;
392     $chk10 =~ s{##CHKNAME##}
393     {q<$qname =~ /\A\p{InXML_NameStartChar10}>.
394     q<\p{InXMLNameChar10}*\z/>}ge;
395     $chk10 =~ s{##CHKQNAME##}
396     {q<$qname =~ /\A\p{InXML_NCNameStartChar10}>.
397     q<\p{InXMLNCNameChar10}*>.
398     q<(?::\p{InXML_NCNameStartChar10}>.
399     q<\p{InXMLNCNameChar10}*)?\z/>}ge;
400     my $chk11 = $chk;
401     $chk11 =~ s{##CHKNAME##}
402     {q<$qname =~ /\A\p{InXMLNameStartChar11}>.
403     q<\p{InXMLNameChar11}*\z/>}ge;
404     $chk11 =~ s{##CHKQNAME##}
405     {q<$qname =~ /\A\p{InXMLNCNameStartChar11}>.
406     q<\p{InXMLNCNameChar11}*>.
407     q<(?::\p{InXMLNCNameStartChar11}>.
408     q<\p{InXMLNCNameChar11}*)?\z/>}ge;
409     my %class;
410     if ($opt{version} and $opt{version} eq '1.0') {
411     $r = $chk10;
412     %class = (qw/InXML_NameStartChar10 InXMLNameChar10
413     InXML_NCNameStartChar10 InXMLNCNameChar10/);
414     } elsif ($opt{version} and $opt{version} eq '1.1') {
415     $r = $chk11;
416     %class = (qw/InXMLNameStartChar11 InXMLNameChar11
417     InXMLNCNameStartChar11 InXMLNCNameChar11/);
418     } elsif ($opt{version}) {
419     $r = perl_if (q<defined >.
420     perl_var (type => '$', local_name => $opt{version}) .
421     q< and >.
422     perl_var (type => '$', local_name => $opt{version}) .
423     q< eq '1.1'>, $chk11, $chk10);
424     %class = (qw/InXML_NameStartChar10 InXMLNameChar10
425     InXML_NCNameStartChar10 InXMLNCNameChar10
426     InXMLNameStartChar11 InXMLNameChar11
427     InXMLNCNameStartChar11 InXMLNCNameChar11/);
428     } else {
429     valid_err q<Built-in code parameter "version" required>;
430     }
431     $opt{qname} or valid_err q<Built-in code parameter "qname" required>;
432     $r =~ s/\$qname\b/\$$opt{qname}/g;
433     $Info->{Require_perl_package_use}->{'Char::Class::XML'} or
434     valid_err q<"Char::Class::XML" must be "Require"d in the interface >.
435     qq{"$Status->{IF}", condition "$Status->{condition}"};
436     for (%class) {
437     $Info->{Require_perl_package_use}->{'Char::Class::XML::::Import'}->{$_} or
438     valid_err qq<"$_" must be exported from "Char::Class::XML" in the >.
439     qq{interface "$Status->{IF}", condition }.
440     qq{"$Status->{condition}"};
441     }
442     } elsif ($name eq 'CheckNCName') {
443     $opt{version} = '1.0' if $opt{condition} and $opt{condition} eq 'DOM2';
444     my $chk = perl_if
445     (qq<##CHKNAME##>, undef,
446     (perl_statement
447     perl_exception
448     (class => 'DOMException',
449     type => 'INVALID_CHARACTER_ERR',
450     subtype_uri =>
451     ExpandedURI q<MDOM_EXCEPTION:MDOM_BAD_NAME>,
452     param => {
453     ExpandedURI q<DOMCore:name>
454     => perl_code_literal
455     (perl_var type => '$', local_name => 'qname'),
456     }))) .
457     perl_if
458     (qq<##CHKNCNAME##>, undef,
459     (perl_statement
460     perl_exception
461     (class => 'DOMException',
462     type => 'NAMESPACE_ERR',
463     subtype_uri =>
464     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_BAD_NCNAME>,
465     param => {
466     ExpandedURI q<infoset:name>
467     => perl_code_literal
468     (perl_var type => '$', local_name => 'qname'),
469     })));
470     my $chk10 = $chk;
471     $chk10 =~ s{##CHKNAME##}
472     {q<$qname =~ /\A\p{InXML_NameStartChar10}>.
473     q<\p{InXMLNameChar10}*\z/>}ge;
474     $chk10 =~ s{##CHKNCNAME##}
475     {q<$qname =~ /:/>}ge;
476     my $chk11 = $chk;
477     $chk11 =~ s{##CHKNAME##}
478     {q<$qname =~ /\A\p{InXMLNameStartChar11}>.
479     q<\p{InXMLNameChar11}*\z/>}ge;
480     $chk11 =~ s{##CHKNCNAME##}
481     {q<$qname =~ /:/>}ge;
482     my $t = ($opt{empty} and $opt{empty} eq 'warn3' and
483     (not $opt{condition} or $opt{condition} ne 'DOM2')) ?
484     perl_if
485     (q<defined $qname and $qname eq q<>>,
486     perl_statement (perl_exception
487     (level => 'WARNING',
488     class => 'ManakaiDOMImplementationWarning',
489     type => 'MDOM_NS_EMPTY_PREFIX',
490     param => {
491     ExpandedURI q<MDOM_EXCEPTION:param-name> => $opt{ncname},
492     })).
493     perl_statement (q<$qname = undef>)) : '';
494     my %class;
495     if ($opt{version} and $opt{version} eq '1.0') {
496     $r = $chk10;
497     %class = (qw/InXML_NameStartChar10 InXMLNameChar10/);
498     } elsif ($opt{version} and $opt{version} eq '1.1') {
499     $r = $chk11;
500     %class = (qw/InXMLNameStartChar11 InXMLNameChar11/);
501     } elsif ($opt{version}) {
502     $r = perl_if (q<defined >.
503     perl_var (type => '$', local_name => $opt{version}) .
504     q< and >.
505     perl_var (type => '$', local_name => $opt{version}) .
506     q< eq '1.1'>, $chk11, $chk10);
507     %class = (qw/InXML_NameStartChar10 InXMLNameChar10
508     InXMLNameStartChar11 InXMLNameChar11/);
509     } else {
510     valid_err q<Built-in code parameter "version" required>;
511     }
512     $r = $t . $r;
513     $opt{ncname} or valid_err q<Built-in code parameter "ncname" required>;
514     $r =~ s/\$qname\b/\$$opt{ncname}/g;
515     $Info->{Require_perl_package_use}->{'Char::Class::XML'} or
516     valid_err q<"Char::Class::XML" must be "Require"d in the interface >.
517     qq{"$Status->{IF}", condition "$Status->{condition}"};
518     for (%class) {
519     $Info->{Require_perl_package_use}->{'Char::Class::XML::::Import'}->{$_} or
520     valid_err qq<"$_" must be exported from "Char::Class::XML" in the >.
521     qq{interface "$Status->{IF}", condition }.
522     qq{"$Status->{condition}"};
523     }
524     } elsif ($name eq 'CheckName') {
525     $opt{version} = '1.0' if $opt{condition} and
526     ($opt{condition} eq 'DOM2' or
527     $opt{condition} eq 'DOM1');
528     my $chk = perl_if
529     (qq<##CHKNAME##>, undef,
530     (perl_statement
531     perl_exception
532     (class => 'DOMException',
533     type => 'INVALID_CHARACTER_ERR',
534     subtype_uri =>
535     ExpandedURI q<MDOM_EXCEPTION:MDOM_BAD_NAME>,
536     param => {
537     ExpandedURI q<DOMCore:name>
538     => perl_code_literal
539     (perl_var type => '$', local_name => 'qname'),
540     })));
541     my $chk10 = $chk;
542     $chk10 =~ s{##CHKNAME##}
543     {q<$qname =~ /\A\p{InXML_NameStartChar10}>.
544     q<\p{InXMLNameChar10}*\z/>}ge;
545     my $chk11 = $chk;
546     $chk11 =~ s{##CHKNAME##}
547     {q<$qname =~ /\A\p{InXMLNameStartChar11}>.
548     q<\p{InXMLNameChar11}*\z/>}ge;
549     my %class;
550    
551     if ($opt{version} and $opt{version} eq '1.0') {
552     $r = $chk10;
553     %class = (qw/InXML_NameStartChar10 InXMLNameChar10/);
554     } elsif ($opt{version} and $opt{version} eq '1.1') {
555     $r = $chk11;
556     %class = (qw/InXMLNameStartChar11 InXMLNameChar11/);
557     } elsif ($opt{version}) {
558     $r = perl_if (q<defined >.
559     perl_var (type => '$', local_name => $opt{version}) .
560     q< and >.
561     perl_var (type => '$', local_name => $opt{version}) .
562     q< eq '1.1'>, $chk11, $chk10);
563     %class = (qw/InXML_NameStartChar10 InXMLNameChar10
564     InXMLNameStartChar11 InXMLNameChar11/);
565     } else {
566     valid_err q<Built-in code parameter "version" required>;
567     }
568     $opt{name} or valid_err q<Built-in code parameter "name" required>;
569     $r =~ s/\$qname\b/\$$opt{name}/g;
570     $Info->{Require_perl_package_use}->{'Char::Class::XML'} or
571     valid_err q<"Char::Class::XML" must be "Require"d in the interface >.
572     qq{"$Status->{IF}", condition "$Status->{condition}"};
573     for (%class) {
574     $Info->{Require_perl_package_use}->{'Char::Class::XML::::Import'}->{$_} or
575     valid_err qq<"$_" must be exported from "Char::Class::XML" in the >.
576     qq{interface "$Status->{IF}", condition }.
577     qq{"$Status->{condition}"};
578     }
579     } elsif ($name eq 'CheckNull') {
580     $r = perl_code q{
581     __EXCEPTION{
582     ManakaiDOMImplementationException.PARAM_NULL_POINTER::
583     <Q:MDOM_EXCEPTION:param-name> => 'arg',
584     }__ unless defined $arg;
585     };
586     $opt{s} or valid_err q<Built-in code parameter "s" required>;
587     $r =~ s/\$arg\b/\$$opt{s}/g;
588     $r =~ s/'arg'/perl_literal ($opt{s})/ge;
589     } elsif ($name eq 'XMLVersion') {
590     $r = perl_code q{
591     $r = defined $node->{<Q:DOMCore:hasFeature>}->{XML} ?
592     defined $node->{<Q:infoset:version>} ?
593     $node->{<Q:infoset:version>} : '1.0' : null;
594     };
595     $opt{docNode} or valid_err q<Built-in code parameter "docNode" required>;
596     $r =~ s/\$node\b/\$$opt{docNode}/g;
597     $opt{out} or valid_err q<Built-in code parameter "out" required>;
598     $r =~ s/\$r\b/\$$opt{out}/g;
599     } elsif ($name eq 'XMLNS') {
600     for (qw/docNode namespaceURI qualifiedName out-version
601     out-prefix out-localName/) {
602     $opt{$_} or valid_err qq<Built-in code parameter "$_" required>,
603     node => $opt{node};
604     }
605    
606     ## Check the Document XML version
607     ## - The Document must support the "XML" feature
608     $r = perl_builtin_code ('XMLVersion', %opt,
609     out => $opt{'out-version'},
610     docNode => $opt{docNode});
611     $r .= perl_if
612     (q<defined >.perl_var (type => '$',
613     local_name => $opt{'out-version'}),
614     undef,
615     perl_statement
616     perl_exception
617     (type => 'NOT_SUPPORTED_ERR',
618     class => 'DOMException',
619     subtype_uri =>
620     ExpandedURI q<MDOM_EXCEPTION:MDOM_DOC_NOSUPPORT_XML>));
621    
622     ## Check the QName
623     $r .= perl_builtin_code ('CheckQName', %opt,
624     qname => $opt{qualifiedName},
625     version => $opt{'out-version'});
626    
627     ## Split QName into prefix and local name
628     my $prefix = perl_var (type => '$', local_name => $opt{'out-prefix'});
629     my $lname = perl_var (type => '$', local_name => $opt{'out-localName'});
630     my $nsURI = perl_var (type => '$', local_name => $opt{namespaceURI});
631     $r .= qq{($prefix, $lname) = split /:/, \$$opt{qualifiedName}, 2;
632     ($prefix, $lname) = (undef, $prefix) unless defined $lname;};
633    
634     ## Check namespace binding
635     $r .= perl_if
636     (qq<defined $prefix>,
637     perl_cases (
638     qq<not defined $nsURI>,
639     => perl_statement
640     (perl_exception
641     (type => 'NAMESPACE_ERR',
642     class => 'DOMException',
643     subtype_uri =>
644     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_PREFIX_WITH_NULL_URI>,
645     param => {
646     ExpandedURI q<infoset:prefix> =>
647     perl_code_literal ($prefix),
648     })),
649     qq<$prefix eq 'xml' and $nsURI ne >.
650     perl_literal (ExpandedURI q<xml:>)
651     => perl_statement
652     (perl_exception
653     (type => 'NAMESPACE_ERR',
654     class => 'DOMException',
655     subtype_uri =>
656     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_XML_WITH_OTHER_URI>,
657     param => {
658     ExpandedURI q<infoset:namespaceName> =>
659     perl_code_literal ($nsURI),
660     })),
661     qq<$prefix eq 'xmlns' and $nsURI ne >.
662     perl_literal (ExpandedURI q<xmlns:>)
663     => perl_statement
664     (perl_exception
665     (type => 'NAMESPACE_ERR',
666     class => 'DOMException',
667     subtype_uri =>
668     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_XMLNS_WITH_OTHER_URI>,
669     param => {
670     ExpandedURI q<infoset:namespaceName> =>
671     perl_code_literal ($nsURI),
672     })),
673     perl_literal (ExpandedURI q<xml:>).
674     qq< eq $nsURI and $prefix ne 'xml'>
675     => perl_statement
676     (perl_exception
677     (type => 'NAMESPACE_ERR',
678     class => 'DOMException',
679     subtype_uri =>
680     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_OTHER_WITH_XML_URI>,
681     param => {
682     ExpandedURI q<infoset:prefix> =>
683     perl_code_literal ($prefix),
684     ExpandedURI q<DOMCore:qualifiedName>
685     => perl_code_literal ('$qualifiedName'),
686     })),
687     perl_literal (ExpandedURI q<xmlns:>).
688     qq< eq $nsURI and $prefix ne 'xmlns'>
689     => perl_statement
690     (perl_exception
691     (type => 'NAMESPACE_ERR',
692     class => 'DOMException',
693     subtype_uri =>
694     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_OTHER_WITH_XMLNS_URI>,
695     param => {
696     ExpandedURI q<infoset:prefix> =>
697     perl_code_literal ($prefix),
698     ExpandedURI q<DOMCore:qualifiedName>
699     => perl_code_literal ('$qualifiedName'),
700     })),
701     perl_literal (ExpandedURI q<xmlns:>).
702     qq< eq $nsURI and $prefix eq 'xmlns' and $lname eq 'xmlns'>
703     => perl_statement
704     (perl_exception
705     (type => 'NAMESPACE_ERR',
706     class => 'DOMException',
707     subtype_uri =>
708     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_XMLNS_XMLNS>,
709     param => {
710     })),
711     ),
712     perl_cases ( # No prefix
713     perl_literal (ExpandedURI q<xml:>).qq< eq $nsURI>
714     => perl_statement
715     (perl_exception
716     (type => 'NAMESPACE_ERR',
717     class => 'DOMException',
718     subtype_uri =>
719     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_OTHER_WITH_XML_URI>,
720     param => {
721     ExpandedURI q<DOMCore:qualifiedName>
722     => perl_code_literal ($lname),
723     })),
724     perl_literal (ExpandedURI q<xmlns:>).
725     qq< eq $nsURI and $lname ne 'xmlns'>
726     => perl_statement
727     (perl_exception
728     (type => 'NAMESPACE_ERR',
729     class => 'DOMException',
730     subtype_uri =>
731     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_OTHER_WITH_XMLNS_URI>,
732     param => {
733     ExpandedURI q<DOMCore:qualifiedName>
734     => perl_code_literal ($lname),
735     })),
736     qq<$lname eq 'xmlns' and $nsURI ne >.
737     perl_literal (ExpandedURI q<xmlns:>)
738     => perl_statement
739     (perl_exception
740     (type => 'NAMESPACE_ERR',
741     class => 'DOMException',
742     subtype_uri =>
743     ExpandedURI q<MDOM_EXCEPTION:MDOM_NS_XMLNSQ_WITH_OTHER_URI>,
744     param => {
745     ExpandedURI q<infoset:namespaceName>
746     => perl_code_literal ($nsURI),
747     })),
748     ));
749     } elsif ($name eq 'isRelativeDOMURI') {
750     $r = q<$in !~ /^[0-9A-Za-z+_.%-]:/>;
751     ## TODO: I18n consideration
752     for (qw/in/) {
753     $opt{$_} or valid_err qq<Built-in code parameter "$_" required>,
754     node => $opt{node};
755     $r =~ s/\$$_/\$$opt{$_}/g;
756     }
757     } elsif ($name eq 'ParseFeatures') {
758     $r = q{
759     {
760     if (ref $in eq 'HASH') {
761     for (keys %$in) {
762     if ($_ =~ /^\+(.+)/) {
763     $out{lc $1} = {version => $in{$_}, plus => 1};
764     } else {
765     $out{lc $_} = {version => $in{$_}, plus => 0};
766     }
767     }
768     } else {
769     my @f = grep {length} split /\s+/, $in;
770     for (my $i = 0; $i < @f; $i++) {
771     my ($name, $plus) = (lc $f[$i]);
772     $plus = 1 if $name =~ s/^\+//;
773     if ($i + 1 < @f and $f[$i + 1] =~ /^\d/) {
774     $out{$name} = {version => $f[$i + 1], plus => $plus}; $i++;
775     } else {
776     $out{$name} = {version => undef, plus => $plus};
777     }
778     }
779     }
780     }
781     }; ## NOTE: Feature name is case-insensitive.
782     ## NOTE: This code does not work if a feature appears more than
783     ## one versions. DOM specification does not specify how
784     ## implementations should cope with such case.
785     for (qw/in out/) {
786     $opt{$_} or valid_err qq<Built-in code parameter "$_" required>,
787     node => $opt{node};
788     $r =~ s/\$$_/\$$opt{$_}/g;
789     $r =~ s/%$_/%$opt{$_}/g;
790     }
791     } else {
792     valid_err qq<Built-in code "$name" not defined>;
793     }
794     $r;
795     }
796    
797     sub ops2perl () {
798     my $result = '';
799     for (keys %{$Status->{Operator}}) {
800     if ($_ eq 'DESTROY') {
801     $result .= perl_statement q<sub DESTROY ($)>;
802     $result .= perl_statement
803     perl_assign
804     perl_var (type => '*', local_name => 'DESTROY')
805     => $Status->{Operator}->{DESTROY};
806     delete $Status->{Operator}->{DESTROY};
807     } elsif ($_ eq 'new') {
808     $result .= perl_statement q<sub new ($)>;
809     $result .= perl_statement
810     perl_assign
811     perl_var (type => '*', local_name => 'new')
812     => $Status->{Operator}->{$_};
813     delete $Status->{Operator}->{$_};
814     } elsif ($_ eq 'object-error-handler') {
815     $result .= perl_statement q<sub ___report_error ($$)>;
816     $result .= perl_statement
817     perl_assign
818     perl_var (type => '*', local_name => '___report_error')
819     => $Status->{Operator}->{$_};
820     delete $Status->{Operator}->{$_};
821     } elsif ({qw[
822     + 1 - 1 * 1 / 1 % 1 ** 1 << 1 >> 1 x 1 . 1
823     += 1 -= 1 *= 1 /= 1 %= 1 **= 1 <<= 1 >>= 1 x= 1 .= 1
824     < 1 <= 1 > 1 >= 1 == 1 != 1 <=> 1
825     lt 1 le 1 gt 1 ge 1 eq 1 ne 1 cmp 1
826     & 1 | 1 ^ 1
827     neg 1 ! 1 ~ 1
828     ++ 1 -- 1
829     atan2 1 cos 1 sin 1 exp 1 abs 1 log 1 sqrt 1
830     bool 1 "" 1 0+ 1
831     <> 1
832     ${} 1 @{} 1 %{} 1 &{} 1 *{} 1
833     ]}->{$_}) {
834     #
835     } else {
836     valid_err qq[$Status->{if}: Operator "$_" not supported];
837     }
838     }
839     if (keys %{$Status->{Operator}}) {
840     $result .= perl_statement 'use overload ' .
841     perl_list map ({($_,
842     perl_code_literal $Status->{Operator}->{$_})}
843     keys %{$Status->{Operator}}),
844     fallback => 1;
845     }
846     $result;
847     }
848    
849    
850    
851     sub qname_label ($;%) {
852     my ($node, %opt) = @_;
853     my $q = defined $opt{qname} ? $opt{qname}
854     : $node->get_attribute_value ('QName');
855     my $prefix = DEFAULT_PFX;
856     if ($q =~ s/^([^:]*)://) {
857     $prefix = $1;
858     }
859    
860     if ($prefix ne DEFAULT_PFX or not $opt{no_default_ns}) {
861     if (defined $Info->{Namespace}->{$prefix}) {
862     my $uri = $Info->{Namespace}->{$prefix};
863     if (defined $Status->{ns_in_doc}->{$prefix}) {
864     if ($Status->{ns_in_doc}->{$prefix} ne $uri) {
865     my $i = 1;
866     {
867     if (defined $Status->{ns_in_doc}->{$prefix.$i}) {
868     if ($Status->{ns_in_doc}->{$prefix.$i} eq $uri) {
869     $prefix .= $i; last;
870     } else {
871     $i++; redo;
872     }
873     } else {
874     $Status->{ns_in_doc}->{$prefix.$i} = $uri;
875     $prefix .= $i; last;
876     }
877     }
878     }
879     } else {
880     $Status->{ns_in_doc}->{$prefix} = $uri;
881     }
882     } else {
883     valid_err q<Namespace prefix "$prefix" not defined>,
884     node => $node->get_attribute ('QName');
885     }
886     }
887    
888     $opt{out_type} ||= ExpandedURI q<DOMMain:any>;
889     if ($opt{out_type} eq ExpandedURI q<lang:pod>) {
890     pod_code ($prefix eq DEFAULT_PFX ? $q : qq<$prefix:$q>);
891     } else {
892     $prefix eq DEFAULT_PFX ? qq<"$q"> : qq<"$prefix:$q">;
893     }
894     }
895    
896     {
897     my $nest = 0;
898     sub type_normalize ($);
899     sub type_normalize ($) {
900     my ($uri) = @_;
901     $nest++ == 100 and valid_err q<Possible loop for DataTypeAlias of <$uri>>;
902     if ($Info->{DataTypeAlias}->{$uri}->{canon_uri}) {
903     $uri = type_normalize ($Info->{DataTypeAlias}->{$uri}->{canon_uri});
904     }
905     $nest--;
906     $uri;
907     }
908     }
909    
910     {
911     my $nest = 0;
912     sub type_isa ($$);
913     sub type_isa ($$) {
914     my ($uri, $uri2) = @_;
915     $nest++ == 100 and valid_err qq<Possible loop for <DataType/ISA> of <$uri>>;
916     my $r = 0;
917     if ($uri eq $uri2) {
918     $r = 1;
919     } else {
920     for (@{$Info->{DataTypeAlias}->{$uri}->{isa_uri}||[]}) {
921     if (type_isa $_, $uri2) {
922     $r = 1;
923     last;
924     }
925     }
926     }
927     $nest--;
928     $r;
929     }
930     }
931    
932     sub type_label ($;%) {
933     my $uri = type_normalize shift;
934     my %opt = @_;
935     my $pod_code = sub { $opt{is_pod} ? pod_code $_[0] : $_[0] };
936     my $r = {
937     ExpandedURI q<DOMMain:unsigned-long> => q<Unsigned Long Integer>,
938     ExpandedURI q<DOMMain:unsigned-short> => q<Unsigned Short Integer>,
939     ExpandedURI q<ManakaiDOM:ManakaiDOMURI>
940     => $pod_code->(q<DOMString>).q< (DOM URI)>,
941     ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>
942     => $pod_code->(q<DOMString>).q< (Namespace URI)>,
943     ExpandedURI q<ManakaiDOM:ManakaiDOMFeatureName>
944     => $pod_code->(q<DOMString>).q< (DOM Feature name)>,
945     ExpandedURI q<ManakaiDOM:ManakaiDOMFeatureVersion>
946     => $pod_code->(q<DOMString>).q< (DOM Feature version)>,
947     ExpandedURI q<ManakaiDOM:ManakaiDOMFeatures>
948     => $pod_code->(q<DOMString>).q< (DOM features)>,
949     }->{$uri};
950     unless ($r) {
951     if ($uri =~ /([\w_-]+)$/) {
952     my $label = $1;
953     $label =~ s/--+/ /g;
954     $label =~ s/__+/ /g;
955     $r = $pod_code->($label);
956     } else {
957     $r = $pod_code->("<$uri>");
958     }
959     }
960     $r;
961     }
962    
963     sub type_package_name ($) {
964     my $qname = shift;
965     if ($qname =~ /^([^:]*):([^:]*)$/) {
966     perl_package_name name => perl_name $2, ucfirst => 1;
967     } else {
968     perl_package_name name => perl_name $qname, ucfirst => 1;
969     }
970     }
971    
972     sub ns_uri_to_perl_package_name ($) {
973     my $uri = shift;
974     if ($Info->{uri_to_perl_package}->{$uri}) {
975     return $Info->{uri_to_perl_package}->{$uri};
976     } else {
977     return qq<Perl package name for namespace <$uri> not defined>;
978     }
979     }
980    
981     sub ns_prefix_to_uri ($) {
982     my $pfx = shift;
983     if (exists $Info->{Namespace}->{$pfx}) {
984     if (not defined $Info->{Namespace}->{$pfx}) {
985     valid_err qq<Namespace name for "$pfx" not defined>;
986     } else {
987     return $Info->{Namespace}->{$pfx};
988     }
989     } else {
990     valid_err qq<Namespace prefix "$pfx" not declared>;
991     }
992     }
993    
994     sub type_expanded_uri ($) {
995     my $qname = shift || '';
996     if ($qname =~ /^[a-z-]+$/ or $qname eq 'Object') {
997     expanded_uri ("DOMMain:$qname");
998     } else {
999     expanded_uri ($qname);
1000     }
1001     }
1002    
1003     sub expanded_uri ($) {
1004     my $lname = shift || '';
1005     my $pfx = DEFAULT_PFX;
1006     if ($lname =~ s/^([^:]*)://) {
1007     $pfx = $1;
1008     }
1009     ns_prefix_to_uri ($pfx) . $lname;
1010     }
1011    
1012     sub array_contains ($$) {
1013     my ($array, $val) = @_;
1014     if (ref $array eq 'ARRAY') {
1015     for (@$array) {
1016     return 1 if $_ eq $val;
1017     }
1018     } else {
1019     return $array eq $val;
1020     }
1021     return 0;
1022     }
1023    
1024    
1025     sub get_warning_perl_code ($) {
1026     my $pnode = shift;
1027     my $r = '';
1028     for my $node (@{$pnode->child_nodes}) {
1029     next unless $node->node_type eq '#element' and
1030     $node->local_name eq 'Warning';
1031     my %param;
1032     for (@{$node->child_nodes}) {
1033     next unless $_->node_type eq '#element' and
1034     $_->local_name eq 'Param';
1035     $param{expanded_uri $_->get_attribute_value ('QName')}
1036     = perl_code_literal get_value_literal ($_, name => 'Value',
1037     type_name => 'Type');
1038     }
1039     $r .= perl_statement
1040     perl_exception
1041     class => type_package_name $node->get_attribute_value
1042     ('Type',
1043     default => 'DOMMain:any'),
1044     type => $node->get_attribute_value ('Name'),
1045     param => \%param;
1046     }
1047     $r;
1048     } # get_warning_perl_code
1049    
1050     sub get_perl_definition_node ($%) {
1051     my ($node, %opt) = @_;
1052     my $ln = $opt{name} || 'Def';
1053     my $def = $node->get_element_by (sub {
1054     my ($me, $you) = @_;
1055     $you->local_name eq $ln and
1056     type_expanded_uri $you->get_attribute_value ('Type', default => '')
1057     eq ExpandedURI q<lang:Perl> and
1058     condition_match ($you, %opt);
1059     }) || ($opt{use_dis} and $node->get_element_by (sub {
1060     my ($me, $you) = @_;
1061     $you->local_name eq $ln and
1062     $you->get_attribute_value ('Type', default => '')
1063     eq ExpandedURI q<lang:dis> and
1064     condition_match ($you, %opt);
1065     })) || $node->get_element_by (sub {
1066     my ($me, $you) = @_;
1067     $you->local_name eq $ln and
1068     not $you->get_attribute_value ('Type', default => '') and
1069     condition_match ($you, %opt);
1070     }) || $node->get_element_by (sub {
1071     my ($me, $you) = @_;
1072     $you->local_name eq $ln and
1073     type_expanded_uri $you->get_attribute_value ('Type', default => '')
1074     eq ExpandedURI q<lang:Perl> and
1075     condition_match ($you); # no condition specified
1076     }) || ($opt{use_dis} and $node->get_element_by (sub {
1077     my ($me, $you) = @_;
1078     $you->local_name eq $ln and
1079     type_expanded_uri $you->get_attribute_value ('Type', default => '')
1080     eq ExpandedURI q<lang:dis> and
1081     condition_match ($you); # no condition specified
1082     })) || $node->get_element_by (sub {
1083     my ($me, $you) = @_;
1084     $you->local_name eq $ln and
1085     not $you->get_attribute_value ('Type', default => '') and
1086     condition_match ($you); # no condition specified
1087     });
1088     $def;
1089     }
1090    
1091     sub get_perl_definition ($%) {
1092     my ($node, %opt) = @_;
1093     my $def = get_perl_definition_node $node, %opt;
1094     $def ? $def->value : $opt{default};
1095     }
1096    
1097     sub dis2perl ($) {
1098     my $node = shift;
1099     my $r = '';
1100     for (@{$node->child_nodes}) {
1101     next unless $_->node_type eq '#element';
1102     if ($_->local_name eq 'GetProp') {
1103     $r .= perl_statement perl_assign
1104     perl_var (type => '$', local_name => 'r')
1105     => '$self->{node}->{' .
1106     perl_literal (expanded_uri ($_->value)) . '}';
1107     } elsif ($_->local_name eq 'GetPropNode') {
1108     $r .= perl_statement perl_assign
1109     perl_var (type => '$', local_name => 'r')
1110     => '$self->{node}->{' .
1111     perl_literal (expanded_uri ($_->value)) . '}';
1112     ## Conditional
1113     $r .= perl_statement
1114     perl_code q{$r = __CLASS{Node}__->__INT{getNodeReference}__ ($r)
1115     if defined $r};
1116     } elsif ($_->local_name eq 'SetProp') {
1117     my $t = perl_statement perl_assign
1118     '$self->{node}->{' .
1119     perl_literal (expanded_uri ($_->value)) . '}'
1120     => perl_var (type => '$', local_name => 'given');
1121     if ($_->get_attribute_value ('CheckReadOnly', default => 1)) {
1122     $r .= perl_if
1123     q[$self->{'node'}->{].
1124     perl_literal (ExpandedURI (q<DOMCore:read-only>)).q[}],
1125     perl_statement
1126     (perl_exception
1127     class => 'DOMException',
1128     type => 'NO_MODIFICATION_ALLOWED_ERR',
1129     param => {}),
1130     $t;
1131     } else {
1132     $r .= $t;
1133     }
1134     } elsif ($_->local_name eq 'Overridden') {
1135     $r = perl_statement perl_exception
1136     class => 'ManakaiDOMImplementationException',
1137     type => 'MDOM_DEBUG_BUG',
1138     param => {
1139     ExpandedURI q<MDOM_EXCEPTION:values> => {
1140     msg => q<This class defines only the interface; >.
1141     q<some other class must inherit this class >.
1142     q<and implement this subroutine.>,
1143     },
1144     };
1145     } elsif ($_->local_name eq 'Type') {
1146     #
1147     } else {
1148     valid_err qq{Element type "@{[$_->local_name]}" not supported},
1149     node => $_;
1150     }
1151     }
1152     if (defined $node->value and length $node->value) {
1153     valid_err q{DIS has value}, node => $node;
1154     }
1155     $r;
1156     } # dis2perl
1157    
1158     {
1159     use re 'eval';
1160     our $Element;
1161     $Element = qr/[A-Za-z0-9]+(?>:(?>[^<>]*)(?>(?>[^<>]+|<(??{$Element})>)*))?/;
1162     my $MElement = qr/([A-Za-z0-9]+)(?>:((?>[^<>]*)(?>(?>[^<>]+|<(??{$Element})>)*)))?/;
1163    
1164     sub disdoc2text ($;%);
1165     sub disdoc2text ($;%) {
1166     my ($s, %opt) = @_;
1167     $s =~ s/\x0D\x0A/\x0A/g;
1168     $s =~ tr/\x0D/\x0A/;
1169     my @s = split /\x0A\x0A+/, $s;
1170     my @r;
1171     for my $s (@s) {
1172     if ($s =~ s/^\{([0-9A-Za-z-]+)::\s*//) { ## Start tag'ed element
1173     my $et = $1;
1174     if ($et eq 'P') { ## Paragraph
1175     push @r, (disdoc_inline2text ($s, %opt));
1176     } elsif ($et eq 'LI' or $et eq 'OLI') { ## List
1177     my $marker = '* ';
1178     if ($et eq 'OLI') {
1179     $marker = '# ';
1180     }
1181     if ($s =~ s/^(.+?)::\s*//) {
1182     $marker = disdoc_inline2text ($1, %opt) . ': ';
1183     }
1184     push @r, $marker . (disdoc_inline2text ($s, %opt));
1185     } else {
1186     valid_err qq<Unknown DISDOC element type "$et">, node => $opt{node};
1187     }
1188     } elsif ($s =~ /^\}\s*$/) { ## End tag
1189     #
1190     } elsif ($s =~ s/^([-=])\s*//) { ## List
1191     my $marker = $1;
1192     if ($marker eq '=') {
1193     $marker = '# ';
1194     } elsif ($marker eq '-') {
1195     $marker = '* ';
1196     }
1197     if ($s =~ s/^(.+?)::\s*//) {
1198     $marker = disdoc_inline2text ($1, %opt) . ': ';
1199     }
1200     push @r, $marker . (disdoc_inline2pod ($s, %opt));
1201     } elsif ($s =~ /^[^\w\s<]/) { ## Reserved for future extension
1202     valid_err qq<Broken DISDOC: "$s">, node => $opt{node};
1203     } else {
1204     $s =~ s/^\s+//;
1205     push @r, disdoc_inline2text ($s, %opt);
1206     }
1207     }
1208     join "\n\n", @r;
1209     } # disdoc2text
1210    
1211     sub disdoc_inline2text ($;%);
1212     sub disdoc_inline2text ($;%) {
1213     my ($s, %opt) = @_;
1214     $s =~ s{\G(?:([^<>]+)|<$MElement>|(.))}{
1215     my ($cdata, $type, $data, $err) = ($1, $2, defined $3 ? $3 : '', $4);
1216     my $r = '';
1217     if (defined $err) {
1218     valid_err qq<Invalid character "$err" in DISDOC>,
1219     node => $opt{node};
1220     } elsif (defined $cdata) {
1221     $r = $cdata;
1222     } elsif ({DFN => 1, CITE => 1}->{$type}) {
1223     $r = disdoc_inline2text $data;
1224     } elsif ({SRC => 1}->{$type}) {
1225     $r = q<[>. disdoc_inline2text ($data) . q<]>;
1226     } elsif ({URI => 1}->{$type}) {
1227     $r = q{<} . $data . q{>};
1228     } elsif ({CODE => 1, Perl => 1}->{$type}) {
1229     $r = q<"> . disdoc_inline2text ($data) . q<">;
1230     } elsif ({IF => 1, TYPE => 1, P => 1, XML => 1, SGML => 1, DOM => 1,
1231     FeatureVer => 1, CHAR => 1, HTML => 1, Prefix => 1,
1232     Module => 1, QUOTE => 1, PerlModule => 1,
1233     FILE => 1}->{$type}) {
1234     $r = q<"> . $data . q<">;
1235     } elsif ({Feature => 1, CP => 1, ERR => 1,
1236     HA => 1, HE => 1, XA => 1, SA => 1, SE => 1}->{$type}) {
1237     $r = qname_label (undef, qname => $data,
1238     no_default_ns => 1);
1239     } elsif ({Q => 1, EV => 1,
1240     XE => 1}->{$type}) {
1241     $r = qname_label (undef, qname => $data);
1242     } elsif ({M => 1, A => 1, X => 1, WARN => 1}->{$type}) {
1243     if ($data =~ /^([^.]+)\.([^.]+)$/) {
1244     $r = q<"> . $1 . '->' . $2 . q<">;
1245     } else {
1246     $r = q<"> . $data . q<">;
1247     }
1248     } elsif ({InfosetP => 1}->{$type}) {
1249     $r = q<[> . $data . q<]>;
1250     } elsif ($type eq 'lt') {
1251     $r = '<';
1252     } elsif ($type eq 'gt') {
1253     $r = '>';
1254     } else {
1255     valid_err qq<DISDOC element type "$type" not supported>,
1256     node => $opt{node};
1257     }
1258     $r;
1259     }ges;
1260     $s;
1261     } # disdoc_inline2text
1262    
1263     sub disdoc2pod ($;%);
1264     sub disdoc2pod ($;%) {
1265     my ($s, %opt) = @_;
1266     $s =~ s/\x0D\x0A/\x0A/g;
1267     $s =~ tr/\x0D/\x0A/;
1268     my @s = split /\x0A\x0A+/, $s;
1269     my @el = ({type => '#document'});
1270     my @r;
1271     for my $s (@s) {
1272     if ($s =~ s/^\{([0-9A-Za-z-]+)::\s*//) { ## Start tag'ed element
1273     my $et = $1;
1274     if ($el[-1]->{type} eq '#list' and
1275     not {qw/LI 1 OLI 1/}->{$et}) {
1276     push @r, '=back';
1277     pop @el;
1278     }
1279     push @el, {type => $et};
1280     if ($et eq 'P') { ## Paragraph
1281     push @r, pod_para (disdoc_inline2pod ($s, %opt));
1282     } elsif ($et eq 'LI' or $et eq 'OLI') { ## List
1283     my $marker = '*';
1284     unless ($el[-1]->{type} eq '#list') {
1285     push @el, {type => '#list', n => 0};
1286     push @r, '=over 4';
1287     }
1288     if ($et eq 'OLI') {
1289     $marker = ++($el[-1]->{n}) . '. ';
1290     }
1291     if ($s =~ s/^(.+?)::\s*//) {
1292     $marker = disdoc_inline2pod ($1, %opt);
1293     }
1294     push @r, pod_item ($marker), pod_para (disdoc_inline2pod ($s, %opt));
1295     } else {
1296     valid_err qq<Unknown DISDOC element type "$et">, node => $opt{node};
1297     }
1298     } elsif ($s =~ /^\}\s*$/) { ## End tag
1299     while (@el > 1 and $el[-1]->{type} =~ /^\#/) {
1300     if ($el[-1]->{type} eq '#list') {
1301     push @r, '=back';
1302     }
1303     pop @el;
1304     }
1305     if ($el[-1]->{type} eq '#document') {
1306     valid_err qq<Unmatched DISDOC end tag>, node => $opt{node};
1307     } else {
1308     pop @el;
1309     }
1310     } elsif ($s =~ s/^([-=])\s*//) { ## List
1311     my $marker = $1;
1312     unless ($el[-1]->{type} eq '#list') {
1313     push @el, {type => '#list', n => 0};
1314     push @r, '=over 4';
1315     }
1316     if ($marker eq '=') {
1317     $marker = ++($el[-1]->{n}) . '. ';
1318     } elsif ($marker eq '-') {
1319     $marker = '*';
1320     }
1321     if ($s =~ s/^(.+?)::\s*//) {
1322     $marker = disdoc_inline2pod ($1, %opt);
1323     }
1324     push @r, pod_item ($marker), pod_para (disdoc_inline2pod ($s, %opt));
1325     } elsif ($s =~ /^[^\w\s<]/) { ## Reserved for future extension
1326     valid_err qq<Broken DISDOC: "$s">, node => $opt{node};
1327     } else {
1328     if ($el[-1]->{type} eq '#list') {
1329     push @r, '=back';
1330     pop @el;
1331     }
1332     $s =~ s/^\s+//;
1333     push @r, pod_para disdoc_inline2pod ($s, %opt);
1334     }
1335     }
1336     while (@el and $el[-1]->{type} =~ /^\#/) {
1337     if ($el[-1]->{type} eq '#list') {
1338     push @r, '=back';
1339     }
1340     pop @el;
1341     }
1342     if (@el) {
1343     valid_err qq[DISDOC end tag required for "$el[-1]->{type}"],
1344     node => $opt{node};
1345     }
1346     wantarray ? @r : join "\n\n", @r;
1347     } # disdoc2pod
1348    
1349     sub disdoc_inline2pod ($;%);
1350     sub disdoc_inline2pod ($;%) {
1351     my ($s, %opt) = @_;
1352     $s =~ s{\G(?:([^<>]+)|<$MElement>|(.))}{
1353     my ($cdata, $type, $data, $err) = ($1, $2, defined $3 ? $3 : '', $4);
1354     my $r = '';
1355     if (defined $err) {
1356     valid_err qq<Invalid character "$err" in DISDOC>,
1357     node => $opt{node};
1358     } elsif (defined $cdata) {
1359     $r = pod_cdata $cdata;
1360     } elsif ({CODE => 1}->{$type}) {
1361     $r = pod_code disdoc_inline2pod $data;
1362     } elsif ({DFN => 1}->{$type}) {
1363     $r = pod_dfn disdoc_inline2pod $data;
1364     } elsif ({CITE => 1}->{$type}) {
1365     $r = q[I<] . disdoc_inline2pod ($data) . q[>];
1366     } elsif ({SRC => 1}->{$type}) {
1367     $r = q<[>. disdoc_inline2pod ($data) . q<]>;
1368     } elsif ({URI => 1}->{$type}) {
1369     $r = pod_uri $data;
1370     } elsif ({
1371     IF => 1, TYPE => 1, P => 1, DOM => 1, XML => 1, HTML => 1,
1372     SGML => 1, FeatureVer => 1, CHAR => 1, Prefix => 1,
1373     Perl => 1, FILE => 1,
1374     }->{$type}) {
1375     $r = pod_code $data;
1376     } elsif ({Feature => 1, CP => 1, ERR => 1,
1377     HA => 1, HE => 1, XA => 1, SA => 1, SE => 1}->{$type}) {
1378     $r = qname_label (undef, qname => $data,
1379     out_type => ExpandedURI q<lang:pod>,
1380     no_default_ns => 1);
1381     } elsif ({Q => 1, EV => 1,
1382     XE => 1}->{$type}) {
1383     $r = qname_label (undef, qname => $data,
1384     out_type => ExpandedURI q<lang:pod>);
1385     } elsif ({
1386     M => 1, A => 1,
1387     }->{$type}) {
1388     if ($data =~ /^([^.]+)\.([^.]+)$/) {
1389     $r = pod_code ($1 . '->' . $2);
1390     } else {
1391     $r = pod_code $data;
1392     }
1393     } elsif ({X => 1, WARN => 1}->{$type}) {
1394     if ($data =~ /^([^.]+)\.([^.]+)$/) {
1395     $r = pod_code ($1) . '.' . pod_code ($2);
1396     } else {
1397     $r = pod_code $data;
1398     }
1399     } elsif ({InfosetP => 1}->{$type}) {
1400     $r = q<[> . $data . q<]>;
1401     } elsif ({QUOTE => 1}->{$type}) {
1402     $r = q<"> . $data . q<">;
1403     } elsif ({PerlModule => 1}->{$type}) {
1404     $r = pod_link label => pod_code ($data), module => $data;
1405     } elsif ({Module => 1}->{$type}) {
1406     $r = pod_link label => pod_code ($data),
1407     module => perl_package_name (name => $data);
1408     } elsif ($type eq 'lt' or $type eq 'gt') {
1409     $r = qq<E<$type>>;
1410     } else {
1411     valid_err qq<DISDOC element type "$type" not supported>,
1412     node => $opt{node};
1413     }
1414     $r;
1415     }ges;
1416     $s;
1417     }
1418     }
1419    
1420     sub get_description ($;%) {
1421     my ($node, %opt) = @_;
1422     my $ln = $opt{name} || 'Description';
1423     my $lang = $opt{lang} || q<en> || q<i-default>;
1424     my $textplain = ExpandedURI q<DOMMain:any>;
1425     my $default = q<lang:disdoc>;
1426     $opt{type} ||= ExpandedURI q<lang:pod>;
1427     my $script = $opt{script} || q<>;
1428     my $def;
1429     for my $type (($opt{type} ne $textplain ? $opt{type} : ()),
1430     ExpandedURI q<lang:disdoc>,
1431     $textplain) {
1432     $def = $node->get_element_by (sub {
1433     my ($me, $you) = @_;
1434     $you->local_name eq $ln and
1435     $you->get_attribute_value ('lang', default => 'i-default') eq $lang and
1436     type_expanded_uri ($you->get_attribute_value ('Type', default => $default))
1437     eq $type;
1438     }) || $node->get_element_by (sub {
1439     my ($me, $you) = @_;
1440     $you->local_name eq $ln and
1441     $you->get_attribute_value ('lang', default => 'i-default')
1442     eq 'i-default' and
1443     type_expanded_uri ($you->get_attribute_value ('Type', default => $default))
1444     eq $type;
1445     });
1446     last if $def;
1447     }
1448     unless ($def) {
1449     $opt{default};
1450     } else {
1451     my $srctype = type_expanded_uri
1452     $def->get_attribute_value ('Type', default => $default);
1453     my $value = $def->value;
1454     valid_err q<Description undefined>, node => $def
1455     unless defined $value;
1456     if ($srctype eq ExpandedURI q<lang:disdoc>) {
1457     if ($opt{type} eq ExpandedURI q<lang:pod>) {
1458     $value = $opt{is_inline} ?
1459     disdoc_inline2pod ($value, node => $def):
1460     disdoc2pod ($value, node => $def);
1461     } else {
1462     $value = $opt{is_inline} ?
1463     disdoc_inline2text ($value, node => $def):
1464     disdoc2text ($value, node => $def);
1465     if ($opt{type} eq ExpandedURI q<lang:muf>) {
1466     $value =~ s/\s+/ /g;
1467     }
1468     }
1469     } elsif ($srctype eq ExpandedURI q<lang:muf>) {
1470     if ($opt{type} eq ExpandedURI q<lang:muf>) {
1471     $value = muf_template $value;
1472     $value =~ s/\s+/ /g;
1473     } else {
1474     impl_err q<Can't convert MUF tempalte to >.$opt{type};
1475     }
1476     } elsif ($srctype eq $opt{type}) {
1477     #
1478     } else {
1479     if ($opt{type} eq ExpandedURI q<lang:pod>) {
1480     $value = pod_paras $def->value;
1481     } elsif ($opt{type} eq ExpandedURI q<lang:muf>) {
1482     $value =~ s/%/%percent;/g;
1483     $value =~ s/\s+/ /g;
1484     }
1485     }
1486     $value;
1487     }
1488     }
1489    
1490     sub get_level_description ($%) {
1491     my ($node, %opt) = @_;
1492     my @l = @{$node->get_attribute_value ('SpecLevel', default => [],
1493     as_array => 1)};
1494     unless (@l) {
1495     my $min = $opt{level}->[0] || 1;
1496     for ($min..$MAX_DOM_LEVEL) {
1497     if ($Info->{Condition}->{'DOM' . $_}) {
1498     unshift @l, $_;
1499     last;
1500     }
1501     }
1502     }
1503     return q<> unless @l;
1504     @l = sort {$a <=> $b} @l;
1505     @{$opt{level}} = @l;
1506     my $r = q<introduced in DOM Level > . (0 + shift @l);
1507     if (@l > 1) {
1508     my $s = 0 + pop @l;
1509     $r .= q< and modified in DOM Levels > . join ', ', @l;
1510     $r .= qq< and $s>;
1511     } elsif (@l == 1) {
1512     $r .= q< and modified in DOM Level > . (0 + $l[0]);
1513     }
1514     $r;
1515     } # get_level_description
1516    
1517     sub get_alternate_description ($;%) {
1518     my ($node, %opt) = @_;
1519     my @desc;
1520     $opt{if} ||= 'interface';
1521     $opt{method} ||= $node->local_name =~ /Attr/ ? 'attribute' : 'method';
1522    
1523     ## XML Namespace unaware alternate
1524     ## (This method is namespace aware.)
1525     my $ns = $node->get_attribute_value ('NoNSVersion', as_array => 1,
1526     default => undef);
1527     if (defined $ns) {
1528     my $a = '';
1529     if (@$ns) {
1530     $a = english_list
1531     [map {
1532     if (/^(?:[AM]:)?([^.]+)\.([^.]+)$/) {
1533     pod_code ($2) . ' on the interface '.
1534     type_label (type_expanded_uri ($1), is_pod => 1)
1535     } else {
1536     pod_code ($_)
1537     }
1538     } @$ns], connector => 'and/or';
1539     $a = qq<DOM applications dealing with documents that do >.
1540     qq<not use XML Namespaces should use $a instead.>;
1541     }
1542     push @desc, pod_para
1543     qq<This $opt{method} is namespace-aware. Mixing >.
1544     qq<namespace-aware and -unaware methods can lead >.
1545     qq<to unpredictable result. $a>;
1546     }
1547    
1548     ## XML Namespace aware alternate
1549     ## (This method is namespace unaware.)
1550     $ns = $node->get_attribute_value ('NSVersion', as_array => 1,
1551     default => undef);
1552     if (defined $ns) {
1553     my $a = '';
1554     if (@$ns) {
1555     $a = english_list
1556     [map {
1557     if (/^(?:[AM]:)?([^.]+)\.([^.]+)$/) {
1558     pod_code ($2) . ' on the interface '.
1559     type_label (type_expanded_uri ($1), is_pod => 1)
1560     } else {
1561     pod_code ($_)
1562     }
1563     } @$ns];
1564     $a = qq<DOM applications dealing with documents that do >.
1565     qq<use XML Namespaces should use $a instead.>;
1566     }
1567     push @desc, pod_para
1568     qq<This $opt{method} is namespace ignorant. Mixing >.
1569     qq<namespace-aware and -unaware methods can lead >.
1570     qq<to unpredictable result. $a>;
1571     }
1572    
1573     @desc;
1574     } # get_alternate_description
1575    
1576     sub get_redef_description ($;%) {
1577     my ($node, %opt) = @_;
1578     my @desc;
1579     $opt{if} ||= 'interface';
1580     $opt{method} ||= 'method';
1581     if ($node->local_name eq 'ReMethod' or
1582     $node->local_name eq 'ReAttr') {
1583     my $redef = $node->get_attribute_value ('Redefine');
1584     push @desc, pod_para qq<This $opt{method} is defined by the >.
1585     ($redef ? qq<$opt{if} > . type_label
1586     (type_expanded_uri ($redef),
1587     is_pod => 1)
1588     : qq<super-$opt{if} of this $opt{if}>).
1589     q< but that definition has been overridden here.>;
1590     }
1591     if ($node->get_attribute_value ('IsAbstract', default => 0)) {
1592     push @desc, pod_para (qq<This $opt{method} is defined abstractly; >.
1593     qq<it must be overridden by cocrete implementation. >);
1594     }
1595     my @redefBy;
1596     for (@{$node->child_nodes}) {
1597     next unless $_->node_type eq '#element' and
1598     $_->local_name eq 'RedefinedBy';
1599     push @redefBy, type_label (type_expanded_uri ($_->value), is_pod => 1);
1600     }
1601     if (@redefBy) {
1602     push @desc, pod_para qq<This $opt{method} is redefined by the >.
1603     qq<implementation of the sub-$opt{if}>.
1604     (@redefBy > 1 ? 's ' : ' ').
1605     english_list (\@redefBy, connector => 'and').'.';
1606     }
1607     @desc;
1608     } # get_redef_description;
1609    
1610     sub get_isa_description ($;%) {
1611     my ($node, %opt) = @_;
1612     $opt{if} ||= $node->get_attribute_value ('IsAbstract', default => 0)
1613     ? 'interface' : 'class';
1614     my @desc;
1615     my @isa;
1616     my @impl;
1617     for (@{$node->child_nodes}) {
1618     next unless $_->node_type eq '#element';
1619     if ($_->local_name eq 'ISA') {
1620     my $v = $_->value;
1621     if (type_expanded_uri $_->get_attribute_value ('Type',
1622     default => 'DOMMain:any') eq
1623     ExpandedURI q<lang:Perl>) {
1624     push @isa, pod_link (module => $v);
1625     } else {
1626     $v =~ s/::[^:]*$//g;
1627     push @isa, type_label (type_expanded_uri ($v), is_pod => 1);
1628     }
1629     } elsif ($_->local_name eq 'Implement') {
1630     my $v = $_->value;
1631     $v =~ s/::[^:]*$//g;
1632     push @impl, type_label (type_expanded_uri ($v), is_pod => 1);
1633     }
1634     }
1635     if (@isa and @impl) {
1636     push @desc, pod_para (qq<This $opt{if} inherits >.
1637     english_list (\@isa, connector => 'and').
1638     qq< and implements >.
1639     (@impl>1?q<interfaces >:q<the interface >).
1640     english_list (\@impl, connector => 'and').q<.>);
1641     } elsif (@isa) {
1642     push @desc, pod_para (qq<This $opt{if} inherits >.
1643     english_list (\@isa, connector => 'and').q<.>);
1644     } elsif (@impl) {
1645     push @desc, pod_para (qq<This $opt{if} implements >.
1646     (@impl>1?q<interfaces >:q<the interface >).
1647     english_list (\@impl, connector => 'and').q<.>);
1648     }
1649     @desc;
1650     } # get_isa_description
1651    
1652     sub get_incase_label ($;%) {
1653     my ($node, %opt) = @_;
1654     my $label = $node->get_attribute_value ('Label', default => '');
1655     unless (length $label) {
1656     $label = $node->get_attribute ('Value');
1657     my $type = type_normalize
1658     type_expanded_uri
1659     ($node->get_attribute_value ('Type') ||
1660     $node->parent_node->get_attribute_value
1661     ('Type',
1662     default => q<DOMMain:any>));
1663     if ($label) {
1664     if ($label->get_attribute_value ('is-null', default => 0)) {
1665     $label = 'null';
1666     } else {
1667     if (not defined $label->value) {
1668     valid_err q<Value is null>, node => $node;
1669     }
1670     if (type_isa $type, ExpandedURI q<DOMMain:DOMString>) {
1671     $label = perl_literal $label->value;
1672     } else {
1673     $label = $label->value;
1674     }
1675     }
1676     $label = $opt{is_pod} ? pod_code $label : $label;
1677     } else {
1678     $label = type_label $type, is_pod => $opt{is_pod};
1679     }
1680     } else {
1681     $label = get_description $node, name => 'Label', is_inline => 1;
1682     }
1683     $label;
1684     }
1685    
1686     sub get_value_literal ($%) {
1687     my ($node, %opt) = @_;
1688     my $value = get_perl_definition_node $node, %opt;
1689     my $type = type_normalize type_expanded_uri
1690     $node->get_attribute_value ($opt{type_name} || 'Type',
1691     default => q<DOMMain:any>);
1692     my $r;
1693     if ($type eq ExpandedURI q<DOMMain:boolean>) {
1694     if ($value) {
1695     $r = ($value->value and $value->value eq 'true') ? 1 : 0;
1696     } else {
1697     $r = $opt{default} ? 1 : 0;
1698     }
1699     } elsif ($type eq ExpandedURI q<DOMMain:unsigned-long> or
1700     $type eq ExpandedURI q<DOMMain:unsigned-long-long> or
1701     $type eq ExpandedURI q<DOMMain:long> or
1702     $type eq ExpandedURI q<DOMMain:float> or
1703     $type eq ExpandedURI q<DOMMain:unsigned-short>) {
1704     if ($value) {
1705     $r = $value->value;
1706     } else {
1707     $r = defined $opt{default} ? $opt{default} : 0;
1708     }
1709     } elsif (type_isa $type, ExpandedURI q<DOMMain:DOMString>) {
1710     if ($value) {
1711     if ($value->get_attribute_value ('is-null', default => 0)) {
1712     $r = 'undef';
1713     } else {
1714     $r = perl_literal $value->value;
1715     }
1716     } else {
1717     if (exists $opt{default}) {
1718     $r = defined $opt{default} ? perl_literal $opt{default} : 'undef';
1719     } else {
1720     $r = perl_literal '';
1721     }
1722     }
1723     } elsif ($type eq ExpandedURI q<Perl:ARRAY>) {
1724     if ($value) {
1725     $r = perl_literal $value->value (as_array => 1);
1726     } else {
1727     $r = perl_literal (defined $opt{default} ? $opt{default} : []);
1728     }
1729     } elsif ($type eq ExpandedURI q<Perl:HASH>) {
1730     if ($value) {
1731     $r = perl_literal $value->value;
1732     } else {
1733     $r = perl_literal (defined $opt{default} ? $opt{default} : {});
1734     }
1735     } else {
1736     if ($value) {
1737     if ($value->get_attribute_value ('is-null', default => 0)) {
1738     $r = 'undef';
1739     } else {
1740     $r = perl_literal $value->value;
1741     }
1742     } else {
1743     if (exists $opt{default}) {
1744     $r = defined $opt{default} ? perl_literal $opt{default} : 'undef';
1745     } else {
1746     $r = 'undef';
1747     }
1748     }
1749     }
1750     $r;
1751     }
1752    
1753     sub get_internal_code ($$;%) {
1754     my ($node, $name, %opt) = @_;
1755     $node = $node->parent_node;
1756     my $m;
1757     my $def;
1758     if ($m = $node->get_element_by (sub {
1759     my ($me, $you) = @_;
1760     $you->node_type eq '#element' and
1761     ($you->local_name eq 'Method' or
1762     $you->local_name eq 'ReMethod') and
1763     $you->get_attribute_value ('Name') eq $name
1764     })) {
1765     $def = $m->get_attribute ('Return');
1766     $def = (get_perl_definition_node $def, name => 'IntDef', use_dis => 1 or
1767     get_perl_definition_node $def, name => 'Def', use_dis => 1) if $def;
1768     } elsif ($m = $node->get_element_by (sub {
1769     my ($me, $you) = @_;
1770     $you->node_type eq '#element' and
1771     ($you->local_name eq 'Attr' or
1772     $you->local_name eq 'ReAttr') and
1773     $you->get_attribute_value ('Name') eq $name
1774     })) {
1775     $def = $m->get_attribute ('Get');
1776     $def = (get_perl_definition_node $def, name => 'IntDef', use_dis => 1 or
1777     get_perl_definition_node $def, name => 'Def', use_dis => 1) if $def;
1778     } elsif ($m = $node->get_element_by (sub {
1779     my ($me, $you) = @_;
1780     $you->node_type eq '#element' and
1781     $you->local_name eq 'IntMethod' and
1782     $you->get_attribute_value ('Name') eq $name
1783     })) {
1784     $def = $m->get_attribute ('Return');
1785     $def = get_perl_definition_node $def, name => 'Def', use_dis => 1 if $def;
1786     } elsif ($m = $node->get_element_by (sub {
1787     my ($me, $you) = @_;
1788     $you->node_type eq '#element' and
1789     $you->local_name eq 'IntAttr' and
1790     $you->get_attribute_value ('Name') eq $name
1791     })) {
1792     $def = $m->get_attribute ('Get');
1793     $def = get_perl_definition_node $def, name => 'Def', use_dis => 1 if $def;
1794     }
1795     if ($def) {
1796     if (type_expanded_uri ($def->get_attribute_value ('Type', default => ''))
1797     eq ExpandedURI q<lang:dis>) {
1798     return dis2perl $def;
1799     } else {
1800     return perl_code $def->value;
1801     }
1802     } else {
1803     valid_warn qq<Internal method "$name" not defined>;
1804     is_implemented (if => $Status->{IF}, method => $name, set => 0);
1805     $Status->{is_implemented} = 0;
1806     return perl_statement perl_exception
1807     level => 'EXCEPTION',
1808     class => 'DOMException',
1809 wakaba 1.2 type => 'NOT_SUPPORTED_ERR',
1810     subtype_uri
1811     => ExpandedURI q<MDOM_EXCEPTION:MDOM_IMPL_METHOD_NOT_IMPLEMENTED>,
1812 wakaba 1.1 param => {
1813     ExpandedURI q<MDOM_EXCEPTION:if> => $Status->{IF},
1814     ExpandedURI q<MDOM_EXCEPTION:method> => $name,
1815     };
1816     }
1817     } # get_internal_code
1818    
1819     sub register_namespace_declaration ($) {
1820     my $node = shift;
1821     for (@{$node->child_nodes}) {
1822     if ($_->node_type eq '#element' and
1823     $_->local_name eq 'Namespace') {
1824     for (@{$_->child_nodes}) {
1825     $Info->{Namespace}->{$_->local_name} = $_->value;
1826     }
1827     }
1828     }
1829     }
1830    
1831     {
1832     my $nest = 0;
1833     sub is_implemented (%);
1834     sub is_implemented (%) {
1835     my (%opt) = @_;
1836     my $r = 0;
1837     $nest++ == 100 and valid_err q<Condition loop detected>;
1838     my $member = ($Info->{is_implemented}->{$opt{if}}->{$opt{method} ||
1839     $opt{attr} . '.' . $opt{on}}
1840     ||= {});
1841     if (exists $opt{set}) {
1842     $r = ($member->{$opt{condition} || ''} = $opt{set});
1843     } else {
1844     if (defined $member->{$opt{condition} || ''}) {
1845     $r = $member->{$opt{condition} || ''};
1846     } else {
1847     for (@{$Info->{Condition}->{$opt{condition} || ''}->{ISA} || []}) {
1848     if (is_implemented (%opt, condition => $_)) {
1849     $r = 1;
1850     last;
1851     }
1852     }
1853     }
1854     }
1855     $nest--;
1856     $r;
1857     }
1858     sub is_all_implemented (%);
1859     sub is_all_implemented (%) {
1860     my (%opt) = @_;
1861     $nest++ == 100 and valid_err q<Condition loop detected>;
1862     $opt{not_implemented} ||= [];
1863     IF: for my $if (keys %{$Info->{is_implemented}}) {
1864     for my $mem (keys %{$Info->{is_implemented}->{$if}}) {
1865     ## Note: In fact, this checks whether the method is NOT implemented
1866     ## rather than the method IS implemented.
1867     if (exists $Info->{is_implemented}->{$if}->{$mem}->{$opt{condition}} and
1868     not $Info->{is_implemented}->{$if}->{$mem}->{$opt{condition}}) {
1869     @{$opt{not_implemented}} = ($if, $mem, $opt{condition} || '');
1870     last IF;
1871     }
1872     }
1873     }
1874     if (not @{$opt{not_implemented}}) {
1875     for (@{$Info->{Condition}->{$opt{condition} || ''}->{ISA} || []}) {
1876     if (not is_all_implemented (%opt, condition => $_)) {
1877     last;
1878     }
1879     }
1880     }
1881     @{$opt{not_implemented}} ? 0 : 1;
1882     }}
1883    
1884     sub condition_match ($%) {
1885     my ($node, %opt) = @_;
1886     my $conds = $node->get_attribute_value ('Condition', default => [],
1887     as_array => 1);
1888     my $level = $node->get_attribute_value
1889     ('Level',
1890     default_list => @$conds ? []
1891     : ($opt{level_default} || []),
1892     as_array => 1);
1893     for (@$conds) {
1894     unless ($Info->{Condition}->{$_}) {
1895     valid_err qq<Condition "$_" not defined>;
1896     }
1897     }
1898     for (@$level) {
1899     unless ($Info->{Condition}->{"DOM".$_}) {
1900     valid_err qq<Condition "DOM$_" not defined>;
1901     }
1902     }
1903     if (not $opt{condition}) {
1904     if (@$conds == 0 and @$level == 0) {
1905     return 1;
1906     } elsif (array_contains $conds, '$normal') {
1907     return 1;
1908     } elsif ($opt{ge} and not @$conds) {
1909     return 1;
1910     } elsif ($opt{any_unless_condition}) {
1911     return 1;
1912     } else {
1913     return 0;
1914     }
1915     } else {
1916     if (array_contains $conds, $opt{condition}) {
1917     return 1;
1918     } elsif ($opt{condition} =~ /^DOM(\d+)$/) {
1919     if ($opt{ge}) {
1920     for (my $i = $1; $i; $i--) {
1921     if (array_contains $level, $i) {
1922     return 1;
1923     }
1924     }
1925     } else {
1926     if ($1 and array_contains $level, $1) {
1927     return 1;
1928     }
1929     }
1930     }
1931     ## 'default_any': Match to 'any' condition (no condition specified)
1932     if ($opt{default_any} and @$conds == 0 and @$level == 0) {
1933     return 1;
1934     }
1935     return 0;
1936     }
1937     }
1938    
1939     =head1 SOURCE FORMAT
1940    
1941     "Dis" (DOM implementation source) file is written in
1942     SuikaWikiConfig/2.0 text format.
1943    
1944     =head2 IF element
1945    
1946     C<IF> element defines a DOM interface with its descriptions
1947     and implementations.
1948    
1949     Children elements:
1950    
1951     =over 4
1952    
1953     =item IF/Name = name (1 - 1)
1954    
1955     Interface name. It should be taken from DOM specification.
1956    
1957     =item IF/Description = text (0 - infinite)
1958    
1959     Description for the interface.
1960    
1961     =item IF/ISA[list] = list of names (0 - 1)
1962    
1963     Names of interfaces that this interface inherits.
1964    
1965     =item IF/Method, IF/IntMethod, IF/ReMethod
1966    
1967     Method definition.
1968    
1969     =item IF/Attr, IF/IntAttr, IF/ReAttr
1970    
1971     Attribute definition.
1972    
1973     =item IF/ConstGroup
1974    
1975     Constant value group definition.
1976    
1977     =item IF/Const
1978    
1979     Constant value definition.
1980    
1981     =back
1982    
1983     =cut
1984    
1985     sub if2perl ($) {
1986     my $node = shift;
1987     local $Status->{depth} = $Status->{depth} + 1;
1988     my $pack_name = perl_package_name
1989     name => my $if_name
1990     = perl_name $node->get_attribute_value ('Name'),
1991     ucfirst => 1;
1992     my $if_pack_name = perl_package_name if => $if_name;
1993     my $iif_pack_name = perl_package_name iif => $if_name;
1994     local $Status->{IF} = $if_name;
1995     local $Status->{if} = {}; ## Temporary data
1996     local $Info->{Namespace} = {%{$Info->{Namespace}}};
1997     local $Info->{Require_perl_package} = {%{$Info->{Require_perl_package}}};
1998     local $Info->{Require_perl_package_use} = {};
1999     local $Status->{is_implemented} = 1;
2000     my $is_abs = $node->get_attribute ('IsAbstract', default => 0);
2001     my $is_fin = $node->get_attribute ('IsFinal', default => 0);
2002     $is_fin = -1 if $is_abs; # 1=no subclass, 0=free, -1=must be subclass
2003     my $impl_by_app = $node->get_attribute ('ImplByApp', default => 0);
2004    
2005     my @level;
2006     my $mod = get_level_description $node, level => \@level;
2007    
2008     push my @desc,
2009     pod_head ($Status->{depth}, 'Interface ' . pod_code ($if_name).
2010     ($is_abs?'':', Class '.pod_code ($pack_name)));
2011    
2012     push @desc, pod_paras (get_description ($node));
2013     push @desc, pod_para ('This interface is ' . $mod . q<.>) if $mod;
2014    
2015     if ($impl_by_app) {
2016     push @desc, pod_para ('This interface is intended to be implemented '.
2017     'by DOM applications. To implement this '.
2018     'interface, put the statement '),
2019     pod_pre ('push our @ISA, q<'.($is_abs?$if_name:$pack_name).'>;'),
2020     pod_para ('on your package and define methods and '.
2021     'attributes.');
2022     }
2023    
2024     push @desc, get_isa_description ($node);
2025    
2026     my $result = pod_block @desc;
2027    
2028     my $has_role = $node->get_attribute ('Role');
2029    
2030     for my $condition ((sort keys %{$Info->{Condition}}), '') {
2031     if ($condition =~ /^DOM(\d+)$/) {
2032     next if @level and $level[0] > $1;
2033     }
2034     local $Status->{Operator} = {};
2035     local $Status->{condition} = $condition;
2036     my $cond_if_pack_name = perl_package_name if => $if_name,
2037     condition => $condition;
2038     my $cond_iif_pack_name = perl_package_name iif => $if_name,
2039     condition => $condition;
2040     my $cond_pack_name = perl_package_name name => $if_name,
2041     condition => $condition;
2042     my $cond_int_pack_name = perl_package_name name => $if_name,
2043     condition => $condition,
2044     is_internal => 1;
2045     my $cond_iint_pack_name = perl_package_name name => $if_name,
2046     condition => $condition,
2047     is_internal => 1,
2048     is_for_inheriting => 1;
2049     $result .= perl_package full_name => $cond_int_pack_name;
2050     my @isa;
2051     for (@{$node->child_nodes}) {
2052     next unless $_->node_type eq '#element' and
2053     condition_match $_, condition => $condition,
2054     default_any => 1, ge => 1;
2055     if ($_->local_name eq 'ISA') {
2056     if (type_expanded_uri ($_->get_attribute_value ('Type',
2057     default => ExpandedURI q<DOMMain:any>))
2058     eq ExpandedURI q<lang:Perl>) {
2059     my $v = $_->value;
2060     if ($v =~ /[^\w:]|(?<!:):(?!:)/) {
2061     valid_err q<Invalid package name "$v">, node => $_;
2062     }
2063     push @isa, $v;
2064     } else {
2065     push @isa, perl_package_name qname_with_condition => $_->value,
2066     condition => $condition,
2067     is_internal => 1,
2068     is_for_inheriting => 1;
2069     }
2070     } elsif ($_->local_name eq 'Implement') {
2071     push @isa, perl_package_name if_qname_with_condition => $_->value,
2072     condition => $condition;
2073     }
2074     }
2075     push my @isag, perl_package_name (name => 'ManakaiDOMObject')
2076     unless $if_name eq 'ManakaiDOMObject';
2077     my @isaa;
2078     if ($condition) {
2079     for (@{$Info->{Condition}->{$condition}->{ISA}}) {
2080     push @isaa, perl_package_name name => $if_name,
2081     condition => $_,
2082     is_internal => 1;
2083     }
2084     $result .= perl_inherit [$cond_int_pack_name, @isaa, @isa, @isag]
2085     => $cond_pack_name;
2086     $result .= perl_inherit [@isaa, $cond_iif_pack_name]
2087     => $cond_int_pack_name;
2088     $result .= perl_inherit [$cond_int_pack_name, @isa]
2089     => $cond_iint_pack_name;
2090     $result .= perl_inherit [$cond_if_pack_name, $iif_pack_name]
2091     => $cond_iif_pack_name;
2092     $result .= perl_inherit [$if_pack_name] => $cond_if_pack_name;
2093     } else { ## No condition specified
2094     $result .= perl_inherit [$cond_int_pack_name, @isa, @isag]
2095     => $cond_pack_name;
2096     if ($Info->{NormalCondition}) {
2097     push @isaa, perl_package_name name => $if_name,
2098     condition => $Info->{NormalCondition},
2099     is_internal => 1;
2100     $result .= perl_inherit [@isaa]
2101     => $cond_int_pack_name;
2102     } else { ## Condition not used
2103     $result .= perl_inherit [$iif_pack_name] => $cond_int_pack_name;
2104     }
2105     $result .= perl_inherit [$cond_int_pack_name, @isa]
2106     => $cond_iint_pack_name;
2107     $result .= perl_inherit [$if_pack_name] => $iif_pack_name;
2108     }
2109     for my $pack ($cond_pack_name, $cond_int_pack_name,
2110     $cond_iif_pack_name, $cond_if_pack_name,
2111     $cond_iint_pack_name) {
2112     $result .= perl_statement perl_assign
2113     perl_var (type => '$',
2114     package => {full_name => $pack},
2115     local_name => 'VERSION')
2116     => version_date time;
2117     }
2118    
2119     my @feature;
2120     for (@{$node->child_nodes}) {
2121     my $gt = 0;
2122     unless (condition_match $_, level_default => \@level,
2123     condition => $condition) {
2124     if (condition_match $_, level_default => \@level,
2125     condition => $condition, ge => 1) {
2126     $gt = 1;
2127     } else {
2128     next;
2129     }
2130     }
2131    
2132     if ($_->local_name eq 'Method' or
2133     $_->local_name eq 'IntMethod' or
2134     $_->local_name eq 'ReMethod') {
2135     $result .= method2perl ($_, level => \@level, condition => $condition)
2136     unless $gt;
2137     } elsif ($_->local_name eq 'Attr' or
2138     $_->local_name eq 'IntAttr' or
2139     $_->local_name eq 'ReAttr') {
2140     $result .= attr2perl ($_, level => \@level, condition => $condition)
2141     unless $gt;
2142     } elsif ($_->local_name eq 'ConstGroup') {
2143     $result .= constgroup2perl ($_, level => \@level,
2144     condition => $condition,
2145     without_document => $gt,
2146     package => $cond_int_pack_name);
2147     } elsif ($_->local_name eq 'Const') {
2148     $result .= const2perl ($_, level => \@level, condition => $condition,
2149     package => $cond_int_pack_name)
2150     unless $gt;
2151     } elsif ($_->local_name eq 'Require') {
2152     $result .= req2perl ($_, level => \@level, condition => $condition);
2153     } elsif ($_->local_name eq 'Feature') {
2154     push @feature, $_;
2155     } elsif ({qw/Name 1 Spec 1 ISA 1 Description 1 Implement 1
2156     Level 1 SpecLevel 1 ImplNote 1 Role 1
2157     IsAbstract 1 IsFinal 1 ImplByApp 1/}->{$_->local_name}) {
2158     #
2159     } else {
2160     valid_warn qq{Element @{[$_->local_name]} not supported};
2161     }
2162     }
2163    
2164     if ($has_role) {
2165     my $role = type_expanded_uri $has_role->value;
2166     if ($role eq ExpandedURI q<DOMCore:DOMImplementationSource>) {
2167     $result .= perl_statement
2168     q<push @org::w3c::dom::DOMImplementationSourceList, >.
2169     perl_literal $cond_pack_name;
2170     } else {
2171     my $var = q<@{>.perl_var (type => '$',
2172     local_name => $ManakaiDOMModulePrefix.'::Role').
2173     q<{>.perl_literal ($role).q<}}>;
2174     my %prop;
2175     if ($has_role->get_attribute ('compat')) {
2176     $prop{compat} = type_expanded_uri
2177     $has_role->get_attribute_value ('compat');
2178     } else {
2179     $prop{compat} = '';
2180     }
2181     $result .= perl_statement
2182     'push '.$var.q<, >.
2183     perl_list {
2184     class => $cond_pack_name,
2185     constructor => 'new',
2186     %prop,
2187     };
2188     }
2189     }
2190    
2191     if (@feature or $has_role) {
2192     $result .= '{' . perl_statement 'our $Feature';
2193     for (@feature) {
2194     my $name = $_->get_attribute ('QName');
2195     if ($name) {
2196     $name = type_expanded_uri ($name->value);
2197     } else {
2198     $name = $_->get_attribute_value ('Name');
2199     }
2200     $result .= perl_statement '$Feature->{'.perl_literal ($name).'}->{'.
2201     perl_literal ($_->get_attribute_value ('Version')).
2202     '} = 1';
2203     }
2204    
2205     $result .= perl_sub
2206     name => '___classHasFeature',
2207     prototype => '$%',
2208     code =>
2209     perl_statement ('my ($self, %f) = @_').
2210     q[
2211     for (keys %f) {
2212     if ($Feature->{$_}) {
2213     if (defined $f{$_}->{version}) {
2214     delete $f{$_}
2215     if $Feature->{$_}->{$f{$_}->{version}};
2216     } else {
2217     delete $f{$_} if keys %{$Feature->{$_}};
2218     }
2219     return 1 if keys (%f) == 0;
2220     }
2221     }
2222     ].
2223     (@isa + @isaa ?
2224     q[for (].perl_list (@isa, @isaa).q[) {
2225     if (my $c = $_->can ('___classHasFeature')) {
2226     if ($c->($self, %f)) {
2227     return 1;
2228     }
2229     }
2230     }] : '').
2231     (($has_role and $has_role->get_attribute ('compat'))?
2232     q[
2233     my %g;
2234     for (keys %f) {
2235     unless ($f{$_}->{plus}) {
2236     return 0;
2237     } else {
2238     $g{$_} = {version => $f{$_}->{version}};
2239     }
2240     }
2241     for (reverse @{$].$ManakaiDOMModulePrefix.'::Role{'.
2242     perl_literal (type_expanded_uri
2243     $has_role->value).'}'.q[||[]}) {
2244     if ($_->{compat} eq ].
2245     perl_literal ($has_role->get_attribute_value
2246     ('compat')).q[) {
2247     if ($_->{class}->___classHasFeature (%g)) {
2248     return 1;
2249     }
2250     }
2251     }
2252     ]:'').
2253     perl_statement (q<return 0>);
2254     $result .= '}';
2255     }
2256    
2257     $result .= ops2perl;
2258     }
2259    
2260     $result;
2261     } # if2perl
2262    
2263     =head2 Method, IntMethod and ReMethod elements
2264    
2265     C<Method>, C<IntMethod> and C<ReMethod> element defines a method.
2266     Methods defined by C<Method> are ones as defined in the DOM
2267     specification. Methods defined by C<IntMethod> are only for
2268     internal use and usually not defined by the specifications.
2269     Methods defined by C<ReMethod> do actually not belong
2270     to this interface but to ancestor interface in the specification
2271     but overriddenly re-defined for this type of descendant interfaces
2272     (for example, some methods defined in Node interface of the DOM
2273     Core Module are re-defined in Element, Attr or other node-type
2274     interfaces, since those methods work differently by type of
2275     the node).
2276    
2277     Children elements:
2278    
2279     =over 4
2280    
2281     =item Name = name (1 - 1)
2282    
2283     Method name. It should be taken from DOM specification
2284     if element type is C<Method> or C<ReMethod>. Method name
2285     for C<ReMethod> must be used as the name of the C<Method>
2286     defined in ancestor interface. Method name for C<IntMethod>
2287     must be different with any other C<Method>, C<IntMethod>
2288     or C<ReMethod> (including those defined by ancestor interfaces).
2289    
2290     =item Description = text (0 - infinite)
2291    
2292     Description for the method.
2293    
2294     =back
2295    
2296     =cut
2297    
2298     sub method2perl ($;%) {
2299     my ($node, %opt) = @_;
2300     local $Status->{depth} = $Status->{depth} + 1;
2301     my $m_name = perl_name $node->get_attribute_value ('Name');
2302     my $level;
2303     my @level = @{$opt{level} || []};
2304     local $Status->{Method} = $m_name;
2305     local $Status->{is_implemented} = 1;
2306     my $result = '';
2307     if ($node->local_name eq 'IntMethod') {
2308     $m_name = perl_internal_name $m_name;
2309     $level = '';
2310     } else {
2311     $level = get_level_description $node, level => \@level;
2312     }
2313    
2314     my @param_list;
2315     my $param_prototype = '$';
2316     my @param_desc;
2317     my @param_domstring;
2318     if ($node->get_attribute ('Param')) {
2319     for (@{$node->child_nodes}) {
2320     if ($_->local_name eq 'Param') {
2321     my $name = perl_name $_->get_attribute_value ('Name');
2322     my $type = type_expanded_uri $_->get_attribute_value
2323     ('Type',
2324     default => 'DOMMain:any');
2325     push @param_list, '$' . $name;
2326     push @param_desc, pod_item (pod_code '$' . $name);
2327     if (type_isa $type, ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>) {
2328     push @param_domstring, [$name, $type];
2329     }
2330     push my @param_desc_val,
2331     pod_item (type_label $type, is_pod => 1),
2332     pod_para get_description $_;
2333     $param_prototype .= '$';
2334     for (@{$_->child_nodes}) {
2335     next unless $_->local_name eq 'InCase';
2336     push @param_desc_val, pod_item (get_incase_label $_, is_pod => 1),
2337     pod_para (get_description $_);
2338     }
2339     push @param_desc, pod_list 4, @param_desc_val;
2340     }
2341     }
2342     }
2343    
2344     my $return = $node->get_attribute ('Return');
2345     unless ($return) {
2346     ## NOTE: A method without return value does not have 'Return'
2347     ## before its code is implemented.
2348     valid_warn q<Required "Return" element not found>, node => $node;
2349     $return = $node->get_attribute ('Return', make_new_node => 1);
2350     }
2351     my $has_return = $return->get_attribute_value ('Type', default => 0) ? 1 : 0;
2352     push my @desc,
2353     pod_head ($Status->{depth}, 'Method ' .
2354     pod_code (($has_return ? '$return = ' : '') .
2355     '$obj->' . $m_name .
2356     ' (' . join (', ', @param_list) . ')')),
2357     pod_paras (get_description ($node)),
2358     $level ? pod_para ('The method ' . pod_code ($m_name) .
2359     q< has been > . $level . '.') : ();
2360    
2361     if (@param_list) {
2362     push @desc, pod_para ('This method requires ' .
2363     english_number (@param_list + 0,
2364     singular => q<parameter>,
2365     plural => q<parameters>) . ':'),
2366     pod_list (4, @param_desc);
2367     } else {
2368     push @desc, pod_para (q<This method has no parameter.>);
2369     }
2370    
2371     my $is_abs = $node->get_attribute_value ('IsAbstract', default => 0);
2372     if ($is_abs) {
2373     unless (get_perl_definition_node $return,
2374     condition => $opt{condition},
2375     level_default => $opt{level_default},
2376     use_dis => 1) {
2377     for ($return->append_new_node (type => '#element',
2378     local_name => 'Def')) {
2379     $_->set_attribute ('Type' => ExpandedURI q<lang:dis>);
2380     $_->set_attribute ('Overridden' => 1);
2381     }
2382     }
2383     }
2384    
2385     my @return;
2386     my @exception;
2387     my $has_exception = 0;
2388     my $code_node = get_perl_definition_node $return,
2389     condition => $opt{condition},
2390     level_default => $opt{level_default},
2391     use_dis => 1;
2392     my $int_code_node = get_perl_definition_node $return, name => 'IntDef',
2393     condition => $opt{condition},
2394     level_default => $opt{level_default},
2395     use_dis => 1;
2396     my $code;
2397     my $int_code;
2398     for ({code => \$code, code_node => $code_node,
2399     internal => sub {
2400     return get_internal_code $node, $_[0] if $_[0];
2401     if ($int_code_node) {
2402     perl_code $int_code_node->value,
2403     internal => sub {
2404     $_[0] ? get_internal_code $node, $_[0] :
2405     valid_err q<Preprocessing macro INT cannot be used here>;
2406     };
2407     } else {
2408     valid_err "<IF[Name = $Status->{IF}]/Method[Name = $m_name]/" .
2409     "Return/IntDef> required";
2410     }
2411     }},
2412     {code => \$int_code, code_node => $int_code_node,
2413     internal => sub {$_[0]?get_internal_code $node,$_[0]:
2414     valid_err q<Preprocessing macro INT cannot be> .
2415     q<used here>}}) {
2416     if ($_->{code_node}) {
2417     my $mcode;
2418     if (type_expanded_uri ($_->{code_node}->get_attribute_value
2419     ('Type', default => q<DOMMain:any>))
2420     eq ExpandedURI q<lang:dis>) {
2421     $mcode = dis2perl $_->{code_node};
2422     } else {
2423     $mcode = perl_code $_->{code_node}->value,
2424     internal => $_->{internal};
2425     }
2426     if ($mcode =~ /^\s*$/) {
2427     ${$_->{code}} = '';
2428     } else {
2429     ${$_->{code}} = perl_code_source ($mcode,
2430     path => $_->{code_node}->node_path
2431     (key => 'Name'));
2432     }
2433     }
2434     }
2435     if ($code_node) {
2436     if ($has_return) {
2437     $code = perl_statement (perl_assign 'my $r' => get_value_literal $return,
2438     name => 'DefaultValue',
2439     type_name => 'Type') .
2440     $code;
2441     if ($code_node->get_attribute_value ('cast-output', default => 1)) {
2442     my $type = type_normalize
2443     type_expanded_uri $return->get_attribute_value
2444     ('Type',
2445     default => q<DOMMain:any>);
2446     if (type_isa $type, ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>) {
2447     $code .= perl_builtin_code $type,
2448     s => 'r', r => 'r',
2449     condition => $opt{condition};
2450     }
2451     }
2452     $code .= perl_statement ('$r');
2453     } else {
2454     $code .= perl_statement ('undef');
2455     }
2456     if ($code_node->get_attribute_value ('auto-argument', default => 1)) {
2457     if ($code_node->get_attribute_value ('cast-input', default => 1)) {
2458     for (@param_domstring) {
2459     $code = perl_builtin_code ($_->[1],
2460     s => $_->[0], r => $_->[0],
2461     condition => $opt{condition}) . $code;
2462     }
2463     }
2464     $code = perl_statement (perl_assign 'my (' .
2465     join (', ', '$self', @param_list) .
2466     ')' => '@_') .
2467     $code;
2468     }
2469     if ($int_code_node) {
2470     if ($has_return) {
2471     $int_code = perl_statement (perl_assign 'my $r' => perl_literal '') .
2472     $int_code .
2473     perl_statement ('$r');
2474     } else {
2475     $int_code .= perl_statement ('undef');
2476     }
2477     $int_code = perl_statement (perl_assign 'my (' .
2478     join (', ', '$self', @param_list) .
2479     ')' => '@_') .
2480     $int_code
2481     if $int_code_node->get_attribute_value ('auto-argument', default => 1);
2482     }
2483    
2484     if ($has_return) {
2485     push @return, pod_item (type_label (type_expanded_uri
2486     ($return->get_attribute_value
2487     ('Type',
2488     default => 'DOMMain:any')),
2489     is_pod => 1)),
2490     pod_para (get_description $return);
2491     }
2492     for (@{$return->child_nodes}) {
2493     if ($_->local_name eq 'InCase') {
2494     push @return, pod_item ( get_incase_label $_, is_pod => 1),
2495     pod_para (get_description $_);
2496     $has_return++;
2497     } elsif ($_->local_name eq 'Exception') {
2498     push @exception, pod_item ('Exception: ' .
2499     (type_label ($_->get_attribute_value
2500     ('Type',
2501     default => 'DOMMain:any'),
2502     is_pod => 1)).
2503     '.' . pod_code $_->get_attribute_value
2504     ('Name',
2505     default => '<unknown>')),
2506     pod_para (get_description $_);
2507     my @st;
2508     for (@{$_->child_nodes}) {
2509     next unless $_->node_type eq '#element';
2510     if ($_->local_name eq 'SubType') {
2511     push @st, subtype2poditem ($_);
2512     } elsif ({qw/Name 1 Type 1
2513     Description 1 ImplNote 1
2514     Condition 1 Level 1 SpecLevel 1/}->{$_->local_name}) {
2515     #
2516     } else {
2517     valid_err qq{Element type "@{[$_->local_name]}" not supported},
2518     node => $_;
2519     }
2520     }
2521     push @exception, pod_list 4, @st if @st;
2522     $has_exception++;
2523     }
2524     }
2525     } else {
2526     $Status->{is_implemented} = 0;
2527     $int_code = $code
2528     = perl_statement ('my $self = shift').
2529     perl_statement perl_exception
2530     level => 'EXCEPTION',
2531     class => 'DOMException',
2532     type => 'NOT_SUPPORTED_ERR',
2533 wakaba 1.2 subtype_uri
2534     => ExpandedURI q<MDOM_EXCEPTION:MDOM_IMPL_METHOD_NOT_IMPLEMENTED>,
2535 wakaba 1.1 param => {
2536     ExpandedURI q<MDOM_EXCEPTION:if> => $Status->{IF},
2537     ExpandedURI q<MDOM_EXCEPTION:method> => $Status->{Method},
2538     };
2539     @return = ();
2540     push @exception, pod_item ('Exception: ' . pod_code ('DOMException') . '.' .
2541     pod_code ('NOT_SUPPORTED_ERR')),
2542     pod_para ('Call of this method allways result in
2543     this exception raisen, since this
2544     method is not implemented yet.');
2545     $has_return = 0;
2546     $has_exception = 1;
2547     }
2548     is_implemented if => $Status->{IF}, method => $Status->{Method},
2549     condition => $opt{condition}, set => $Status->{is_implemented};
2550     if ($has_return or $has_exception) {
2551     if ($has_return) {
2552     push @desc, pod_para (q<This method results in > .
2553     ($has_return == 1 ? q<the value:>
2554     : q<either:>)),
2555     pod_list 4, pod_item (pod_code q<$return>),
2556     pod_list (4, @return),
2557     @exception;
2558     } elsif ($has_exception) {
2559     push @desc, pod_para (q<This method does not return any value,
2560     but it might raise > .
2561     ($has_exception == 1 ? q<an exception:>
2562     : q<one of exceptions from:>)),
2563     pod_list 4, @exception;
2564     }
2565     } else {
2566     push @desc, pod_para q<This method does not return any value
2567     nor does raise any exceptions.>;
2568     }
2569    
2570     push @desc, get_alternate_description $node;
2571     push @desc, get_redef_description $node;
2572    
2573     if ($node->local_name eq 'IntMethod' or
2574     $Status->{if}->{method_documented}->{$m_name}++) {
2575     $result .= pod_block pod_comment @desc;
2576     } else {
2577     $result .= pod_block @desc;
2578     }
2579    
2580     $result .= perl_sub name => $m_name,
2581     prototype => $param_prototype,
2582     code => $code;
2583     $result .= perl_sub name => perl_internal_name $m_name,
2584     prototype => $param_prototype,
2585     code => $int_code
2586     if $int_code_node;
2587    
2588     if (my $op = get_perl_definition_node $node, name => 'Operator') {
2589     my $value = $op->value;
2590     valid_err qq{Overloaded operator name not specified},
2591     node => $op
2592     unless defined $value;
2593     $Status->{Operator}->{$value} = '\\' . perl_var type => '&',
2594     local_name => $m_name;
2595     }
2596    
2597     $result;
2598     } # method2perl
2599    
2600     sub attr2perl ($;%) {
2601     my ($node, %opt) = @_;
2602     local $Status->{depth} = $Status->{depth} + 1;
2603     my $m_name = perl_name $node->get_attribute_value ('Name');
2604     my $level;
2605     my @level = @{$opt{level} || []};
2606     local $Status->{Method} = $m_name;
2607     local $Status->{is_implemented} = 1;
2608     my $result = '';
2609     if ($node->local_name eq 'IntAttr') {
2610     $m_name = perl_internal_name $m_name;
2611     $level = '';
2612     } else {
2613     $level = get_level_description $node, level => \@level;
2614     }
2615    
2616     my $return = $node->get_attribute ('Get');
2617     unless ($return) {
2618     valid_err q<Required "Get" element not found>, node => $node;
2619     }
2620     my $set = $node->get_attribute ('Set');
2621     my $has_set = defined $set ? 1 : 0;
2622     push my @desc,
2623     pod_head ($Status->{depth}, 'Attribute ' .
2624     pod_code ('$obj->' . $m_name)),
2625     pod_paras (get_description ($node)),
2626     $level ? pod_para ('The method ' . pod_code ($m_name) .
2627     q< has been > . $level . '.') : ();
2628    
2629     my $is_abs = $node->get_attribute_value ('IsAbstract', default => 0);
2630     if ($is_abs) {
2631     unless (get_perl_definition_node $return,
2632     condition => $opt{condition},
2633     level_default => $opt{level_default},
2634     use_dis => 1) {
2635     for ($return->append_new_node (type => '#element',
2636     local_name => 'Def')) {
2637     $_->set_attribute ('Type' => ExpandedURI q<lang:dis>);
2638     $_->set_attribute ('Overridden' => 1);
2639     }
2640     }
2641     }
2642    
2643     my $code_node = get_perl_definition_node $return,
2644     condition => $opt{condition},
2645     level_default => $opt{level_default},
2646     use_dis => 1;
2647     my $int_code_node = get_perl_definition_node $return, name => 'IntDef',
2648     condition => $opt{condition},
2649     level_default => $opt{level_default},
2650     use_dis => 1;
2651     my ($set_code_node, $int_set_code_node);
2652     if ($has_set) {
2653     if ($is_abs) {
2654     unless (get_perl_definition_node $set,
2655     condition => $opt{condition},
2656     level_default => $opt{level_default},
2657     use_dis => 1) {
2658     for ($return->append_new_node (type => '#element',
2659     local_name => 'Def')) {
2660     $_->set_attribute ('Type' => ExpandedURI q<lang:dis>);
2661     $_->set_attribute ('Overridden' => 1);
2662     }
2663     }
2664     }
2665     $set_code_node = get_perl_definition_node $set,
2666     condition => $opt{condition},
2667     level_default => $opt{level_default},
2668     use_dis => 1;
2669     $int_set_code_node = get_perl_definition_node $set, name => 'IntDef',
2670     condition => $opt{condition},
2671     level_default => $opt{level_default},
2672     use_dis => 1;
2673     }
2674     my $code = '';
2675     my $int_code = '';
2676     my $set_code = '';
2677     my $int_set_code = '';
2678     for ({code => \$code, code_node => $code_node,
2679     internal => sub {
2680     return get_internal_code $node, $_[0] if $_[0];
2681     if ($int_code_node) {
2682     perl_code $int_code_node->value,
2683     internal => sub {
2684     $_[0] ? get_internal_code $node, $_[0] :
2685     valid_err q<Preprocessing macro INT cannot be used here>;
2686     };
2687     } else {
2688     valid_err "<IF[Name = $Status->{IF}]/Attr[Name = $m_name]/" .
2689     "Get/IntDef> required";
2690     }
2691     }},
2692     {code => \$int_code, code_node => $int_code_node,
2693     internal => sub {$_[0]?get_internal_code $node,$_[0]:
2694     valid_err q<Preprocessing macro INT cannot be> .
2695     q<used here>}},
2696     {code => \$set_code, code_node => $set_code_node,
2697     internal => sub {
2698     return get_internal_code $node, $_[0] if $_[0];
2699     if ($int_set_code_node) {
2700     perl_code $int_set_code_node->value,
2701     internal => sub {
2702     $_[0] ? get_internal_code $node, $_[0] :
2703     valid_err q<Preprocessing macro INT cannot be used here>;
2704     };
2705     } else {
2706     valid_err "<IF[Name = $Status->{IF}]/Attr[Name = $m_name]/" .
2707     "Set/IntDef> required";
2708     }
2709     }},
2710     {code => \$int_set_code, code_node => $int_set_code_node,
2711     internal => sub {$_[0]?get_internal_code $node,$_[0]:
2712     valid_err q<Preprocessing macro INT cannot be> .
2713     q<used here>}}) {
2714     if ($_->{code_node}) {
2715     my $mcode;
2716     if (type_expanded_uri ($_->{code_node}->get_attribute_value
2717     ('Type', default => q<DOMMain:any>))
2718     eq ExpandedURI q<lang:dis>) {
2719     $mcode = dis2perl $_->{code_node};
2720     } else {
2721     $mcode = perl_code $_->{code_node}->value,
2722     internal => $_->{internal},
2723     node => $_->{code_node};
2724     }
2725     if ($mcode =~ /^\s*$/) {
2726     ${$_->{code}} = '';
2727     } else {
2728     ${$_->{code}} = perl_code_source ($mcode,
2729     path => $_->{code_node}->node_path
2730     (key => 'Name'));
2731     }
2732     }
2733     }
2734    
2735     my @return;
2736     my @return_xcept;
2737     if ($code_node) {
2738     is_implemented if => $Status->{IF}, attr => $Status->{Method},
2739     condition => $opt{condition}, set => 1, on => 'get';
2740     my $co = $code_node->get_attribute_value ('cast-output',
2741     default => $code eq '' ? 0 : 1);
2742     if ($code eq '' and not $co) {
2743     $code = perl_statement get_value_literal $return,
2744     name => 'DefaultValue',
2745     type_name => 'Type';
2746     } else {
2747     $code = perl_statement (perl_assign 'my $r' => get_value_literal $return,
2748     name => 'DefaultValue',
2749     type_name => 'Type') .
2750     $code;
2751     if ($co) {
2752     my $type = type_normalize
2753     type_expanded_uri $return->get_attribute_value
2754     ('Type',
2755     default => q<DOMMain:any>);
2756     if (type_isa $type, ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>) {
2757     $code .= perl_builtin_code $type,
2758     s => 'r', r => 'r',
2759     condition => $opt{condition};
2760     }
2761     }
2762     $code .= perl_statement ('$r');
2763     }
2764     $code = get_warning_perl_code ($return) . $code;
2765     if ($int_code_node) {
2766     $int_code = perl_statement (perl_assign 'my $r' => perl_literal '') .
2767     $int_code .
2768     perl_statement ('$r');
2769     $int_code = perl_statement (perl_assign 'my ($self)' => '@_') . $int_code
2770     if $int_code_node->get_attribute_value ('auto-argument', default => 1);
2771     }
2772    
2773     push @return, pod_item (type_label (type_expanded_uri
2774     $return->get_attribute_value
2775     ('Type',
2776     default => 'DOMMain:any'),
2777     is_pod => 1)),
2778     pod_para (get_description $return);
2779     for (@{$return->child_nodes}) {
2780     if ($_->local_name eq 'InCase') {
2781     push @return, pod_item (get_incase_label $_, is_pod => 1),
2782     pod_para (get_description $_);
2783     } elsif ($_->local_name eq 'Exception') {
2784     push @return_xcept, pod_item ('Exception: ' .
2785     (type_label ($_->get_attribute_value
2786     ('Type',
2787     default => 'DOMMain:any'),
2788     is_pod => 1)) .
2789     '.' . pod_code $_->get_attribute_value
2790     ('Name',
2791     default => '<unknown>')),
2792     pod_para (get_description $_);
2793     my @st;
2794     for (@{$_->child_nodes}) {
2795     next unless $_->node_type eq '#element';
2796     if ($_->local_name eq 'SubType') {
2797     push @st, subtype2poditem ($_);
2798     } elsif ({qw/Name 1 Type 1
2799     Description 1 ImplNote 1
2800     Condition 1 Level 1 SpecLevel 1/}->{$_->local_name}) {
2801     #
2802     } else {
2803     valid_err qq{Element type "@{[$_->local_name]}" not supported},
2804     node => $_;
2805     }
2806     }
2807     push @return_xcept, pod_list 4, @st if @st;
2808     }
2809     }
2810     } else {
2811     is_implemented if => $Status->{IF}, attr => $Status->{Method},
2812     condition => $opt{condition}, set => 0, on => 'get';
2813     $Status->{is_implemented} = 0;
2814     $int_code = $code
2815     = perl_statement perl_exception
2816     level => 'EXCEPTION',
2817     class => 'DOMException',
2818     type => 'NOT_SUPPORTED_ERR',
2819 wakaba 1.2 subtype_uri
2820     => ExpandedURI q<MDOM_EXCEPTION:MDOM_IMPL_ATTR_NOT_IMPLEMENTED>,
2821 wakaba 1.1 param => {
2822     ExpandedURI q<MDOM_EXCEPTION:if> => $Status->{IF},
2823     ExpandedURI q<MDOM_EXCEPTION:attr> => $Status->{Method},
2824     ExpandedURI q<MDOM_EXCEPTION:on> => 'get',
2825     };
2826     @return = ();
2827     push @return_xcept,
2828     pod_item ('Exception: ' . pod_code ('DOMException') . '.' .
2829     pod_code ('NOT_SUPPORTED_ERR')),
2830     pod_para ('Getting of this attribute allways result in
2831     this exception raisen, since this
2832     attribute is not implemented yet.');
2833     }
2834     push @desc, pod_para ('DOM applications can get the value by:'),
2835     pod_pre (qq{\$return = \$obj->$m_name}),
2836     pod_list (4,
2837     @return ? (pod_item pod_code q<$return>,
2838     pod_list 4, @return): (),
2839     @return_xcept);
2840    
2841     my @set_desc;
2842     my @set_xcept;
2843     if ($set_code_node) {
2844     is_implemented if => $Status->{IF}, attr => $Status->{Method},
2845     condition => $opt{condition}, set => 1, on => 'set';
2846     if ($set_code_node->get_attribute_value ('cast-input',
2847     default => $set_code eq '' ? 0 : 1)) {
2848     my $type = type_normalize
2849     type_expanded_uri $set->get_attribute_value
2850     ('Type',
2851     default => q<DOMMain:any>);
2852     if (type_isa $type, ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>) {
2853     $set_code = perl_builtin_code ($type,
2854     s => 'given', r => 'given',
2855     condition => $opt{condition})
2856     . $set_code;
2857     }
2858     }
2859     $set_code = get_warning_perl_code ($set) . $set_code;
2860    
2861     push @set_desc, pod_item (type_label (type_expanded_uri
2862     ($set->get_attribute_value
2863     ('Type',
2864     default => 'DOMMain:any')),
2865     is_pod => 1)),
2866     pod_para (get_description $set);
2867     for (@{$set->child_nodes}) {
2868     if ($_->local_name eq 'InCase') {
2869     push @set_desc, pod_item (get_incase_label $_, is_pod => 1),
2870     pod_para (get_description $_);
2871     } elsif ($_->local_name eq 'Exception') {
2872     push @set_xcept, pod_item ('Exception: ' .
2873     (type_label ($_->get_attribute_value
2874     ('Type',
2875     default => 'DOMMain:any'),
2876     is_pod => 1)) .
2877     '.' . pod_code $_->get_attribute_value
2878     ('Name',
2879     default => '<unknown>')),
2880     pod_para (get_description $_);
2881     my @st;
2882     for (@{$_->child_nodes}) {
2883     next unless $_->node_type eq '#element';
2884     if ($_->local_name eq 'SubType') {
2885     push @st, subtype2poditem ($_);
2886     } elsif ({qw/Name 1 Type 1
2887     Description 1 ImplNote 1
2888     Condition 1 Level 1 SpecLevel 1/}->{$_->local_name}) {
2889     #
2890     } else {
2891     valid_err qq{Element type "@{[$_->local_name]}" not supported},
2892     node => $_;
2893     }
2894     }
2895     push @set_xcept, pod_list 4, @st if @st;
2896     }
2897     }
2898     } elsif ($has_set) {
2899     is_implemented if => $Status->{IF}, attr => $Status->{Method},
2900     condition => $opt{condition}, set => 0, on => 'set';
2901     $Status->{is_implemented} = 0;
2902     $int_set_code = $set_code
2903     = perl_statement perl_exception
2904     level => 'EXCEPTION',
2905     class => 'DOMException',
2906     type => 'NOT_SUPPORTED_ERR',
2907 wakaba 1.2 subtype_uri
2908     => ExpandedURI q<MDOM_EXCEPTION:MDOM_IMPL_ATTR_NOT_IMPLEMENTED>,
2909 wakaba 1.1 param => {
2910     ExpandedURI q<MDOM_EXCEPTION:if> => $Status->{IF},
2911     ExpandedURI q<MDOM_EXCEPTION:attr> => $Status->{Method},
2912     ExpandedURI q<MDOM_EXCEPTION:on> => 'set',
2913     };
2914     @set_desc = pod_item '(Not implemented yet)';
2915     @set_xcept = ();
2916     push @set_xcept, pod_item ('Exception: ' . pod_code ('DOMException') . '.' .
2917     pod_code ('NOT_SUPPORTED_ERR')),
2918     pod_para ('Setting of this attribute allways result in
2919     this exception raisen, since this
2920     attribute is not implemented yet.');
2921     }
2922    
2923     if ($has_set) {
2924     push @desc, pod_para ('DOM applications can set the value by:'),
2925     pod_pre (qq{\$obj->$m_name (\$newValue)}),
2926     pod_list 4,
2927     pod_item (pod_code q<$newValue>),
2928     pod_list 4, @set_desc;
2929     push @desc, (@set_xcept ?
2930     (pod_para (q<Setting this attribute may raise exception:>),
2931     pod_list (4, @set_xcept)) :
2932     (pod_para (q<Setting this attribute does not raise >.
2933     q<exception in general.>)));
2934     } else {
2935     push @desc, pod_para ('This attribute is read-only.');
2936     }
2937     is_implemented if => $Status->{IF}, method => $Status->{Method},
2938     condition => $opt{condition}, set => $Status->{is_implemented};
2939    
2940     push @desc, get_alternate_description $node;
2941     push @desc, get_redef_description $node, method => 'attribute';
2942    
2943     if ($node->local_name eq 'IntAttr' or
2944     $Status->{if}->{method_documented}->{$m_name}++) {
2945     $result .= pod_block pod_comment @desc;
2946     } else {
2947     $result .= pod_block @desc;
2948     }
2949    
2950     my $warn = get_warning_perl_code ($node);
2951     my $proto;
2952     if ($has_set) {
2953     $code = perl_statement (perl_assign
2954     perl_var (scope => 'my', type => '$', local_name => 'self')
2955     => 'shift').
2956     $warn.
2957     perl_if
2958     q<exists $_[0]>,
2959     ($set_code =~/\bgiven\b/ ?
2960     perl_statement (q<my $given = shift>) : '') . $set_code .
2961     perl_statement ('undef'),
2962     $code;
2963     $int_code = perl_statement (perl_assign
2964     perl_var (scope => 'my', type => '$', local_name => 'self')
2965     => 'shift').
2966     perl_if
2967     q<exists $_[0]>,
2968     perl_statement (q<my $given = shift>) . $int_set_code,
2969     $int_code;
2970     $proto = '$;$';
2971     } else {
2972     $code = q<my $self = shift; > . $warn . $code;
2973     $int_code = q<my $self = shift; > . $int_code;
2974     $proto = '$';
2975     }
2976     $result .= perl_sub name => $m_name,
2977     prototype => $proto,
2978     code => $code;
2979     $result .= perl_sub name => perl_internal_name $m_name,
2980     prototype => $proto,
2981     code => $int_code
2982     if $int_code_node;
2983    
2984     if (my $op = get_perl_definition_node $node, name => 'Operator') {
2985     $Status->{Operator}->{$op->value} = '\\' . perl_var type => '&',
2986     local_name => $m_name;
2987     }
2988    
2989     $result;
2990     } # attr2perl
2991    
2992     =head2 DataType element
2993    
2994     The C<DataType> element defines a datatype.
2995    
2996     =cut
2997    
2998     sub datatype2perl ($;%) {
2999     my ($node, %opt) = @_;
3000     local $Status->{depth} = $Status->{depth} + 1;
3001     my $pack_name = perl_package_name
3002     name => my $if_name
3003     = perl_name $node->get_attribute_value ('Name'),
3004     ucfirst => 1;
3005     local $Status->{IF} = $if_name;
3006     local $Status->{if} = {}; ## Temporary data
3007     local $Info->{Namespace} = {%{$Info->{Namespace}}};
3008     local $Info->{Require_perl_package} = {%{$Info->{Require_perl_package}}};
3009     local $Info->{Require_perl_package_use} = {};
3010     local $Status->{Operator} = {};
3011     my $result = perl_package full_name => $pack_name;
3012     my @isa;
3013     for (@{$node->child_nodes}) {
3014     next unless $_->node_type eq '#element' and
3015     $_->local_name eq 'ISA' and
3016     condition_match $_, condition => $opt{condition},
3017     default_any => 1, ge => 1;
3018     push @isa, perl_package_name qname_with_condition => $_->value,
3019     condition => $opt{condition};
3020     }
3021     $result .= perl_inherit [@isa, perl_package_name (name => 'ManakaiDOMObject'),
3022     perl_package_name (if => $if_name)];
3023     for my $pack ({full_name => $pack_name}, {if => $if_name}) {
3024     $result .= perl_statement perl_assign
3025     perl_var (type => '$',
3026     package => $pack,
3027     local_name => 'VERSION')
3028     => version_date time;
3029     }
3030    
3031     my @level = @{$opt{level} || []};
3032     my $mod = get_level_description $node, level => \@level;
3033     $result .= pod_block
3034     pod_head ($Status->{depth}, 'Type ' . pod_code $if_name),
3035     pod_paras (get_description ($node)),
3036     ($mod ? pod_para ('This type is ' . $mod) : ());
3037    
3038     for (@{$node->child_nodes}) {
3039     if ($_->local_name eq 'Method' or
3040     $_->local_name eq 'IntMethod') {
3041     $result .= method2perl ($_, level => \@level,
3042     condition => $opt{condition});
3043     } elsif ($_->local_name eq 'Attr' or
3044     $_->local_name eq 'IntAttr') {
3045     $result .= attr2perl ($_, level => \@level, condition => $opt{condition});
3046     } elsif ($_->local_name eq 'ConstGroup') {
3047     $result .= constgroup2perl ($_, level => \@level,
3048     condition => $opt{condition},
3049     package => $pack_name);
3050     } elsif ($_->local_name eq 'Const') {
3051     $result .= const2perl ($_, level => \@level,
3052     condition => $opt{condition},
3053     package => $pack_name);
3054     } elsif ($_->local_name eq 'ISA') {
3055     push @{$Info->{DataTypeAlias}->{type_expanded_uri $if_name}
3056     ->{isa_uri}||=[]},
3057     type_expanded_uri $_->value;
3058     } elsif ({qw/Name 1 FullName 1 Spec 1 Description 1
3059     Level 1 SpecLevel 1 Def 1 ImplNote 1/}->{$_->local_name}) {
3060     #
3061     } else {
3062     valid_warn qq{Element @{[$_->local_name]} not supported};
3063     }
3064     }
3065    
3066     $result .= ops2perl;
3067    
3068     $result;
3069     } # datatype2perl
3070    
3071     sub datatypealias2perl ($;%) {
3072     my ($node, %opt) = @_;
3073     local $Status->{depth} = $Status->{depth} + 1;
3074     my $if_name = $node->get_attribute_value ('Name');
3075     my $long_name = expanded_uri $if_name;
3076     my $real_long_name = type_expanded_uri
3077     (my $real_name = $node->get_attribute_value
3078     ('Type', default => 'DOMMain:any'));
3079     if (type_label ($real_long_name) eq type_label ($long_name)) {
3080     $Info->{DataTypeAlias}->{$long_name}->{canon_uri} = $real_long_name;
3081     return perl_comment sprintf '%s <%s> := %s <%s>',
3082     type_label ($long_name), $long_name,
3083     type_label ($real_long_name), $real_long_name;
3084     }
3085     $Info->{DataTypeAlias}->{$long_name}->{canon_uri} = $real_long_name;
3086    
3087     $if_name = perl_name $if_name, ucfirst => 1;
3088     $real_name = type_package_name $real_name;
3089     my $pack_name = perl_package_name name => $if_name;
3090     local $Status->{IF} = $if_name;
3091     local $Status->{if} = {}; ## Temporary data
3092     local $Info->{Namespace} = {%{$Info->{Namespace}}};
3093     local $Info->{Require_perl_package} = {%{$Info->{Require_perl_package}}};
3094     local $Info->{Require_perl_package_use} = {};
3095     my $result = perl_package full_name => $pack_name;
3096     $result .= perl_inherit [perl_package_name (full_name => $real_name),
3097     perl_package_name (if => $if_name)];
3098     for my $pack ({if => $if_name}) {
3099     $result .= perl_statement perl_assign
3100     perl_var (type => '$',
3101     package => $pack,
3102     local_name => 'VERSION')
3103     => version_date time;
3104     }
3105    
3106     my @level = @{$opt{level} || []};
3107     my $mod = get_level_description $node, level => \@level;
3108     $result .= pod_block
3109     pod_head ($Status->{depth}, 'Type ' . pod_code $if_name),
3110     pod_paras (get_description ($node)),
3111     pod_para ('This type is an alias of the type ' .
3112     (type_label $real_long_name, is_pod => 1) . '.'),
3113     ($mod ? pod_para ('This type is ' . $mod) : ());
3114    
3115     for (@{$node->child_nodes}) {
3116     if ({qw/Name 1 FullName 1 Spec 1 Type 1 Description 1
3117     Level 1 SpecLevel 1 Condition 1 ImplNote 1
3118     Def 1/}->{$_->local_name}) {
3119     #
3120     } else {
3121     valid_warn qq{Element @{[$_->local_name]} not supported};
3122     }
3123     }
3124    
3125     $result;
3126     } # datatypealias2perl
3127    
3128     =item Exception top-level element
3129    
3130     =item Warning top-level element
3131    
3132     =cut
3133    
3134     sub exception2perl ($;%) {
3135     my ($node, %opt) = @_;
3136     local $Status->{depth} = $Status->{depth} + 1;
3137     local $Status->{const} = {};
3138     local $Status->{if} = {}; ## Temporary data
3139     local $Status->{in_exception} = 1;
3140     local $Info->{Namespace} = {%{$Info->{Namespace}}};
3141     local $Info->{Require_perl_package} = {%{$Info->{Require_perl_package}}};
3142     local $Info->{Require_perl_package_use} = {};
3143     my $pack_name = perl_package_name
3144     name => my $if_name
3145     = perl_name $node->get_attribute_value ('Name'),
3146     ucfirst => 1;
3147     my $type = $node->local_name eq 'Exception' ? 'Exception' : 'Warning';
3148     local $Status->{IF} = $if_name;
3149     my $result = perl_package full_name => $pack_name;
3150     $result .= perl_statement perl_assign 'our $VERSION', version_date time;
3151     my @isa = perl_package_name (if => $if_name);
3152     if ($if_name eq 'ManakaiDOM'.$type) {
3153     push @isa, perl_package_name name => 'ManakaiDOMExceptionOrWarning';
3154     } elsif ($if_name eq 'ManakaiDOMExceptionOrWarning') {
3155     push @isa, 'Message::Util::Error';
3156     } else {
3157     push @isa, perl_package_name name => 'ManakaiDOM'.$type
3158     }
3159     $result .= perl_inherit [@isa];
3160     $result .= perl_statement perl_assign
3161     perl_var (type => '$',
3162     package => {if => $if_name},
3163     local_name => 'VERSION')
3164     => version_date time;
3165     my @level = @{$opt{level} || []};
3166     my $mod = get_level_description $node, level => \@level;
3167     $result .= pod_block
3168     pod_head ($Status->{depth}, $type . ' ' . pod_code $if_name),
3169     pod_paras (get_description ($node)),
3170     ($mod ? pod_para ('This ' . lc ($type) . ' is introduced in ' .
3171     $mod . '.') : ()),
3172     ($type eq 'Exception' ?
3173     (pod_para ('To catch this class of exceptions:'),
3174     pod_pre (join "\n",
3175     q|try { |,
3176     q| ... |,
3177     q|} catch | . $pack_name . q| with { |,
3178     q| my $err = shift; |,
3179     q| if ($err->{type} eq 'ERROR_NAME') { |,
3180     q| ... # Recover from some error, |,
3181     q| } else { |,
3182     q| $err->throw; # rethrow if other |,
3183     q| } |,
3184     q|}; # Don't forget semicolon! |))
3185     : ());
3186    
3187     for (@{$node->child_nodes}) {
3188     if ($_->local_name eq 'Method' or
3189     $_->local_name eq 'IntMethod' or
3190     $_->local_name eq 'ReMethod') {
3191     $result .= method2perl ($_, level => \@level,
3192     condition => $opt{condition},
3193     any_unless_condition => 1);
3194     } elsif ($_->local_name eq 'Attr' or
3195     $_->local_name eq 'IntAttr' or
3196     $_->local_name eq 'ReAttr') {
3197     my $get;
3198     if ($_->local_name eq 'Attr' and
3199     $_->get_attribute_value ('Name') eq 'code' and
3200     $get = $_->get_attribute ('Get') and
3201     not get_perl_definition_node $get, name => 'Def') {
3202     for ($get->append_new_node (type => '#element',
3203     local_name => 'Def',
3204     value => q{
3205     $r = $self->{<Q:ManakaiDOM:code>};
3206     })) {
3207     $_->set_attribute (type => 'lang:Perl'); ## ISSUE: NS prefix assoc.
3208     }
3209     }
3210     $result .= attr2perl ($_, level => \@level, condition => $opt{condition},
3211     any_unless_condition => 1);
3212     } elsif ($_->local_name eq 'ConstGroup') {
3213     $result .= constgroup2perl ($_, level => \@level,
3214     condition => $opt{condition},
3215     package => $pack_name,
3216     any_unless_condition => 1);
3217     } elsif ($_->local_name eq 'Const') {
3218     $result .= const2perl ($_, level => \@level,
3219     condition => $opt{condition},
3220     package => $pack_name,
3221     any_unless_condition => 1);
3222     } elsif ({qw/Name 1 Spec 1 Description 1
3223     Level 1 SpecLevel 1 Condition 1
3224     ImplNote 1/}->{$_->local_name}) {
3225     #
3226     } else {
3227     valid_warn qq{Element @{[$_->local_name]} not supported};
3228     }
3229     }
3230    
3231     $result .= perl_sub
3232     name => '___error_def', prototype => '',
3233     code => perl_list {
3234     map {
3235     $_ => {
3236     ExpandedURI q<DOMCore:code> => perl_code_literal
3237     ($Status->{const}->{$_}->{code_literal}),
3238     description
3239     => $Status->{const}->{$_}->{description},
3240     ExpandedURI q<MDOM_EXCEPTION:subtype>
3241     => $Status->{const}->{$_}->{subtype},
3242     }
3243     } sort keys %{$Status->{const}}
3244     };
3245    
3246     $result;
3247     } # exception2perl
3248    
3249     sub constgroup2perl ($;%);
3250     sub constgroup2perl ($;%) {
3251     my ($node, %opt) = @_;
3252     local $Status->{depth} = $Status->{depth} + 1;
3253     my $name = $node->get_attribute ('Name');
3254     if (defined $name) {
3255     $name = perl_name $name->value, ucfirst => 1;
3256     }
3257     local $Status->{IF} = $name || q<[anonymous constant group]>;
3258     my @level = @{$opt{level} || []};
3259     my $mod = get_level_description $node, level => \@level;
3260     my $result = '';
3261     my $consts = {};
3262     $Info->{DataTypeAlias}->{expanded_uri $node->get_attribute_value ('Name')}
3263     ->{isa_uri} = [type_expanded_uri $node->get_attribute_value
3264     ('Type', default => q<DOMMain:any>)]
3265     if defined $name;
3266    
3267     my $i = 0;
3268     {
3269     local $Status->{EXPORT_OK} = $consts;
3270     for (@{$node->child_nodes}) {
3271     my $only_document = $opt{only_document} || 0;
3272     unless ($_->node_type eq '#element' and
3273     condition_match $_, level_default => \@level,
3274     condition => $opt{condition},
3275     any_unless_condition
3276     => $opt{any_unless_condition}) {
3277     $only_document = 1;
3278     }
3279    
3280     if ($_->local_name eq 'ConstGroup') {
3281     $result .= constgroup2perl ($_, level => \@level,
3282     condition => $opt{condition},
3283     without_document => $opt{without_document},
3284     only_document => $only_document,
3285     package => $opt{package},
3286     any_unless_condition
3287     => $opt{any_unless_condition});
3288     $i++;
3289     } elsif ($_->local_name eq 'Const') {
3290     $result .= const2perl ($_, level => \@level,
3291     condition => $opt{condition},
3292     without_document => $opt{without_document},
3293     only_document => $only_document,
3294     package => $opt{package},
3295     any_unless_condition
3296     => $opt{any_unless_condition});
3297     $i++;
3298     } elsif ({qw/Name 1 Spec 1 ISA 1 Description 1 Type 1 IsBitMask 1
3299     Level 1 SpecLevel 1 Def 1 ImplNote 1
3300     FullName 1/}->{$_->local_name}) {
3301     #
3302     } else {
3303     valid_warn qq{Element @{[$_->local_name]} not supported};
3304     }
3305     }
3306     }
3307    
3308     for (keys %$consts) {
3309     $Status->{EXPORT_OK}->{$_} = 1;
3310     $Status->{EXPORT_TAGS}->{$name}->{$_} = 1 if defined $name;
3311     }
3312    
3313     return $result if $opt{without_document};
3314    
3315     my @desc;
3316     if (defined $name) {
3317     push @desc, pod_head $Status->{depth}, 'Constant Group ' . pod_code $name;
3318     } else {
3319     push @desc, pod_head $Status->{depth}, 'Constant Group: ' .
3320     get_description ($node,
3321     name => 'FullName');
3322     }
3323    
3324     push @desc, pod_paras (get_description ($node)),
3325     ($mod ? pod_para ('This constant group has been ' . $mod . '.')
3326     : ()),
3327     pod_para ('This constant group has ' .
3328     english_number $i, singular => q<value.>,
3329     plural => q<values.>);
3330    
3331     push @desc, pod_para ('To export all constant values in this group:'),
3332     pod_pre (perl_statement "use $Info->{Package} qw/:$name/")
3333     if defined $name;
3334    
3335     $result = pod_block (@desc) . $result;
3336    
3337     $result;
3338     } # constgroup2perl
3339    
3340     sub const2perl ($;%) {
3341     my ($node, %opt) = @_;
3342     local $Status->{depth} = $Status->{depth} + 1;
3343     my $name = perl_name $node->get_attribute_value ('Name');
3344     my $longname = perl_var local_name => $name,
3345     package => {full_name => $opt{package} ||
3346     $Info->{Package}};
3347     local $Status->{IF} = $name;
3348     local $Status->{const_subtype} = {};
3349     my @level = @{$opt{level} || []};
3350     my $mod = get_level_description $node, level => \@level;
3351     my @desc;
3352     unless ($opt{without_document}) {
3353     @desc = (pod_head ($Status->{depth}, 'Constant Value ' . pod_code $name),
3354     pod_paras (get_description ($node)),
3355     ($mod ? pod_para ('This constant value has been ' . $mod . '.')
3356     : ()));
3357    
3358     if ($Status->{in_exception}) { ## Is Exception/Warning code
3359     #
3360     } else { ## Is NOT Exception/Warning code
3361     push @desc, pod_para ('To export this constant value:'),
3362     pod_pre (perl_statement "use $Info->{Package} qw/$name/");
3363     }
3364    
3365     my @param;
3366     for (@{$node->child_nodes}) {
3367     next unless $_->node_type eq '#element';
3368     if ($_->local_name eq 'Param') {
3369     if ($Status->{in_exception}) {
3370     push @param, param2poditem ($_);
3371     } else {
3372     valid_err qq{Element "Param" may not be used with non-Exception}.
3373     qq{/Warning constants},
3374     node => $node;
3375     }
3376     } elsif ($_->local_name eq 'SubType') {
3377     if ($Status->{in_exception}) {
3378     push @param, subtype2poditem ($_);
3379     } else {
3380     valid_err qq{Element "SubType" may not be used with non-Exception}.
3381     qq{/Warning constants},
3382     node => $node;
3383     }
3384     } elsif ({qw/Name 1 Spec 1 Description 1
3385     Condition 1 Level 1 SpecLevel 1
3386     Type 1 Value 1 ImplNote 1/}->{$_->local_name}) {
3387     #
3388     } else {
3389     valid_err qq{Element type "@{[$_->local_name]}" not supported},
3390     node => $node;
3391     }
3392     }
3393     push @desc, pod_list 4, @param if @param;
3394     }
3395    
3396     my $result = '';
3397     unless ($opt{only_document}) {
3398     $result = perl_sub name => $longname, prototype => '',
3399     code => my $code = get_value_literal
3400     $node, name => 'Value';
3401     $result .= perl_sub name => perl_var (package => {full_name
3402     => $Info->{Package}},
3403     local_name => $name), prototype => '',
3404     code => $code
3405     if $opt{package} and $Info->{Package} ne $opt{package};
3406     my $desc_template = get_description $node,
3407     type => ExpandedURI q<lang:muf>,
3408     default => $name;
3409     $Status->{const}->{$name} = {
3410     description => $desc_template,
3411     code_literal => $code,
3412     subtype => $Status->{const_subtype} || {},
3413     };
3414     }
3415    
3416     $Status->{EXPORT_OK}->{$name} = 1;
3417    
3418     unless ($opt{without_document}) {
3419     $result = pod_block (@desc) . $result;
3420     }
3421    
3422     $result;
3423     } # const2perl
3424    
3425     sub param2poditem ($;%) {
3426     my ($node, %opt) = @_;
3427     my @desc;
3428     $opt{name_prefix} = 'Parameter: ' unless defined $opt{name_prefix};
3429     if ($node->get_attribute ('Name')) {
3430     push @desc, $opt{name_prefix} . pod_code $node->get_attribute_value ('Name');
3431     } elsif ($node->get_attribute ('QName')) {
3432     push @desc, pod_item $opt{name_prefix} .
3433     qname_label ($node,
3434     out_type => ExpandedURI q<lang:pod>);
3435     } else {
3436     valid_err q<Attribute "Name" or "QName" required>,
3437     node => $node;
3438     }
3439    
3440     my @val;
3441     push @val, pod_item (type_label (type_expanded_uri
3442     ($node->get_attribute_value
3443     ('Type',
3444     default => 'DOMMain:any')),
3445     is_pod => 1)),
3446     pod_para (get_description $node);
3447     for (@{$node->child_nodes}) {
3448     last unless $_->node_type eq '#element';
3449     if ($_->local_name eq 'InCase') {
3450     push @val, pod_item (get_incase_label $_, is_pod => 1),
3451     pod_para (get_description $_);
3452     } elsif ({qw/Name 1 QName 1 Type 1
3453     Description 1 ImplNote 1/}->{$_->local_name}) {
3454     #
3455     } else {
3456     valid_err qq{Element type "@{[$_->local_name]}" not supported},
3457     node => $_;
3458     }
3459     }
3460    
3461     if (@val) {
3462     push @desc, pod_list 4, @val;
3463     }
3464    
3465     @desc;
3466     } # param2poditem
3467    
3468     sub subtype2poditem ($;%) {
3469     my ($node, %opt) = @_;
3470     my @desc;
3471     $opt{name_prefix} = 'SubType: ' unless defined $opt{name_prefix};
3472     my $qname = $node->get_attribute_value ('QName');
3473     if (defined $qname) {
3474     push @desc, pod_item $opt{name_prefix} .
3475     qname_label ($node, qname => $qname,
3476     out_type => ExpandedURI q<lang:pod>);
3477     } else {
3478     valid_err q<Attribute "QName" required>,
3479     node => $node;
3480     }
3481    
3482     push @desc, pod_para (get_description $node);
3483     my @param;
3484     for (@{$node->child_nodes}) {
3485     last unless $_->node_type eq '#element';
3486     if ($_->local_name eq 'Param') {
3487     push @param, param2poditem ($_);
3488     } elsif ({qw/QName 1 Type 1 SpecLevel 1
3489     Description 1 ImplNote 1/}->{$_->local_name}) {
3490     #
3491     } else {
3492     valid_err qq{Element type "@{[$_->local_name]}" not supported},
3493     node => $_;
3494     }
3495     }
3496    
3497     if (@param) {
3498     push @desc, pod_list 4, @param;
3499     }
3500    
3501     my $desc_template = get_description $node,
3502     type => ExpandedURI q<lang:muf>,
3503     default => $qname;
3504     $Status->{const_subtype}->{type_expanded_uri $qname} = {
3505     description => $desc_template,
3506     };
3507    
3508    
3509     @desc;
3510     } # subtype2poditem
3511    
3512     =head2 Require element
3513    
3514     The C<Require> element indicates that some external modules
3515     are required. Both DOM-implementing modules and language-specific
3516     library modules are allowed.
3517    
3518     Children:
3519    
3520     =over 4
3521    
3522     =item Require/Module (0 - infinite)
3523    
3524     A required module.
3525    
3526     Children:
3527    
3528     =over 4
3529    
3530     =item Require/Module/Name = name (0 - 1)
3531    
3532     The DOM module name. Iif it is a DOM-implementing module,
3533     this attribute MUST be specified.
3534    
3535     =item Require/Module/Namespace = namespace-uri (0 - 1)
3536    
3537     The namespace URI for the module, if any. Namespace prefix
3538     C<Name> is to be binded with C<Namespace> if both
3539     C<Name> and C<Namespace> are available.
3540    
3541     =item Require/Module/Def = Type-dependent (0 - infinite)
3542    
3543     Language-depending definition of loading of the required module.
3544     If no appropriate C<Type> of C<Def> element is available,
3545     loading code is generated from C<Name> attribute.
3546    
3547     =back
3548    
3549     =back
3550    
3551     =cut
3552    
3553     sub req2perl ($) {
3554     my $node = shift;
3555     my $reqnode = $node->local_name eq 'Require' ? $node :
3556     $node->get_attribute ('Require', make_new_node => 1);
3557     my $result = '';
3558     for (@{$reqnode->child_nodes}) {
3559     if ($_->local_name eq 'Module') {
3560     my $m_name = $_->get_attribute_value ('Name', default => '<anon>');
3561     my $ns_uri = $_->get_attribute_value ('Namespace');
3562     $Info->{Namespace}->{$m_name} = $ns_uri if defined $ns_uri;
3563     $m_name = perl_name $m_name, ucfirst => 1;
3564     my $desc = get_description $_;
3565     $result .= perl_comment (($m_name ne '<anon>' ? $m_name : '') .
3566     ($desc ? ' - ' . $desc : ''))
3567     if $desc or $m_name ne '<anon>';
3568     my $def = get_perl_definition_node $_, name => 'Def';
3569     if ($def) {
3570     my $s;
3571     my $req;
3572     my $pack_name;
3573     if ($req = $def->get_attribute ('require')) {
3574     $s = 'require ' . ($pack_name = perl_code $req->value);
3575     $Info->{uri_to_perl_package}->{$ns_uri} = $pack_name if $ns_uri;
3576     $Info->{Require_perl_package}->{$pack_name} = 1;
3577     } elsif ($req = $def->get_attribute ('use')) {
3578     $s = 'use ' . ($pack_name = perl_code $req->value);
3579     $Info->{uri_to_perl_package}->{$ns_uri} = $pack_name if $ns_uri;
3580     $Info->{Require_perl_package}->{$pack_name} = 1;
3581     $Info->{Require_perl_package_use}->{$pack_name} = 1;
3582     } elsif (defined ($s = $def->value)) {
3583     #
3584     } else {
3585     valid_warn qq<Required module definition for $m_name is empty>;
3586     }
3587     if ($req and my $list = $req->get_attribute_value ('Import',
3588     as_array => 1)) {
3589     if (@$list) {
3590     $s .= ' ' . perl_list @$list;
3591     $Info->{Require_perl_package_use}
3592     ->{$pack_name . '::::Import'}->{$_} = 1 for @$list;
3593     }
3594     }
3595     $result .= perl_statement $s;
3596     } else {
3597     $result .= perl_statement 'require ' .
3598     perl_code "__CLASS{$m_name}__";
3599     }
3600     } elsif ($_->local_name eq 'Condition') {
3601     } else {
3602     valid_warn qq[Requiredness type @{[$_->local_name]} not supported];
3603     }
3604     }
3605     $result;
3606     }
3607    
3608     =head2 Module element
3609    
3610     A "dis" file requires one (and only one) C<Module> top-level element.
3611     Other elements, such as C<Require>, may include C<Module> elements
3612     as their children.
3613    
3614     Children:
3615    
3616     =over 4
3617    
3618     =item Module/Name = name (0 - 1)
3619    
3620     The module name. Usually DOM IDL module name is used.
3621    
3622     This attribute is required when C<Module> element is used as
3623     a top-level element. It is optional if C<Module> is a child
3624     of other element.
3625    
3626     =item Module/Package = Type-dependent (0 - infinite)
3627    
3628     The module package name. For example,
3629    
3630     Module:
3631     @Name: module1
3632     @Package:
3633     @@@: Module1
3634     @@Type:
3635     lang:Perl
3636    
3637     means that general module name is C<module1> and Perl-specific
3638     module name is C<Module1>.
3639    
3640     =item Module/Namespace = namespace (1 - 1)
3641    
3642     The namespace URI (an absolute URI with optional fragment identifier)
3643     that is assigned to this module. Datatypes defined by this module
3644     (such as C<DataType> or C<Interface>) are considered to belong to
3645     this namespace.
3646    
3647     In addition, the default namespace is binding to this namespace name
3648     (in other word, special namespace prefix C<#default> is associated
3649     with the URI reference).
3650    
3651     =item Module/FullName = text (0 - infinite)
3652    
3653     A human-readable module name.
3654    
3655     =item Module/Description = text (0 - infinite)
3656    
3657     A human-readable module description.
3658    
3659     =item Module/License = qname (1 - 1)
3660    
3661     A qname that identify the license term.
3662    
3663     =item Module/Date.RCS = <rcs date> (1 - 1)
3664    
3665     The last-modified date-time of this module,
3666     represented in RCS format (text C<Date:> with date and time,
3667     enclosed by C<$>s).
3668    
3669     =item Module/Require (0 - infinite)
3670    
3671     A list of modules (DOM modules or other liburary modules)
3672     that is required by entire module.
3673    
3674     =back
3675    
3676     =cut
3677    
3678     ## Get general information
3679     $Info->{source_filename} = $ARGV;
3680    
3681     ## Initial Namespace bindings
3682     for ([ManakaiDOM => ExpandedURI q<ManakaiDOM:>],
3683     [http => q<http:>]) {
3684     $Info->{Namespace}->{$_->[0]} = $_->[1];
3685     }
3686    
3687     ## Initial DataType aliasing and inheritance
3688     for (ExpandedURI q<ManakaiDOM:ManakaiDOMURI>,
3689     ExpandedURI q<ManakaiDOM:ManakaiDOMNamespaceURI>,
3690     ExpandedURI q<ManakaiDOM:ManakaiDOMFeatureName>,
3691     ExpandedURI q<ManakaiDOM:ManakaiDOMFeatureVersion>,
3692     ExpandedURI q<ManakaiDOM:ManakaiDOMFeatures>) {
3693     $Info->{DataTypeAlias}->{$_}
3694     ->{isa_uri} = [ExpandedURI q<DOMMain:DOMString>];
3695     }
3696    
3697     register_namespace_declaration ($source);
3698    
3699     my $Module = $source->get_attribute ('Module', make_new_node => 1);
3700     $Info->{Name} = perl_name $Module->get_attribute_value ('Name'), ucfirst => 1
3701     or valid_err q<Module name (/Module/Name) MUST be specified>;
3702     $Info->{Namespace}->{(DEFAULT_PFX)}
3703     = $Module->get_attribute_value ('Namespace')
3704     or valid_err q<Module namespace URI (/Module/Namespace) MUST be specified>;
3705     $Info->{Namespace}->{$Module->get_attribute_value ('Name')}
3706     = $Info->{Namespace}->{(DEFAULT_PFX)};
3707     my $pack_node = get_perl_definition_node $Module, name => 'BindingName';
3708     if ($pack_node) {
3709     $Info->{Package} = perl_code $pack_node->value;
3710     } else {
3711     $Info->{Package} = perl_package_name name => $Info->{Name};
3712     }
3713     $Info->{uri_to_perl_package}->{$Info->{Namespace}->{(DEFAULT_PFX)}}
3714     = $Info->{Package};
3715     $Info->{Require_perl_package} = {};
3716     $Info->{Require_perl_package_use} = {};
3717    
3718     ## Make source code
3719     $result .= perl_comment q<This file is automatically generated from> . "\n" .
3720     q<"> . $Info->{source_filename} . q<" at > .
3721     rfc3339_date (time) . qq<.\n> .
3722     q<Don't edit by hand!>;
3723    
3724     $result .= perl_statement q<use strict>;
3725    
3726     local $Status->{depth} = $Status->{depth} + 1;
3727     $result .= perl_package full_name => $Info->{Package};
3728     $result .= perl_statement perl_assign 'our $VERSION' => version_date time;
3729    
3730     $result .= pod_block
3731     pod_head (1, 'NAME'),
3732     pod_para ($Info->{Package} .
3733     ' - ' . get_description ($Module, name => 'FullName')),
3734     section (
3735     opt => pod_head (1, 'DESCRIPTION'),
3736     req => pod_para (get_description ($Module)),
3737     ),
3738     pod_head (1, 'DOM INTERFACES');
3739    
3740     ## Conditions
3741     my $defcond = 0;
3742     for my $cond (@{$Module->child_nodes}) {
3743     next unless $cond->node_type eq '#element' and
3744     $cond->local_name eq 'ConditionDef';
3745     my $name = $cond->get_attribute_value ('Name', default => '');
3746     my $isa = $cond->get_attribute_value ('ISA', default => []);
3747     my $fullname = get_description $cond, name => 'FullName';
3748     $isa = [$isa] unless ref $isa;
3749     if ($name =~ /^DOM(\d+)$/) {
3750     $defcond = $1 if $1 > $defcond;
3751     $fullname ||= "DOM Level " . (0 + $1);
3752     }
3753     $Info->{Condition}->{$name}->{ISA} = $isa;
3754     $Info->{Condition}->{$name}->{FullName} = $fullname || $name;
3755     }
3756     if (keys %{$Info->{Condition}}) {
3757     $Info->{NormalCondition} = $Module->get_attribute_value
3758     ('NormalCondition') ||
3759     $defcond ? 'DOM' . $defcond :
3760     valid_err q<Module/NormalCondition required>;
3761     }
3762    
3763     ## 'require'ing external modules
3764     {
3765     my $req = $Module->get_attribute ('Require', make_new_node => 1);
3766     my $reqModule = sub {
3767     my ($name, $me, $you) = @_;
3768     if ($you->get_attribute_value ('Name', default => '') eq $name) {
3769     return 1;
3770     } else {
3771     return 0;
3772     }
3773     };
3774     if (not $req->get_element_by (sub {$reqModule->('ManakaiDOMMain', @_)})) {
3775     for ($req->append_new_node (type => '#element',
3776     local_name => 'Module')) {
3777     $_->set_attribute (Name => 'ManakaiDOMMain');
3778     $_->set_attribute (Namespace => ExpandedURI q<ManakaiDOM:>);
3779     }
3780     }
3781     if (not $req->get_element_by (sub {$reqModule->('DOMMain', @_)})) {
3782     for ($req->append_new_node (type => '#element',
3783     local_name => 'Module')) {
3784     $_->set_attribute (Name => 'DOMMain');
3785     $_->set_attribute (Namespace => ExpandedURI q<DOMMain:>);
3786     }
3787     }
3788     $result .= req2perl $Module;
3789     }
3790    
3791     for my $node (@{$source->child_nodes}) {
3792     if ($node->node_type ne '#element') {
3793     ##
3794     } elsif ($node->local_name eq 'IF') {
3795     $result .= if2perl $node;
3796     } elsif ($node->local_name eq 'Exception' or
3797     $node->local_name eq 'Warning') {
3798     $result .= exception2perl $node;
3799     } elsif ($node->local_name eq 'DataType') {
3800     $result .= datatype2perl $node;
3801     } elsif ($node->local_name eq 'DataTypeAlias') {
3802     $result .= datatypealias2perl $node;
3803     } elsif ($node->local_name eq 'ConstGroup') {
3804     $result .= constgroup2perl $node;
3805     } elsif ($node->local_name eq 'Const') {
3806     $result .= const2perl $node;
3807     } elsif ({qw/Module 1 Namespace 1 ImplNote 1/}->{$node->local_name}) {
3808     #
3809     } else {
3810     valid_warn qq{Top-level element type "@{[$node->local_name]}" not supported};
3811     }
3812     }
3813    
3814     ## Export
3815     if (keys %{$Status->{EXPORT_OK}||{}}) {
3816     $result .= perl_package full_name => $Info->{Package};
3817     $result .= perl_statement 'require Exporter';
3818     $result .= perl_inherit ['Exporter'];
3819     $result .= perl_statement
3820     perl_assign
3821     perl_var (type => '@', scope => 'our',
3822     local_name => 'EXPORT_OK')
3823     => '(' . perl_list (keys %{$Status->{EXPORT_OK}}) . ')';
3824     if (keys %{$Status->{EXPORT_TAGS}||{}}) {
3825     $result .= perl_statement
3826     perl_assign
3827     perl_var (type => '%', scope => 'our',
3828     local_name => 'EXPORT_TAGS')
3829     => '(' . perl_list (map {
3830     $_ => [keys %{$Status->{EXPORT_TAGS}->{$_}}]
3831     } keys %{$Status->{EXPORT_TAGS}}) . ')';
3832     }
3833     }
3834    
3835     ## Feature
3836     my @feature_desc;
3837     my $features = 0;
3838     for my $condition (sort keys %{$Info->{Condition}}, '') {
3839     for my $Feature (@{$Module->child_nodes}) {
3840     next unless $Feature->node_type eq '#element' and
3841     $Feature->local_name eq 'Feature' and
3842     condition_match $Feature, condition => $condition;
3843     is_all_implemented condition => $condition,
3844     not_implemented => (my $not_implemented = []);
3845    
3846     my $f_name = $Feature->get_attribute_value ('Name', default => '');
3847     unless (length $f_name) {
3848     $f_name = expanded_uri $Feature->get_attribute_value ('QName');
3849     }
3850     my $f_ver = $Feature->get_attribute_value ('Version');
3851    
3852     push @feature_desc, pod_item ('Feature ' . pod_code ($f_name) .
3853     ' version ' . pod_code ($f_ver) .
3854     ($Info->{Condition}->{$condition}->{FullName} ?
3855     ' [' . $Info->{Condition}->{$condition}
3856     ->{FullName} . ']' : '')),
3857     pod_paras (get_description $Feature);
3858    
3859     if (@$not_implemented) {
3860     push @feature_desc, pod_para ('This module provides interfaces '.
3861     'of this feature but not yet fully ' .
3862     'implemented.');
3863     $result .= perl_comment "$f_name, $f_ver: $not_implemented->[0]." .
3864     "$not_implemented->[1]<$not_implemented->[2]>" .
3865     " not implemented.";
3866     } else {
3867     push @feature_desc, pod_para ('This module implements this feature, ' .
3868     'so that the method calls such as ' .
3869     pod_code ('$DOMImplementation' .
3870     '->hasFeature (' .
3871     perl_literal ($f_name) .
3872     ', ' . perl_literal ($f_ver) .
3873     ')') . ' or ' .
3874     pod_code ('$DOMImplementation' .
3875     '->hasFeature (' .
3876     perl_literal ($f_name) .
3877     ', null)') .
3878     ' will return ' . pod_code ('true') . '.');
3879     }
3880    
3881     for (@{$Feature->child_nodes}) {
3882     next unless $_->node_type eq '#element';
3883     if ($_->local_name eq 'Contrib') {
3884     my $n = $_->value;
3885     my $ccondition;
3886     if ($n =~ s/::([^:]*)$//) {
3887     $ccondition = $1;
3888     }
3889     if ($n =~ s/^[^:]*://) {
3890     # currently prefix is not used
3891     }
3892     $result .= perl_statement
3893     perl_assign
3894     perl_var (type => '$',
3895     package => {
3896     name => $n,
3897     condition => $ccondition,
3898     is_internal => 1,
3899     },
3900     local_name => 'Feature').
3901     ## Feature name is case-insensitive
3902     '->{'.perl_literal (lc $f_name).'}->{'.
3903     perl_literal (@$not_implemented ? '+dummy+' : $f_ver) . '}'
3904     => 1;
3905     } elsif ({
3906     qw/Name 1 QName 1 FullName 1 Version 1
3907     Description 1 ImplNote 1 Spec 1
3908     Condition 1 /
3909     }->{$_->local_name}) {
3910     } else {
3911     valid_err q<Unknown element type>, node => $_;
3912     }
3913     }
3914    
3915     $features++;
3916     }
3917     }
3918     if (@feature_desc) {
3919     $result .= pod_block
3920     pod_head (1, 'DOM FEATURE'.($features>1?'S':'')),
3921     pod_list 4, @feature_desc;
3922     }
3923    
3924     ## TODO list
3925     my @todo;
3926     ## From not-implemented list
3927     for my $if (sort keys %{$Info->{is_implemented}}) {
3928     for my $mem (sort keys %{$Info->{is_implemented}->{$if}}) {
3929     for my $cond (sort keys %{$Info->{is_implemented}->{$if}->{$mem}}) {
3930     if (not $Info->{is_implemented}->{$if}->{$mem}->{$cond}) {
3931     push @todo, pod_item ('Implement '.pod_code ($if).'.'.
3932     pod_code ($mem).'.'),
3933     pod_para ('Condition = '.
3934     ($Info->{Condition}->{$cond}->{FullName} ||
3935     '(empty)'));
3936     }
3937     }
3938     }
3939     }
3940     ## From Description, ImplNote, Def
3941     my $a;
3942     $a = sub {
3943     my $n = shift;
3944     for (@{$n->child_nodes}) {
3945     if ($_->node_type eq '#element') {
3946     $a->($_);
3947     }
3948     }
3949     if (($n->node_type eq '#element' and
3950     {qw/Description 1 ImplNote 1
3951     Def 1 IntDef 1/}->{$n->local_name}) or
3952     $n->node_type eq '#comment') {
3953     my $v = $n->value;
3954     if (defined $v) {
3955     if (ref $v eq 'ARRAY') {
3956     $v = join "\n", @$v;
3957     }
3958     if ($v =~ /\b(TODO|ISSUE|BUG):/) {
3959     push @todo, pod_item ($1.': '.pod_code $n->node_path(key => 'Name'));
3960     my $t = $n->node_type eq '#comment' ? ExpandedURI q<DOMMain:any> :
3961     $n->get_attribute_value
3962     ('Type',
3963     default => {
3964     Description => ExpandedURI q<lang:disdoc>,
3965     ImplNote => ExpandedURI q<lang:disdoc>,
3966     Def => ExpandedURI q<DOMMain:any>,
3967     IntDef => ExpandedURI q<DOMMain:any>,
3968     }->{$n->local_name});
3969     if ($t eq ExpandedURI q<lang:disdoc>) {
3970     push @todo, disdoc2pod $v;
3971     } else {
3972     push @todo, pod_pre ($v);
3973     }
3974     }
3975     }
3976     }
3977     };
3978     $a->($source);
3979     if (@todo) {
3980     $result .= pod_block
3981     pod_head (1, 'TO DO'),
3982     pod_list 4, @todo;
3983     }
3984    
3985    
3986     ## Namespace bindings for documentation
3987     if (my $n = keys %{$Status->{ns_in_doc}}) {
3988     my @desc = (pod_head (1, 'NAMESPACE BINDING'.($n > 1 ? 'S' : '')),
3989     pod_para ('In this documentation, namespace prefix'.
3990     ($n > 1 ? 'es ' : ' ').
3991     ($n > 1 ? 'are' : 'is').' bound to:'));
3992     push @desc,
3993     pod_list 4, map {
3994     pod_item (pod_code $_),
3995     pod_para (pod_code ($Status->{ns_in_doc}->{$_})),
3996     } keys %{$Status->{ns_in_doc}};
3997     $result .= pod_block @desc;
3998     }
3999    
4000     ## See also
4001     ## TODO: implement this.
4002    
4003     ## Author
4004     my @desc;
4005     my @author;
4006     my $author;
4007     my $authors = 0;
4008     for (@{$Module->child_nodes}) {
4009     if ($_->node_type eq '#element' and $_->local_name eq 'Author') {
4010     my $n = get_description ($_, name => 'FullName');
4011     push @author, pod_item $n;
4012     my @d;
4013     $author = defined $author ? $authors ? $author
4014     : ($authors++, $author . ', et al.')
4015     : $n;
4016     for (@{$_->child_nodes}) {
4017     next unless $_->node_type eq '#element';
4018     if ($_->local_name eq 'Mail') {
4019     push @d, pod_item ('Mail'), pod_para (pod_mail $_->value);
4020     } elsif ({qw/FullName 1/}->{$_->local_name}) {
4021     #
4022     } else {
4023     valid_err q<Unknown element type>, node => $_;
4024     }
4025     }
4026     push @author, pod_list 6, @d if @d;
4027     }
4028     }
4029     $author = 'AUTHORS' unless defined $author;
4030     if (@author) {
4031     push @desc, pod_head (1, 'AUTHOR'.($authors?'S':'')),
4032     pod_list (4, @author);
4033     }
4034    
4035     ## License
4036     push @desc, pod_head (1, 'LICENSE');
4037     my $year = (gmtime)[5]+1900;
4038     my $license = expanded_uri
4039     $Module->get_attribute_value ('License', default => '');
4040     if ($license eq ExpandedURI q<license:Perl>) {
4041     push @desc,
4042     pod_para (qq<Copyright $year $author. All rights reserved.>),
4043     pod_para q<This program is free software; you can redistribute it and/or
4044     modify it under the same terms as Perl itself.>;
4045     } elsif ($license eq ExpandedURI q<license:Perl+MPL>) {
4046     push @desc,
4047     pod_para (qq<Copyright $year $author. All rights reserved.>),
4048     pod_para (q<This program is free software; you can redistribute it and/or >.
4049     q<modify it under the same terms as Perl itself.>),
4050    
4051     pod_para (q<Alternatively, the contents of this file may be used >.
4052     q<under the following terms (the >.pod_dfn (q<MPL/GPL/LGPL>).
4053     q<, in which case the provisions of the MPL/GPL/LGPL are applicable instead >.
4054     q<of those above. If you wish to allow use of your version of this file only >.
4055     q<under the terms of the MPL/GPL/LGPL, and not to allow others to >.
4056     q<use your version of this file under the terms of the Perl, indicate your >.
4057     q<decision by deleting the provisions above and replace them with the notice >.
4058     q<and other provisions required by the MPL/GPL/LGPL. If you do not delete >.
4059     q<the provisions above, a recipient may use your version of this file under >.
4060     q<the terms of any one of the Perl or the MPL/GPL/LGPL. >),
4061    
4062     pod_head (2, 'MPL/GPL/LGPL'),
4063    
4064     # q<***** BEGIN LICENSE BLOCK *****>
4065     pod_para (q<Version: MPL 1.1/GPL 2.0/LGPL 2.1>),
4066    
4067     pod_para
4068     (q<The contents of this file are subject to the Mozilla Public License Version >.
4069     q<1.1 (the >.pod_dfn (q<License>).q<); you may not use this file except in >.
4070     q<compliance with >.
4071     q<the License. You may obtain a copy of the License at >.
4072     pod_uri (q<http://www.mozilla.org/MPL/>).q<.>),
4073    
4074     pod_para
4075     (q<Software distributed under the License is distributed on an ">.
4076     pod_em (q<AS IS>).q<" basis, >.
4077     pod_em (q<WITHOUT WARRANTY OF ANY KIND>).
4078     q<, either express or implied. See the License >.
4079     q<for the specific language governing rights and limitations under the >.
4080     q<License. >);
4081    
4082     my $orig = $Module->get_attribute ('License')->get_attribute ('Original');
4083     if ($orig) {
4084     push @desc, pod_para ('The Original Code is the '.
4085     get_description ($orig, name => 'FullName').'.');
4086     push @desc, pod_para ('The Initial Developer of the Original Code is '.
4087     get_description ($orig->get_attribute ('Author'),
4088     name => 'FullName').'. '.
4089     q<Portions created by the Initial Developer are >.
4090     q<Copyright >.pod_char (name => 'copy').' '.
4091     $orig->get_attribute_value ('Year',
4092     default => $year).
4093     q< the Initial Developer. All Rights Reserved.>);
4094     } else {
4095     my $a = $author;
4096     $a =~ /, et al\.$/ if $authors;
4097    
4098     push @desc, pod_para
4099     (q<The Original Code is the manakai DOM module.>),
4100    
4101     pod_para (qq<The Initial Developer of the Original Code is $a. >.
4102     q<Portions created by the Initial Developer are Copyright >.
4103     pod_char (name => 'copy').qq< $year >.
4104     ## ISSUE: Should first created year provided from some source?
4105     q<the Initial Developer. All Rights Reserved.>);
4106     }
4107    
4108     push @desc, pod_list 4,
4109     pod_item (q<Contributor(s):>),
4110     pod_para (q<See >.
4111     pod_link (section => 'AUTHOR'.($authors?'S':'')).
4112     q<.>);
4113    
4114     push @desc, pod_para
4115     q<Alternatively, the contents of this file may be used under the terms of >.
4116     q<either the GNU General Public License Version 2 or later (the ">.
4117     pod_dfn (q<GPL>).q<"), or >.
4118     q<the GNU Lesser General Public License Version 2.1 or later (the ">.
4119     pod_dfn (q<LGPL>).q<"), >.
4120     q<in which case the provisions of the GPL or the LGPL are applicable instead >.
4121     q<of those above. If you wish to allow use of your version of this file only >.
4122     q<under the terms of either the GPL or the LGPL, and not to allow others to >.
4123     q<use your version of this file under the terms of the MPL, indicate your >.
4124     q<decision by deleting the provisions above and replace them with the notice >.
4125     q<and other provisions required by the GPL or the LGPL. If you do not delete >.
4126     q<the provisions above, a recipient may use your version of this file under >.
4127     q<the terms of any one of the MPL, the GPL or the LGPL. >;
4128    
4129     # ***** END LICENSE BLOCK *****
4130     } elsif ($license) {
4131     valid_warn q<Unknown license: <$license>>;
4132     push @desc,
4133     pod_para (qq<Copyright $year $author. All rights reserved.>),
4134     pod_para (qq<License: >.pod_uri ($license).q<.>);
4135     } else {
4136     valid_err q<Required attribute "/Module/License" not specified>;
4137     }
4138     $result .= pod_block @desc;
4139    
4140    
4141     $result .= perl_statement 1;
4142    
4143     output_result $result;
4144    
4145    
4146     __END__
4147    
4148     =head1 SEE ALSO
4149    
4150     W3C DOM Specifications <http://www.w3.org/DOM/DOMTR>
4151    
4152     SuikaWiki:DOM <http://suika.fam.cx/~wakaba/-temp/wiki/wiki?DOM>
4153    
4154     C<idl2dis.pl>: This script generates "dis" files,
4155     that can be used as a template for the DOM implementation,
4156     from DOM IDL files.
4157    
4158     =head1 LICENSE
4159    
4160     Copyright 2004 Wakaba <w@suika.fam.cx>. All rights reserved.
4161    
4162     This program is free software; you can redistribute it and/or
4163     modify it under the same terms as Perl itself.
4164    
4165     Note that copyright holder(s) of this script does not claim
4166     any rights for materials outputed by this script, although it will
4167     contain some fragments from this script. License terms for them should be
4168     defined by the copyright holder of the source document.
4169    
4170     =cut
4171    
4172 wakaba 1.2 # $Date: 2004/10/10 00:01:08 $
4173 wakaba 1.1
4174    

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24