Generate ePub files of documentation.
[exim.git] / doc / doc-docbook / Pre-xml
1 #! /usr/bin/perl
2
3 # Script to pre-process XML input before processing it for various purposes.
4 # Options specify which transformations are to be done. Monospaced literal
5 # layout blocks are never touched.
6
7 # Changes:
8
9 # -ascii:    Replace ’ by '
10 #            Replace ©   by (c)
11 #            Replace † by *
12 #            Replace ‡ by **
13 #            Replace     by a space
14 #            Replace –  by -
15 #            Put quotes round <quote> text
16 #
17 # -quoteliteral:
18 #            Put quotes round <literal> text
19 #
20 # -bookinfo: Remove the <bookinfo> element from the file
21 #
22 # -fi:       Replace "fi" by &#xFB01; except when it is in an XML element, or
23 #            inside a <literal>.
24 #
25 # -html:     Certain things are done only for HTML output:
26 #
27 #            If <literallayout> is followed by optional space and then a
28 #            newline, the space and newline are removed, because otherwise you
29 #            get a blank line in the HTML output.
30 #
31 # -noindex   Remove the XML that generates indexes.
32 # -oneindex  Ditto, but add XML to generate a single index.
33 #
34 # -optbreak  Insert an optional line break (zero-width space, &#x200B;) after
35 #            every underscore in text within <option> and <variable> elements,
36 #            except when preceded by <entry> (i.e. not in tables). The same is
37 #            also done within a word of four or more upper-case letters (for
38 #            compile-time options).
39 #
40 # -epub      Convert date formats to comply with epub specification
41 #
42
43
44 # The function that processes non-literal, non-monospaced text
45
46 sub process()
47 {
48 my($s) = $_[0];
49
50 $s =~ s/fi(?![^<>]*>)/&#xFB01;/g if $ligatures;
51
52 if ($optbreak)
53   {
54   $s =~ s%(?<!<entry>)(<option>|<varname>)([^<]+)%
55     my($x,$y) = ($1,$2); $y =~ s/_/_&#x200B;/g; "$x"."$y"%gex;
56
57   $s =~ s?\b([A-Z_]{4,})\b?
58     my($x) = $1; $x =~ s/_/_&#x200B;/g; "$x"?gex;
59   }
60
61 if ($ascii)
62   {
63   $s =~ s/&#x2019;/'/g;
64   $s =~ s/&copy;/(c)/g;
65   $s =~ s/&dagger;/*/g;
66   $s =~ s/&Dagger;/**/g;
67   $s =~ s/&nsbp;/ /g;
68   $s =~ s/&ndash;/-/g;
69   $s =~ s/<quote>/"/g;
70   $s =~ s/<\/quote>/"/g;
71   }
72
73 $s;
74 }
75
76 # Mapping needed for epub
77
78 my %months = (
79   jan => '01', feb => '02', mar => '03', apr => '04', may => '05', jun => '06',
80   jul => '07', aug => '08', sep => '09', oct => '10', nov => '11', dec => '12',
81 );
82
83 # The main program
84
85 $ascii     = 0;
86 $bookinfo  = 0;
87 $epub      = 0;
88 $html      = 0;
89 $inliteral = 0;
90 $inliterallayout = 0;
91 $ligatures = 0;
92 $madeindex = 0;
93 $noindex   = 0;
94 $oneindex  = 0;
95 $optbreak  = 0;
96 $quoteliteral = 0;
97
98 foreach $arg (@ARGV)
99   {
100   if    ($arg eq "-fi")       { $ligatures = 1; }
101   elsif ($arg eq "-ascii")    { $ascii = 1; }
102   elsif ($arg eq "-bookinfo") { $bookinfo = 1; }
103   elsif ($arg eq "-epub")     { $epub = 1; }
104   elsif ($arg eq "-html")     { $html = 1; }
105   elsif ($arg eq "-noindex")  { $noindex = 1; }
106   elsif ($arg eq "-oneindex") { $oneindex = 1; }
107   elsif ($arg eq "-optbreak") { $optbreak = 1; }
108   elsif ($arg eq "-quoteliteral") { $quoteliteral = 1; }
109   else  { die "** Pre-xml: Unknown option \"$arg\"\n"; }
110   }
111
112 while (<STDIN>)
113   {
114   # Remove <bookinfo> if required
115
116   if ($bookinfo && /^<bookinfo/)
117     {
118     while (<STDIN>) { last if /^<\/bookinfo/; }
119     next;
120     }
121
122   # Copy monospaced literallayout blocks
123
124   if (/^<literallayout class="monospaced">/)
125     {
126     $_ = substr($_, 0, -1) if $html;
127     print;
128     while (<STDIN>)
129       {
130       print;
131       last if /^<\/literallayout>/;
132       }
133     next;
134     }
135
136   # Adjust index-generation code if required
137
138   if (($noindex || $oneindex) && /^<index[\s>]/)
139     {
140     while (<STDIN>)
141       {
142       last if /^<\/index>/;
143       }
144
145     if ($oneindex && !$madeindex)
146       {
147       $madeindex = 1;
148       print "<index><title>Index</title></index>\n";
149       }
150
151     next;
152     }
153
154   # Adjust dates to YYYY-MM-DD
155
156   if ($epub && /^\s*<date[\s>]/)
157     {
158     print;
159     while (<STDIN>)
160       {
161       last if /^\s*<\/date>/;
162
163       if (/^ \s* (\d{1,2}) \s+ ([a-zA-Z]{3}) \s+ (\d{4})/x)
164         {
165         die "Unknown month '$2'\n" unless exists $months{lc $2};
166         my $month = $months{lc $2};
167         s//$3-$month-$1/;
168         }
169       print;
170       }
171     }
172
173   # A line that is not in a monospaced literal block; keep track of which
174   # parts are in <literal> and which not. The latter get processed by the
175   # function above. Items in <literal> get quoted unless they are also in
176   # a <literallayout> block, or are already being quoted.
177
178   for (;;)
179     {
180     $_ = substr($_, 0, -1) if $html && /^<literallayout[^>]*>\s*\n$/;
181     $inliterallayout = 1 if /^<literallayout/;
182     $inliterallayout = 0 if /^<\/literallayout/;
183
184     if ($inliteral)
185       {
186       if (/^(.*?)<\/literal>(?!<\/quote>)(.*)$/)
187         {
188         print $1;
189         print "\"" if $quoteliteral && !$inliterallayout;
190         print "</literal>";
191         $inliteral = 0;
192         $_ = "$2\n";
193         }
194       else
195         {
196         print;
197         last;
198         }
199       }
200
201     # Not in literal state
202
203     else
204       {
205       if (/^(.*?)(?<!<quote>)<literal>(.*)$/)
206         {
207         print &process($1);
208         print "<literal>";
209         print "\"" if $quoteliteral && !$inliterallayout;
210         $inliteral = 1;
211         $_ = "$2\n";
212         }
213       else
214         {
215         print &process($_);
216         last;
217         }
218       }
219     }    # Loop for different parts of one line
220   }      # Loop for multiple lines
221
222 # End