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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (hide annotations) (download)
Tue Apr 4 14:30:29 2006 UTC (19 years, 2 months ago) by wakaba
Branch: MAIN
Changes since 1.10: +7 -2 lines
File MIME type: text/plain
++ manakai/bin/ChangeLog	4 Apr 2006 14:28:32 -0000
2006-04-04  Wakaba  <wakaba@suika.fam.cx>

	* daf.pl (--dafs-suffix): New option.
	(daf_resolve_db_module_file): The |dp:ModuleNodeStorageFile|
	type support.

++ manakai/lib/Message/Util/ChangeLog	4 Apr 2006 14:29:09 -0000
	* DIS.dis (Require): Requires the |MDOM:TreeStore| module.
	(getNodeFromStorage, setNodeToStorage): New methods.

2006-04-04  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/Message/Util/DIS/ChangeLog	4 Apr 2006 14:30:17 -0000
2006-04-04  Wakaba  <wakaba@suika.fam.cx>

	* Perl.dis (plStore): The |mainDatabase| parameter is removed.
	(plStoreNodeStorage): New method.
	(plLoadNodeStorage): New method.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24