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

Contents of /markup/tool/mkdtds.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations) (download)
Mon Jul 5 13:57:21 2004 UTC (20 years, 4 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +99 -9 lines
File MIME type: text/plain
Error occurred while calculating annotation data.
Typo fix and ...

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24