source: git/doc/texi2html @ 94fcf4

spielwiese
Last change on this file since 94fcf4 was 94fcf4, checked in by Kai Krüger <krueger@…>, 26 years ago
*** empty log message *** git-svn-id: file:///usr/local/Singular/svn/trunk@2088 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 60.4 KB
RevLine 
[5d13bc]1#!/usr/bin/perl
2'di ';
3'ig 00 ';
[94fcf4]4# $Id: texi2html,v 1.2 1998-06-08 13:22:47 krueger Exp $
[5d13bc]5# Description: Program to transform most Texinfo documents to HTML.
6# The plan is for the next version of makeinfo to support HTML output
7# directly, but until then ...
8
9$THISPROG = "texi2html 1.54";                   # program name and version
10# This version of texi2html is currently maintained at
11# ftp://ftp.cs.umb.edu/pub/tex/texi2html by kb@cs.umb.edu.
12
13# The man page for this program is included at the end of this file and can be
14# viewed using the command 'nroff -man texi2html'.
15# Please read the copyright at the end of the man page.
16
17# Fixme:
18# deal with @macro @unmacro @shorttitlepage @detailmenu @image
19# [plus more fixmes below]
20# Use <link>s for Up, Index, Glossary?
21# Inserting copyright links: Having texinfo markup for the online copyright
22#  would allow a link to that from wherever.
23
24#+++############################################################################
25#                                                                              #
26# Constants                                                                    #
27#                                                                              #
28#---############################################################################
29
30$DEBUG_TOC   =  1;
31$DEBUG_INDEX =  2;
32$DEBUG_BIB   =  4;
33$DEBUG_GLOSS =  8;
34$DEBUG_DEF   = 16;
35$DEBUG_HTML  = 32;
36$DEBUG_USER  = 64;
37
38$BIBRE = '\[[\w\/]+\]';                 # RE for a bibliography reference
39$FILERE = '[\/\w.+-]+';                 # RE for a file name
40$VARRE = '[^\s\{\}]+';                  # RE for a variable name
41$NODERE = '[^@{}:\'`",]+';              # RE for a node name
42$NODESRE = '[^@{}:\'`"]+';              # RE for a list of node names
43$XREFRE = '[^@{}]+';                    # RE for a xref (should use NODERE)
44
45$ERROR = "***";                         # prefix for errors and warnings
46$HOMEPAGE = "http://wwwcn.cern.ch/dci/texi2html/"; # program home page
47$TODAY = &pretty_date;                  # like "20 September 1993"
48$SPLITTAG = "<!-- SPLIT HERE -->\n";    # tag to know where to split
49$PROTECTTAG = "_ThisIsProtected_";      # tag to recognize protected sections
50$TOPTAG = "<!--top-->";         # tag to mark first node (end of preamble)
51$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">';
52
53#
54# language dependent constants
55#
56#$LDC_SEE = 'see';
57#$LDC_SECTION = 'section';
58#$LDC_IN = 'in';
59#$LDC_TOC = 'Table of Contents';
60#$LDC_GOTO = 'Go to the';
61#$LDC_FOOT = 'Footnotes';
62# TODO: @def* shortcuts
63
64#
65# pre-defined indices
66#
67%predefined_index = (
68                    'cp', 'c',
69                    'fn', 'f',
70                    'vr', 'v',
71                    'ky', 'k',
72                    'pg', 'p',
73                    'tp', 't',
74                    );
75
76#
77# valid indices
78#
79%valid_index = (
80                    'c', 1,
81                    'f', 1,
82                    'v', 1,
83                    'k', 1,
84                    'p', 1,
85                    't', 1,
86                );
87
88#
89# texinfo section names to level
90#
91%sec2level = (
92              'top', 0,
93              'chapter', 1,
94              'unnumbered', 1,
95              'majorheading', 1,
96              'chapheading', 1,
97              'appendix', 1,
98              'section', 2,
99              'unnumberedsec', 2,
100              'heading', 2,
101              'appendixsec', 2,
102              'appendixsection', 2,
103              'subsection', 3,
104              'unnumberedsubsec', 3,
105              'subheading', 3,
106              'appendixsubsec', 3,
107              'subsubsection', 4,
108              'unnumberedsubsubsec', 4,
109              'subsubheading', 4,
110              'appendixsubsubsec', 4,
111              );
112
113#
114# accent map, TeX command to ISO name
115#
116%accent_map = (
117               '"',  'uml',
118               '~',  'tilde',
119               '^',  'circ',
120               '`',  'grave',
121               '\'', 'acute',
122               ',',  'cedil',
123               # fixme: (not Latin1) = H d dotaccent dotless ringaccent
124               # tieaccent u ubaraccent v
125               );
126
127#
128# texinfo "simple things" (@foo) to HTML ones
129#
130%simple_map = (
131               # cf. makeinfo.c
132               "*", "<BR>",             # HTML+
133               " ", "&#160;",   # nbsp
134               "\n", "\n",
135               "|", "",
136               # spacing commands
137               ":", "",
138               "!", "!",
139               "?", "?",
140               ".", ".",
141               "\t", " ",
142               "-", "&#173;",   # soft hyphen
143               'tab', '<TD>',
144               );
145
146#
147# texinfo "things" (@foo{}) to HTML ones
148#
149%things_map = (
150               'TeX', 'TeX',
151               'br', '<P>',             # paragraph break.  Gone from texinfo 3.9
152               'bullet', '*',
153               'copyright', '&#169;',
154               'dots', '...',
155               'enddots', '....',
156               'equiv', '==',
157               'error', 'error-->',
158               'expansion', '==>',
159               'minus', '-',
160               'point', '-!-',
161               'print', '-|',
162               'result', '=>',
163               'today', $TODAY,
164               # fixme: output these Latin1 characters as such rather
165               # than as entities?
166               'pounds', '&#163;',
167               'questiondown', '&#191;',
168               'ss', '&#223;',
169               'exclamdown', '&#161;',
170               'AA', '&#197;',
171               'AE', '&#198;',
172               'aa', '&#229;',
173               'ae', '&#230;',
174               'O', '&#216;',
175               'o', '&#248;',
176               # follow info rendering:
177               'L', 'L\/',
178               'l', 'l\/',
179               'OE', 'OE',
180               'oe', 'oe',
181               );
182
183#
184# texinfo styles (@foo{bar}) to HTML ones
185#
186%style_l_map = (
187              'center', 'CENTER',
188              );
189
190%style_map = (
191              'asis', '',               # ??
192              'b', 'B',
193              'cite', 'CITE',
194              'code', 'CODE',
195              'ctrl', '&do_ctrl',       # special case (obsolete)
196              'dfn', 'STRONG',          # DFN tag is illegal in the standard
197              'dmn', '',                # useless
198              'emph', 'EM',
199              'email', '&do_email',     # new special case
200              'file', '"TT',            # will put quotes, cf. &apply_style
201              'i', 'I',
202              'image', '&do_image',     # in-line images
203              'kbd', 'KBD',
204              'key', 'KBD',             # fixme: probably not <KBD>; possibly
205                                        # enclose in angles like makeinfo now does
206              'r', '',                  # unsupported
207              'samp', '"SAMP',          # will put quotes, cf. &apply_style
208              'sc', '&do_sc',           # special case
209              'strong', 'STRONG',
210              't', 'TT',
211              'titlefont', 'B',         # make it distinctive, at least
212              'uref', '&do_uref',       # new special case
213              'url', '&do_url',         # new special case
214              'var', 'VAR',
215              'w', '',                  # unsupported
216#             'math', 'I',              # not very useful, but at least italicize
217              'math', '',               # don't want italic numbers
218              );
219
220#
221# texinfo format (@foo/@end foo) to HTML ones
222#
223%format_map = (
224               'display', 'PRE',
225               'example', 'PRE',
226               'format', 'PRE', # fixme: shouldn't use tt, but can't avoid?
227               'lisp', 'PRE',
228               'quotation', 'BLOCKQUOTE',
229               'smallexample', 'PRE',
230               'smalllisp', 'PRE',
231               # lists
232               'itemize', 'UL',
233               'enumerate', 'OL',
234               # poorly supported
235               'flushleft', 'PRE',
236               'flushright', 'PRE',
237               );
238
239#
240# texinfo definition shortcuts to real ones
241#
242%def_map = (
243            # basic commands
244            'deffn', 0,
245            'defvr', 0,
246            'deftypefn', 0,
247            'deftypevr', 0,
248            'defcv', 0,
249            'defop', 0,
250            'deftp', 0,
251            # basic x commands
252            'deffnx', 0,
253            'defvrx', 0,
254            'deftypefnx', 0,
255            'deftypevrx', 0,
256            'defcvx', 0,
257            'defopx', 0,
258            'deftpx', 0,
259            # shortcuts
260            'defun', 'deffn Function',
261            'defmac', 'deffn Macro',
262            'defspec', 'deffn {Special Form}',
263            'defvar', 'defvr Variable',
264            'defopt', 'defvr {User Option}',
265            'deftypefun', 'deftypefn Function',
266            'deftypevar', 'deftypevr Variable',
267            'defivar', 'defcv {Instance Variable}',
268            'defmethod', 'defop Method',
269            # x shortcuts
270            'defunx', 'deffnx Function',
271            'defmacx', 'deffnx Macro',
272            'defspecx', 'deffnx {Special Form}',
273            'defvarx', 'defvrx Variable',
274            'defoptx', 'defvrx {User Option}',
275            'deftypefunx', 'deftypefnx Function',
276            'deftypevarx', 'deftypevrx Variable',
277            'defivarx', 'defcvx {Instance Variable}',
278            'defmethodx', 'defopx Method',
279            );
280
281#
282# things to skip
283#
284%to_skip = (
285            # comments
286            'c', 1,
287            'comment', 1,
288            # useless
289            'contents', 1,
290            'shortcontents', 1,
291            'summarycontents', 1,
292            'footnotestyle', 1,
293            'end ifclear', 1,
294            'end ifset', 1,
295            'titlepage', 1,
296            'end titlepage', 1,
297            'dircategory', 1,
298            # unsupported commands (formatting)
299            'afourpaper', 1,
300            'cropmarks', 1,
301            'finalout', 1,
302            'headings', 1,
303            'need', 1,
304            'page', 1,
305            'setchapternewpage', 1,
306            'everyheading', 1,
307            'everyfooting', 1,
308            'evenheading', 1,
309            'evenfooting', 1,
310            'oddheading', 1,
311            'oddfooting', 1,
312            'smallbook', 1,
313            'vskip', 1,
314            'filbreak', 1,
315            'centerchap', 1,
316            'setchapterstyle', 1,
317            'hyphenation', 1,
318            # unsupported formats
319            'cartouche', 1,
320            'end cartouche', 1,
321            'group', 1,
322            'end group', 1,
323            );
324
325#+++############################################################################
326#                                                                              #
327# Argument parsing, initialisation                                             #
328#                                                                              #
329#---############################################################################
330
331$use_bibliography = 1;
332$use_acc = 0;
333$debug = 0;
334$doctype = '';
335$check = 0;
336$expandinfo = 0;
337$use_glossary = 0;
338$invisible_mark = '';
339$use_iso = 0;
340@include_dirs = ();
341$show_menu = 0;
342$number_sections = 0;
343$split_node = 0;
344$split_chapter = 0;
345$monolithic = 0;
346$verbose = 0;
347$make_entry_page = 1;
348$make_menu_page = 1;
349$section_type = 0;
350$usage = <<EOT;
351This is $THISPROG
352To convert a Texinfo file to HMTL: $0 [options] file
353  where options can be:
354    -expandinfo    : use \@ifinfo sections, not \@iftex
355    -glossary      : handle a glossary
356    -invisible name: use 'name' as an invisible anchor
357    -I dir         : search also for files in 'dir'
358    -menu          : handle menus and don\'t do the ToC
359    -monolithic    : output only one file including ToC
360    -number        : number sections
361    -split_chapter : split on main sections
362    -split_node    : split on nodes
363    -check         : check given file for possible Texinfo commands
364    -usage         : print usage instructions
365    -verbose       : verbose output
366To check converted files: $0 -check [-verbose] files
367EOT
368
369while ($#ARGV >= 0 && $ARGV[0] =~ /^-/) {
370    $_ = shift(@ARGV);
371    if (/^-acc$/)            { $use_acc = 1; next; }
372    if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; }
373    if (/^-doctype$/)        { $doctype = shift(@ARGV); next; }
374    if (/^-c(heck)?$/)       { $check = 1; next; }
375    if (/^-e(xpandinfo)?$/)  { $expandinfo = 1; next; }
376    if (/^-g(lossary)?$/)    { $use_glossary = 1; next; }
377    if (/^-i(nvisible)?$/)   { $invisible_mark = shift(@ARGV); next; }
378    if (/^-iso$/)            { $use_iso = 1; next; }
379    if (/^-I(.+)?$/)         { push(@include_dirs, $1 || shift(@ARGV)); next; }
380    if (/^-m(enu)?$/)        { $show_menu = 1; next; }
381    if (/^-mono(lithic)?$/)  { $monolithic = 1; next; }
382    if (/^-n(umber)?$/)      { $number_sections = 1; next; }
383    if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) {
384        if ($2 =~ /^n/) {
385            $split_node = 1;
386        } else {
387            $split_chapter = 1;
388        }
389        next;
390    }
391    if (/^-v(erbose)?$/)     { $verbose = 1; next; }
392    die $usage;
393}
394if ($check) {
395    die $usage unless @ARGV > 0;
396    &check;
397    exit;
398}
399
400if (($split_node || $split_chapter) && $monolithic) {
401    warn "Can't use -monolithic with -split, -monolithic ignored.\n";
402    $monolithic = 0;
403}
404if ($expandinfo) {
405    $to_skip{'ifinfo'}++;
406    $to_skip{'end ifinfo'}++;
407} else {
408    $to_skip{'iftex'}++;
409    $to_skip{'end iftex'}++;
410}
411$invisible_mark = '<IMG SRC="invisible.xbm" ALT="">' if $invisible_mark eq 'xbm';
412die $usage unless @ARGV == 1;
413$docu = shift(@ARGV);
414if ($docu =~ /.*\//) {
415    chop($docu_dir = $&);
416    $docu_name = $';
417} else {
418    $docu_dir = '.';
419    $docu_name = $docu;
420}
421unshift(@include_dirs, $docu_dir);
422$docu_name =~ s/\.te?x(i|info)?$//;     # basename of the document
423
424$docu_doc = "$docu_name.html";          # document's contents
425if ($monolithic) {
426    $docu_toc = $docu_foot = $docu_doc;
427} else {
428    $docu_toc  = "${docu_name}_toc.html";  # document's table of contents
429    $docu_foot = "${docu_name}_foot.html"; # document's footnotes
430    $docu_left = "${docu_name}_left.html";
431    $docu_main = "index.html";
432}
433
434#
435# variables
436#
437%value = ();                            # hold texinfo variables
438$value{'html'} = 1;                     # predefine html (the output format)
439$value{'texi2html'} = '1.51a';          # predefine texi2html (the translator)
440# _foo: internal to track @foo
441foreach ('_author', '_title', '_subtitle',
442         '_settitle', '_setfilename') {
443    $value{$_} = '';                    # prevent -w warnings
444}
445%node2sec = ();                         # node to section name
446%node2href = ();                        # node to HREF
447%bib2href = ();                         # bibliography reference to HREF
448%gloss2href = ();                       # glossary term to HREF
449@sections = ();                         # list of sections
[94fcf4]450@left_index = ();
[5d13bc]451%tag2pro = ();                          # protected sections
452
453#
454# initial indexes
455#
456$bib_num = 0;
457$foot_num = 0;
458$gloss_num = 0;
459$idx_num = 0;
460$sec_num = 0;
461$doc_num = 0;
462$html_num = 0;
463
464#
465# can I use ISO8879 characters? (HTML+)
466#
467if ($use_iso) {
468    $things_map{'bullet'} = "&bull;";
469    $things_map{'copyright'} = "&copy;";
470    $things_map{'dots'} = "&hellip;";
471    $things_map{'equiv'} = "&equiv;";
472    $things_map{'expansion'} = "&rarr;";
473    $things_map{'point'} = "&lowast;";
474    $things_map{'result'} = "&rArr;";
475}
476
477#
478# read texi2html extensions (if any)
479#
480$extensions = 'texi2html.ext'; # extensions in working directory
481if (-f $extensions) {
482    print "# reading extensions from $extensions\n" if $verbose;
483    require($extensions);
484}
485($progdir = $0) =~ s/[^\/]+$//;
486if ($progdir && ($progdir ne './')) {
487    $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
488    if (-f $extensions) {
489        print "# reading extensions from $extensions\n" if $verbose;
490        require($extensions);
491    }
492}
493
494print "# reading from $docu\n" if $verbose;
495
496#+++############################################################################
497#                                                                              #
498# Pass 1: read source, handle command, variable, simple substitution           #
499#                                                                              #
500#---############################################################################
501
502@lines = ();                            # whole document
503@toc_lines = ();                        # table of contents
504@top_lines = ();                        # contents of top node
505@menu_lines = ();
506$toplevel = 0;                          # top level seen in hierarchy
507$curlevel = 0;                          # current level in TOC
508$node = '';                             # current node name
509$in_table = 0;                          # am I inside a table
510$table_type = '';                       # type of table ('', 'f', 'v')
511@tables = ();                           # nested table support
512$in_bibliography = 0;                   # am I inside a bibliography
513$in_glossary = 0;                       # am I inside a glossary
514$in_top = 0;                            # am I inside the top node
515$in_pre = 0;                            # am I inside a preformatted section
516$in_list = 0;                           # am I inside a list
517$in_html = 0;                           # am I inside an HTML section (@ifhtml)
518$in_raw_html = 0;                       # am I inside an HTML section (@html)
519$in_preamble = 1;                       # am I before the top node
520$first_line = 1;                        # is it the first line
521$dont_html = 0;                         # don't protect HTML on this line
522$split_num = 0;                         # split index
523$deferred_ref = '';                     # deferred reference for indexes
524@html_stack = ();                       # HTML elements stack
525$html_element = '';                     # current HTML element
526&html_reset;
527
528# build code for simple substitutions
529# the maps used (%simple_map and %things_map) MUST be aware of this
530# watch out for regexps, / and escaped characters!
531$subst_code = '';
532foreach (keys(%simple_map)) {
533    ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
534    $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
535}
536foreach (keys(%things_map)) {
537    $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
538}
539if ($use_acc) {
540    # accentuated characters
541    foreach (keys(%accent_map)) {
542        if ($_ eq "`") {
543            $subst_code .= "s/$;3";
544        } elsif ($_ eq "'") {
545            $subst_code .= "s/$;4";
546        } else {
547            $subst_code .= "s/\\\@\\$_";
548        }
549        $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
550    }
551}
552eval("sub simple_substitutions { $subst_code }");
553
554&init_input;
555while ($_ = &next_line) {
556    #
557    # remove \input on the first lines only
558    #
559    if ($first_line) {
560        next if /^\\input/;
561        $first_line = 0;
562    }
563    #
564    # parse texinfo tags
565    #
566    $tag = '';
567    $end_tag = '';
568    if (/^\@end\s+(\w+)\b/) {
569        $end_tag = $1;
570    } elsif (/^\@(\w+)\b/) {
571        $tag = $1;
572    }
573    #
574    # handle @ifhtml / @end ifhtml
575    #
576    if ($in_html) {
577        if ($end_tag eq 'ifhtml') {
578            $in_html = 0;
579        } else {
580            $tag2pro{$in_html} .= $_;
581        }
582        next;
583    } elsif ($tag eq 'ifhtml') {
584        $in_html = $PROTECTTAG . ++$html_num;
585        push(@lines, $in_html);
586        next;
587    }
588    #
589    # do raw HTML (no escapes)
590    #
591    if ($in_raw_html) {
592        if ($end_tag eq 'html') {
593            $in_raw_html = 0;
594        } else {
595            push (@lines, $_);
596        }
597        next;
598    } elsif ($tag eq 'html') {
599        $in_raw_html = 1;
600    }
601    #
602    # try to skip the line
603    #
604    if ($end_tag) {
605        next if $to_skip{"end $end_tag"};
606    } elsif ($tag) {
607        next if $to_skip{$tag};
608        last if $tag eq 'bye';
609    }
610    #
611    # try to remove inlined comments
612    # syntax from tex-mode.el comment-start-skip
613    #
614    s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
615    # non-@ substitutions cf. texinfmt.el
616    s/``/\"/g;
617    s/''/\"/g;
618    s/([\w ])---([\w ])/$1--$2/g;
619    #
620    # analyze the tag
621    #
622    if ($tag) {
623        # skip lines
624        &skip_until($tag), next if $tag eq 'ignore';
625        if ($expandinfo) {
626            &skip_until($tag), next if $tag eq 'iftex';
627        } else {
628            &skip_until($tag), next if $tag eq 'ifinfo' &&
629                ! $in_preamble; # we want the contents of the top node
630        }
631        &skip_until($tag), next if $tag eq 'tex';
632        # handle special tables
633        if ($tag eq 'table') {
634            $table_type = '';
635        } elsif ($tag eq 'ftable') {
636            $tag = 'table';
637            $table_type = 'f';
638        } elsif ($tag eq 'vtable') {
639            $tag = 'table';
640            $table_type = 'v';
641        } elsif ($tag eq 'multitable') {
642            $tag = 'table';
643            $table_type = '';
644        }
645        # special cases
646        if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+Top\s*,/i)) {
647            # We want to stash the contents of the top node (including
648            # @ifinfo bits).
649            $in_top = 1;
650            $in_preamble = 0;
651            @lines = (); # ignore all lines before top (title page garbage)
652            next;
653        } elsif ($tag eq 'node') {
654            push (@lines, "$TOPTAG") if ($in_top); # Mark end of top node
655            $in_top = 0;
656            $in_preamble = 0;
657            warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
658            $_ = &protect_html($_); # if node contains '&' for instance
659            s/^\@node\s+//;
660            ($node) = split(/,/);
661            &normalise_node($node);
662            if ($split_node) {
663                &next_doc;
664                push(@lines, $SPLITTAG) if $split_num++;
665                push(@sections, $node);
666            }
667            next;
668        } elsif ($tag eq 'include') {
669            if (/^\@include\s+($FILERE)\s*$/o) {
670                $file = $1;
671                unless (-e $file) {
672                    foreach $dir (@include_dirs) {
673                        $file = "$dir/$1";
674                        last if -e $file;
675                    }
676                }
677                if (-e $file) {
678                    &open($file);
679                    print "# including $file\n" if $verbose;
680                } else {
681                    warn "$ERROR Can't find $file, skipping";
682                }
683            } else {
684                warn "$ERROR Bad include line: $_";
685            }
686            next;
687        } elsif ($tag eq 'ifclear') {
688            if (/^\@ifclear\s+($VARRE)\s*$/o) {
689                next unless defined($value{$1});
690                &skip_until($tag);
691            } else {
692                warn "$ERROR Bad ifclear line: $_";
693            }
694            next;
695        } elsif ($tag eq 'ifset') {
696            if (/^\@ifset\s+($VARRE)\s*$/o) {
697                next if defined($value{$1});
698                &skip_until($tag);
699            } else {
700                warn "$ERROR Bad ifset line: $_";
701            }
702            next;
703        } elsif ($tag eq 'menu') {
704            unless ($show_menu) {
705                &skip_until($tag);
706                next;
707            }
708            &html_push_if($tag);
709            push(@lines, &html_debug("\n", __LINE__));
710        } elsif ($format_map{$tag}) {
711            $in_pre = 1 if $format_map{$tag} eq 'PRE';
712            &html_push_if($format_map{$tag});
713            push(@lines, &html_debug("\n", __LINE__));
714            $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
715            push(@lines, &debug("<$format_map{$tag}>\n", __LINE__));
716            next;
717        } elsif ($tag eq 'table') {
718            if (/^\@[fv]?table\s+\@(\w+)\s*$/) {
719                $in_table = $1;
720                unshift(@tables, join($;, $table_type, $in_table));
721                push(@lines, &debug("<DL COMPACT>\n", __LINE__));
722                &html_push_if('DL');
723                push(@lines, &html_debug("\n", __LINE__));
724            } elsif (/^\@multitable\s+/) {
725                # Note descent to HTML 3.2 necessary for multitable.
726                $in_table = ' ';
727                unshift(@tables, join($;, $table_type, $in_table));
728                push(@lines, &debug("<TABLE>\n", __LINE__));
729                &html_push_if('TABLE');
730                push(@lines, &html_debug("\n", __LINE__));
731            } else {
732                warn "$ERROR Bad table line: $_";
733            }
734            next;
735        } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
736            if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
737                eval("*${1}index = *${2}index");
738            } else {
739                warn "$ERROR Bad syn*index line: $_";
740            }
741            next;
742        } elsif ($tag eq 'sp') {
743            push(@lines, &debug("<P>\n", __LINE__));
744            next;
745        } elsif ($tag eq 'setref') {
746            &protect_html; # if setref contains '&' for instance
747            if (/^\@$tag\s*{($NODERE)}\s*$/) {
748                $setref = $1;
749                $setref =~ s/\s+/ /g; # normalize
750                $setref =~ s/ $//;
751                $node2sec{$setref} = $name;
752                $node2href{$setref} = "$docu_doc#$docid";
753            } else {
754                warn "$ERROR Bad setref line: $_";
755            }
756            next;
757        } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
758            if (/^\@$tag\s+(\w\w)\s*$/) {
759                $valid_index{$1} = 1;
760            } else {
761                warn "$ERROR Bad defindex line: $_";
762            }
763            next;
764        } elsif ($tag eq 'direntry') {
765            &skip_until ($tag);
766            next;
767        } elsif (defined($def_map{$tag})) {
768            if ($def_map{$tag}) {
769                s/^\@$tag\s+//;
770                $tag = $def_map{$tag};
771                $_ = "\@$tag $_";
772                $tag =~ s/\s.*//;
773            }
774        } elsif (defined($user_sub{$tag})) {
775            s/^\@$tag\s+//;
776            $sub = $user_sub{$tag};
777            print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER;
778            if (defined(&$sub)) {
779                chop($_);
780                &$sub($_);
781            } else {
782                warn "$ERROR Bad user sub for $tag: $sub\n";
783            }
784            next;
785        }
786        if (defined($def_map{$tag})) {
787            s/^\@$tag\s+//;
788            if ($tag =~ /x$/) {
789                # extra definition line
790                $tag = $`;
791                $is_extra = 1;
792            } else {
793                $is_extra = 0;
794            }
795            while (/\{([^\{\}]*)\}/) {
796                # this is a {} construct
797                ($before, $contents, $after) = ($`, $1, $');
798                # protect spaces
799                $contents =~ s/\s+/$;9/g;
800                # restore $_ protecting {}
801                $_ = "$before$;7$contents$;8$after";
802            }
803            @args = split(/\s+/, &protect_html($_));
804            foreach (@args) {
805                s/$;9/ /g;      # unprotect spaces
806                s/$;7/\{/g;     # ... {
807                s/$;8/\}/g;     # ... }
808            }
809            $type = shift(@args);
810            $type =~ s/^\{(.*)\}$/$1/;
811            print "# def ($tag): {$type} ", join(', ', @args), "\n"
812                if $debug & $DEBUG_DEF;
813            $type .= ':'; # it's nicer like this
814            $name = shift(@args);
815            $name =~ s/^\{(.*)\}$/$1/;
816            if ($is_extra) {
817                $_ = &debug("<DT>", __LINE__);
818            } else {
819                $_ = &debug("<DL>\n<DT>", __LINE__);
820            }
821            if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') {
822                $_ .= "<U>$type</U> <B>$name</B>";
823                $_ .= " <I>@args</I>" if @args;
824            } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
825                     || $tag eq 'defcv' || $tag eq 'defop') {
826                $ftype = $name;
827                $name = shift(@args);
828                $name =~ s/^\{(.*)\}$/$1/;
829                $_ .= "<U>$type</U> $ftype <B>$name</B>";
830                $_ .= " <I>@args</I>" if @args;
831            } else {
832                warn "$ERROR Unknown definition type: $tag\n";
833                $_ .= "<U>$type</U> <B>$name</B>";
834                $_ .= " <I>@args</I>" if @args;
835            }
836            $_ .= &debug("\n<DD>", __LINE__);
837            $name = &unprotect_html($name);
838            if ($tag eq 'deffn' || $tag eq 'deftypefn') {
839                unshift(@input_spool, "\@findex $name\n");
840            } elsif ($tag eq 'defop') {
841                unshift(@input_spool, "\@findex $name on $ftype\n");
842            } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') {
843                unshift(@input_spool, "\@vindex $name\n");
844            } else {
845                unshift(@input_spool, "\@tindex $name\n");
846            }
847            $dont_html = 1;
848        }
849    } elsif ($end_tag) {
850        if ($format_map{$end_tag}) {
851            $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
852            $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
853            &html_pop_if('LI', 'P');
854            &html_pop_if();
855            push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
856            push(@lines, &html_debug("\n", __LINE__));
857        } elsif ($end_tag eq 'table' ||
858                 $end_tag eq 'ftable' ||
859                 $end_tag eq 'vtable' ||
860                 $end_tag eq 'multitable') {
861            shift(@tables);
862            if (@tables) {
863                ($table_type, $in_table) = split($;, $tables[0]);
864            } else {
865                $in_table = 0;
866            }
867            if ($end_tag eq 'multitable') {
868                push(@lines, "</TABLE>\n");
869                &html_pop_if('TABLE');
870            } else {
871            push(@lines, "</DL>\n");
872            &html_pop_if('DD');
873            }
874            &html_pop_if();
875        } elsif (defined($def_map{$end_tag})) {
876            push(@lines, &debug("</DL>\n", __LINE__));
877        } elsif ($end_tag eq 'menu') {
878            &html_pop_if();
879            push(@lines, $_); # must keep it for pass 2
880        }
881        next;
882    }
883    #
884    # misc things
885    #
886    # protect texi and HTML things
887    &protect_texi;
888    $_ = &protect_html($_) unless $dont_html;
889    $dont_html = 0;
890    # substitution (unsupported things)
891    # s/^\@center\s+//g;                # fixme: use <center> or <div align=center>?
892    s/^\@exdent\s+//g;
893    s/\@noindent\s+//g;
894    s/\@refill\s+//g;
895    # other substitutions
896    &simple_substitutions;
897    s/\@value{($VARRE)}/$value{$1}/eg;
898    s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
899    #
900    # analyze the tag again
901    #
902    if ($tag) {
903        if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
904            if (/^\@$tag\s+(.+)$/) {
905                $name = $1;
906                $name =~ s/\s+$//;
907                $level = $sec2level{$tag};
908                $name = &update_sec_num($tag, $level) . "  $name"
909                    if $number_sections && $tag !~ /^unnumbered/;
[94fcf4]910                push(@left_index, $name);
[5d13bc]911                if ($tag =~ /heading$/) {
912                    push(@lines, &html_debug("\n", __LINE__));
913                    if ($html_element ne 'body') {
914                        # We are in a nice pickle here. We are trying to get a H? heading
915                        # even though we are not in the body level. So, we convert it to a
916                        # nice, bold, line by itself.
917                        $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__);
918                    } else {
919                        $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
920                        &html_push_if('body');
921                    }
922                    print "# heading, section $name, level $level\n"
923                        if $debug & $DEBUG_TOC;
924                } else {
925                    if ($split_chapter) {
926                        unless ($toplevel) {
927                            # first time we see a "section"
928                            unless ($level == 1) {
929                                warn "$ERROR The first section found is not of level 1: $_";
930                                warn "$ERROR I'll split on sections of level $level...\n";
931                            }
932                            $toplevel = $level;
933                        }
934                        if ($level == $toplevel) {
935                            &next_doc;
936                            push(@lines, $SPLITTAG) if $split_num++;
937                            push(@sections, $name);
938                        }
939                    }
940                    $sec_num++;
941                    $docid = "SEC$sec_num";
942                    $tocid = "TOC$sec_num";
943                    # check biblio and glossary
944                    $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
945                    $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
946                    # check node
947                    if ($node) {
948                        if ($node2sec{$node}) {
949                            warn "$ERROR Duplicate node found: $node\n";
950                        } else {
951                            $node2sec{$node} = $name;
952                            $node2href{$node} = "$docu_doc#$docid";
953                            print "# node $node, section $name, level $level\n"
954                                if $debug & $DEBUG_TOC;
955                        }
956                        $node = '';
957                    } else {
958                        print "# no node, section $name, level $level\n"
959                            if $debug & $DEBUG_TOC;
960                    }
961                    # update TOC
962                    while ($level > $curlevel) {
963                        $curlevel++;
964                        push(@toc_lines, "<UL>\n");
965                    }
966                    while ($level < $curlevel) {
967                        $curlevel--;
968                        push(@toc_lines, "</UL>\n");
969                    }
970                    $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", '', $name, 1);
971                    push(@toc_lines, &substitute_style($_));
972                    # update DOC
973                    push(@lines, &html_debug("\n", __LINE__));
974                    &html_reset;
975                    $_ =  "<H$level>".&anchor($docid, "$docu_toc#$tocid", '', $name)."</H$level>\n";
976                    $_ = &debug($_, __LINE__);
977                    push(@lines, &html_debug("\n", __LINE__));
978                }
979                # update DOC
980                foreach $line (split(/\n+/, $_)) {
981                    push(@lines, "$line\n");
982                }
983                next;
984            } else {
985                warn "$ERROR Bad section line: $_";
986            }
987        } else {
988            # track variables
989            $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o;
990            delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
991            # store things
992            $value{'_setfilename'}   = $1, next if /^\@setfilename\s+(.*)$/;
993            $value{'_settitle'}      = $1, next if /^\@settitle\s+(.*)$/;
994            $value{'_author'}   .= "$1\n", next if /^\@author\s+(.*)$/;
995            $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/;
996            $value{'_title'}    .= "$1\n", next if /^\@title\s+(.*)$/;
997            # index
998            if (/^\@(..?)index\s+/) {
999                unless ($valid_index{$1}) {
1000                    warn "$ERROR Undefined index command: $_";
1001                    next;
1002                }
1003                $id = 'IDX' . ++$idx_num;
1004                $index = $1 . 'index';
1005                $what = &substitute_style($');
1006                $what =~ s/\s+$//;
1007                print "# found $index for '$what' id $id\n"
1008                    if $debug & $DEBUG_INDEX;
1009                eval(<<EOC);
1010                if (defined(\$$index\{\$what\})) {
1011                    \$$index\{\$what\} .= "$;$docu_doc#$id";
1012                } else {
1013                    \$$index\{\$what\} = "$docu_doc#$id";
1014                }
1015EOC
1016                #
1017                # dirty hack to see if I can put an invisible anchor...
1018                #
1019                if ($html_element eq 'P' ||
1020                    $html_element eq 'LI' ||
1021                    $html_element eq 'DT' ||
1022                    $html_element eq 'DD' ||
1023                    $html_element eq 'ADDRESS' ||
1024                    $html_element eq 'B' ||
1025                    $html_element eq 'BLOCKQUOTE' ||
1026                    $html_element eq 'PRE' ||
1027                    $html_element eq 'SAMP') {
1028                    push(@lines, &anchor($id, '', '', $invisible_mark, !$in_pre));
1029                } elsif ($html_element eq 'body') {
1030                    push(@lines, &debug("<P>\n", __LINE__));
1031                    push(@lines, &anchor($id, '', '', $invisible_mark, !$in_pre));
1032                    &html_push('P');
1033                } elsif ($html_element eq 'DL' ||
1034                         $html_element eq 'UL' ||
1035                         $html_element eq 'OL' ) {
1036                    $deferred_ref .= &anchor($id, '', '', $invisible_mark, !$in_pre) . " ";
1037                }
1038                next;
1039            }
1040            # list item
1041            if (/^\@itemx?\s+/) {
1042                $what = $';
1043                $what =~ s/\s+$//;
1044                if ($in_bibliography && $use_bibliography) {
1045                    if ($what =~ /^$BIBRE$/o) {
1046                        $id = 'BIB' . ++$bib_num;
1047                        $bib2href{$what} = "$docu_doc#$id";
1048                        print "# found bibliography for '$what' id $id\n"
1049                            if $debug & $DEBUG_BIB;
1050                        $what = &anchor($id, '', '', $what);
1051                    }
1052                } elsif ($in_glossary && $use_glossary) {
1053                    $id = 'GLOSS' . ++$gloss_num;
1054                    $entry = $what;
1055                    $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
1056                    $gloss2href{$entry} = "$docu_doc#$id";
1057                    print "# found glossary for '$entry' id $id\n"
1058                        if $debug & $DEBUG_GLOSS;
1059                    $what = &anchor($id, '', '', $what);
1060                }
1061                &html_pop_if('P');
1062                if ($html_element eq 'DL' || $html_element eq 'DD') {
1063                    if ($things_map{$in_table} && !$what) {
1064                        # special case to allow @table @bullet for instance
1065                        push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__));
1066                    } else {
1067                        push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
1068                    }
1069                    push(@lines, "<DD>");
1070                    &html_push('DD') unless $html_element eq 'DD';
1071                    if ($table_type) { # add also an index
1072                        unshift(@input_spool, "\@${table_type}index $what\n");
1073                    }
1074                } elsif ($html_element eq 'TABLE' || $html_element eq 'TR') {
1075                    # Add <br> at ends of rows for non-tables browsers.
1076                    push(@lines, "<BR>\n") if $html_element eq 'TR';
1077                    push(@lines, "<TR>$what");
1078                    &html_push('TR') unless $html_element eq 'TR';
1079                } else {
1080                    push(@lines, &debug("<LI>$what\n", __LINE__));
1081                    &html_push('LI') unless $html_element eq 'LI';
1082                }
1083                push(@lines, &html_debug("\n", __LINE__));
1084                if ($deferred_ref) {
1085                    push(@lines, &debug("$deferred_ref\n", __LINE__));
1086                    $deferred_ref = '';
1087                }
1088                next;
1089            }
1090        }
1091    }
1092    # paragraph separator
1093    if ($_ eq "\n") {
1094        next if $#lines >= 0 && $lines[$#lines] eq "\n";
1095        if ($html_element eq 'P') {
1096            push(@lines, "\n");
1097            $_ = &debug("</P>\n", __LINE__);
1098            &html_pop;
1099        }
1100    } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') {
1101        push(@lines, "<P>\n");
1102        &html_push('P');
1103        $_ = &debug($_, __LINE__);
1104    }
1105    # otherwise
1106    push(@lines, $_);
1107}
1108
1109# finish TOC
1110$level = 0;
1111while ($level < $curlevel) {
1112    $curlevel--;
1113    push(@toc_lines, "</UL>\n");
1114}
1115
1116print "# end of pass 1\n" if $verbose;
1117
1118#+++############################################################################
1119#                                                                              #
1120# Pass 2/3: handle style, menu, index, cross-reference                         #
1121#                                                                              #
1122#---############################################################################
1123
1124@lines2 = ();                           # whole document (2nd pass)
1125@lines3 = ();                           # whole document (3rd pass)
1126$in_menu = 0;                           # am I inside a menu
1127$in_top = 1;
1128
1129while (@lines) {
1130    $_ = shift(@lines);
1131    #
1132    # special case (protected sections)
1133    #
1134    if (/^$PROTECTTAG/o) {
1135        push(@lines2, $_);
1136        next;
1137    }
1138    if ($in_top && $_ eq "$TOPTAG") {
1139        $in_top = 0;
1140        while(@lines2) {
1141            $_ = shift(@lines2);
1142            if (/\@(\w+)\ /) {
1143                ($before, $style, $after) = ($`, $1, $');
1144                if (defined($style_l_map{$style})) {
1145                    $_ = $after;
1146                    $text = '';
1147                    $after = '';
1148                    $failed = 1;
1149                    while (@lines2) {
1150                        if (/\n/) {
1151                            $text .= $`;
1152                            $after = $';
1153                            $failed = 0;
1154                            last;
1155                        } else {
1156                            $text .= $_;
1157                            $_ = shift(@lines2);
1158                        }
1159                    }
1160                    if ($failed) {
1161                        die "* Bad syntax (\@$style) after: $before\n";
1162                    } else {
1163                        $text = &apply_l_style($style, $text);
1164                        $_ = "$before$text$after\n";
1165                    }
1166                }
1167            }
1168            push(@top_lines, $_);
1169        }
1170        #@top_lines = @lines2;  # Contents of the top node.
1171        @lines2 = ();           # Don't use them in place.
1172        next;
1173    }
1174    #
1175    # menu
1176    #
1177    $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\@menu\b/;
1178    $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\@end\s+menu\b/;
1179    if ($in_menu) {
1180        if (/^\*\s+($NODERE)::/o) {
1181            $descr = $';
1182            chop($descr);
1183            &menu_entry($1, $1, $descr);
1184        } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
1185            $descr = $';
1186            chop($descr);
1187            &menu_entry($1, $2, $descr);
1188        } elsif (/^\*/) {
1189            warn "$ERROR Bad menu line: $_";
1190        } else { # description continued?
1191            push(@lines2, $_);
1192        }
1193        next;
1194    }
1195    #
1196    # printindex
1197    #
1198    if (/^\@printindex\s+(\w\w)\b/) {
1199        local($index, *ary, @keys, $key, $letter, $last_letter, @refs);
1200        if ($predefined_index{$1}) {
1201            $index = $predefined_index{$1} . 'index';
1202        } else {
1203            $index = $1 . 'index';
1204        }
1205        eval("*ary = *$index");
1206        @keys = keys(%ary);
1207        foreach $key (@keys) {
1208            $_ = $key;
1209            1 while s/<(\w+)>\`(.*)\'<\/\1>/$2/; # remove HTML tags with quotes
1210            1 while s/<(\w+)>(.*)<\/\1>/$2/;     # remove HTML tags
1211            $_ = &unprotect_html($_);
1212            &unprotect_texi;
1213            tr/A-Z/a-z/; # lowercase
1214            $key2alpha{$key} = $_;
1215            print "# index $key sorted as $_\n"
1216                if $key ne $_ && $debug & $DEBUG_INDEX;
1217        }
1218        $last_letter = undef;
1219        foreach $key (sort byalpha @keys) {
1220            $letter = substr($key2alpha{$key}, 0, 1);
1221            $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
1222            if (!defined($last_letter) || $letter ne $last_letter) {
1223                push(@lines2, "</DIR>\n") if defined($last_letter);
1224                push(@lines2, "<H2>" . &protect_html($letter) . "</H2>\n");
1225                push(@lines2, "<DIR>\n");
1226                $last_letter = $letter;
1227            }
1228            @refs = ();
1229            foreach (split(/$;/, $ary{$key})) {
1230                push(@refs, &anchor('', $_, '', $key, 0));
1231            }
1232            push(@lines2, "<LI>" . join(", ", @refs) . "\n");
1233        }
1234        push(@lines2, "</DIR>\n") if defined($last_letter);
1235        next;
1236    }
1237    #
1238    # simple style substitutions
1239    #
1240    $_ = &substitute_style($_);
1241    #
1242    # xref
1243    #
1244    while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) {
1245        # note: Texinfo may accept other characters
1246        ($type, $nodes, $full) = ($1, $2, $3);
1247        ($before, $after) = ($`, $');
1248        if (! $full && $after) {
1249            warn "$ERROR Bad xref (no ending } on line): $_";
1250            $_ = "$before$;0${type}ref\{$nodes$after";
1251            next; # while xref
1252        }
1253        if ($type eq 'x') {
1254            $type = 'See ';
1255        } elsif ($type eq 'px') {
1256            $type = 'see ';
1257        } elsif ($type eq 'info') {
1258            $type = 'See Info';
1259        } else {
1260            $type = '';
1261        }
1262        unless ($full) {
1263            $next = shift(@lines);
1264            $next = &substitute_style($next);
1265            chop($nodes); # remove final newline
1266            if ($next =~ /\}/) { # split on 2 lines
1267                $nodes .= " $`";
1268                $after = $';
1269            } else {
1270                $nodes .= " $next";
1271                $next = shift(@lines);
1272                $next = &substitute_style($next);
1273                chop($nodes);
1274                if ($next =~ /\}/) { # split on 3 lines
1275                    $nodes .= " $`";
1276                    $after = $';
1277                } else {
1278                    warn "$ERROR Bad xref (no ending }): $_";
1279                    $_ = "$before$;0xref\{$nodes$after";
1280                    unshift(@lines, $next);
1281                    next; # while xref
1282                }
1283            }
1284        }
1285        $nodes =~ s/\s+/ /g; # remove useless spaces
1286        @args = split(/\s*,\s*/, $nodes);
1287        $node = $args[0]; # the node is always the first arg
1288        &normalise_node($node);
1289        $sec = $node2sec{$node};
1290        if (@args == 5) { # reference to another manual
1291            $sec = $args[2] || $node;
1292            $man = $args[4] || $args[3];
1293            $_ = "${before}${type}section `$sec' in \@cite{$man}$after";
1294        } elsif ($type =~ /Info/) { # inforef
1295            warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
1296            ($nn, $_, $in) = @args;
1297            $_ = "${before}${type} file `$in', node `$nn'$after";
1298        } elsif ($sec) {
1299            $href = $node2href{$node};
1300            $_ = "${before}${type}section " . &anchor('', $href, '', $sec) . $after;
1301        } else {
1302            warn "$ERROR Undefined node ($node): $_";
1303            $_ = "$before$;0xref{$nodes}$after";
1304        }
1305    }
1306    #
1307    # try to guess bibliography references or glossary terms
1308    #
1309    unless (/^<H\d><A NAME=\"SEC\d/) {
1310        if ($use_bibliography) {
1311            $done = '';
1312            while (/$BIBRE/o) {
1313                ($pre, $what, $post) = ($`, $&, $');
1314                $href = $bib2href{$what};
1315                if (defined($href) && $post !~ /^[^<]*<\/A>/) {
1316                    $done .= $pre . &anchor('', $href, '', $what);
1317                } else {
1318                    $done .= "$pre$what";
1319                }
1320                $_ = $post;
1321            }
1322            $_ = $done . $_;
1323        }
1324        if ($use_glossary) {
1325            $done = '';
1326            while (/\b\w+\b/) {
1327                ($pre, $what, $post) = ($`, $&, $');
1328                $entry = $what;
1329                $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
1330                $href = $gloss2href{$entry};
1331                if (defined($href) && $post !~ /^[^<]*<\/A>/) {
1332                    $done .= $pre . &anchor('', $href, '', $what);
1333                } else {
1334                    $done .= "$pre$what";
1335                }
1336                $_ = $post;
1337            }
1338            $_ = $done . $_;
1339        }
1340    }
1341    # otherwise
1342    push(@lines2, $_);
1343}
1344print "# end of pass 2\n" if $verbose;
1345
1346#
1347# split style substitutions
1348#
1349while (@lines2) {
1350    $_ = shift(@lines2);
1351    #
1352    # special case (protected sections)
1353    #
1354    if (/^$PROTECTTAG/o) {
1355        push(@lines3, $_);
1356        next;
1357    }
1358    #
1359    # split style substitutions
1360    #
1361    $old = '';
1362    while ($old ne $_) {
1363        $old = $_;
1364        if (/\@(\w+)\{/) {
1365            ($before, $style, $after) = ($`, $1, $');
1366            if (defined($style_map{$style})) {
1367                $_ = $after;
1368                $text = '';
1369                $after = '';
1370                $failed = 1;
1371                while (@lines2) {
1372                    if (/\}/) {
1373                        $text .= $`;
1374                        $after = $';
1375                        $failed = 0;
1376                        last;
1377                    } else {
1378                        $text .= $_;
1379                        $_ = shift(@lines2);
1380                    }
1381                }
1382                if ($failed) {
1383                    die "* Bad syntax (\@$style) after: $before\n";
1384                } else {
1385                    $text = &apply_style($style, $text);
1386                    $_ = "$before$text$after";
1387                }
1388            }
1389        }
1390        if (/\@(\w+)\ /) {
1391            ($before, $style, $after) = ($`, $1, $');
1392            if (defined($style_l_map{$style})) {
1393                $_ = $after;
1394                $text = '';
1395                $after = '';
1396                $failed = 1;
1397                while (@lines2) {
1398                    if (/\n/) {
1399                        $text .= $`;
1400                        $after = $';
1401                        $failed = 0;
1402                        last;
1403                    } else {
1404                        $text .= $_;
1405                        $_ = shift(@lines2);
1406                    }
1407                }
1408                if ($failed) {
1409                    die "* Bad syntax (\@$style) after: $before\n";
1410                } else {
1411                    $text = &apply_l_style($style, $text);
1412                    $_ = "$before$text$after";
1413                }
1414            }
1415        }
1416    }
1417    # otherwise
1418    push(@lines3, $_);
1419}
1420print "# end of pass 3\n" if $verbose;
1421
1422#+++############################################################################
1423#                                                                              #
1424# Pass 4: foot notes, final cleanup                                            #
1425#                                                                              #
1426#---############################################################################
1427
1428@foot_lines = ();                       # footnotes
1429@doc_lines = ();                        # final document
1430$end_of_para = 0;                       # true if last line is <P>
1431
1432while (@lines3) {
1433    $_ = shift(@lines3);
1434    #
1435    # special case (protected sections)
1436    #
1437    if (/^$PROTECTTAG/o) {
1438        push(@doc_lines, $_);
1439        $end_of_para = 0;
1440        next;
1441    }
1442    #
1443    # footnotes
1444    #
1445    while (/\@footnote([^\{\s]+)\{/) {
1446        ($before, $d, $after) = ($`, $1, $');
1447        $_ = $after;
1448        $text = '';
1449        $after = '';
1450        $failed = 1;
1451        while (@lines3) {
1452            if (/\}/) {
1453                $text .= $`;
1454                $after = $';
1455                $failed = 0;
1456                last;
1457            } else {
1458                $text .= $_;
1459                $_ = shift(@lines3);
1460            }
1461        }
1462        if ($failed) {
1463            die "* Bad syntax (\@footnote) after: $before\n";
1464        } else {
1465            $foot_num++;
1466            $docid  = "DOCF$foot_num";
1467            $footid = "FOOT$foot_num";
1468            $foot = "($foot_num)";
1469            push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", '', $foot) . "</H3>\n");
1470            $text = "<P>$text" unless $text =~ /^\s*<P>/;
1471            push(@foot_lines, "$text\n");
1472            $_ = $before . &anchor($docid, "$docu_foot#$footid", '', $foot) . $after;
1473        }
1474    }
1475    #
1476    # remove unnecessary <P>
1477    #
1478    if (/^\s*<P>\s*$/) {
1479        next if $end_of_para++;
1480    } else {
1481        $end_of_para = 0;
1482    }
1483    # otherwise
1484    push(@doc_lines, $_);
1485}
1486print "# end of pass 4\n" if $verbose;
1487
1488push(@menu_lines, "<BODY BACKGROUND=\"/rock.gif\">\n");
1489#push(@menu_lines, "<BODY BACKGROUND=\"/rock.gif\" TEXT=\"yellow\"");
1490#push(@menu_lines, " LINK=#FFFFFF ALINK=#FF00FF VLINK=\"#00FF00\">\n");
1491#push(@menu_lines, "<NOBR>\n");
1492push(@menu_lines, "<DL>\n");
[94fcf4]1493foreach (@left_index) {
1494    if (!/^[A-Z0-9]\./) {
1495        &left_menu_entry($_);
1496    }
[5d13bc]1497}
1498push(@menu_lines, "</DL>\n");
1499print "# end of pass 5\n" if $verbose;
1500
1501#+++############################################################################
1502#                                                                              #
1503# Pass 6: print things                                                         #
1504#                                                                              #
1505#---############################################################################
1506
1507$header = <<EOT;
1508<!-- This HTML file has been created by $THISPROG
1509     from $docu on $TODAY -->
1510EOT
1511
1512$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
1513$title = $value{'_settitle'} || $full_title;
1514$_ = &substitute_style($full_title);
1515&unprotect_texi;
1516s/\n$//; # rmv last \n (if any)
1517$full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
1518
1519#
1520# print ToC
1521#
1522# ... unless using menus instead.  Make the TOC lines empty rather than
1523# null so we get a ToC page with the top node (including menu).
1524@toc_lines = ("") if $show_menu;
1525
1526if (!$monolithic && @toc_lines) {
1527    if (open(FILE, "> $docu_toc")) {
1528        print "# creating $docu_toc...\n" if $verbose;
1529        &print_toplevel_header("$title - Table of Contents");
1530        &print_ruler;
1531        &print (*top_lines, FILE); # Contents of the top node before the TOC.
1532        &print(*toc_lines, FILE);
1533        &print_toplevel_footer;
1534        close(FILE);
1535    } else {
1536        warn "$ERROR Can't write to $docu_toc: $!\n";
1537    }
1538}
1539
1540#
1541# print footnotes
1542#
1543if (!$monolithic && @foot_lines) {
1544    if (open(FILE, "> $docu_foot")) {
1545        print "# creating $docu_foot...\n" if $verbose;
1546        &print_toplevel_header("$title - Footnotes");
1547        &print_ruler;
1548        &print(*foot_lines, FILE);
1549        &print_toplevel_footer;
1550        close(FILE);
1551    } else {
1552        warn "$ERROR Can't write to $docu_foot: $!\n";
1553    }
1554}
1555
1556#
1557#
1558#
1559if (!$monolithic && $make_entry_page) {
1560    if(open(FILE, "> $docu_main")) {
1561        &print_header("$title - $docu_name", "", 1);
1562        print "# creating $docu_main...\n" if $verbose;
1563        &print_frame($docu_name);
1564        &print_toplevel_footer;
1565        close(FILE);
1566    } else {
1567        warn "$ERROR Can't write to $docu_main: $!\n";
1568    }
1569}
1570
1571#
1572#
1573#
1574if (!$monolithic && $make_menu_page && @menu_lines) {
1575    if(open(FILE, "> $docu_left")) {
1576        &print_header("$title - $docu_left", "", 1);
1577        print "# creating $docu_left...\n" if $verbose;
1578        &print(*menu_lines, FILE);
1579        &print_footer;
1580        close(FILE);
1581    } else {
1582        warn "$ERROR Can't write to $docu_main: $!\n";
1583    }
1584}
1585
1586#
1587# print document
1588#
1589if ($split_chapter || $split_node) { # split
1590    $doc_num = 0;
1591    $last_num = scalar(@sections);
1592    $first_doc = &doc_name(1);
1593    $last_doc = &doc_name($last_num);
1594    while (@sections) {
1595        $section = shift(@sections);
1596        &next_doc;
1597        if (open(FILE, "> $docu_doc")) {
1598            print "# creating $docu_doc...\n" if $verbose;
1599            $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1));
1600            $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1));
1601            $links = ($next_doc ? "<link href=\"$next_doc\" rel=Next>\n" : "");
1602            $links .= ($prev_doc ? "<link href=\"$prev_doc\" rel=Previous>\n" : "");
1603            $links .= "<link href=\"$docu_toc\" rel=ToC>\n";
1604            # fixme: try rel=Index too?
1605            &print_header("$title - $section", $links, 0);
1606
1607            $navigation = "<p>Go to the ";
1608            $navigation .= ($prev_doc ? &anchor('', $first_doc, '', "first") : "first");
1609            $navigation .= ", ";
1610            $navigation .= ($prev_doc ? &anchor('', $prev_doc, '', "previous") : "previous");
1611            $navigation .= ", ";
1612            $navigation .= ($next_doc ? &anchor('', $next_doc, '', "next") : "next");
1613            $navigation .= ", ";
1614            $navigation .= ($next_doc ? &anchor('', $last_doc, '', "last") : "last");
1615            $navigation .= " section, " . &anchor('', $docu_toc, '', "table of contents") . ".\n";
1616            print FILE $navigation;
1617            &print_ruler;
1618            # find corresponding lines
1619            @tmp_lines = ();
1620            while (@doc_lines) {
1621                $_ = shift(@doc_lines);
1622                last if ($_ eq $SPLITTAG);
1623                push(@tmp_lines, $_);
1624            }
1625            &print(*tmp_lines, FILE);
1626            &print_ruler;
1627            print FILE $navigation;
1628            &print_footer;
1629            close(FILE);
1630        } else {
1631            warn "$ERROR Can't write to $docu_doc: $!\n";
1632        }
1633    }
1634} else { # not split
1635    if (open(FILE, "> $docu_doc")) {
1636        print "# creating $docu_doc...\n" if $verbose;
1637        if ($monolithic || !@toc_lines) {
1638            &print_toplevel_header($title);
1639        } else {
1640            &print_header($title, "", 0);
1641            print FILE $full_title;
1642        }
1643        if ($monolithic && @toc_lines) {
1644            &print_ruler;
1645            print FILE "<H1>Table of Contents</H1>\n";
1646            &print(*toc_lines, FILE);
1647        }
1648        &print_ruler;
1649        &print(*doc_lines, FILE);
1650        if ($monolithic && @foot_lines) {
1651            &print_ruler;
1652            print FILE "<H1>Footnotes</H1>\n";
1653            &print(*foot_lines, FILE);
1654        }
1655        if ($monolithic || !@toc_lines) {
1656            &print_toplevel_footer;
1657        } else {
1658            &print_footer;
1659        }
1660        close(FILE);
1661    } else {
1662        warn "$ERROR Can't write to $docu_doc: $!\n";
1663    }
1664}
1665
1666print "# that's all folks\n" if $verbose;
1667
1668#+++############################################################################
1669#                                                                              #
1670# Low level functions                                                          #
1671#                                                                              #
1672#---############################################################################
1673
1674sub update_sec_num {
1675    local($name, $level) = @_;
1676
1677    $level--; # here we start at 0
1678    if (($name =~ /^appendix/) || ($section_type)) {
1679        # appendix style
1680        $section_type = 1;
1681        if (defined(@appendix_sec_num)) {
1682            &incr_sec_num($level, @appendix_sec_num);
1683        } else {
1684            @appendix_sec_num = ('A', 0, 0, 0);
1685        }
1686        return(join('.', @appendix_sec_num[0..$level]));
1687    } else {
1688        # normal style
1689        $section_type = 0;
1690        if (defined(@normal_sec_num)) {
1691            &incr_sec_num($level, @normal_sec_num);
1692        } else {
1693            @normal_sec_num = (1, 0, 0, 0);
1694        }
1695        return(join('.', @normal_sec_num[0..$level]));
1696    }
1697}
1698
1699sub incr_sec_num {
1700    local($level, $l);
1701    $level = shift(@_);
1702    $_[$level]++;
1703    foreach $l ($level+1 .. 3) {
1704        $_[$l] = 0;
1705    }
1706}
1707
1708sub check {
1709    local($_, %seen, %context, $before, $match, $after);
1710
1711    while (<>) {
1712        if (/\@(\*|\.|\:|\@|\{|\})/) {
1713            $seen{$&}++;
1714            $context{$&} .= "> $_" if $verbose;
1715            $_ = "$`XX$'";
1716            redo;
1717        }
1718        if (/\@(\w+)/) {
1719            ($before, $match, $after) = ($`, $&, $');
1720            if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
1721                $seen{'e-mail address'}++;
1722                $context{'e-mail address'} .= "> $_" if $verbose;
1723            } else {
1724                $seen{$match}++;
1725                $context{$match} .= "> $_" if $verbose;
1726            }
1727            $match =~ s/^\@/X/;
1728            $_ = "$before$match$after";
1729            redo;
1730        }
1731    }
1732   
1733    foreach (sort(keys(%seen))) {
1734        if ($verbose) {
1735            print "$_\n";
1736            print $context{$_};
1737        } else {
1738            print "$_ ($seen{$_})\n";
1739        }
1740    }
1741}
1742
1743sub open {
1744    local($name) = @_;
1745
1746    ++$fh_name;
1747    if (open($fh_name, $name)) {
1748        unshift(@fhs, $fh_name);
1749    } else {
1750        warn "$ERROR Can't read file $name: $!\n";
1751    }
1752}
1753
1754sub init_input {
1755    @fhs = ();                  # hold the file handles to read
1756    @input_spool = ();          # spooled lines to read
1757    $fh_name = 'FH000';
1758    &open($docu);
1759}
1760
1761sub next_line {
1762    local($fh, $line);
1763
1764    if (@input_spool) {
1765        $line = shift(@input_spool);
1766        return($line);
1767    }
1768    while (@fhs) {
1769        $fh = $fhs[0];
1770        $line = <$fh>;
1771        return($line) if $line;
1772        close($fh);
1773        shift(@fhs);
1774    }
1775    return(undef);
1776}
1777
1778# used in pass 1, use &next_line
1779sub skip_until {
1780    local($tag) = @_;
1781    local($_);
1782
1783    while ($_ = &next_line) {
1784        return if /^\@end\s+$tag\s*$/;
1785    }
1786    die "* Failed to find '$tag' after: " . $lines[$#lines];
1787}
1788
1789#
1790# HTML stacking to have a better HTML output
1791#
1792
1793sub html_reset {
1794    @html_stack = ('html');
1795    $html_element = 'body';
1796}
1797
1798sub html_push {
1799    local($what) = @_;
1800    push(@html_stack, $html_element);
1801    $html_element = $what;
1802}
1803
1804sub html_push_if {
1805    local($what) = @_;
1806    push(@html_stack, $html_element)
1807        if ($html_element && $html_element ne 'P');
1808    $html_element = $what;
1809}
1810
1811sub html_pop {
1812    $html_element = pop(@html_stack);
1813}
1814
1815sub html_pop_if {
1816    local($elt);
1817
1818    if (@_) {
1819        foreach $elt (@_) {
1820            if ($elt eq $html_element) {
1821                $html_element = pop(@html_stack) if @html_stack;
1822                last;
1823            }
1824        }
1825    } else {
1826        $html_element = pop(@html_stack) if @html_stack;
1827    }
1828}
1829
1830sub html_debug {
1831    local($what, $line) = @_;
1832    return("<!-- $line @html_stack, $html_element -->$what")
1833        if $debug & $DEBUG_HTML;
1834    return($what);
1835}
1836
1837# to debug the output...
1838sub debug {
1839    local($what, $line) = @_;
1840    return("<!-- $line -->$what")
1841        if $debug & $DEBUG_HTML;
1842    return($what);
1843}
1844
1845sub normalise_node {
1846    $_[0] =~ s/\s+/ /g;
1847    $_[0] =~ s/ $//;
1848    $_[0] =~ s/^ //;
1849}
1850
1851sub left_menu_entry {
1852    local($entry) = @_;
1853    local($_);
1854    local($href, $descr);
1855
1856    $_ = $entry;
1857    print "===>$_\n";
1858    s/^[0-9A-Z.]+ //;
1859    &normalise_node($_);
1860    $href = $node2href{$_};
1861    if ($href) {
1862        $descr =~ s/^\s+//;
1863        $descr = ": $descr" if $descr;
1864        push(@menu_lines, "<DT>" . &anchor('', $href, "Main", $entry) . "$descr</DT>\n");
1865    } else {
1866        warn "$ERROR Undefined node ($node): $_";
1867    }
1868}
1869
1870sub menu_entry {
1871    local($entry, $node, $descr) = @_;
1872    local($href);
1873
1874    &normalise_node($node);
1875    $href = $node2href{$node};
1876    if ($href) {
1877        $descr =~ s/^\s+//;
1878        $descr = ": $descr" if $descr;
1879        push(@lines2, "<LI>" . &anchor('', $href, '', $entry) . "$descr\n");
1880    } else {
1881        warn "$ERROR Undefined node ($node): $_";
1882    }
1883}
1884
1885sub do_email {
1886    my($address,$text);
1887    ($address,$text) = split(/,/, "$_[0]");
1888    $text =~ s/(^\s+)|(\s+$)//; # trim leading and trailing white space
1889    $text = $address unless $text;
1890    &anchor('', "mailto:${address}", '', "<TT>${text}</TT>")
1891}
1892
1893sub do_image {
1894    my($base,$width,$height,$image);
1895    ($base,$width,$height) = split(/,/,"$_[0]");
1896    if ( -f "${base}.jpg" ) {
1897        $image = "${base}.jpg";
1898    } elsif ( -f "${base}.gif" ) {
1899        $image = "${base}.gif";
1900    } else {
1901        $image = $base;
1902        warn "$ERROR image not found for ($base): $_";
1903    }
1904    "<BR><IMG SRC=\"${image}\"><BR>";
1905}
1906
1907sub do_uref {
1908  my($href,$text);
1909  ($href,$text) = split(/,/,"$_[0]");
1910  $text =~ s/(^\s+)|(\s+$)//;   # trim leading and trailing white space
1911  $text = $href unless $text;
1912# args to anchor() are: ($name, $href, $text, $newline)
1913  &anchor('', "$href", '', "<TT>$text</TT>")
1914}
1915
1916sub do_url {
1917    my($address,$text);
1918    ($address,$text) = split(/,/, "$_[0]");
1919    $text =~ s/(^\s+)|(\s+$)//; # trim leading and trailing white space
1920    $text = $address unless $text;
1921    $address =~ s/&#173;//g;
1922    &anchor('', "${address}", '', "<TT>${text}</TT>")
1923}
1924
1925sub do_ctrl { "^$_[0]" }
1926
1927sub do_sc { "\U$_[0]\E" }
1928
1929sub apply_style {
1930    local($texi_style, $text) = @_;
1931    local($style);
1932
1933    $style = $style_map{$texi_style};
1934    if (defined($style)) { # known style
1935        if ($style =~ /^\"/) { # add quotes
1936            $style = $';
1937            $text = "\`$text\'";
1938        }
1939        if ($style =~ /^\&/) { # custom
1940            $style = $';
1941            $text = &$style($text);
1942        } elsif ($style) { # good style
1943            $text = "<$style>$text</$style>";
1944        } else { # no style
1945        }
1946    } else { # unknown style
1947        $text = undef;
1948    }
1949    return($text);
1950}
1951
1952sub apply_l_style {
1953    local($texi_style, $text) = @_;
1954    local($style);
1955
1956    $style = $style_l_map{$texi_style};
1957    if (defined($style)) { # known style
1958        if ($style =~ /^\"/) { # add quotes
1959            $style = $';
1960            $text = "\`$text\'";
1961        }
1962        if ($style =~ /^\&/) { # custom
1963            $style = $';
1964            $text = &$style($text);
1965        } elsif ($style) { # good style
1966            $text = "<$style>$text</$style>";
1967        } else { # no style
1968        }
1969    } else { # unknown style
1970        $text = undef;
1971    }
1972    return($text);
1973}
1974
1975# remove Texinfo styles
1976sub remove_style {
1977    local($_) = @_;
1978    s/\@\w+{([^\{\}]+)}/$1/g;
1979    return($_);
1980}
1981
1982sub substitute_style {
1983    local($_) = @_;
1984    local($changed, $done, $style, $text);
1985
1986    $changed = 1;
1987    while ($changed) {
1988        $changed = 0;
1989        $done = '';
1990        while (/\@(\w+){([^\{\}]+)}/) {
1991            $text = &apply_style($1, $2);
1992            if ($text) {
1993                $_ = "$`$text$'";
1994                $changed = 1;
1995            } else {
1996                $done .= "$`\@$1";
1997                $_ = "{$2}$'";
1998            }
1999        }
2000        $_ = $done . $_;
2001    }
2002    return($_);
2003}
2004
2005sub anchor {
2006    local($name, $href, $target, $text, $newline) = @_;
2007    local($result);
2008
2009    $result = "<A";
2010    $result .= " NAME=\"$name\"" if $name;
2011    $result .= " HREF=\"$href\"" if $href;
2012    $result .= " TARGET=\"$target\"" if $target;
2013    $result .= ">$text</A>";
2014    $result .= "\n" if $newline;
2015    return($result);
2016}
2017
2018sub pretty_date {
2019    local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
2020
2021    @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
2022            'July', 'August', 'September', 'October', 'November', 'December');
2023    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
2024    $year += ($year < 70) ? 2000 : 1900;
2025    return("$mday $MoY[$mon] $year");
2026}
2027
2028sub doc_name {
2029    local($num) = @_;
2030
2031    return("${docu_name}_$num.html");
2032}
2033
2034sub next_doc {
2035    $docu_doc = &doc_name(++$doc_num);
2036}
2037
2038sub print {
2039    local(*lines, $fh) = @_;
2040    local($_);
2041
2042    while (@lines) {
2043        $_ = shift(@lines);
2044        if (/^$PROTECTTAG/o) {
2045            $_ = $tag2pro{$_};
2046        } else {
2047            &unprotect_texi;
2048        }
2049        print $fh $_;
2050    }
2051}
2052
2053sub print_ruler {
2054    print FILE "<P><HR><P>\n";
2055}
2056
2057sub print_frame {
2058    local($docu_right) = $_[0] . "_1";
2059    print FILE <<EOT;
2060<FRAMESET COLS="20%,*" BORDER=0>
2061<FRAME SRC="$docu_left" NAME="Links">
2062<FRAME SRC="$docu_right.html" NAME="Main">
2063</FRAMESET>
2064
2065EOT
2066}
2067
2068sub print_header {
2069    local($_);
2070
2071    $links = $_[1];
2072    $is_frame = $_[2];
2073    # clean the title
2074    $_ = &remove_style($_[0]);
2075    &unprotect_texi;
2076    # print the header
2077    if ($doctype eq 'html2') {
2078        print FILE $html2_doctype; # Wrong if any multitable used
2079    } elsif ($doctype) {
2080        print FILE $doctype;
2081    }
2082    print FILE <<EOT;
2083<HTML>
2084<HEAD>
2085$header
2086<TITLE>$_</TITLE>
2087$links
2088</HEAD>
2089EOT
2090    if(!$is_frame) { print FILE "<BODY background=\"/rock.gif\">\n"; }
2091}
2092
2093sub print_toplevel_header {
2094    local($_);
2095
2096    &print_header ($_[0], "", 0);
2097    print FILE $full_title;
2098    if ($value{'_subtitle'}) {
2099        $value{'_subtitle'} =~ s/\n+$//;
2100        foreach (split(/\n/, $value{'_subtitle'})) {
2101            $_ = &substitute_style($_);
2102            &unprotect_texi;
2103            print FILE "<H2>$_</H2>\n";
2104        }
2105    }
2106    if ($value{'_author'}) {
2107        $value{'_author'} =~ s/\n+$//;
2108        foreach (split(/\n/, $value{'_author'})) {
2109            $_ = &substitute_style($_);
2110            &unprotect_texi;
2111#           s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
2112            print FILE "<ADDRESS>$_</ADDRESS>\n";
2113        }
2114    }
2115    print FILE "<P>\n";
2116}
2117
2118sub print_footer {
2119    print FILE <<EOT;
2120</BODY>
2121</HTML>
2122EOT
2123}
2124
2125sub print_toplevel_footer {
2126    &print_ruler;
2127    print FILE <<EOT;
2128This document was generated on $TODAY using the
2129<A HREF=\"$HOMEPAGE\">texi2html</A>
2130translator version 1.51a.</P>
2131EOT
2132    &print_footer;
2133}
2134
2135sub protect_texi {
2136    # protect @ { } ` '
2137    s/\@\@/$;0/go;
2138    s/\@\{/$;1/go;
2139    s/\@\}/$;2/go;
2140    s/\@\`/$;3/go;
2141    s/\@\'/$;4/go;
2142}
2143
2144sub protect_html {
2145    local($what) = @_;
2146    # protect & < >
2147    $what =~ s/\&/\&\#38;/g;
2148    $what =~ s/\</\&\#60;/g;
2149    $what =~ s/\>/\&\#62;/g;
2150    # but recognize some HTML things
2151    $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g;             # </A>
2152    $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g;     # <A [^&]+>
2153    $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
2154    return($what);
2155}
2156
2157sub unprotect_texi {
2158    s/$;0/\@/go;
2159    s/$;1/\{/go;
2160    s/$;2/\}/go;
2161    s/$;3/\`/go;
2162    s/$;4/\'/go;
2163}
2164
2165sub unprotect_html {
2166    local($what) = @_;
2167    $what =~ s/\&\#38;/\&/g;
2168    $what =~ s/\&\#60;/\</g;
2169    $what =~ s/\&\#62;/\>/g;
2170    return($what);
2171}
2172
2173sub byalpha {
2174    $key2alpha{$a} cmp $key2alpha{$b};
2175}
2176
2177##############################################################################
2178
2179        # These next few lines are legal in both Perl and nroff.
2180
2181.00 ;                   # finish .ig
2182 
2183'di                     \" finish diversion--previous line must be blank
2184.nr nl 0-1              \" fake up transition to first page again
2185.nr % 0                 \" start at page 1
2186'; __END__ ############# From here on it's a standard manual page ############
2187.TH TEXI2HTML 1 "08/12/97"
2188.AT 3
2189.SH NAME
2190texi2html \- a Texinfo to HTML converter
2191.SH SYNOPSIS
2192.B texi2html [OPTION]... FILE
2193.PP
2194.B texi2html -check [-verbose] FILE...
2195.SH DESCRIPTION
2196.I Texi2html
2197converts the given Texinfo file to a set of HTML files. It tries to handle
2198most of the Texinfo commands. It creates hypertext links for cross-references,
2199footnotes...
2200.PP
2201It also tries to add links from a reference to its corresponding entry in the
2202bibliography (if any). It may also handle a glossary (see the
2203.B \-glossary
2204option).
2205.PP
2206.I Texi2html
2207creates several files depending on the contents of the Texinfo file and on
2208the chosen options (see FILES).
2209.PP
2210The HTML files created by
2211.I texi2html
2212are closer to TeX than to Info, that's why
2213.I texi2html
2214converts @iftex sections and not @ifinfo ones by default. You can reverse
2215this with the \-expandinfo option.
2216.SH OPTIONS
2217.TP 12
2218.B \-check
2219Check the given file and give the list of all things that may be Texinfo commands.
2220This may be used to check the output of
2221.I texi2html
2222to find the Texinfo commands that have been left in the HTML file.
2223.TP
2224.B \-expandinfo
2225Expand @ifinfo sections, not @iftex ones.
2226.TP
2227.B \-glossary
2228Use the section named 'Glossary' to build a list of terms and put links in the HTML
2229document from each term toward its definition.
2230.TP
2231.B \-invisible \fIname\fP
2232Use \fIname\fP to create invisible destination anchors for index links. This is a workaround
2233for a known bug of many WWW browsers, including xmosaic.
2234.TP
2235.B \-I \fIdir\fP
2236Look also in \fIdir\fP to find included files.
2237.TP
2238.B \-menu
2239Show the Texinfo menus; by default they are ignored.
2240.TP
2241.B \-monolithic
2242Output only one file, including the table of contents and footnotes.
2243.TP
2244.B \-number
2245Number the sections.
2246.TP
2247.B \-split_chapter
2248Split the output into several HTML files (one per main section:
2249chapter, appendix...).
2250.TP
2251.B \-split_node
2252Split the output into several HTML files (one per node).
2253.TP
2254.B \-usage
2255Print usage instructions, listing the current available command-line options.
2256.TP
2257.B \-verbose
2258Give a verbose output. Can be used with the
2259.B \-check
2260option.
2261.PP
2262.SH FILES
2263By default
2264.I texi2html
2265creates the following files (foo being the name of the Texinfo file):
2266.TP 16
2267.B foo_toc.html
2268The table of contents.
2269.TP
2270.B foo.html
2271The document's contents.
2272.TP
2273.B foo_foot.html
2274The footnotes (if any).
2275.PP
2276When used with the
2277.B \-split
2278option, it creates several files (one per chapter or node), named
2279.B foo_n.html
2280(n being the indice of the chapter or node), instead of the single
2281.B foo.html
2282file.
2283.PP
2284When used with the
2285.B \-monolithic
2286option, it creates only one file:
2287.B foo.html
2288.SH VARIABLES
2289.I texi2html
2290predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
2291.SH ADDITIONAL COMMANDS
2292.I texi2html
2293implements the following non-Texinfo commands:
2294.TP 16
2295.B @ifhtml
2296This indicates the start of an HTML section, this section will passed through
2297without any modofication.
2298.TP
2299.B @end ifhtml
2300This indcates the end of an HTML section.
2301.SH VERSION
2302This is \fItexi2html\fP version 1.54, 1998-01-17
2303.PP
2304The latest version of \fItexi2html\fP can be found at
2305ftp://ftp.cs.umb.edu/pub/tex/texi2html
2306.SH AUTHOR
2307The main author is Lionel Cons, CERN CN/DCI/UWS.
2308This version is maintained at ftp://ftp.cs.umb.edu/pub/tex/texi2html
2309by kb@cs.umb.edu.
2310Many other people around the net contributed to this program.
2311.SH COPYRIGHT
2312This program is the intellectual property of the European
2313Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
2314provided by CERN. No liability whatsoever is accepted for any loss or damage
2315of any kind resulting from any defect or inaccuracy in this information or
2316code.
2317.PP
2318CERN, 1211 Geneva 23, Switzerland
2319.SH "SEE ALSO"
2320GNU Texinfo Documentation Format,
2321HyperText Markup Language (HTML),
2322World Wide Web (WWW).
2323.SH BUGS
2324This program does not understand all Texinfo commands (yet).
2325.PP
2326TeX specific commands (normally enclosed in @iftex) will be
2327passed unmodified.
2328.ex
Note: See TracBrowser for help on using the repository browser.