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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations) (download)
Sun Apr 9 14:29:41 2006 UTC (19 years, 2 months ago) by wakaba
Branch: MAIN
CVS Tags: manakai-release-0-3-1
Changes since 1.11: +14 -13 lines
File MIME type: text/plain
++ manakai/bin/ChangeLog	9 Apr 2006 14:25:10 -0000
2006-04-09  Wakaba  <wakaba@suika.fam.cx>

	* daf.pl (daf_generate_perl_test): Old |PerlCode| methods
	are replaced by new ones.

++ manakai/lib/Message/Util/DIS/ChangeLog	9 Apr 2006 14:29:02 -0000
2006-04-09  Wakaba  <wakaba@suika.fam.cx>

	* Perl.dis (plAppendThrow): Use key for exception parameters.

++ manakai/lib/Message/DOM/ChangeLog	9 Apr 2006 14:28:28 -0000
2006-04-09  Wakaba  <wakaba@suika.fam.cx>

	* XMLParser.dis (Require): Requires the |MCharset:Encode|
	module.
	(parse): Set the |inputEncoding| attribute of the generated document
	object.
	(resolveLSInput default implementation): The |byteStream|
	and |encoding| attributes of the |LSInput| interface
	are now supported.
	(resolveLSInput): Parameters |impl| and |parser| are added.
	(InputFile.inputEncoding): New attribute.

++ manakai/lib/Message/Charset/ChangeLog	9 Apr 2006 14:25:44 -0000
2006-04-09  Wakaba  <wakaba@suika.fam.cx>

	* Encode.dis (close): New method.

