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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations) (download)
Sat Oct 16 13:34:55 2004 UTC (20 years, 1 month ago) by wakaba
Branch: MAIN
Changes since 1.2: +105 -24 lines
File MIME type: text/plain
New DISDOC elements introduced

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24