7c9d1f67899992250bfd9ad4de6057a557ec2483
[perl.git] / pod / pod2latex.SH
1 case $CONFIG in
2 '')
3         if test -f config.sh; then TOP=.;
4         elif test -f ../config.sh; then TOP=..;
5         elif test -f ../../config.sh; then TOP=../..;
6         elif test -f ../../../config.sh; then TOP=../../..;
7         elif test -f ../../../../config.sh; then TOP=../../../..;
8         else
9                 echo "Can't find config.sh."; exit 1
10         fi
11         . $TOP/config.sh
12         ;;
13 esac
14 case "$0" in
15 */*) cd `expr X$0 : 'X\(.*\)/'` ;;
16 esac
17 echo "Extracting pod/pod2latex (with variable substitutions)"
18 rm -f pod2latex
19 $spitshell >pod2latex <<!GROK!THIS!
20 #!$bin/perl
21 eval 'exec $bin/perl -S \$0 \${1+"\$@"}'
22         if \$running_under_some_shell;
23 !GROK!THIS!
24
25 $spitshell >>pod2latex <<'!NO!SUBS!'
26 #
27 # pod2latex, version 1.1
28 # by Taro Kawagish (kawagish@imslab.co.jp),  Jan 11, 1995.
29 #
30 # pod2latex filters Perl pod documents to LaTeX documents.
31 #
32 # What pod2latex does:
33 # 1. Pod file 'perl_doc_entry.pod' is filtered to 'perl_doc_entry.tex'.
34 # 2. Indented paragraphs are translated into
35 #    '\begin{verbatim} ... \end{verbatim}'.
36 # 3. '=head1 heading' command is translated into '\section{heading}'
37 # 4. '=head2 heading' command is translated into '\subsection*{heading}'
38 # 5. '=over N' command is translated into
39 #        '\begin{itemize}'      if following =item starts with *,
40 #        '\begin{enumerate}'    if following =item starts with 1.,
41 #        '\begin{description}'  if else.
42 #      (indentation level N is ignored.)
43 # 6. '=item * heading' command is translated into '\item heading',
44 #    '=item 1. heading' command is translated into '\item heading',
45 #    '=item heading' command(other) is translated into '\item[heading]'.
46 # 7. '=back' command is translated into
47 #        '\end{itemize}'        if started with '\begin{itemize}',
48 #        '\end{enumerate}'      if started with '\begin{enumerate}',
49 #        '\end{description}'    if started with '\begin{description}'.
50 # 8. other paragraphs are translated into strings with TeX special characters
51 #    escaped.
52 # 9. In heading text, and other paragraphs, the following translation of pod
53 #    quotes are done, and then TeX special characters are escaped after that.
54 #      I<text> to {\em text\/},
55 #      B<text> to {\bf text},
56 #      S<text> to text1,
57 #        where text1 is a string with blank characters replaced with ~,
58 #      C<text> to {\tt text2},
59 #        where text2 is a string with TeX special characters escaped to
60 #        obtain a literal printout,
61 #      E<text> (HTML escape) to TeX escaped string,
62 #      L<text> to referencing string as is done by pod2man,
63 #      F<file> to {\em file\/},
64 #      Z<> to a null string,
65 # 10. those headings are indexed:
66 #       '=head1 heading'   =>  \section{heading}\index{heading}
67 #       '=head2 heading'   =>  \subsection*{heading}\index{heading}
68 #                 only when heading does not match frequent patterns such as
69 #                 DESCRIPTION, DIAGNOSTICS,...
70 #       '=item heading'   =>  \item{heading}\index{heading}
71 #
72 # Usage:
73 #     pod2latex perl_doc_entry.pod
74 # this will write to a file 'perl_doc_entry.tex'.
75 #
76 # To LaTeX:
77 # The following commands need to be defined in the preamble of the LaTeX
78 # document:
79 # \def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}}
80 # \def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}}
81 # and \parindent should be set zero:
82 # \setlength{\parindent}{0pt}
83 #
84 # Note:
85 # This script was written modifing pod2man.
86 #
87 # Bug:
88 # If HTML escapes E<text> other than E<amp>,E<lt>,E<gt>,E<quot> are used
89 # in C<>, translation will produce wrong character strings.
90 # Translation of HTML escapes of various European accents might be wrong.
91
92
93 $/ = "";                        # record separator is blank lines
94 # TeX special characters.
95 ##$tt_ables = "!@*()-=+|;:'\"`,./?<>";
96 $backslash_escapables = "#\$%&{}_";
97 $backslash_escapables2 = "#\$%&{}";     # except _
98 ##$nonverbables = "^\\~";
99 ##$bracketesc = "[]";
100 ##@tex_verb_fences = unpack("aaaaaaaaa","|#@!*+?:;");
101
102 @head1_freq_patterns            # =head1 patterns which need not be index'ed
103     = ("AUTHOR","Author","BUGS","DATE","DESCRIPTION","DIAGNOSTICS",
104        "ENVIRONMENT","EXAMPLES","FILES","INTRODUCTION","NAME","NOTE",
105        "SEE ALSO","SYNOPSIS","WARNING");
106
107 $indent = 0;
108
109 # parse the pods, produce LaTeX.
110
111 open(POD,"<$ARGV[0]") || die "cant open $ARGV[0]";
112 ($pod=$ARGV[0]) =~ s/\.pod$//;
113 open(LATEX,">$pod.tex");
114 &do_hdr();
115
116 $cutting = 1;
117 while (<POD>) {
118     if ($cutting) {
119         next unless /^=/;
120         $cutting = 0;
121     }
122     chop;
123     length || (print LATEX  "\n") && next;
124
125     # translate indented lines as a verabatim paragraph
126     if (/^\s/) {
127         @lines = split(/\n/);
128         print LATEX  "\\begin{verbatim}\n";
129         for (@lines) {
130             1 while s
131                 {^( [^\t]* ) \t ( \t* ) }
132                 { $1 . ' ' x (8 - (length($1)%8) + 8*(length($2))) }ex;
133             print LATEX  $_,"\n";
134         }
135         print LATEX  "\\end{verbatim}\n";
136         next;
137     }
138
139     # preserve '=item' line with pod quotes as they are.
140     if (/^=item/) {
141         ($bareitem = $_) =~ s/^=item\s*//;
142     }
143
144     # check for things that'll hosed our noremap scheme; affects $_
145     &init_noremap();
146
147     # expand strings "func()" as pod quotes.
148     if (!/^=item/) {
149         # first hide pod escapes.
150         # escaped strings are mapped into the ones with the MSB's on.
151         s/([A-Z]<[^<>]*>)/noremap($1)/ge;
152
153         # func() is a reference to a perl function
154         s{\b([:\w]+\(\))}{I<$1>}g;
155         # func(n) is a reference to a man page
156         s{(\w+)(\([^\s,\051]+\))}{I<$1>$2}g;
157         # convert simple variable references
158 #       s/([\$\@%][\w:]+)/C<$1>/g;
159 #       s/\$[\w:]+\[[0-9]+\]/C<$&>/g;
160
161         if (m{ ([\-\w]+\([^\051]*?[\@\$,][^\051]*?\))
162                }x && $` !~ /([LCI]<[^<>]*|-)$/ && !/^=\w/)
163         {
164             warn "``$1'' should be a [LCI]<$1> ref";
165         }
166         while (/(-[a-zA-Z])\b/g && $` !~ /[\w\-]$/) {
167             warn "``$1'' should be [CB]<$1> ref";
168         }
169
170         # put back pod quotes so we get the inside of <> processed;
171         $_ = &clear_noremap($_);
172     }
173
174
175     # process TeX special characters
176
177     # First hide HTML quotes E<> since they can be included in C<>.
178     s/(E<[^<>]+>)/noremap($1)/ge;
179
180     # Then hide C<> type literal quotes.
181     # String inside of C<> will later be expanded into {\tt ..} strings
182     # with TeX special characters escaped as needed.
183     s/(C<[^<>]*>)/&noremap($1)/ge;
184
185     # Next escape TeX special characters including other pod quotes B< >,...
186     #
187     # NOTE: s/re/&func($str)/e evaluates $str just once in perl5.
188     # (in perl4 evaluation takes place twice before getting passed to func().)
189
190     # - hyphen => ---
191     s/(\S+)(\s+)-+(\s+)(\S+)/"$1".&noremap(" --- ")."$4"/ge;
192     # '-', '--', "-"  =>  '{\tt -}', '{\tt --}', "{\tt -}"
193 ##    s/("|')(\s*)(-+)(\s*)\1/&noremap("$1$2\{\\tt $3\}$4$1")/ge;
194 ## changed Wed Jan 25 15:26:39 JST 1995
195     # '-', '--', "-"  =>  '$-$', '$--$', "$-$"
196     s/(\s+)(['"])(-+)([^'"\-]*)\2(\s+|[,.])/"$1$2".&noremap("\$$3\$")."$4$2$5"/ge;
197     s/(\s+)(['"])([^'"\-]*)(-+)(\s*)\2(\s+|[,.])/"$1$2$3".&noremap("\$$4\$")."$5$2$6"/ge;
198     # (--|-)  =>  ($--$|$-$)
199     s/(\s+)\((-+)([=@%\$\+\\\|\w]*)(-*)([=@%\$\+\\\|\w]*)\)(\s+|[,.])/"$1\(".&noremap("\$$2\$")."$3".&noremap("\$$4\$")."$5\)$6"/ge;
200     # numeral -  =>  $-$
201     s/(\(|[0-9]+|\s+)-(\s*\(?\s*[0-9]+)/&noremap("$1\$-\$$2")/ge;
202     # -- in quotes  =>  two separate -
203     s/B<([^<>]*)--([^<>]*)>/&noremap("B<$1\{\\tt --\}$2>")/ge;
204
205     # backslash escapable characters except _.
206     s/([$backslash_escapables2])/&noremap("\\$1")/ge;
207     s/_/&noremap("\\underscore{}")/ge;          # a litle thicker than \_.
208     # quote TeX special characters |, ^, ~, \.
209     s/\|/&noremap("\$|\$")/ge;
210     s/\^/&noremap("\$\\hat{\\hspace{0.4em}}\$")/ge;
211     s/\~/&noremap("\$\\tilde{\\hspace{0.4em}}\$")/ge;
212     s/\\/&noremap("\$\\backslash{}\$")/ge;
213     # quote [ and ] to be used in \item[]
214     s/([\[\]])/&noremap("{\\tt $1}")/ge;
215     # characters need to be treated differently in TeX
216     # keep * if an item heading
217     s/^(=item[ \t]+)[*]((.|\n)*)/"$1" . &noremap("*") . "$2"/ge;
218     s/[*]/&noremap("\$\\ast\$")/ge;     # other *
219
220     # hide other pod quotes.
221     s/([ABD-Z]<[^<>]*>)/&noremap($1)/ge;
222
223     # escape < and > as math strings,
224     # now that we are done with hiding pod <> quotes.
225     s/</&noremap("\$<\$")/ge;
226     s/>/&noremap("\$>\$")/ge;
227
228     # put it back so we get the <> processed again;
229     $_ = &clear_noremap($_);
230
231
232     # Expand pod quotes recursively:
233     # (1) type face directives [BIFS]<[^<>]*> to appropriate TeX commands,
234     # (2) L<[^<>]*> to reference strings,
235     # (3) C<[^<>]*> to TeX literal quotes,
236     # (4) HTML quotes E<> inside of C<> quotes.
237
238     # Hide E<> again since they can be included in C<>.
239     s/(E<[^<>]+>)/noremap($1)/ge;
240
241     $maxnest = 10;
242     while ($maxnest-- && /[A-Z]</) {
243
244         # bold and italic quotes
245         s/B<([^<>]*)>/"{\\bf $1}"/eg;
246         s#I<([^<>]*)>#"{\\em $1\\/}"#eg;
247
248         # files and filelike refs in italics
249         s#F<([^<>]*)>#"{\\em $1\\/}"#eg;
250
251         # no break quote -- usually we want C<> for this
252         s/S<([^<>]*)>/&nobreak($1)/eg;
253
254         # LREF: a manpage(3f)
255         s:L<([a-zA-Z][^\s\/]+)(\([^\)]+\))?>:the {\\em $1\\/}$2 manpage:g;
256
257         # LREF: an =item on another manpage
258         s{
259             L<([^/]+)/([:\w]+(\(\))?)>
260         } {the C<$2> entry in the I<$1> manpage}gx;
261
262         # LREF: an =item on this manpage
263         s{
264            ((?:L</([:\w]+(\(\))?)>
265             (,?\s+(and\s+)?)?)+)
266         } { &internal_lrefs($1) }gex;
267
268         # LREF: a =head2 (head1?), maybe on a manpage, maybe right here
269         # the "func" can disambiguate
270         s{
271             L<(?:([a-zA-Z]\S+?) /)?"?(.*?)"?>
272         }{
273             do {
274                 $1      # if no $1, assume it means on this page.
275                     ?  "the section on I<$2> in the I<$1> manpage"
276                     :  "the section on I<$2>"
277             } 
278         }gex;
279
280         s/Z<>/\\&/g;            # the "don't format me" thing
281
282         # comes last because not subject to reprocessing
283         s{
284             C<([^<>]*)>
285         }{
286             do {
287                 ($str = $1) =~ tr/\200-\377/\000-\177/; #normalize hidden stuff
288                 # expand HTML escapes if any;
289                 # WARNING: if HTML escapes other than E<amp>,E<lt>,E<gt>,
290                 # E<quot> are in C<>, they will not be printed correctly.
291                 $str = &expand_HTML_escapes($str);
292                 $strverb = &alltt($str);    # Tex verbatim escape of a string.
293                 &noremap("$strverb");
294             }
295         }gex;
296
297 #       if ( /C<([^<>]*)/ ) {
298 #           $str = $1;
299 #           if ($str !~ /\|/) {         # if includes |
300 #               s/C<([^<>]*)>/&noremap("\\verb|$str|")/eg;
301 #           } else {
302 #               print STDERR "found \| in C<.*> at paragraph $.\n";
303 #               # find a character not contained in $str to use it as a
304 #               # separator of the \verb
305 #               ($chars = $str) =~ s/(\W)/\\$1/g;
306 #               ## ($chars = $str) =~ s/([\$<>,\|"'\-^{}()*+?\\])/\\$1/g;
307 #               @fence = grep(!/[ $chars]/,@tex_verb_fences);
308 #               s/C<([^<>]*)>/&noremap("\\verb$fence[0]$str$fence[0]")/eg;
309 #           }
310 #       }
311     }
312
313
314     # process each pod command
315     if (s/^=//) {                               # if a command
316         s/\n/ /g;
317         ($cmd, $rest) = split(' ', $_, 2);
318         $rest =~ s/^\s*//;
319         $rest =~ s/\s*$//;
320
321         if (defined $rest) {
322             &escapes;
323         }
324
325         $rest = &clear_noremap($rest);
326         $rest = &expand_HTML_escapes($rest);
327
328         if ($cmd eq 'cut') {
329             $cutting = 1;
330             $lastcmd = 'cut';
331         }
332         elsif ($cmd eq 'head1') {       # heading type 1
333             $rest =~ s/^\s*//; $rest =~ s/\s*$//;
334             print LATEX  "\n\\subsection*{$rest}";
335             # put index entry
336             ($index = $rest) =~ s/^(An?\s+|The\s+)//i;  # remove 'A' and 'The'
337             # index only those heads not matching the frequent patterns.
338             foreach $pat (@head1_freq_patterns) {
339                 if ($index =~ /^$pat/) {
340                     goto freqpatt;
341                 }
342             }
343             print LATEX  "%\n\\index{$index}\n" if ($index);
344           freqpatt:
345             $lastcmd = 'head1';
346         }
347         elsif ($cmd eq 'head2') {       # heading type 2
348             $rest =~ s/^\s*//; $rest =~ s/\s*$//;
349             print LATEX  "\n\\subsubsection*{$rest}";
350             # put index entry
351             ($index = $rest) =~ s/^(An?\s+|The\s+)//i;  # remove 'A' and 'The'
352             $index =~ s/^Example\s*[1-9][0-9]*\s*:\s*//; # remove 'Example :'
353             print LATEX  "%\n\\index{$index}\n"  if ($index);
354             $lastcmd = 'head2';
355         }
356         elsif ($cmd eq 'over') {        # 1 level within a listing environment
357             push(@indent,$indent);
358             $indent = $rest + 0;
359             $lastcmd = 'over';
360         }
361         elsif ($cmd eq 'back') {        # 1 level out of a listing environment
362             $indent = pop(@indent);
363             warn "Unmatched =back\n" unless defined $indent;
364             $listingcmd = pop(@listingcmd);
365             print LATEX  "\n\\end{$listingcmd}\n"  if ($listingcmd);
366             $lastcmd = 'back';
367         }
368         elsif ($cmd eq 'item') {        # an item paragraph starts
369             if ($lastcmd eq 'over') {   # if we have just entered listing env
370                 # see what type of list environment we are in.
371                 if ($rest =~ /^[0-9]\.?/) {     # if numeral heading
372                     $listingcmd = 'enumerate';
373                 } elsif ($rest =~ /^\*\s*/) {   # if * heading
374                     $listingcmd = 'itemize';
375                 } elsif ($rest =~ /^[^*]/) {    # if other headings
376                     $listingcmd = 'description';
377                 } else {
378                     warn "unknown list type for item $rest";
379                 }
380                 print LATEX  "\n\\begin{$listingcmd}\n";
381                 push(@listingcmd,$listingcmd);
382             } elsif ($lastcmd ne 'item') {
383                 warn "Illegal '=item' command without preceding 'over':";
384                 warn "=item $bareitem";
385             }
386
387             if ($listingcmd eq 'enumerate') {
388                 $rest =~ s/^[0-9]+\.?\s*//;     # remove numeral heading
389                 print LATEX  "\n\\item";
390                 print LATEX  "{\\bf $rest}" if $rest;
391             } elsif ($listingcmd eq 'itemize') {
392                 $rest =~ s/^\*\s*//;            # remove * heading
393                 print LATEX  "\n\\item";
394                 print LATEX  "{\\bf $rest}" if $rest;
395             } else {                            # description item
396                 print LATEX  "\n\\item[$rest]";
397             }
398             $lastcmd = 'item';
399             $rightafter_item = 'yes';
400
401             # check if the item heading is short or long.
402             ($itemhead = $rest) =~ s/{\\bf (\S*)}/$1/g;
403             if (length($itemhead) < 4) {
404                 $itemshort = "yes";
405             } else {
406                 $itemshort = "no";
407             }
408             # write index entry
409             if ($pod =~ "perldiag") {                   # skip 'perldiag.pod'
410                 goto noindex;
411             }
412             # strip out the item of pod quotes and get a plain text entry
413             $bareitem =~ s/\n/ /g;                      # remove newlines
414             $bareitem =~ s/\s*$//;                      # remove trailing space
415             $bareitem =~ s/[A-Z]<([^<>]*)>/$1/g;        # remove <> quotes
416             ($index = $bareitem) =~ s/^\*\s+//;         # remove leading '*'
417             $index =~ s/^(An?\s+|The\s+)//i;            # remove 'A' and 'The'
418             $index =~ s/^\s*[1-9][0-9]*\s*[.]\s*$//; # remove numeral only
419             $index =~ s/^\s*\w\s*$//;                   # remove 1 char only's
420                 # quote ", @ and ! with " to be used in makeindex.
421             $index =~ s/"/""/g;                         # quote "
422             $index =~ s/@/"@/g;                         # quote @
423             $index =~ s/!/"!/g;                         # quote !
424             ($rest2=$rest) =~ s/^\*\s+//;       # remove *
425             $rest2 =~ s/"/""/g;                         # quote "
426             $rest2 =~ s/@/"@/g;                         # quote @
427             $rest2 =~ s/!/"!/g;                         # quote !
428             if ($pod =~ "(perlfunc|perlvar)") { # when doc is perlfunc,perlvar
429                 # take only the 1st word of item heading
430                 $index =~ s/^([^{}\s]*)({.*})?([^{}\s]*)\s+.*/\1\2\3/;
431                 $rest2 =~ s/^([^{}\s]*)({.*})?([^{}\s]*)\s+.*/\1\2\3/;
432             }
433             if ($index =~ /[A-Za-z\$@%]/) {
434                     #  write  \index{plain_text_entry@TeX_string_entry}
435                 print LATEX  "%\n\\index{$index\@$rest2}%\n";
436             }
437           noindex:
438             ;
439         }
440         else {
441             warn "Unrecognized directive: $cmd\n";
442         }
443     }
444     else {                                      # if not command
445         &escapes;
446         $_ = &clear_noremap($_);
447         $_ = &expand_HTML_escapes($_);
448
449         # if the present paragraphs follows an =item declaration,
450         # put a line break.
451         if ($lastcmd eq 'item' &&
452             $rightafter_item eq 'yes' && $itemshort eq "no") {
453             print LATEX  "\\hfil\\\\";
454             $rightafter_item = 'no';
455         }
456         print LATEX  "\n",$_;
457     }
458 }
459
460 print LATEX  "\n";
461 close(POD);
462 close(LATEX);
463
464
465 #########################################################################
466
467 sub do_hdr {
468     print LATEX "% LaTeX document produced by pod2latex from \"$pod.pod\".\n";
469     print LATEX "% The followings need be defined in the preamble of this document:\n";
470     print LATEX "%\\def\\C++{{\\rm C\\kern-.05em\\raise.3ex\\hbox{\\footnotesize ++}}}\n";
471     print LATEX "%\\def\\underscore{\\leavevmode\\kern.04em\\vbox{\\hrule width 0.4em height 0.3pt}}\n";
472     print LATEX "%\\setlength{\\parindent}{0pt}\n";
473     print LATEX "\n";
474     $podq = &escape_tex_specials("\U$pod\E");
475     print LATEX "\\section{$podq}%\n";
476     print LATEX "\\index{$podq}";
477     print LATEX "\n";
478 }
479
480 sub nobreak {
481     my $string = shift;
482     $string =~ s/ +/~/g;                # TeX no line break
483     $string;
484 }
485
486 sub noremap {
487     local($thing_to_hide) = shift;
488     $thing_to_hide =~ tr/\000-\177/\200-\377/;
489     return $thing_to_hide;
490 }
491
492 sub init_noremap {
493     if ( /[\200-\377]/ ) {
494         warn "hit bit char in input stream";
495     }
496 }
497
498 sub clear_noremap {
499     local($tmp) = shift;
500     $tmp =~ tr/\200-\377/\000-\177/;
501     return $tmp;
502 }
503
504 sub expand_HTML_escapes {
505     local($s) = $_[0];
506     $s =~ s { E<([A-Za-z]+)> }
507     {
508         do {
509             exists $HTML_Escapes{$1}
510             ? do { $HTML_Escapes{$1} }
511             : do {
512                 warn "Unknown escape: $& in $_";
513                 "E<$1>";
514             }
515         }
516     }egx;
517     return $s;
518 }
519
520 sub escapes {
521     # make C++ into \C++, which is to be defined as
522     # \def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}}
523     s/\bC\+\+/\\C++{}/g;
524 }
525
526 # Translate a string into a TeX \tt string to obtain a verbatim print out.
527 # TeX special characters are escaped by \.
528 # This can be used inside of LaTeX command arguments.
529 # We don't use LaTeX \verb since it doesn't work inside of command arguments.
530 sub alltt {
531     local($str) = shift;
532         # other chars than #,\,$,%,&,{,},_,\,^,~ ([ and ] included).
533     $str =~ s/([^${backslash_escapables}\\\^\~]+)/&noremap("$&")/eg;
534         # chars #,\,$,%,&,{,}  =>  \# , ...
535     $str =~ s/([$backslash_escapables2])/&noremap("\\$&")/eg;
536         # chars _,\,^,~  =>  \char`\_ , ...
537     $str =~ s/_/&noremap("\\char`\\_")/eg;
538     $str =~ s/\\/&noremap("\\char`\\\\")/ge;
539     $str =~ s/\^/\\char`\\^/g;
540     $str =~ s/\~/\\char`\\~/g;
541
542     $str =~ tr/\200-\377/\000-\177/;            # put back
543     $str = "{\\tt ".$str."}";                   # make it a \tt string
544     return $str;
545 }
546
547 sub escape_tex_specials {
548     local($str) = shift;
549         # other chars than #,\,$,%,&,{,},  _,\,^,~ ([ and ] included).
550     # backslash escapable characters #,\,$,%,&,{,} except _.
551     $str =~ s/([$backslash_escapables2])/&noremap("\\$1")/ge;
552     $str =~ s/_/&noremap("\\underscore{}")/ge;  # \_ is too thin.
553     # quote TeX special characters |, ^, ~, \.
554     $str =~ s/\|/&noremap("\$|\$")/ge;
555     $str =~ s/\^/&noremap("\$\\hat{\\hspace{0.4em}}\$")/ge;
556     $str =~ s/\~/&noremap("\$\\tilde{\\hspace{0.4em}}\$")/ge;
557     $str =~ s/\\/&noremap("\$\\backslash{}\$")/ge;
558     # characters need to be treated differently in TeX
559     # *
560     $str =~ s/[*]/&noremap("\$\\ast\$")/ge;
561     # escape < and > as math string,
562     $str =~ s/</&noremap("\$<\$")/ge;
563     $str =~ s/>/&noremap("\$>\$")/ge;
564     $str =~ tr/\200-\377/\000-\177/;            # put back
565     return $str;
566 }
567
568 sub internal_lrefs {
569     local($_) = shift;
570
571     s{L</([^>]+)>}{$1}g;
572     my(@items) = split( /(?:,?\s+(?:and\s+)?)/ );
573     my $retstr = "the ";
574     my $i;
575     for ($i = 0; $i <= $#items; $i++) {
576         $retstr .= "C<$items[$i]>";
577         $retstr .= ", " if @items > 2 && $i != $#items;
578         $retstr .= " and " if $i+2 == @items;
579     }
580     $retstr .= " entr" . ( @items > 1  ? "ies" : "y" )
581             .  " elsewhere in this document";
582
583     return $retstr;
584 }
585
586 # map of HTML escapes to TeX escapes.
587 BEGIN {
588 %HTML_Escapes = (
589     'amp'       =>      '&',    #   ampersand
590     'lt'        =>      '<',    #   left chevron, less-than
591     'gt'        =>      '>',    #   right chevron, greater-than
592     'quot'      =>      '"',    #   double quote
593
594     "Aacute"    =>      "\\'{A}",       #   capital A, acute accent
595     "aacute"    =>      "\\'{a}",       #   small a, acute accent
596     "Acirc"     =>      "\\^{A}",       #   capital A, circumflex accent
597     "acirc"     =>      "\\^{a}",       #   small a, circumflex accent
598     "AElig"     =>      '\\AE',         #   capital AE diphthong (ligature)
599     "aelig"     =>      '\\ae',         #   small ae diphthong (ligature)
600     "Agrave"    =>      "\\`{A}",       #   capital A, grave accent
601     "agrave"    =>      "\\`{a}",       #   small a, grave accent
602     "Aring"     =>      '\\u{A}',       #   capital A, ring
603     "aring"     =>      '\\u{a}',       #   small a, ring
604     "Atilde"    =>      '\\~{A}',       #   capital A, tilde
605     "atilde"    =>      '\\~{a}',       #   small a, tilde
606     "Auml"      =>      '\\"{A}',       #   capital A, dieresis or umlaut mark
607     "auml"      =>      '\\"{a}',       #   small a, dieresis or umlaut mark
608     "Ccedil"    =>      '\\c{C}',       #   capital C, cedilla
609     "ccedil"    =>      '\\c{c}',       #   small c, cedilla
610     "Eacute"    =>      "\\'{E}",       #   capital E, acute accent
611     "eacute"    =>      "\\'{e}",       #   small e, acute accent
612     "Ecirc"     =>      "\\^{E}",       #   capital E, circumflex accent
613     "ecirc"     =>      "\\^{e}",       #   small e, circumflex accent
614     "Egrave"    =>      "\\`{E}",       #   capital E, grave accent
615     "egrave"    =>      "\\`{e}",       #   small e, grave accent
616     "ETH"       =>      '\\OE',         #   capital Eth, Icelandic
617     "eth"       =>      '\\oe',         #   small eth, Icelandic
618     "Euml"      =>      '\\"{E}',       #   capital E, dieresis or umlaut mark
619     "euml"      =>      '\\"{e}',       #   small e, dieresis or umlaut mark
620     "Iacute"    =>      "\\'{I}",       #   capital I, acute accent
621     "iacute"    =>      "\\'{i}",       #   small i, acute accent
622     "Icirc"     =>      "\\^{I}",       #   capital I, circumflex accent
623     "icirc"     =>      "\\^{i}",       #   small i, circumflex accent
624     "Igrave"    =>      "\\`{I}",       #   capital I, grave accent
625     "igrave"    =>      "\\`{i}",       #   small i, grave accent
626     "Iuml"      =>      '\\"{I}',       #   capital I, dieresis or umlaut mark
627     "iuml"      =>      '\\"{i}',       #   small i, dieresis or umlaut mark
628     "Ntilde"    =>      '\\~{N}',       #   capital N, tilde
629     "ntilde"    =>      '\\~{n}',       #   small n, tilde
630     "Oacute"    =>      "\\'{O}",       #   capital O, acute accent
631     "oacute"    =>      "\\'{o}",       #   small o, acute accent
632     "Ocirc"     =>      "\\^{O}",       #   capital O, circumflex accent
633     "ocirc"     =>      "\\^{o}",       #   small o, circumflex accent
634     "Ograve"    =>      "\\`{O}",       #   capital O, grave accent
635     "ograve"    =>      "\\`{o}",       #   small o, grave accent
636     "Oslash"    =>      "\\O",          #   capital O, slash
637     "oslash"    =>      "\\o",          #   small o, slash
638     "Otilde"    =>      "\\~{O}",       #   capital O, tilde
639     "otilde"    =>      "\\~{o}",       #   small o, tilde
640     "Ouml"      =>      '\\"{O}',       #   capital O, dieresis or umlaut mark
641     "ouml"      =>      '\\"{o}',       #   small o, dieresis or umlaut mark
642     "szlig"     =>      '\\ss',         #   small sharp s, German (sz ligature)
643     "THORN"     =>      '\\L',          #   capital THORN, Icelandic
644     "thorn"     =>      '\\l',,         #   small thorn, Icelandic
645     "Uacute"    =>      "\\'{U}",       #   capital U, acute accent
646     "uacute"    =>      "\\'{u}",       #   small u, acute accent
647     "Ucirc"     =>      "\\^{U}",       #   capital U, circumflex accent
648     "ucirc"     =>      "\\^{u}",       #   small u, circumflex accent
649     "Ugrave"    =>      "\\`{U}",       #   capital U, grave accent
650     "ugrave"    =>      "\\`{u}",       #   small u, grave accent
651     "Uuml"      =>      '\\"{U}',       #   capital U, dieresis or umlaut mark
652     "uuml"      =>      '\\"{u}',       #   small u, dieresis or umlaut mark
653     "Yacute"    =>      "\\'{Y}",       #   capital Y, acute accent
654     "yacute"    =>      "\\'{y}",       #   small y, acute accent
655     "yuml"      =>      '\\"{y}',       #   small y, dieresis or umlaut mark
656 );
657 }
658 !NO!SUBS!
659 chmod 755 pod2latex
660 $eunicefix pod2latex