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 |
|