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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations) (download)
Sat Mar 18 05:57:48 2006 UTC (19 years, 6 months ago) by wakaba
Branch: MAIN
Changes since 1.7: +1 -1 lines
File MIME type: text/plain
++ manakai/t/ChangeLog	18 Mar 2006 05:57:39 -0000
2006-03-18  Wakaba  <wakaba@suika.fam.cx>

	* Makefile (t-XML.t): New test.

++ manakai/bin/ChangeLog	18 Mar 2006 05:54:09 -0000
2006-03-18  Wakaba  <wakaba@suika.fam.cx>

	* daf.pl (daf_get_file_path_stem): The '.' is removed from
	the default search path.

++ manakai/lib/Message/DOM/ChangeLog	18 Mar 2006 05:56:17 -0000
2006-03-18  Wakaba  <wakaba@suika.fam.cx>

	* TreeCore.dis (Require): The |MDOM:XML| module is added.
	(createAttributeNS, createTextNode, createComment,
	createCDATASection): New methods.
	(Attr, Text, Comment, CharacterData): New interfaces.

	* Makefile: |XML.dis| is added.

	* XML.dis: New module.

2006-03-17  Wakaba  <wakaba@suika.fam.cx>

	* TreeCore.dis (manakaiReadOnly): New attribute.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24