/[suikacvs]/markup/tool/mkdtds.pl
Suika

Contents of /markup/tool/mkdtds.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (hide annotations) (download)
Sun Jun 20 05:16:45 2004 UTC (20 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.4: +12 -5 lines
File MIME type: text/plain
Minor fix

1 wakaba 1.3 #!/usr/bin/perl
2 wakaba 1.1 use strict;
3 wakaba 1.3 our $SCRIPT_NAME = 'mkdtds';
4 wakaba 1.5 our $VERSION = do{my @r=(q$Revision: 1.4 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
5 wakaba 1.3 {require Message::Markup::SuikaWikiConfig20::Parser;
6 wakaba 1.1
7 wakaba 1.3 my $parser = new Message::Markup::SuikaWikiConfig20::Parser;
8 wakaba 1.1 local $/ = undef;
9     my $src = $parser->parse_text (scalar <>);
10     my $Info = {};
11    
12     for my $src ($src->get_attribute ('ModuleSet')
13     || $src->get_attribute ('DocumentType')) {
14 wakaba 1.4 for (qw/Description/) {
15 wakaba 1.1 $Info->{$_} = $src->get_attribute_value ($_);
16     }
17 wakaba 1.4 for (qw/Name ID Copyright BaseURI Version/) {
18     $Info->{$_} = normalize_wsp ($src->get_attribute_value ($_));
19     }
20     $Info->{realname} = $Info->{Name};
21 wakaba 1.3 $Info->{Name} .= ' ' . $Info->{Version} if length $Info->{Version};
22 wakaba 1.1 $Info->{ns} = $src->get_attribute ('Namespace');
23     }
24    
25     for (@{$src->child_nodes}) {
26     if ($_->local_name eq 'Attribute') {
27     attrib_module ($_, $Info);
28     } elsif ($_->local_name eq 'Datatype') {
29     datatype_module ($_, $Info);
30     } elsif ($_->local_name eq 'Notation') {
31     notation_module ($_, $Info);
32     } elsif ($_->local_name eq 'Module') {
33     submodule ($_, $Info);
34     } elsif ($_->local_name eq 'Model') {
35     model_module ($_, $Info);
36 wakaba 1.2 $Info->{has_model} = 1;
37 wakaba 1.1 } elsif ($_->local_name eq 'Driver') {
38     dtd_driver ($_, $Info);
39     }
40     }
41    
42     if (ref $src->get_attribute ('ModuleSet')) {
43     qname_module ($src->get_attribute ('ModuleSet'), $Info);
44     }
45     exit}
46    
47 wakaba 1.4 sub normalize_wsp ($;%) {
48     my $s = shift;
49     $s =~ s/\s+/ /g;
50     $s =~ s/^ +//;
51     $s =~ s/ +$//;
52     $s;
53     }
54 wakaba 1.3 sub make_paragraphs ($;%) {
55     my ($para, %opt) = @_;
56     join "\n\n", map {
57     my $s = $_;
58     $s =~ s/\n+$//g;
59     $s =~ s/\n/\n$opt{indent}/g;
60     $opt{indent}.$s;
61     } grep {length} @$para;
62     }
63    
64     sub dot_padding ($%) {
65     my ($s, %opt) = @_;
66     if ($opt{length} - length $s > 0) {
67     return $s . ( ($opt{dot} or q(.)) x ($opt{length} - length $s) );
68     } else {
69     return $s;
70     }
71     }
72    
73 wakaba 1.1 sub submodule_id_of ($$;%) {
74     my ($src, $Info, %opt) = @_;
75     my $id = $src->get_attribute_value ('ID') || $opt{default};
76     unless ($id) {
77     die "$0: Submodule identifier not specified";
78     }
79     $id;
80     }
81     sub xml_datatype_of ($$;%) {
82     my ($src, $Info, %opt) = @_;
83     my $type = $src->get_attribute_value ('XMLType') || $opt{default};
84     $type =~ s/\s+//g;
85     $type;
86     }
87 wakaba 1.2 sub system_id_of ($$;%) {
88     my ($src, $Info, %opt) = @_;
89     my $sysid = $src->get_attribute_value ('SYSTEM');
90     if ($sysid =~ /<([^>]+)>/) {
91     return $1;
92     } else {
93     return $opt{base}.($sysid || $opt{default});
94     }
95     }
96 wakaba 1.1 sub external_id_of ($$;%) {
97     my ($src, $Info, %opt) = @_;
98 wakaba 1.2 my $sysid = system_id_of ($src, $Info, %opt);
99 wakaba 1.1 my $pubid = $src->get_attribute_value ('PUBLIC');
100     if ($pubid) {
101     if ($sysid) {
102     return qq(PUBLIC "$pubid"\n\t "$sysid");
103     } else {
104     return qq(PUBLIC "$pubid");
105     }
106     } else {
107     return qq(SYSTEM "$sysid");
108     }
109     }
110     sub name_of ($$;%) {
111     my ($src, $Info, %opt) = @_;
112     unless (ref $src) {require Carp; Carp::croak ('$src undefined')}
113     my $name = $src->get_attribute_value ($opt{key} || 'Name');
114     if ($name =~ /^:(.+)/) { ## Global namespace
115     return $1;
116     } elsif ($name =~ /([^:]+):(.+)/) { ## Named space
117     return $1.($opt{delim}||'.').$2;
118     } else { ## Default namespace
119     return $Info->{ID}.($opt{delim}||'.').$name;
120     }
121     }
122     sub local_name_of ($$;%) {
123     my ($src, $Info, %opt) = @_;
124     my $name = $src->get_attribute_value ($opt{key} || 'Name');
125     if ($name =~ /^:(.+)/) { ## Global namespace
126     return $1;
127     } elsif ($name =~ /[^:]+:(.+)/) { ## Named space
128     return $1;
129     } else { ## Default namespace
130     return $name;
131     }
132     }
133     sub set_name_of ($$;%) {
134     my ($src, $Info, %opt) = @_;
135     my $name = $src->get_attribute_value ($opt{key} || 'Name');
136     if ($name =~ /^:.+/) { ## Global namespace
137     return 'XHTML';
138     } elsif ($name =~ /([^:]+):.+/) { ## Named space
139     return $1;
140     } else { ## Default namespace
141     return $Info->{ID};
142     }
143     }
144     sub class_name_of ($$;%) {
145     my ($src, $Info, %opt) = @_;
146     my $name = name_of ($src, $Info, %opt);
147     unless ($name =~ /\.(class|mix|content|datatype)$/) {
148     $name .= '.class';
149     }
150     $name;
151     }
152     sub convert_content_model ($$;%) {
153     my ($src, $Info, %opt) = @_;
154     my $model = $src->get_attribute_value ($opt{key} || 'Content') || $opt{default};
155     $model =~ s/\s//g;
156     my $nonsymbol = qr/[^%#?,\$;()+*|:]/;
157     $model =~ s/(?<![%#.])((?:\$|\b)$nonsymbol+(?::$nonsymbol+)?|\$?:$nonsymbol+|"[^"]+")/get_model_token ($1, $Info)/ge;
158     $model;
159     }
160 wakaba 1.2 sub sparalit ($) {
161     my $s = paralit (shift);
162     $s =~ s/&/&#x26;/g;
163     $s =~ s/%/&#x25;/g;
164     $s;
165     }
166 wakaba 1.1 sub paralit ($) {
167     my $s = shift;
168     if ($s =~ /"/) {
169     if ($s =~ /'/) {
170     $s =~ s/'/&#x27;/g;
171     return qq("$s");
172     } else {
173     return qq('$s');
174     }
175     } else {
176     return qq("$s");
177     }
178     }
179     sub description ($$;%) {
180     my ($src, $Info, %opt) = @_;
181     my $desc = $src->get_attribute_value ('Description');
182     $desc =~ s/\n/\n /g;
183     unless ($desc) {
184     $desc = {
185     load_module => {
186     AttributeModule => q/Common Attributes Module/,
187     DatatypeModule => q/Datatypes Module/,
188     NotationModule => q/Notation Module/,
189     QNameModule => q/QName Module/,
190     },
191     }->{$opt{context}}->{$opt{id} || $src->get_attribute_value ($opt{id_key}||'ID')};
192     }
193     $desc = qq(<!-- $desc -->\n) if $desc;
194     $desc;
195     }
196 wakaba 1.3 sub xml_condition_section ($$;%) {
197     my ($condition, $content, %opt) = @_;
198     qq(<![%$condition;[\n)
199     . $content
200     . qq(<!-- end of $condition -->]]>\n);
201     }
202     sub xml_parameter_ENTITY ($%) {
203     my ($name, %opt) = @_;
204     qq(<!ENTITY % $name @{[paralit $opt{value}]}>\n);
205     }
206 wakaba 1.1
207 wakaba 1.2 sub entity_declaration ($$;%) {
208     my ($src, $Info, %opt) = @_;
209     my $val;
210     if ($src->get_attribute_value ('ID')
211     || $src->get_attribute_value ('SYSTEM')
212     || $src->get_attribute_value ('PUBLIC')) {
213     $val = "\n\t".external_id_of ($src, $Info, default => $src->get_attribute_value ('ID'));
214     } elsif (ref $src->get_attribute ('Declaration')) {
215     $val = "\n\t".sparalit submodule_declarations ($src->get_attribute ('Declaration'), $Info);
216     } else {
217     $val = paralit $src->get_attribute_value ('EntityValue');
218     }
219     my $s = <<EOH;
220     @{[description ($src, $Info)]}<!ENTITY @{[$opt{param}?'% ':'']}@{[$src->get_attribute_value ('Name')]} $val>
221    
222     EOH
223     $s;
224     }
225 wakaba 1.1
226     sub dtd_driver ($$) {
227     my ($src, $Info) = @_;
228     my $s = '';
229     my %s;
230     my @module_set;
231     for my $src (@{$src->child_nodes}) {
232     if ($src->local_name eq 'Module') {
233     $s .= dtd_driver_load_module ($src, $Info);
234 wakaba 1.2 } elsif ($src->local_name eq 'DTD') {
235     $s .= dtd_driver_load_dtd ($src, $Info);
236 wakaba 1.1 } elsif ($src->local_name eq 'ModuleSet') {
237     push @module_set, $src;
238     } elsif ($src->local_name =~ /^(?:QName|Attribute|Datatype|Notation)Module/) {
239     $s{$src->local_name} .= dtd_driver_load_module ($src, $Info);
240     } elsif ($src->local_name eq 'IfModuleSet') {
241     $s .= qq(<![%@{[$src->get_attribute_value ('ModuleSet')]}.module;[\n);
242     $s .= submodule_declarations ($src, $Info);
243     $s .= qq(]]>\n);
244     } elsif ($src->local_name eq 'GeneralEntity') {
245 wakaba 1.2 $s .= entity_declaration ($src, $Info, param => 0);
246 wakaba 1.1 } elsif ($src->local_name eq 'ParameterEntity') {
247 wakaba 1.2 $s .= entity_declaration ($src, $Info, param => 1);
248 wakaba 1.1 }
249     }
250    
251 wakaba 1.2 $s{ModelModule} = $src->get_attribute_value ('NoModelModule') ? '' :
252     $Info->{has_model} ? <<EOH : '';
253 wakaba 1.1 <!-- Document Model module -->
254     <!ENTITY % $Info->{ID}-model.module "INCLUDE">
255     <![%$Info->{ID}-model.module;[
256     <!ENTITY % $Info->{ID}-model.decl
257     'SYSTEM "$Info->{ID}-model.mod"'>
258     <!ENTITY % $Info->{ID}-model.mod %$Info->{ID}-model.decl;>
259     %$Info->{ID}-model.mod;]]>
260    
261     EOH
262    
263     $s = dtd_driver_module_sets (\@module_set, $Info)
264     . $s{QNameModule}.$s{DatatypeModule}.$s{NotationModule}.$s{AttributeModule}
265     . $s{ModelModule}
266     .$s;
267     make_dtd ($src, $Info, $src->get_attribute_value ('ID'), $s);
268     }
269    
270     sub dtd_driver_module_sets ($$) {
271     my ($srces, $Info) = @_;
272     my @src = map {{src => $_}} @$srces;
273     my $s = qq(<!-- Switchers to include/ignore each vocabulary -->\n);
274     for my $module_set (@src) {
275     $module_set->{ID} = $module_set->{src}->get_attribute_value ('ID') || 'XHTML';
276     $s .= qq(<!ENTITY % $module_set->{ID}.module "@{[$module_set->{src}->get_attribute_value ('Default') > 0 ? 'INCLUDE' : 'IGNORE']}">\n);
277     }
278     $s .= qq(\n<!-- Namespace names -->\n);
279     for my $module_set (@src) {
280     $module_set->{ns} = $module_set->{src}->get_attribute ('Namespace');
281     $s .= qq(<!ENTITY % $module_set->{ID}.xmlns "@{[$module_set->{ns}->get_attribute_value ('Name')]}">\n);
282     }
283     $s .= qq(\n<!-- Base URIs for the relavant DTD modules -->\n);
284     for my $module_set (@src) {
285     $s .= qq(<!ENTITY % $module_set->{ID}.sysid.base "@{[$module_set->{src}->get_attribute_value ('BaseURI')]}">\n);
286     }
287     $s .= qq(\n<!-- Namespace prefix -->\n);
288     $s .= qq(<!ENTITY % NS.prefixed "@{[$Info->{ns}->get_attribute_value ('UsePrefix') > 0 ? 'INCLUDE' : 'IGNORE']}">\n);
289     for my $module_set (@src) {
290     $s .= qq(<!ENTITY % $module_set->{ID}.prefix "@{[$module_set->{ns}->get_attribute_value ('DefaultPrefix')]}">\n);
291     $s .= qq(<!ENTITY % $module_set->{ID}.prefixed "@{[$module_set->{ns}->get_attribute_value ('UsePrefix') > 0 ? 'INCLUDE' : $module_set->{ns}->get_attribute_value ('UsePrefix') < 0 ? 'IGNORE' : '%NS.prefixed;']}">\n);
292     }
293     $s .= qq(\n<!-- a URI reference -->\n<!ENTITY % URI.datatype "CDATA">\n);
294     $s .= qq(\n<!-- Placefolders for foreign namespace declarations -->\n);
295     for my $module_set (@src) {
296     $s .= qq(<!ENTITY % $module_set->{ID}.xmlns.extra.attrib "">\n);
297     }
298     $s .= qq(\n<!-- Namespace declarations -->\n);
299     for my $module_set (@src) {
300     $s .= qq(<![%$module_set->{ID}.module;[
301     <![%$module_set->{ID}.prefixed;[
302     <!ENTITY % $module_set->{ID}.xmlns.decl.attrib
303     "xmlns:%$module_set->{ID}.prefix; %URI.datatype; #FIXED '%$module_set->{ID}.xmlns;'">
304     ]]>
305     <!ENTITY % $module_set->{ID}.xmlns.decl.attrib
306     "xmlns %URI.datatype; #FIXED '%$module_set->{ID}.xmlns;'">
307     ]]>
308     <!ENTITY % $module_set->{ID}.xmlns.decl.attrib "">\n\n);
309     }
310 wakaba 1.4 $s .= <<EOH;
311     <!-- Declare a parameter entity %XSI.prefix as a prefix to use for
312     XML Schema Instance attributes. -->
313     <!ENTITY % XSI.prefix "xsi">
314    
315     <!ENTITY % XSI.pfx "%XSI.prefix;:">
316    
317     <!ENTITY % XSI.xmlns "http://www.w3.org/2001/XMLSchema-instance">
318    
319     <!-- Declare a parameter entity %XSI.xmlns.attrib as support for
320     the schemaLocation attribute. -->
321     <!ENTITY % XSI.xmlns.attrib
322     "xmlns:%XSI.prefix; %URI.datatype; #FIXED '%XSI.xmlns;'">
323     EOH
324 wakaba 1.1 $s .= qq(\n<!ENTITY % NS.decl.attrib
325     ").join ("\n\t", (map {qq(%$_->{ID}.xmlns.decl.attrib;)} @src),
326 wakaba 1.4 map {qq(%$_->{ID}.xmlns.extra.attrib;)} @src)
327     .qq(\n\t%XSI.xmlns.attrib;">\n);
328 wakaba 1.1 $s .= qq(\n);
329     for my $module_set (@src) {
330     $s .= qq(<!ENTITY % $module_set->{ID}.xmlns.attrib "%NS.decl.attrib;">\n);
331     }
332     $s .= qq(\n\n);
333     $s;
334     }
335    
336     sub dtd_driver_load_module ($$) {
337     my ($src, $Info) = @_;
338     my $module_name = name_of ($src, $Info, key => 'ID');
339     my $module_hyphen_name = name_of ($src, $Info, key => 'ID', delim => '-');
340     my $module_set_name = set_name_of ($src, $Info, key => 'ID');
341     my $module_id = local_name_of ($src, $Info, key => 'ID');
342    
343     my $s .= <<EOH;
344     @{[description ($src, $Info, context => 'load_module', id => $src->local_name)]}<![%$module_set_name.module;[
345 wakaba 1.2 <!ENTITY % $module_name.module "@{[$src->get_attribute_value ('Default') >= 0 ? 'INCLUDE' : 'IGNORE']}">
346 wakaba 1.1 <![%$module_name.module;[
347     @{[submodule_declarations ($src, $Info)]}<!ENTITY % $module_name.decl
348     @{[paralit external_id_of ($src, $Info, default => qq($module_hyphen_name.mod), base => qq(%$module_set_name.sysid.base;))]}>
349     <!ENTITY % $module_name.mod %$module_name.decl;>
350     %$module_name.mod;]]>
351     ]]>
352    
353     EOH
354     $s;
355     }
356 wakaba 1.2
357     sub dtd_driver_load_dtd ($$) {
358     my ($src, $Info) = @_;
359     my $module_set_name = $src->get_attribute_value ('ID');
360    
361     my $s .= <<EOH;
362     @{[description ($src, $Info)]}<![%$module_set_name.module;[
363     @{[submodule_declarations ($src, $Info)]}<!ENTITY % $module_set_name.dtd.sysid "@{[system_id_of ($src, $Info, default => $src->get_attribute_value ('ID').'.dtd', base => qq(%$module_set_name.sysid.base;))]}">
364     @{[do{
365     my $pubid = $src->get_attribute_value ('PUBLIC');
366     if ($pubid) {
367     qq(<!ENTITY % $module_set_name.dtd.fpi "$pubid">\n<!ENTITY % $module_set_name.dtd.fpi.defined "INCLUDE">\n);
368     } else {
369     qq(<!ENTITY % $module_set_name.dtd.fpi "">\n<!ENTITY % $module_set_name.dtd.fpi.defined "IGNORE">\n);
370     }
371     }]}
372     <![%$module_set_name.dtd.fpi.defined;[
373     <!ENTITY % $module_set_name.dtd.decl
374     'PUBLIC "%$module_set_name.dtd.fpi;"
375     "%$module_set_name.dtd.sysid;"'>
376     ]]>
377     <!ENTITY % $module_set_name.dtd.decl
378     'SYSTEM "%$module_set_name.dtd.sysid;"'>
379     <!ENTITY % $module_set_name.dtd %$module_set_name.dtd.decl;>
380     %$module_set_name.dtd;]]>
381    
382     EOH
383     $s;
384     }
385    
386 wakaba 1.1 sub model_module ($$) {
387     my ($src, $Info) = @_;
388     my $s = '';
389     for my $src (@{$src->child_nodes}) {
390     if ($src->local_name eq 'Class') {
391 wakaba 1.2 $s .= qq(@{[description ($src, $Info)]}<!ENTITY % @{[class_name_of ($src, $Info)]} @{[paralit convert_content_model ($src, $Info)]}>\n\n);
392 wakaba 1.1 } elsif ($src->local_name eq 'Content') {
393     $s .= element_content_def ($src, $Info);
394     }
395     }
396     make_module ($src, $Info, submodule_id_of ($src, $Info, default => 'model'), $s);
397     }
398    
399     sub datatype_module ($$) {
400     my ($src, $Info) = @_;
401     my $s = '';
402     for my $src (@{$src->child_nodes}) {
403     if ($src->local_name eq 'Type') {
404     $s .= qq(@{[get_desc ($src, $Info)]}<!ENTITY % @{[name_of ($src, $Info)]}.datatype "@{[xml_datatype_of ($src, $Info, default => 'CDATA')]}">\n\n);
405     }
406     }
407     make_module ($src, $Info, submodule_id_of ($src, $Info, default => 'datatype'), $s);
408     }
409    
410     sub notation_module ($$) {
411     my ($src, $Info) = @_;
412     my $s = '';
413     for my $src (@{$src->child_nodes}) {
414     if ($src->local_name eq 'Notation') {
415     $s .= qq(@{[get_desc ($src, $Info)]}<!NOTATION @{[name_of ($src, $Info)]} @{[external_id_of ($src, $Info)]}>\n\n);
416     }
417     }
418     make_module ($src, $Info, submodule_id_of ($src, $Info, default => 'notation'), $s);
419     }
420    
421     sub qname_module ($$) {
422     my ($src, $Info) = @_;
423     my $ID = $Info->{ID};
424     my $ns = $src->get_attribute ('Namespace');
425     my $s = <<EOH;
426 wakaba 1.5 <!ENTITY % sgml.tag.minimizable "IGNORE">
427    
428 wakaba 1.1 <!ENTITY % NS.prefixed "@{[$ns->get_attribute_value ('UsePrefix')==1?
429     q(INCLUDE):q(IGNORE)]}">
430 wakaba 1.2
431 wakaba 1.3 <!-- Section A: XML Namespace Framework :::::::::::::::::::::::::: -->
432    
433 wakaba 1.4 <!-- 1. Declare a %$ID.prefixed; conditional section keyword, used
434     to activate namespace prefixing. -->
435 wakaba 1.1 <!ENTITY % $ID.prefixed "@{[$ns->get_attribute_value ('UsePrefix')==1?
436     q(INCLUDE):
437     $ns->get_attribute_value ('UsePrefix')==-1?
438     q(IGNORE):
439     q(%NS.prefixed;)]}">
440 wakaba 1.2
441 wakaba 1.4 <!ENTITY % $ID.global.attrs.prefixed "@{[$ns->get_attribute_value ('UsePrefix')==1?
442     q(INCLUDE):
443     $ns->get_attribute_value ('UsePrefix')==-1?
444     q(IGNORE):
445     q(%NS.prefixed;)]}">
446    
447     <!ENTITY % $ID.xsi.attrs "INCLUDE">
448    
449     <!-- 2. Declare a parameter entity %$ID.xmlns; containing
450     the URI reference used to identity the namespace. -->
451 wakaba 1.1 <!ENTITY % $ID.xmlns "@{[$ns->get_attribute_value ('Name')]}">
452 wakaba 1.2
453 wakaba 1.4 <!-- 3. Declare parameter entity %$ID.prefix; containing
454     the default namespace prefix string to use when prefixing
455     is enabled. This may be overridden in the DTD driver or the
456     internal subset of a document instance.
457    
458     NOTE: As specified in XML Namespace speficications, the namespace
459     prefix serves as a proxy for the URI reference, and is not in itself
460     significant. -->
461 wakaba 1.1 <!ENTITY % $ID.prefix "@{[$ns->get_attribute_value ('DefaultPrefix')]}">
462 wakaba 1.2
463 wakaba 1.4 <!-- 4. Declare parameter entity %$ID.pfx; containing the
464     colonized prefix (e.g, '%$ID.prefix;:') used when
465     prefixing is active, an empty string when it is not. -->
466 wakaba 1.1 <![%$ID.prefixed;[
467     <!ENTITY % $ID.pfx "%$ID.prefix;:">
468     ]]>
469     <!ENTITY % $ID.pfx "">
470 wakaba 1.2
471 wakaba 1.4 <!-- declare qualified name extensions here ............ -->
472 wakaba 1.2 <!ENTITY % ${ID}-qname-extra.mod "">
473     %${ID}-qname-extra.mod;
474    
475 wakaba 1.4 <!-- 5. The parameter entity %$ID.xmlns.extra.attrib; may be
476     redeclared to contain any foreign namespace declaration
477     attributes for namespaces embedded. The default
478     is an empty string. -->
479 wakaba 1.1 <!ENTITY % $ID.xmlns.extra.attrib "">
480    
481 wakaba 1.4 <!-- The parameter entity %URI.datatype; should already be defined in
482     Datatype module. -->
483     <!ENTITY % URI.datatype; "CDATA">
484    
485 wakaba 1.1 <![%$ID.prefixed;[
486     <!ENTITY % $ID.xmlns.decl.attrib
487     "xmlns:%$ID.prefix; %URI.datatype; #FIXED '%$ID.xmlns;'">
488     ]]>
489     <!ENTITY % $ID.xmlns.decl.attrib
490     "xmlns %URI.datatype; #FIXED '%$ID.xmlns;'">
491    
492 wakaba 1.4 <!-- Declare a parameter entity %XSI.prefix as a prefix to use for
493     XML Schema Instance attributes. -->
494     <!ENTITY % XSI.prefix "xsi">
495    
496     <!ENTITY % XSI.pfx "%XSI.prefix;:">
497    
498     <!ENTITY % XSI.xmlns "http://www.w3.org/2001/XMLSchema-instance">
499    
500     <!-- Declare a parameter entity %XSI.xmlns.attrib as support for
501     the schemaLocation attribute. -->
502     <!ENTITY % XSI.xmlns.attrib
503     "xmlns:%XSI.prefix; %URI.datatype; #FIXED '%XSI.xmlns;'">
504    
505 wakaba 1.1 <![%$ID.prefixed;[
506     <!ENTITY % NS.decl.attrib
507     "%$ID.xmlns.decl.attrib;
508 wakaba 1.4 %$ID.xmlns.extra.attrib;
509     %XSI.xmlns.attrib;">
510 wakaba 1.1 ]]>
511     <!ENTITY % NS.decl.attrib
512 wakaba 1.4 "%$ID.xmlns.extra.attrib;
513     %XSI.xmlns.attrib;">
514 wakaba 1.1
515 wakaba 1.2 <!-- Declare a parameter entity containing all XML namespace declaration
516     attributes used, including a default xmlns declaration when prefixing
517     is inactive. -->
518 wakaba 1.1 <![%$ID.prefixed;[
519     <!ENTITY % $ID.xmlns.attrib
520     "%NS.decl.attrib;">
521     ]]>
522     <!ENTITY % $ID.xmlns.attrib
523     "%$ID.xmlns.decl.attrib;
524     %NS.decl.attrib;">
525    
526 wakaba 1.4 <!-- @{[dot_padding qq(Section B: $Info->{realname} Qualified Names ),
527     length => 71-9, dot => q(:)]} -->
528 wakaba 1.3
529     <!-- placeholder for qualified name redeclarations -->
530 wakaba 1.4 <!ENTITY % ${ID}-qname.redecl "">
531     %${ID}-qname.redecl;
532 wakaba 1.3
533 wakaba 1.4 <!-- 6. This section declare parameter entities used to provide
534     namespace-qualified names for all element types and global
535     attribute names. -->
536 wakaba 1.1 EOH
537 wakaba 1.3 for my $lname (sort keys %{$Info->{QName}}) {
538     $s .= qq(<!ENTITY % )
539     . (dot_padding qq($Info->{ID}.$lname.qname),
540     length => 15 + length ($Info->{ID}), dot => ' ')
541     . qq( "%$Info->{ID}.pfx;$lname">\n);
542 wakaba 1.1 }
543     $s .= qq(\n);
544 wakaba 1.3 for my $lname (sort keys %{$Info->{QNameA}}) {
545     $s .= qq(<!ENTITY % )
546     . (dot_padding qq($Info->{ID}.$lname.attrib.qname),
547     length => 15 + length ($Info->{ID}), dot => ' ')
548     . qq( "%$Info->{ID}.prefix;:$lname">\n);
549 wakaba 1.1 }
550     $s .= qq(\n);
551 wakaba 1.3 for my $lname (sort keys %{$Info->{QNameB}}) {
552     $s .= qq(<!ENTITY % )
553     . (dot_padding qq($Info->{ID}.$lname.attribute.qname),
554     length => 15 + length ($Info->{ID}), dot => ' ')
555     . qq( "%$Info->{ID}.pfx;$lname">\n);
556 wakaba 1.1 }
557 wakaba 1.3 make_module ($src->get_attribute ('QName', make_new_node => 1), $Info, 'qname', $s);
558 wakaba 1.1 }
559    
560     sub get_name ($$;$) {
561     my ($src, $Info, $key) = @_;
562     my $name = $src->get_attribute_value ($key || 'Name');
563     if ($name =~ /^:(.+)/) {
564     $name = $1;
565     } elsif ($name =~ /([^:]+):(.+)/) {
566     $name = qq($1.$2);
567     } else {
568     $name = qq($Info->{ID}.$name);
569     }
570     $name;
571     }
572    
573     sub get_qname ($$) {
574     my ($src, $Info) = @_;
575     my $name = $src->get_attribute_value ('Name');
576     if ($name =~ /"([^"]+)"/) {
577     $name = qq($1);
578     } elsif ($name =~ /^:(.+)/) {
579     $name = qq(%$1.qname;);
580     } elsif ($name =~ /([^:]+):(.+)/) {
581     $name = qq(%$1.$2.qname;);
582     } elsif ($name =~ /\{([^{}]+)\}/) {
583     $Info->{QNameB}->{$1} = 1;
584     $name = qq(%$Info->{ID}.$1.attribute.qname;);
585     } else {
586     $Info->{QNameA}->{$name} = 1;
587     $name = qq(%$Info->{ID}.$name.attrib.qname;);
588     }
589     $name;
590     }
591    
592     sub get_atype ($$) {
593     my ($src, $Info) = @_;
594     my $name = $src->get_attribute_value ('Type');
595     if ($name =~ /^:(.+)/) {
596     $name = qq(%$1.datatype;);
597     } elsif ($name =~ /([^:]+):(.+)/) {
598     $name = qq(%$1.$2.datatype;);
599     } elsif ($name =~ /"([^"]+)"/) {
600     $name = qq($1);
601     } else {
602     $name = qq(%$Info->{ID}.$name.datatype;);
603     }
604     $name;
605     }
606    
607     sub get_adefault ($$) {
608     my ($src, $Info) = @_;
609     my $name = $src->get_attribute_value ('Default');
610     if (defined $name) {
611     } else {
612     $name = qq(#IMPLIED);
613     }
614     $name;
615     }
616    
617 wakaba 1.3 sub get_desc ($$;%) {
618     my ($src, $Info, %opt) = @_;
619 wakaba 1.4 my $desc = $src->get_attribute_value ('Description');
620     $desc =~ s/\n/\n /g;
621 wakaba 1.3 if (length $desc) {
622     $desc = qq($opt{prefix}$desc);
623     $desc .= q( ) if $opt{padding_length};
624     $desc = q(<!-- ).(dot_padding $desc, length => $opt{padding_length},
625     dot => $opt{padding_dot}).qq( -->\n);
626 wakaba 1.4 } elsif (length $opt{default}) {
627     $desc = $opt{default};
628     $desc .= q( ) if $opt{padding_length};
629     $desc = q(<!-- ).(dot_padding $desc, length => $opt{padding_length},
630     dot => $opt{padding_dot}).qq( -->\n);
631 wakaba 1.3 }
632 wakaba 1.1 $desc;
633     }
634    
635     sub attset_def ($$) {
636     my ($src, $Info) = @_;
637     my $name = get_name ($src, $Info);
638     my $s .= qq(@{[get_desc ($src, $Info)]}<!ENTITY % $name.attrib\n\t);
639     my @s;
640     if ($name eq qq($Info->{ID}.common)) {
641     push @s, qq(%$Info->{ID}.common.extra.attrib;);
642     push @s, qq(%$Info->{ID}.xmlns.attrib;);
643     }
644     for my $src (@{$src->child_nodes}) {
645     ## Attribute Definition
646     if ($src->local_name eq 'Attribute') {
647     push @s, attrib_def ($src, $Info);
648     ## Reference to Attribute Definition
649     } elsif ($src->local_name eq 'ref') {
650     push @s, attrib_ref ($src, $Info);
651     } elsif ($src->local_name eq 'REF') {
652     push @s, attrib_REF ($src, $Info);
653     }
654     }
655     $s .= paralit join "\n\t", @s;
656     $s .= qq(>\n\n);
657     $s;
658     }
659    
660     sub attrib_module ($$) {
661     my ($src, $Info) = @_;
662     my $s = <<EOH;
663     <!ENTITY % $Info->{ID}.common.extra.attrib "">
664    
665     EOH
666     my $output_common = 0;
667     for my $src (@{$src->child_nodes}) {
668     ## Attributes Set
669     if ($src->local_name eq 'Attribute' or $src->local_name eq 'AttributeSet') {
670     $s .= attset_def ($src, $Info);
671     $output_common = 1 if get_name ($src, $Info) eq qq($Info->{ID}.common);
672     }
673     }
674     unless ($output_common) {
675     $s .= <<EOH;
676     <!ENTITY % $Info->{ID}.common.attrib
677     "%$Info->{ID}.common.extra.attrib;
678     %$Info->{ID}.xmlns.attrib;">
679    
680     EOH
681     }
682     make_module ($src, $Info, ($src->get_attribute_value ('ID') || 'attribs'), $s);
683     }
684    
685     sub attrib_def ($$) {
686     my ($src, $Info) = @_;
687     my $s = qq(@{[get_qname ($src, $Info)]} @{[get_atype ($src, $Info)]} @{[get_adefault ($src, $Info)]});
688     $s;
689     }
690    
691     sub attrib_ref ($$) {
692     my ($src, $Info) = @_;
693     my $name = $src->value;
694     if ($name =~ /^:(.+)/) {
695     $name = $1;
696     } elsif ($name =~ /([^:]+):(.+)/) {
697     $name = qq($1.$2);
698     } else {
699     $name = qq($Info->{ID}.$name);
700     }
701     qq(%$name.attrib;);
702     }
703    
704     sub attrib_REF ($$) {
705     my ($src, $Info) = @_;
706     {
707     'xml:base' => q<xml:base %URI.datatype; #IMPLIED>,
708     'xml:lang' => q<xml:lang %LanguageCode.datatype; #IMPLIED>,
709     'xml:space' => q<xml:space (default|preserve) #IMPLIED>,
710 wakaba 1.4 'xsi:nil' => q<%XSI.prefix;:nil (true|false|1|0) #IMPLIED>,
711     'xsi:noNamespaceSchemaLocation' => q<%XSI.prefix;:noNamespaceSchemaLocation CDATA #IMPLIED>,
712     'xsi:schemaLocation' => q<%XSI.prefix;:schemaLocation CDATA #IMPLIED>,
713     'xsi:type' => q<%XSI.prefix;:type NMTOKEN #IMPLIED>,
714 wakaba 1.1 }->{$src->value};
715     }
716    
717     sub submodule ($$) {
718     my ($src, $Info) = @_;
719 wakaba 1.3 local $Info->{elements} = [];
720 wakaba 1.1 my $s = submodule_declarations ($src, $Info);
721     make_module ($src, $Info, $src->get_attribute_value ('ID'), $s);
722     }
723    
724     sub submodule_declarations ($$) {
725     my ($src, $Info) = @_;
726     my $s = '';
727     for my $src (@{$src->child_nodes}) {
728     if ($src->local_name eq 'Element') {
729     $s .= element_def ($src, $Info);
730     } elsif ($src->local_name eq 'Attribute') {
731     $s .= attlist_def ($src, $Info);
732     } elsif ($src->local_name eq 'AttributeSet') {
733     $s .= attset_def ($src, $Info);
734 wakaba 1.2 } elsif ($src->local_name eq 'Class') {
735     $s .= qq(@{[description ($src, $Info)]}<!ENTITY % @{[class_name_of ($src, $Info)]} @{[paralit convert_content_model ($src, $Info)]}>\n\n);
736 wakaba 1.1 } elsif ($src->local_name eq 'Content') {
737     $s .= element_content_def ($src, $Info);
738     } elsif ($src->local_name eq 'IfModuleSet') {
739     $s .= qq(<![%@{[$src->get_attribute_value ('ModuleSet')]}.module;[\n);
740     $s .= submodule_declarations ($src, $Info);
741 wakaba 1.3 $s .= qq(<!-- end of -->]]>\n);
742 wakaba 1.1 } elsif ($src->local_name eq 'ElementSwitch') {
743     $s .= qq(<!ENTITY % @{[name_of ($src, $Info)]}.element "@{[$src->get_attribute_value ('Use')>0?'INCLUDE':'IGNORE']}">\n);
744     } elsif ($src->local_name eq 'AttributeSwitch') {
745     $s .= qq(<!ENTITY % @{[name_of ($src, $Info)]}.attlist "@{[$src->get_attribute_value ('Use')>0?'INCLUDE':'IGNORE']}">\n);
746 wakaba 1.2 } elsif ($src->local_name eq 'ModuleSwitch') {
747     $s .= qq(<!ENTITY % @{[name_of ($src, $Info)]}.module "@{[$src->get_attribute_value ('Use')>0?'INCLUDE':'IGNORE']}">\n);
748     } elsif ($src->local_name eq 'GeneralEntity') {
749     $s .= entity_declaration ($src, $Info, param => 0);
750 wakaba 1.1 } elsif ($src->local_name eq 'ParameterEntity') {
751 wakaba 1.2 $s .= entity_declaration ($src, $Info, param => 1);
752 wakaba 1.1 }
753     }
754     $s;
755     }
756    
757     sub element_content_def ($$) {
758     my ($src, $Info) = @_;
759     qq(<!ENTITY % @{[name_of ($src, $Info, key => 'ElementType')]}.content @{[paralit convert_content_model ($src, $Info, default => 'EMPTY')]}>\n);
760     }
761    
762     sub element_def ($$) {
763     my ($src, $Info) = @_;
764     my $name = get_name ($src, $Info);
765     my $mname = $name =~ /^\Q$Info->{ID}.\E/ ? $name : qq($Info->{ID}.$name);
766 wakaba 1.3 my $short_name = $name;
767     if ($name =~ /^\Q$Info->{ID}\E\.(.+)/) {
768     $Info->{QName}->{$1} = 1;
769     push @{$Info->{elements}}, $1;
770     $short_name = $1;
771     }
772     my $s = get_desc $src, $Info, prefix => qq($short_name: ),
773 wakaba 1.4 padding_length => 51, padding_dot => q(.),
774     default => qq($short_name);
775 wakaba 1.3 $s .= "\n";
776     $s .= xml_parameter_ENTITY qq($mname.element), value => 'INCLUDE';
777 wakaba 1.5 my $cm = convert_content_model ($src, $Info, default => 'EMPTY');
778 wakaba 1.3 $s .= xml_condition_section (qq($mname.element) =>
779 wakaba 1.5 xml_parameter_ENTITY (qq($name.content), value => $cm)
780 wakaba 1.3 . xml_parameter_ENTITY (qq($name.qname), value => $short_name)
781 wakaba 1.5 . xml_parameter_ENTITY (qq($name.tagmin.start), value => q<->)
782     . xml_parameter_ENTITY (qq($name.tagmin.end), value => $cm eq 'EMPTY' ? q<o> : q<->)
783     . xml_condition_section (qq(sgml.tag.minimizable) =>
784     xml_parameter_ENTITY (qq($name.tagmin),
785     value => qq"%$name.tagmin.start; %$name.tagmin.end;"))
786     . xml_parameter_ENTITY (qq($name.tagmin), value => q"")
787     . qq(<!ELEMENT %$name.qname; %$name.tagmin; %$name.content;>\n));
788 wakaba 1.3 $s .= "\n";
789 wakaba 1.1 $s .= attlist_def (scalar $src->get_attribute ('Attribute', make_new_node => 1), $Info, $mname);
790     $s;
791     }
792    
793     sub get_model_token ($$) {
794     my ($name, $Info) = @_;
795     my $suffix = '.qname';
796     if ($name =~ s/^\$//) {
797     $suffix = $name =~ /\.(?:mix|class|content|datatype)$/ ? '' : '.class';
798     }
799     if ($name =~ /^:(.+)/) {
800     $name = qq(%$1$suffix;);
801     } elsif ($name =~ /([^:]+):(.+)/) {
802     $name = qq(%$1.$2$suffix;);
803     } elsif ($name =~ /"([^"]+)"/) {
804     $name = qq($1);
805     } else {
806     $name = qq(%$Info->{ID}.$name$suffix;);
807     }
808     $name;
809     }
810    
811     sub attlist_def ($$;$) {
812     my ($src, $Info, $name) = @_;
813     $name ||= get_name ($src, $Info, 'ElementType');
814     my $mname = get_name ($src, $Info);
815     $mname = ($name =~ /^\Q$Info->{ID}.\E/ ? $name : qq($Info->{ID}.$name))
816     if $mname eq "$Info->{ID}.";
817     $Info->{QName}->{$1} = 1 if $name =~ /^\Q$Info->{ID}\E\.(.+)/;
818 wakaba 1.3 my $s = qq(<!ATTLIST %$name.qname;);
819 wakaba 1.1 for my $src (@{$src->child_nodes}) {
820     ## Attribute Definition
821     if ($src->local_name eq 'Attribute') {
822     $s .= "\n\t". attrib_def ($src, $Info);
823     ## Reference to Attribute Definition
824     } elsif ($src->local_name eq 'ref') {
825     $s .= "\n\t". attrib_ref ($src, $Info);
826     } elsif ($src->local_name eq 'REF') {
827     $s .= "\n\t". attrib_REF ($src, $Info);
828     }
829     }
830     if ($_[2]) {
831     $s .= qq(\n\t%$Info->{ID}.common.attrib;);
832     }
833 wakaba 1.3 $s .= qq(>\n);
834     qq(@{[description ($src, $Info)]}<!ENTITY % $mname.attlist "INCLUDE">\n)
835     . xml_condition_section (qq($mname.attlist) => $s)
836     . "\n";
837 wakaba 1.1 }
838    
839 wakaba 1.3 sub make_module ($$$$;%) {
840     my ($src, $Info, $id, $s, %opt) = @_;
841 wakaba 1.1 my $name = $src->get_attribute_value ('Name')
842 wakaba 1.3 || {arch => q/Base Architecture/,
843     attribs => q/Common Attributes/,
844     blkphras => q/Block Phrasal/,
845     blkpres => q/Block Presentation/,
846     blkstruct => q/Block Structural/,
847     charent => q/Character Entities/,
848 wakaba 1.1 datatype => q/Datatypes/,
849 wakaba 1.3 framework => q/Modular Framework/,
850     inlphras => q/Inline Phrasal/,
851     inlpres => q/Inline Presentation/,
852     inlstruct => q/Inline Structural/,
853     legacy => q/Legacy Markup/,
854     list => q/Lists/,
855     meta => q/Metainformation/,
856 wakaba 1.1 model => q/Document Model/,
857 wakaba 1.3 notations => q/Notations/,
858     pres => q/Presentation/,
859     qname => q/QName (Qualified Name)/,
860     struct => q/Document Structure/,
861     text => q/Text/,
862 wakaba 1.1 }->{$id}
863     || $id;
864 wakaba 1.2 return unless $s;
865 wakaba 1.1
866     my $r = <<EOH;
867 wakaba 1.3 <!-- ...................................................................... -->
868     <!-- @{[do{
869     my $s = qq($Info->{Name} $name Module );
870     if (70 - length $s > 0) {
871     $s = dot_padding $s, length => 70, dot => q(.);
872     } else {
873     $s = qq( $name Module );
874     $s = qq($Info->{Name}\n ) . dot_padding $s, length => 70, dot => q(.);
875     }
876     $s;
877     }]} -->
878     <!-- file: $Info->{ID}-$id.mod
879 wakaba 1.1
880 wakaba 1.4 @{[make_paragraphs [$Info->{Description}], indent => q< >]}
881    
882 wakaba 1.3 Copyright @{[(gmtime)[5]+1900]} $Info->{Copyright}, All Rights Reserved.
883 wakaba 1.4
884     Permission to use, copy, modify and distribute this DTD and its
885     accompanying documentation for any purpose and without fee is hereby
886     granted in perpetuity, provided that the above copyright notice and
887     this paragraph appear in all copies. The copyright holders make no
888     representation about the suitability of the DTD for any purpose.
889    
890     It is provided "as is" without expressed or implied warranty.
891    
892 wakaba 1.1 Revision: @{[sprintf '%04d-%02d-%02dT%02d:%02d:%02d+00:00',
893 wakaba 1.3 (gmtime)[5]+1900, (gmtime)[4]+1, (gmtime)[3,2,1,0]
894     ]} (Generated by $SCRIPT_NAME/$VERSION)
895    
896     This DTD module is identified by the SYSTEM identifier:
897 wakaba 1.1
898 wakaba 1.3 SYSTEM "$Info->{BaseURI}$Info->{ID}-$id.mod"
899    
900     ...................................................................... -->
901    
902     EOH
903     ## TODO: Support PUBLIC identifier.
904 wakaba 1.1
905 wakaba 1.3 ## Module description
906     my @para = ({
907     arch => (join "\n",
908     q!This optional module includes declarations that enable to be used!,
909     q!as a base architecture according to the 'Architectural Forms Definition!,
910     q!Requirements' (Annex A.3, ISO/IEC 10744, 2nd edition). For more!,
911     q!information on use of architectural forms, see the HyTime web site at!,
912     q!<http://www.hytime.org/>.!),
913     attribs => q/This module declares many of the common attributes./,
914     blkphras => qq/This module declares the element types and their attributes used\n/.
915     q/to support block-level phrasal markup./,
916     blkpres => qq/This module declares the element types and their attributes used\n/.
917     q/to support block-level presentational markup./,
918     blkstruct => qq/This module declares the element types and their attributes used\n/.
919     q/to support block-level structural markup./,
920     charent => q/This module declares the set of character entities./,
921     datatype => q/This module defines containers for the datatypes./,
922     framework => qq/This module imstantiates the modules needed to support\n/.
923     q/the modularization model./,
924     inlphras => qq/This module declares the element types and their attributes used\n/.
925     q/to support inline phrasal markup./,
926     inlpres => qq/This module declares the element types and their attributes used\n/.
927     q/to support inline presentational markup./,
928     inlstruct => qq/This module declares the element types and their attributes used\n/.
929     q/to support inline structural markup./,
930     legacy => q/This module declares additional markup that is considered obsolete./,
931     list => qq/This module declares the list-oriented element types\n/.
932     q/and their attributes./,
933     meta => qq/This module declares the element types and their attributes\n/.
934     q/to support metainformation markup./,
935     model => qq/This model describes the groupings of element types that\n/.
936     q/make up common content models./,
937     pres => qq/This module declares the element types and their attributes used\n/.
938     q/to support presentational markup./,
939     qname => (join "\n",
940     q!This module is contained in two parts, labeled Section 'A' and 'B':!,
941     q!!,
942     q! Section A declares parameter entities to support namespace-qualified!,
943     q! names, namespace declarations, and name prefixing.!,
944     q!!,
945     q! Section B declares parameter entities used to provide namespace-qualified!,
946     q! names for all element types and global attribute names.!),
947     struct => qq/This module defines the major structural element types and\n/.
948     q/their attributes./,
949     }->{$id}, $src->get_attribute_value ('Description'));
950     unshift @para, ' '.join ', ', sort @{$Info->{elements}||[]} if @{$Info->{elements}||[]};
951     if (@para) {
952 wakaba 1.4 $name = qq($Info->{realname} QName (Qualified Name) Module)
953     if $id eq 'qname';
954 wakaba 1.3 $r .= <<EOH;
955     <!-- $name
956    
957     @{[make_paragraphs \@para, indent => ' ']}
958     -->
959    
960 wakaba 1.1 EOH
961 wakaba 1.3 }
962 wakaba 1.1
963     $r .= $s;
964    
965     $r .= qq(\n<!-- end of $Info->{ID}-$id.mod -->\n);
966    
967     my $file = qq"$Info->{ID}-$id.mod";
968     open FILE, '>', $file or die "$0: $file: $!";
969     print FILE $r;
970     close FILE;
971     print STDERR "$0: $file created\n";
972     }
973    
974     sub make_dtd ($$$$) {
975     my ($src, $Info, $id, $s) = @_;
976     $id = "-$id" if $id;
977    
978     my $r = <<EOH;
979 wakaba 1.3 <!-- ....................................................................... -->
980     <!-- @{[ dot_padding "$Info->{Name} DTD ", length => 71, dot => q(.) ]} -->
981     <!-- file: $Info->{ID}.dtd
982     -->
983    
984     <!-- $Info->{Name} DTD
985    
986 wakaba 1.4 @{[make_paragraphs [$Info->{Description}], indent => q< >]}
987 wakaba 1.3
988     Copyright @{[(gmtime)[5]+1900]} $Info->{Copyright}, All Rights Reserved.
989    
990     Permission to use, copy, modify and distribute this DTD and its
991     accompanying documentation for any purpose and without fee is hereby
992     granted in perpetuity, provided that the above copyright notice and
993     this paragraph appear in all copies. The copyright holders make no
994     representation about the suitability of the DTD for any purpose.
995    
996     It is provided "as is" without expressed or implied warranty.
997    
998     Revision: @{[sprintf '%04d-%02d-%02dT%02d:%02d:%02d+00:00',
999     (gmtime)[5]+1900, (gmtime)[4]+1, (gmtime)[3,2,1,0]]}
1000    
1001     -->
1002     <!-- This is the driver file for the $Info->{Name} DTD.
1003    
1004     This DTD is identified by the SYSTEM identifier:
1005    
1006 wakaba 1.1 SYSTEM "$Info->{BaseURI}$Info->{ID}$id.dtd"
1007 wakaba 1.3 -->
1008    
1009 wakaba 1.1 EOH
1010    
1011     $r .= $s;
1012    
1013     $r .= qq(\n<!-- end of $Info->{ID}$id.dtd -->\n);
1014    
1015     my $file = qq"$Info->{ID}$id.dtd";
1016     open FILE, '>', $file or die "$0: $file: $!";
1017     print FILE $r;
1018     close FILE;
1019     print STDERR "$0: $file created\n";
1020     }
1021    
1022    
1023     =head1 NAME
1024    
1025 wakaba 1.3 mkdtds.pl - Modularized XML Document Type Definition (DTD) Generator
1026 wakaba 1.1
1027     =head1 DESCRIPTION
1028    
1029 wakaba 1.3 This script generates XML DTD module implementations and/or DTD drivers,
1030     that can be used with modularized XHTML DTDs.
1031 wakaba 1.1
1032     =head1 USAGE
1033    
1034     $ perl mkdtds.pl driver.dds
1035     mkdtds.pl: driver.dtd created
1036     mkdtds.pl: driver-model.mod created
1037    
1038     $ perl mkdtds.pl moduleset.dms
1039     mkdtds.pl: moduleset-datatype.mod created
1040     mkdtds.pl: moduleset-attrib.mod created
1041     mkdtds.pl: moduleset-module1.mod created
1042    
1043     =head1 DTD SOURCE FORMAT
1044    
1045     (((See examples on <http://suika.fam.cx/gate/cvs/markup/>)))
1046    
1047 wakaba 1.3 =head1 REQUIRED MODULES
1048 wakaba 1.1
1049 wakaba 1.3 This script uses C<Message::Markup::SuikaWikiConfig20::Node> and
1050     C<Message::Markup::SuikaWikiConfig20::Parser>. Please retrive it from
1051     <http://suika.fam.cx/gate/cvs/messaging/manakai/lib/Message/Markup/SuikaWikiConfig20/>
1052     and put into your C<lib> directory.
1053 wakaba 1.1
1054     =head1 AUTHOR
1055    
1056     Wakaba <w@suika.fam.cx>
1057    
1058     =head1 LICENSE
1059    
1060 wakaba 1.3 Copyright 2003-2004 Wakaba <w@suika.fam.cx>
1061 wakaba 1.1
1062     This program is free software; you can redistribute it and/or
1063     modify it under the same terms as Perl itself.
1064    
1065 wakaba 1.3 Note that author claims no copyright with regard to DTD modules/drivers generated
1066     by this script. Author(s) of DTD modules/drivers should explicily state their
1067     license terms in them and their documentation (if any).
1068 wakaba 1.1
1069     =cut

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24