1 #!/usr/bin/perl -w
2 use strict;
3 use Message::Util::QName::Filter {
4 c => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/dom-core#>,
5 DIS => q<http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/DIS#>,
6 dis => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#dis-->,
7 DOMLS => q<http://suika.fam.cx/~wakaba/archive/2004/dom/ls#>,
8 dp => q<http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/DIS#Perl/>,
9 fe => q<http://suika.fam.cx/www/2006/feature/>,
10 ManakaiDOM => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/manakai-dom#>,
11 pc => q<http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/PerlCode#>,
12 swcfg21 => q<http://suika.fam.cx/~wakaba/archive/2005/swcfg21#>,
13 test => q<http://suika.fam.cx/~wakaba/archive/2004/dis/Test#>,
14 Util => q<http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/>,
15 xp => q<http://suika.fam.cx/~wakaba/archive/2004/dom/xml-parser#>,
16 };
17
18 use Cwd;
19 use Getopt::Long;
20 use Pod::Usage;
21 my %Opt = (create_module => []);
22 GetOptions (
23 'create-perl-module=s' => sub {
24 shift;
25 my $i = [split /\s+/, shift, 3];
26 $i->[3] = 'perl-pm';
27 push @{$Opt{create_module}}, $i;
28 },
29 'create-perl-test=s' => sub {
30 shift;
31 my $i = [split /\s+/, shift, 3];
32 $i->[3] = 'perl-t';
33 push @{$Opt{create_module}}, $i;
34 },
35 'debug' => \$Opt{debug},
36 'dis-file-suffix=s' => \$Opt{dis_suffix},
37 'daem-file-suffix=s' => \$Opt{daem_suffix},
38 'dafs-file-suffix=s' => \$Opt{dafs_suffix},
39 'dafx-file-suffix=s' => \$Opt{dafx_suffix},
40 'help' => \$Opt{help},
41 'search-path|I=s' => sub {
42 shift;
43 my @value = split /\s+/, shift;
44 while (my ($ns, $path) = splice @value, 0, 2, ()) {
45 unless (defined $path) {
46 die qq[$0: Search-path parameter without path: "$ns"];
47 }
48 push @{$Opt{input_search_path}->{$ns} ||= []}, $path;
49 }
50 },
51 'search-path-catalog-file-name=s' => sub {
52 shift;
53 require File::Spec;
54 my $path = my $path_base = shift;
55 $path_base =~ s#[^/]+$##;
56 $Opt{search_path_base} = $path_base;
57 open my $file, '<', $path or die "$0: $path: $!";
58 while (<$file>) {
59 if (s/^\s*\@//) { ## Processing instruction
60 my ($target, $data) = split /\s+/;
61 if ($target eq 'base') {
62 $Opt{search_path_base} = File::Spec->rel2abs ($data, $path_base);
63 } else {
64 die "$0: $target: Unknown target";
65 }
66 } elsif (/^\s*\#/) { ## Comment
67 #
68 } elsif (/\S/) { ## Catalog entry
69 s/^\s+//;
70 my ($ns, $path) = split /\s+/;
71 push @{$Opt{input_search_path}->{$ns} ||= []},
72 File::Spec->rel2abs ($path, $Opt{search_path_base});
73 }
74 }
75 ## NOTE: File paths with SPACEs are not supported
76 ## NOTE: Future version might use file: URI instead of file path.
77 },
78 'undef-check!' => \$Opt{no_undef_check},
79 'verbose!' => \$Opt{verbose},
80 ) or pod2usage (2);
81 pod2usage ({-exitval => 0, -verbose => 1}) if $Opt{help};
82 $Opt{no_undef_check} = defined $Opt{no_undef_check}
83 ? $Opt{no_undef_check} ? 0 : 1 : 0;
84 $Opt{dis_suffix} = '.dis' unless defined $Opt{dis_suffix};
85 $Opt{daem_suffix} = '.dafm' unless defined $Opt{daem_suffix};
86 $Opt{dafx_suffix} = '.dafx' unless defined $Opt{dafx_suffix};
87 $Opt{dafs_suffix} = '.dafs' unless defined $Opt{dafs_suffix};
88 $Message::DOM::DOMFeature::DEBUG = 1 if $Opt{debug};
89 require Error;
90 $Error::Debug = 1 if $Opt{debug};
91 $Message::Util::Error::VERBOSE = 1 if $Opt{verbose};
92
93 sub status_msg ($) {
94 my $s = shift;
95 $s .= "\n" unless $s =~ /\n$/;
96 print STDERR $s;
97 }
98
99 sub status_msg_ ($) {
100 my $s = shift;
101 print STDERR $s;
102 }
103
104 sub verbose_msg ($) {
105 my $s = shift;
106 $s .= "\n" unless $s =~ /\n$/;
107 print STDERR $s if $Opt{verbose};
108 }
109
110 sub verbose_msg_ ($) {
111 my $s = shift;
112 print STDERR $s if $Opt{verbose};
113 }
114
115 ## ---- The MAIN Program
116
117 my $start_time;
118 BEGIN { $start_time = time }
119
120 use Message::Util::DIS::DNLite;
121 use Message::Util::PerlCode;
122
123 my %feature;
124 eval q{
125 use Message::Util::DIS::Test;
126 use Message::DOM::GenericLS;
127 $feature{ExpandedURI q<fe:GenericLS>} = '3.0';
128 $feature{'+' . ExpandedURI q<DIS:TDT>} = '1.0';
129 };
130
131 my $limpl = $Message::DOM::ImplementationRegistry->get_implementation
132 ({ExpandedURI q<fe:Min> => '3.0',
133 '+' . ExpandedURI q<DIS:DNLite> => '1.0',
134 '+' . ExpandedURI q<DIS:Core> => '1.0',
135 '+' . ExpandedURI q<Util:PerlCode> => '1.0',
136 %feature,
137 });
138 my $impl = $limpl->get_feature (ExpandedURI q<DIS:Core> => '1.0');
139 my $tdt_parser;
140
141 ## --- Loading and Updating the Database
142
143 my $HasError;
144 my $db = $impl->create_dis_database;
145 $db->pl_database_module_resolver (\&daf_db_module_resolver);
146 $db->dom_config->set_parameter ('error-handler' => \&daf_on_error);
147
148 my $parser = $impl->create_dis_parser;
149 my $DNi = $impl->get_feature (ExpandedURI q<DIS:DNLite> => '1.0');
150 my %ModuleSourceDISDocument;
151 my %ModuleSourceDNLDocument;
152 my %ModuleNameNamespaceBinding = (
153 DISCore => q<http://suika.fam.cx/~wakaba/archive/2004/dis/Core#>,
154 ## This builtin binding is required since
155 ## some module has |DISCore:author| property before |dis:Require|
156 ## property.
157 );
158
159 my @target_modules;
160 for (@{$Opt{create_module}}) {
161 my ($mod_uri, $out_path, $mod_for, $out_type) = @$_;
162 push @target_modules, [$mod_uri, $mod_for];
163 }
164
165 my $ResourceCount = 0;
166 $db->pl_update_module (\@target_modules,
167 get_module_index_file_name => sub {
168 shift; # $db
169 daf_get_module_index_file_name (@_);
170 },
171 get_module_source_document_from_uri => sub {
172 my ($db, $module_uri, $module_for) = @_;
173 status_msg '';
174 status_msg qq<Loading module <$module_uri> for <$module_for>...>;
175 $ResourceCount = 0;
176
177 unless (defined $ModuleSourceDNLDocument{$module_uri}) {
178 unless (defined $ModuleSourceDISDocument{$module_uri}) {
179 daf_open_source_dis_document ($module_uri);
180 }
181 daf_convert_dis_document_to_dnl_document ();
182 }
183 return $ModuleSourceDNLDocument{$module_uri};
184 },
185 get_module_source_document_from_resource => sub ($$$$$$) {
186 my ($self, $db, $uri, $ns, $ln, $for) = @_;
187 status_msg '';
188 status_msg qq<Loading module "$ln" for <$for>...>;
189 $ResourceCount = 0;
190
191 my $module_uri = $ns.$ln;
192 unless (defined $ModuleSourceDNLDocument{$module_uri}) {
193 unless (defined $ModuleSourceDISDocument{$module_uri}) {
194 daf_open_source_dis_document ($module_uri);
195 }
196 daf_convert_dis_document_to_dnl_document ();
197 }
198 return $ModuleSourceDNLDocument{$module_uri};
199 },
200 get_module_source_revision => sub {
201 my ($db, $module_uri) = @_;
202 my $ns = $module_uri;
203 $ns =~ s/(\w+)\z//;
204 my $ln = $1;
205
206 my $name = dac_search_file_path_stem ($ns, $ln, $Opt{dis_suffix});
207 if (defined $name) {
208 return [stat $name.$Opt{dis_suffix}]->[9];
209 } else {
210 return 0;
211 }
212 },
213 get_referring_module_uri_list => sub {
214 my ($db, $module_uri) = @_;
215 unless (defined $ModuleSourceDNLDocument{$module_uri}) {
216 unless (defined $ModuleSourceDISDocument{$module_uri}) {
217 daf_open_source_dis_document ($module_uri);
218 }
219 }
220 return daf_get_referring_module_uri_list ($module_uri);
221 },
222 on_resource_read => sub ($$) {
223 if ((++$ResourceCount % 10) == 0) {
224 status_msg_ "*";
225 status_msg_ " " if ($ResourceCount % (10 * 10)) == 0;
226 status_msg '' if ($ResourceCount % (10 * 50)) == 0;
227 }
228 });
229
230
231 ## Removes reference from document to database
232 our @Document;
233 for my $dis (@Document) {
234 $dis->unlink_from_document;
235 $dis->dis_database (undef);
236 }
237
238 status_msg '';
239
240 status_msg qq<Reading properties...>;
241 $ResourceCount = 0;
242 $db->read_properties (on_resource_read => sub ($$) {
243 if ((++$ResourceCount % 10) == 0) {
244 status_msg_ "*";
245 status_msg_ " " if ($ResourceCount % (10 * 10)) == 0;
246 status_msg '' if ($ResourceCount % (10 * 50)) == 0;
247 }
248 });
249 status_msg '';
250 status_msg "done";
251
252 status_msg_ qq<Writing database files...>;
253 $db->pl_store ('dummy', sub ($$) {
254 my ($db, $mod, $type) = @_;
255 my $ns = $mod->namespace_uri;
256 my $ln = $mod->local_name;
257 my $suffix = $type eq ExpandedURI q<dp:ModuleIndexFile>
258 ? $Opt{dafx_suffix} : $Opt{daem_suffix};
259 my $name = dac_search_file_path_stem ($ns, $ln, $suffix);
260 if (defined $name) {
261 $name .= $suffix;
262 } elsif (defined ($name = dac_search_file_path_stem
263 ($ns, $ln, $Opt{dis_suffix}))) {
264 $name .= $suffix;
265 } else {
266 $name = Cwd::abs_path
267 (File::Spec->canonpath
268 (File::Spec->catfile
269 (defined $Opt{input_search_path}->{$ns}->[0]
270 ? $Opt{input_search_path}->{$ns}->[0] : '.',
271 $ln.$suffix)));
272 }
273 verbose_msg qq<Database >.
274 ($type eq <Q::dp|ModuleIndexFile> ? 'index' : 'module').
275 qq< <$ns$ln> is written to "$name">;
276 return $name;
277 }, no_main_database => 1);
278 status_msg "done";
279
280 daf_check_undefined ();
281
282 undef $DNi;
283 undef %ModuleSourceDNLDocument;
284 exit $HasError if $HasError;
285
286 ## --- Creating Files
287
288 for (@{$Opt{create_module}}) {
289 my ($mod_uri, $out_file_path, $mod_for, $out_type) = @$_;
290 unless (defined $mod_for) {
291 $mod_for = $db->get_module ($mod_uri)
292 ->get_property_text (ExpandedURI q<dis:DefaultFor>,
293 ExpandedURI q<ManakaiDOM:all>);
294 }
295 my $mod = $db->get_module ($mod_uri, for_arg => $mod_for);
296
297 if ($out_type eq 'perl-pm') {
298 status_msg_ qq<Generating Perl module from <$mod_uri> for <$mod_for>...>;
299 local $Message::Util::DIS::Perl::Implementation
300 = $impl->get_feature (ExpandedURI q<Util:PerlCode> => '1.0');
301 my $pl = $mod->pl_generate_perl_module_file
302 ($impl->get_feature (ExpandedURI q<Util:PerlCode> => '1.0'));
303 status_msg qq<done>;
304
305 my $output;
306 defined $out_file_path
307 ? (open $output, '>', $out_file_path or die "$0: $out_file_path: $!")
308 : ($output = \*STDOUT);
309
310 status_msg_ sprintf qq<Writing Perl module %s...>,
311 defined $out_file_path
312 ? q<">.$out_file_path.q<">
313 : 'to stdout';
314 print $output $pl->stringify;
315 close $output;
316 status_msg q<done>;
317 } elsif ($out_type eq 'perl-t') {
318 status_msg_ qq<Generating Perl test from <$mod_uri> for <$mod_for>...>;
319 my $pl = daf_generate_perl_test_file ($mod);
320 status_msg qq<done>;
321
322 my $cfg = $pl->owner_document->dom_config;
323 $cfg->set_parameter (ExpandedURI q<pc:preserve-line-break> => 1);
324
325 my $output;
326 defined $out_file_path
327 ? (open $output, '>', $out_file_path or die "$0: $out_file_path: $!")
328 : ($output = \*STDOUT);
329
330 status_msg_ sprintf qq<Writing Perl test %s...>,
331 defined $out_file_path
332 ? q<">.$out_file_path.q<">
333 : 'to stdout';
334 print $output $pl->stringify;
335 close $output;
336 status_msg q<done>;
337 }
338 }
339
340 daf_check_undefined ();
341
342 ## --- The END
343
344 status_msg_ "Closing the database...";
345 $db->free;
346 undef $db;
347 status_msg "done";
348
349 undef $limpl;
350 undef $impl;
351
352 {
353 use integer;
354 my $time = time - $start_time;
355 status_msg sprintf qq<%d'%02d''>, $time / 60, $time % 60;
356 }
357 exit $HasError;
358
359 END {
360 $db->free if $db;
361 }
362
363 ## ---- Subroutines
364
365 sub daf_open_source_dis_document ($) {
366 my ($module_uri) = @_;
367
368 ## -- Finds |dis| source file
369 my $ns = $module_uri;
370 $ns =~ s/(\w+)\z//;
371 my $ln = $1;
372 my $file_name = dac_search_file_path_stem ($ns, $ln, $Opt{dis_suffix});
373 unless (defined $file_name) {
374 die "$0: Source file for <$ns$ln> is not found";
375 }
376 $file_name .= $Opt{dis_suffix};
377
378 status_msg_ qq<Opening dis source file "$file_name"...>;
379
380 ## -- Opens |dis| file and construct |DISDocument| tree
381 open my $file, '<', $file_name or die "$0: $file_name: $!";
382 my $dis = $parser->parse ({character_stream => $file});
383 require File::Spec;
384 $dis->flag (ExpandedURI q<swcfg21:fileName> =>
385 File::Spec->abs2rel ($file_name));
386 $dis->dis_namespace_resolver (\&daf_module_name_namespace_resolver);
387 close $file;
388
389 ## -- Registers namespace URI
390 my $mod = $dis->module_element;
391 if ($mod) {
392 my $qn = $mod->get_attribute_ns (ExpandedURI q<dis:>, 'QName');
393 if ($qn) {
394 my $prefix = $qn->value;
395 $prefix =~ s/^[^:|]*[:|]\s*//;
396 $prefix =~ s/\s+$//;
397 unless (defined $ModuleNameNamespaceBinding{$prefix}) {
398 $ModuleNameNamespaceBinding{$prefix} = $mod->defining_namespace_uri;
399 }
400 }
401 }
402
403 $ModuleSourceDISDocument{$module_uri} = $dis;
404 status_msg q<done>;
405
406 R: for (@{daf_get_referring_module_uri_list ($module_uri)}) {
407 next R if defined $db->{modDef}->{$_};
408 next R if defined $ModuleSourceDNLDocument{$_};
409 next R if defined $ModuleSourceDISDocument{$_};
410 my $idx_file_name = daf_get_module_index_file_name ($_);
411 if (-f $idx_file_name) {
412 daf_open_current_module_index ($_, $idx_file_name);
413 } else {
414 daf_open_source_dis_document ($_);
415 }
416 }
417 } # daf_open_source_dis_document
418
419 sub daf_open_current_module_index ($$) {
420 my ($module_uri, $file_name) = @_;
421 $db->pl_load_dis_database_index ($file_name);
422
423 R: for (@{$db->get_module ($module_uri)
424 ->get_referring_module_uri_list}) {
425 next R if defined $db->{modDef}->{$_};
426 next R if defined $ModuleSourceDNLDocument{$_};
427 next R if defined $ModuleSourceDISDocument{$_};
428 my $idx_file_name = daf_get_module_index_file_name ($_);
429 if (-f $idx_file_name) {
430 daf_open_current_module_index ($_, $idx_file_name);
431 } else {
432 daf_open_source_dis_document ($_);
433 }
434 }
435 } # daf_open_current_module_index
436
437 sub daf_convert_dis_document_to_dnl_document () {
438 M: for my $module_uri (keys %ModuleSourceDISDocument) {
439 my $dis_doc = $ModuleSourceDISDocument{$module_uri};
440 next M unless $dis_doc;
441 verbose_msg_ qq<Converting <$module_uri>...>;
442 my $dnl_doc = $DNi->convert_dis_document_to_dnl_document
443 ($dis_doc, database_arg => $db,
444 base_namespace_binding =>
445 {(map {$_->local_name => $_->target_namespace_uri}
446 grep {$_} values %{$db->{modDef}}),
447 %ModuleNameNamespaceBinding});
448 push @Document, $dnl_doc;
449 $ModuleSourceDNLDocument{$module_uri} = $dnl_doc;
450 $dis_doc->free;
451 delete $ModuleSourceDISDocument{$module_uri};
452 verbose_msg q<done>;
453 }
454 } # daf_convert_dis_document_to_dnl_document
455
456 sub daf_get_referring_module_uri_list ($) {
457 my $module_uri = shift;
458 my $ns = $module_uri;
459 $ns =~ s/\w+\z//;
460 my $src = $ModuleSourceDNLDocument{$module_uri};
461 $src = $ModuleSourceDISDocument{$module_uri} unless defined $src;
462 my $mod_el = $src->module_element;
463 my $r = [];
464 if ($mod_el) {
465 my $req_el = $mod_el->require_element;
466 if ($req_el) {
467 M: for my $m_el (@{$req_el->child_nodes}) {
468 next M unless $m_el->node_type eq '#element';
469 next M unless $m_el->expanded_uri eq ExpandedURI q<dis:Module>;
470 my $qn_el = $m_el->get_attribute_ns (ExpandedURI q<dis:>, 'QName');
471 if ($qn_el) {
472 push @$r, $qn_el->qname_value_uri;
473 } else {
474 my $n_el = $m_el->get_attribute_ns (ExpandedURI q<dis:>, 'Name');
475 if ($n_el) {
476 push @$r, $ns.$n_el->value;
477 } else {
478 # The module itself
479 }
480 }
481 }
482 }
483 }
484 return $r;
485 } # daf_get_referring_module_uri_list
486
487 sub dac_search_file_path_stem ($$$) {
488 my ($ns, $ln, $suffix) = @_;
489 require File::Spec;
490 for my $dir (@{$Opt{input_search_path}->{$ns}||[]}) {
491 my $name = Cwd::abs_path
492 (File::Spec->canonpath
493 (File::Spec->catfile ($dir, $ln)));
494 if (-f $name.$suffix) {
495 return $name;
496 }
497 }
498 return undef;
499 } # dac_search_file_path_stem;
500
501 sub daf_get_module_index_file_name ($$) {
502 my ($module_uri) = @_;
503 my $ns = $module_uri;
504 $ns =~ s/(\w+)\z//;
505 my $ln = $1;
506
507 verbose_msg qq<Database module index <$module_uri> is requested>;
508 my $suffix = $Opt{dafx_suffix};
509 my $name = dac_search_file_path_stem ($ns, $ln, $suffix);
510 if (defined $name) {
511 $name .= $suffix;
512 } elsif (defined ($name = dac_search_file_path_stem
513 ($ns, $ln, $Opt{dis_suffix}))) {
514 $name .= $suffix;
515 } else {
516 $name = Cwd::abs_path
517 (File::Spec->canonpath
518 (File::Spec->catfile
519 (defined $Opt{input_search_path}->{$ns}->[0]
520 ? $Opt{input_search_path}->{$ns}->[0] : '.',
521 $ln.$suffix)));
522 }
523 return $name;
524 } # daf_get_module_index_file_name
525
526 sub daf_module_name_namespace_resolver ($) {
527 my $prefix = shift;
528
529 ## -- From modules in database
530 M: for (values %{$db->{modDef}}) {
531 my $mod = $_;
532 next M unless defined $mod;
533 if ($mod->local_name eq $prefix) {
534 return $mod->target_namespace_uri;
535 }
536 }
537
538 ## -- From not-in-database-yet module list
539 if (defined $ModuleNameNamespaceBinding{$prefix}) {
540 return $ModuleNameNamespaceBinding{$prefix};
541 }
542 return undef;
543 } # daf_module_name_namespace_resolver
544
545 sub daf_db_module_resolver ($$$) {
546 my ($db, $mod, $type) = @_;
547 my $ns = $mod->namespace_uri;
548 my $ln = $mod->local_name;
549 my $suffix = {
550 ExpandedURI q<dp:ModuleIndexFile> => $Opt{dafx_suffix},
551 ExpandedURI q<dp:ModuleResourceFile> => $Opt{daem_suffix},
552 ExpandedURI q<dp:ModuleNodeStorageFile> => $Opt{dafs_suffix},
553 }->{$type} or die "Unsupported type: <$type>";
554 verbose_msg qq<Database module <$ns$ln> is requested>;
555 my $name = dac_search_file_path_stem ($ns, $ln, $suffix);
556 if (defined $name) {
557 return $name.$suffix;
558 } else {
559 return undef;
560 }
561 } # daf_db_module_resolver
562
563 sub daf_on_error ($$) {
564 my ($self, $err) = @_;
565 if ($err->severity == $err->SEVERITY_WARNING) {
566 my $info = ExpandedURI q<dp:info>;
567 if ($err->type =~ /\Q$info\E/) {
568 my $msg = $err->text;
569 if ($msg =~ /\.\.\.\z/) {
570 verbose_msg_ $msg;
571 } else {
572 verbose_msg $msg;
573 }
574 } else {
575 my $msg = $err->text;
576 if ($msg =~ /\.\.\.\z/) {
577 status_msg_ $msg;
578 } else {
579 status_msg $msg;
580 }
581 }
582 } else {
583 warn $err;
584 $HasError = 1;
585 }
586 } # daf_on_error
587
588 sub daf_check_undefined () {
589 unless ($Opt{no_undef_check}) {
590 status_msg_ "Checking undefined resources...";
591 $db->check_undefined_resource;
592 print STDERR "done\n";
593 }
594 } # daf_check_undefined
595
596 sub daf_generate_perl_test_file ($) {
597 my $mod = shift;
598 my $pc = $impl->get_feature (ExpandedURI q<Util:PerlCode> => '1.0');
599 local $Message::Util::DIS::Perl::Implementation = $pc;
600 my $pl = $pc->create_pc_file;
601 my $factory = $pl->owner_document;
602 my $pack = $pl->get_last_package ("Manakai::Test", make_new_package => 1);
603 $pack->add_use_perl_module_name ("Message::Util::DIS::Test");
604 $pack->add_use_perl_module_name ("Message::Util::Error");
605 $pack->add_require_perl_module_name ($mod->pl_fully_qualified_name);
606
607 $pl->source_file ($mod->get_property_text (ExpandedURI q<DIS:sourceFile>, ""));
608 $pl->source_module ($mod->name_uri);
609 $pl->source_for ($mod->for_uri);
610 $pl->license_uri ($mod->get_property_resource (ExpandedURI q<dis:License>)
611 ->uri);
612
613 $pack->append_code ('
614 use Getopt::Long;
615 my %Skip;
616 GetOptions (
617 "Skip=s" => sub {
618 shift;
619 for (split /\s+/, shift) {
620 if (/^(\d+)-(\d+)$/) {
621 $Skip{$_} = 1 for $1..$2;
622 } else {
623 $Skip{$_} = 1;
624 }
625 }
626 },
627 );
628 ');
629
630 $pack->append_child ($factory->create_pc_statement)
631 ->append_code
632 ('my $impl = $Message::DOM::ImplementationRegistry
633 ->get_implementation ({
634 "http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/DIS#Test"
635 => "1.0",
636 })');
637
638 my $num_statement = $pack->append_child ($factory->create_pc_statement);
639 $num_statement->append_code ('my $test = $impl->create_test_manager');
640
641 my $total_tests = 0;
642 my %processed;
643 for my $res (@{$mod->get_resource_list}) {
644 next if $res->owner_module ne $mod or $processed{$res->uri};
645 $processed{$res->uri} = 1;
646
647 if ($res->is_type_uri (ExpandedURI q<test:Test>)) {
648 if ($res->is_type_uri (ExpandedURI q<test:StandaloneTest>)) {
649 my $test_num = ++$total_tests;
650 my $test_uri = $res->name_uri || $res->uri;
651
652 $pack->append_code ('$test->start_new_test (');
653 $pack->append_new_pc_literal ($test_uri);
654 $pack->append_code (');');
655
656 $pack->append_code ('if (not $Skip{'.$test_num.'} and not $Skip{');
657 $pack->append_new_pc_literal ($test_uri);
658 $pack->append_code ('}) {');
659
660 $pack->append_code ('try {');
661
662 my $test_pc = $res->pl_code_fragment ($factory);
663 if (not defined $test_pc) {
664 die "Perl test code not defined for <".$res->uri.">";
665 }
666
667 $pack->append_child ($test_pc);
668
669 $pack->append_code ('$test->ok;');
670
671 $pack->append_code ('} catch Message::Util::IF::DTException with {
672 ##
673 } otherwise {
674 my $err = shift;
675 warn $err;
676 $test->not_ok;
677 };');
678
679 $pack->append_code ('} else { warn "'.$test_num.' skipped\n" }');
680
681 } elsif ($res->is_type_uri (ExpandedURI q<test:ParserTestSet>)) {
682 my $block = $pack->append_new_pc_block;
683 my @test;
684
685 $tdt_parser ||= $limpl->create_gls_parser
686 ({
687 ExpandedURI q<DIS:TDT> => '1.0',
688 });
689 for my $tres (@{$res->get_child_resource_list_by_type
690 (ExpandedURI q<test:ParserTest>)}) {
691 $total_tests++;
692 push @test, my $ttest = {entity => {}};
693 $ttest->{uri} = $tres->uri;
694 for my $eres (@{$tres->get_child_resource_list_by_type
695 (ExpandedURI q<test:Entity>)}) {
696 my $tent = $ttest->{entity}->{$eres->uri} = {};
697 for (ExpandedURI q<test:uri>, ExpandedURI q<test:baseURI>,
698 ExpandedURI q<test:value>, ExpandedURI q<xp:encoding>) {
699 my $v = $eres->get_property_text ($_);
700 $tent->{$_} = $v if defined $v;
701 }
702 $ttest->{root_uri} = $eres->uri
703 if $eres->is_type_uri (ExpandedURI q<test:RootEntity>) or
704 not defined $ttest->{root_uri};
705 }
706
707 ## DOM configuration parameters
708 for my $v (@{$tres->get_property_value_list
709 (ExpandedURI q<c:anyDOMConfigurationParameter>)}) {
710 my $cpuri = $v->name;
711 my $cp = $db->get_resource ($cpuri, for_arg => $tres->for_uri);
712 $ttest->{dom_config}->{$cp->get_dom_configuration_parameter_name}
713 = $v->get_perl_code ($block->owner_document, $tres);
714 }
715
716 ## Result DOM tree
717 my $tree_t = $tres->get_property_text (ExpandedURI q<test:domTree>);
718 if (defined $tree_t) {
719 $ttest->{dom_tree} = $tdt_parser->parse_string ($tree_t);
720 }
721
722 ## Expected |DOMError|s
723 for (@{$tres->get_property_value_list (ExpandedURI q<c:erred>)}) {
724 my $err = $tdt_parser->parse_tdt_error_string
725 ($_->string_value, $db, $_,
726 undef, $tres->for_uri);
727 push @{$ttest->{dom_error}->{$err->{type}->{value}} ||= []}, $err;
728 }
729 }
730
731 for ($block->append_statement
732 ->append_new_pc_expression ('=')) {
733 $_->append_new_pc_variable ('$', undef, 'TestData')
734 ->variable_scope ('my');
735 $_->append_new_pc_literal (\@test);
736 }
737
738 my $plc = $res->pl_code_fragment ($factory);
739 unless ($plc) {
740 die "Resource <".$res->uri."> does not have Perl test code";
741 }
742
743 $block->append_child ($plc);
744
745 } # test resource type
746 } # test:Test
747 }
748
749 $num_statement->append_code (' (' . $total_tests . ')');
750
751 return $pl;
752 } # daf_generate_perl_test_file
753
754 __END__
755
756 =head1 NAME
757
758 dac.pl - Creating "dac" Database File from "dis" Source Files
759
760 =head1 SYNOPSIS
761
762 perl path/to/dac.pl [--input-db-file-name=input.dac] \
763 --output-file-name=out.dac [options...] \
764 input.dis
765 perl path/to/dac.pl --help
766
767 =head1 DESCRIPTION
768
769 This script, C<dac.pl>, compiles "dis" source files into "dac"
770 database file. The generated database file can be used
771 in turn to generate Perl module file, for example, by another
772 script C<dac2pm.pl> or can be used to create larger database
773 by specifying its file name as the C<--input-db-file-name>
774 argument of another C<dac.pl> execution.
775
776 This script is part of manakai.
777
778 =head1 OPTIONS
779
780 =over 4
781
782 =item I<input.dis> (Required)
783
784 The unnamed option specifies a file name path of the source "dis" file
785 from which a database is created. This option is required.
786
787 =item C<--input-db-file-name=I<file-name>> (Default: none)
788
789 A file path of the base database. This option is optional; if this
790 option is specified, the database file is loaded first
791 and then I<input.dis> file is loaded in the context of it.
792 Otherwise, a new database is created.
793
794 =item C<--output-file-name=I<file-name>> (Required)
795
796 The
797
798 =back
799
800 =head1 SEE ALSO
801
802 L<bin/dac2pm.pl> - Generating Perl module from "dac" file.
803
804 L<lib/Message/Util/DIS.dis> - The actual implementation
805 of the "dis" interpretation.
806
807 =head1 LICENSE
808
809 Copyright 2004-2005 Wakaba <w@suika.fam.cx>. All rights reserved.
810
811 This program is free software; you can redistribute it and/or
812 modify it under the same terms as Perl itself.
813
814 =cut

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24