source: git/doc/texi2html @ 5d13bc

spielwiese
Last change on this file since 5d13bc was 5d13bc, checked in by Kai Krüger <krueger@…>, 26 years ago
added texi2html git-svn-id: file:///usr/local/Singular/svn/trunk@2086 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 ';
4# $Id: texi2html,v 1.1 1998-06-08 13:06:03 krueger Exp $
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
450%tag2pro = ();                          # protected sections
451
452#
453# initial indexes
454#
455$bib_num = 0;
456$foot_num = 0;
457$gloss_num = 0;
458$idx_num = 0;
459$sec_num = 0;
460$doc_num = 0;
461$html_num = 0;
462
463#
464# can I use ISO8879 characters? (HTML+)
465#
466if ($use_iso) {
467    $things_map{'bullet'} = "&bull;";
468    $things_map{'copyright'} = "&copy;";
469    $things_map{'dots'} = "&hellip;";
470    $things_map{'equiv'} = "&equiv;";
471    $things_map{'expansion'} = "&rarr;";
472    $things_map{'point'} = "&lowast;";
473    $things_map{'result'} = "&rArr;";
474}
475
476#
477# read texi2html extensions (if any)
478#
479$extensions = 'texi2html.ext'; # extensions in working directory
480if (-f $extensions) {
481    print "# reading extensions from $extensions\n" if $verbose;
482    require($extensions);
483}
484($progdir = $0) =~ s/[^\/]+$//;
485if ($progdir && ($progdir ne './')) {
486    $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
487    if (-f $extensions) {
488        print "# reading extensions from $extensions\n" if $verbose;
489        require($extensions);
490    }
491}
492
493print "# reading from $docu\n" if $verbose;
494
495#+++############################################################################
496#                                                                              #
497# Pass 1: read source, handle command, variable, simple substitution           #
498#                                                                              #
499#---############################################################################
500
501@lines = ();                            # whole document
502@toc_lines = ();                        # table of contents
503@top_lines = ();                        # contents of top node
504@menu_lines = ();
505$toplevel = 0;                          # top level seen in hierarchy
506$curlevel = 0;                          # current level in TOC
507$node = '';                             # current node name
508$in_table = 0;                          # am I inside a table
509$table_type = '';                       # type of table ('', 'f', 'v')
510@tables = ();                           # nested table support
511$in_bibliography = 0;                   # am I inside a bibliography
512$in_glossary = 0;                       # am I inside a glossary
513$in_top = 0;                            # am I inside the top node
514$in_pre = 0;                            # am I inside a preformatted section
515$in_list = 0;                           # am I inside a list
516$in_html = 0;                           # am I inside an HTML section (@ifhtml)
517$in_raw_html = 0;                       # am I inside an HTML section (@html)
518$in_preamble = 1;                       # am I before the top node
519$first_line = 1;                        # is it the first line
520$dont_html = 0;                         # don't protect HTML on this line
521$split_num = 0;                         # split index
522$deferred_ref = '';                     # deferred reference for indexes
523@html_stack = ();                       # HTML elements stack
524$html_element = '';                     # current HTML element
525&html_reset;
526
527# build code for simple substitutions
528# the maps used (%simple_map and %things_map) MUST be aware of this
529# watch out for regexps, / and escaped characters!
530$subst_code = '';
531foreach (keys(%simple_map)) {
532    ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
533    $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
534}
535foreach (keys(%things_map)) {
536    $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
537}
538if ($use_acc) {
539    # accentuated characters
540    foreach (keys(%accent_map)) {
541        if ($_ eq "`") {
542            $subst_code .= "s/$;3";
543        } elsif ($_ eq "'") {
544            $subst_code .= "s/$;4";
545        } else {
546            $subst_code .= "s/\\\@\\$_";
547        }
548        $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
549    }
550}
551eval("sub simple_substitutions { $subst_code }");
552
553&init_input;
554while ($_ = &next_line) {
555    #
556    # remove \input on the first lines only
557    #
558    if ($first_line) {
559        next if /^\\input/;
560        $first_line = 0;
561    }
562    #
563    # parse texinfo tags
564    #
565    $tag = '';
566    $end_tag = '';
567    if (/^\@end\s+(\w+)\b/) {
568        $end_tag = $1;
569    } elsif (/^\@(\w+)\b/) {
570        $tag = $1;
571    }
572    #
573    # handle @ifhtml / @end ifhtml
574    #
575    if ($in_html) {
576        if ($end_tag eq 'ifhtml') {
577            $in_html = 0;
578        } else {
579            $tag2pro{$in_html} .= $_;
580        }
581        next;
582    } elsif ($tag eq 'ifhtml') {
583        $in_html = $PROTECTTAG . ++$html_num;
584        push(@lines, $in_html);
585        next;
586    }
587    #
588    # do raw HTML (no escapes)
589    #
590    if ($in_raw_html) {
591        if ($end_tag eq 'html') {
592            $in_raw_html = 0;
593        } else {
594            push (@lines, $_);
595        }
596        next;
597    } elsif ($tag eq 'html') {
598        $in_raw_html = 1;
599    }
600    #
601    # try to skip the line
602    #
603    if ($end_tag) {
604        next if $to_skip{"end $end_tag"};
605    } elsif ($tag) {
606        next if $to_skip{$tag};
607        last if $tag eq 'bye';
608    }
609    #
610    # try to remove inlined comments
611    # syntax from tex-mode.el comment-start-skip
612    #
613    s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
614    # non-@ substitutions cf. texinfmt.el
615    s/``/\"/g;
616    s/''/\"/g;
617    s/([\w ])---([\w ])/$1--$2/g;
618    #
619    # analyze the tag
620    #
621    if ($tag) {
622        # skip lines
623        &skip_until($tag), next if $tag eq 'ignore';
624        if ($expandinfo) {
625            &skip_until($tag), next if $tag eq 'iftex';
626        } else {
627            &skip_until($tag), next if $tag eq 'ifinfo' &&
628                ! $in_preamble; # we want the contents of the top node
629        }
630        &skip_until($tag), next if $tag eq 'tex';
631        # handle special tables
632        if ($tag eq 'table') {
633            $table_type = '';
634        } elsif ($tag eq 'ftable') {
635            $tag = 'table';
636            $table_type = 'f';
637        } elsif ($tag eq 'vtable') {
638            $tag = 'table';
639            $table_type = 'v';
640        } elsif ($tag eq 'multitable') {
641            $tag = 'table';
642            $table_type = '';
643        }
644        # special cases
645        if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+Top\s*,/i)) {
646            # We want to stash the contents of the top node (including
647            # @ifinfo bits).
648            $in_top = 1;
649            $in_preamble = 0;
650            @lines = (); # ignore all lines before top (title page garbage)
651            next;
652        } elsif ($tag eq 'node') {
653            push (@lines, "$TOPTAG") if ($in_top); # Mark end of top node
654            $in_top = 0;
655            $in_preamble = 0;
656            warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
657            $_ = &protect_html($_); # if node contains '&' for instance
658            s/^\@node\s+//;
659            ($node) = split(/,/);
660            &normalise_node($node);
661            if ($split_node) {
662                &next_doc;
663                push(@lines, $SPLITTAG) if $split_num++;
664                print "= = =>$node\n";
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/;
910                if ($tag =~ /heading$/) {
911                    push(@lines, &html_debug("\n", __LINE__));
912                    if ($html_element ne 'body') {
913                        # We are in a nice pickle here. We are trying to get a H? heading
914                        # even though we are not in the body level. So, we convert it to a
915                        # nice, bold, line by itself.
916                        $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__);
917                    } else {
918                        $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
919                        &html_push_if('body');
920                    }
921                    print "# heading, section $name, level $level\n"
922                        if $debug & $DEBUG_TOC;
923                } else {
924                    if ($split_chapter) {
925                        unless ($toplevel) {
926                            # first time we see a "section"
927                            unless ($level == 1) {
928                                warn "$ERROR The first section found is not of level 1: $_";
929                                warn "$ERROR I'll split on sections of level $level...\n";
930                            }
931                            $toplevel = $level;
932                        }
933                        if ($level == $toplevel) {
934                            &next_doc;
935                            push(@lines, $SPLITTAG) if $split_num++;
936                            print "=+=+=> $name;\n";
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");
1493foreach (@sections) {
1494    &left_menu_entry($_);
1495}
1496push(@menu_lines, "</DL>\n");
1497print "# end of pass 5\n" if $verbose;
1498
1499#+++############################################################################
1500#                                                                              #
1501# Pass 6: print things                                                         #
1502#                                                                              #
1503#---############################################################################
1504
1505$header = <<EOT;
1506<!-- This HTML file has been created by $THISPROG
1507     from $docu on $TODAY -->
1508EOT
1509
1510$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
1511$title = $value{'_settitle'} || $full_title;
1512$_ = &substitute_style($full_title);
1513&unprotect_texi;
1514s/\n$//; # rmv last \n (if any)
1515$full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
1516
1517#
1518# print ToC
1519#
1520# ... unless using menus instead.  Make the TOC lines empty rather than
1521# null so we get a ToC page with the top node (including menu).
1522@toc_lines = ("") if $show_menu;
1523
1524if (!$monolithic && @toc_lines) {
1525    if (open(FILE, "> $docu_toc")) {
1526        print "# creating $docu_toc...\n" if $verbose;
1527        &print_toplevel_header("$title - Table of Contents");
1528        &print_ruler;
1529        &print (*top_lines, FILE); # Contents of the top node before the TOC.
1530        &print(*toc_lines, FILE);
1531        &print_toplevel_footer;
1532        close(FILE);
1533    } else {
1534        warn "$ERROR Can't write to $docu_toc: $!\n";
1535    }
1536}
1537
1538#
1539# print footnotes
1540#
1541if (!$monolithic && @foot_lines) {
1542    if (open(FILE, "> $docu_foot")) {
1543        print "# creating $docu_foot...\n" if $verbose;
1544        &print_toplevel_header("$title - Footnotes");
1545        &print_ruler;
1546        &print(*foot_lines, FILE);
1547        &print_toplevel_footer;
1548        close(FILE);
1549    } else {
1550        warn "$ERROR Can't write to $docu_foot: $!\n";
1551    }
1552}
1553
1554#
1555#
1556#
1557if (!$monolithic && $make_entry_page) {
1558    if(open(FILE, "> $docu_main")) {
1559        &print_header("$title - $docu_name", "", 1);
1560        print "# creating $docu_main...\n" if $verbose;
1561        &print_frame($docu_name);
1562        &print_toplevel_footer;
1563        close(FILE);
1564    } else {
1565        warn "$ERROR Can't write to $docu_main: $!\n";
1566    }
1567}
1568
1569#
1570#
1571#
1572if (!$monolithic && $make_menu_page && @menu_lines) {
1573    if(open(FILE, "> $docu_left")) {
1574        &print_header("$title - $docu_left", "", 1);
1575        print "# creating $docu_left...\n" if $verbose;
1576        &print(*menu_lines, FILE);
1577        &print_footer;
1578        close(FILE);
1579    } else {
1580        warn "$ERROR Can't write to $docu_main: $!\n";
1581    }
1582}
1583
1584#
1585# print document
1586#
1587if ($split_chapter || $split_node) { # split
1588    $doc_num = 0;
1589    $last_num = scalar(@sections);
1590    $first_doc = &doc_name(1);
1591    $last_doc = &doc_name($last_num);
1592    while (@sections) {
1593        $section = shift(@sections);
1594        &next_doc;
1595        if (open(FILE, "> $docu_doc")) {
1596            print "# creating $docu_doc...\n" if $verbose;
1597            $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1));
1598            $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1));
1599            $links = ($next_doc ? "<link href=\"$next_doc\" rel=Next>\n" : "");
1600            $links .= ($prev_doc ? "<link href=\"$prev_doc\" rel=Previous>\n" : "");
1601            $links .= "<link href=\"$docu_toc\" rel=ToC>\n";
1602            # fixme: try rel=Index too?
1603            &print_header("$title - $section", $links, 0);
1604
1605            $navigation = "<p>Go to the ";
1606            $navigation .= ($prev_doc ? &anchor('', $first_doc, '', "first") : "first");
1607            $navigation .= ", ";
1608            $navigation .= ($prev_doc ? &anchor('', $prev_doc, '', "previous") : "previous");
1609            $navigation .= ", ";
1610            $navigation .= ($next_doc ? &anchor('', $next_doc, '', "next") : "next");
1611            $navigation .= ", ";
1612            $navigation .= ($next_doc ? &anchor('', $last_doc, '', "last") : "last");
1613            $navigation .= " section, " . &anchor('', $docu_toc, '', "table of contents") . ".\n";
1614            print FILE $navigation;
1615            &print_ruler;
1616            # find corresponding lines
1617            @tmp_lines = ();
1618            while (@doc_lines) {
1619                $_ = shift(@doc_lines);
1620                last if ($_ eq $SPLITTAG);
1621                push(@tmp_lines, $_);
1622            }
1623            &print(*tmp_lines, FILE);
1624            &print_ruler;
1625            print FILE $navigation;
1626            &print_footer;
1627            close(FILE);
1628        } else {
1629            warn "$ERROR Can't write to $docu_doc: $!\n";
1630        }
1631    }
1632} else { # not split
1633    if (open(FILE, "> $docu_doc")) {
1634        print "# creating $docu_doc...\n" if $verbose;
1635        if ($monolithic || !@toc_lines) {
1636            &print_toplevel_header($title);
1637        } else {
1638            &print_header($title, "", 0);
1639            print FILE $full_title;
1640        }
1641        if ($monolithic && @toc_lines) {
1642            &print_ruler;
1643            print FILE "<H1>Table of Contents</H1>\n";
1644            &print(*toc_lines, FILE);
1645        }
1646        &print_ruler;
1647        &print(*doc_lines, FILE);
1648        if ($monolithic && @foot_lines) {
1649            &print_ruler;
1650            print FILE "<H1>Footnotes</H1>\n";
1651            &print(*foot_lines, FILE);
1652        }
1653        if ($monolithic || !@toc_lines) {
1654            &print_toplevel_footer;
1655        } else {
1656            &print_footer;
1657        }
1658        close(FILE);
1659    } else {
1660        warn "$ERROR Can't write to $docu_doc: $!\n";
1661    }
1662}
1663
1664print "# that's all folks\n" if $verbose;
1665
1666#+++############################################################################
1667#                                                                              #
1668# Low level functions                                                          #
1669#                                                                              #
1670#---############################################################################
1671
1672sub update_sec_num {
1673    local($name, $level) = @_;
1674
1675    $level--; # here we start at 0
1676    if (($name =~ /^appendix/) || ($section_type)) {
1677        # appendix style
1678        $section_type = 1;
1679        if (defined(@appendix_sec_num)) {
1680            &incr_sec_num($level, @appendix_sec_num);
1681        } else {
1682            @appendix_sec_num = ('A', 0, 0, 0);
1683        }
1684        return(join('.', @appendix_sec_num[0..$level]));
1685    } else {
1686        # normal style
1687        $section_type = 0;
1688        if (defined(@normal_sec_num)) {
1689            &incr_sec_num($level, @normal_sec_num);
1690        } else {
1691            @normal_sec_num = (1, 0, 0, 0);
1692        }
1693        return(join('.', @normal_sec_num[0..$level]));
1694    }
1695}
1696
1697sub incr_sec_num {
1698    local($level, $l);
1699    $level = shift(@_);
1700    $_[$level]++;
1701    foreach $l ($level+1 .. 3) {
1702        $_[$l] = 0;
1703    }
1704}
1705
1706sub check {
1707    local($_, %seen, %context, $before, $match, $after);
1708
1709    while (<>) {
1710        if (/\@(\*|\.|\:|\@|\{|\})/) {
1711            $seen{$&}++;
1712            $context{$&} .= "> $_" if $verbose;
1713            $_ = "$`XX$'";
1714            redo;
1715        }
1716        if (/\@(\w+)/) {
1717            ($before, $match, $after) = ($`, $&, $');
1718            if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
1719                $seen{'e-mail address'}++;
1720                $context{'e-mail address'} .= "> $_" if $verbose;
1721            } else {
1722                $seen{$match}++;
1723                $context{$match} .= "> $_" if $verbose;
1724            }
1725            $match =~ s/^\@/X/;
1726            $_ = "$before$match$after";
1727            redo;
1728        }
1729    }
1730   
1731    foreach (sort(keys(%seen))) {
1732        if ($verbose) {
1733            print "$_\n";
1734            print $context{$_};
1735        } else {
1736            print "$_ ($seen{$_})\n";
1737        }
1738    }
1739}
1740
1741sub open {
1742    local($name) = @_;
1743
1744    ++$fh_name;
1745    if (open($fh_name, $name)) {
1746        unshift(@fhs, $fh_name);
1747    } else {
1748        warn "$ERROR Can't read file $name: $!\n";
1749    }
1750}
1751
1752sub init_input {
1753    @fhs = ();                  # hold the file handles to read
1754    @input_spool = ();          # spooled lines to read
1755    $fh_name = 'FH000';
1756    &open($docu);
1757}
1758
1759sub next_line {
1760    local($fh, $line);
1761
1762    if (@input_spool) {
1763        $line = shift(@input_spool);
1764        return($line);
1765    }
1766    while (@fhs) {
1767        $fh = $fhs[0];
1768        $line = <$fh>;
1769        return($line) if $line;
1770        close($fh);
1771        shift(@fhs);
1772    }
1773    return(undef);
1774}
1775
1776# used in pass 1, use &next_line
1777sub skip_until {
1778    local($tag) = @_;
1779    local($_);
1780
1781    while ($_ = &next_line) {
1782        return if /^\@end\s+$tag\s*$/;
1783    }
1784    die "* Failed to find '$tag' after: " . $lines[$#lines];
1785}
1786
1787#
1788# HTML stacking to have a better HTML output
1789#
1790
1791sub html_reset {
1792    @html_stack = ('html');
1793    $html_element = 'body';
1794}
1795
1796sub html_push {
1797    local($what) = @_;
1798    push(@html_stack, $html_element);
1799    $html_element = $what;
1800}
1801
1802sub html_push_if {
1803    local($what) = @_;
1804    push(@html_stack, $html_element)
1805        if ($html_element && $html_element ne 'P');
1806    $html_element = $what;
1807}
1808
1809sub html_pop {
1810    $html_element = pop(@html_stack);
1811}
1812
1813sub html_pop_if {
1814    local($elt);
1815
1816    if (@_) {
1817        foreach $elt (@_) {
1818            if ($elt eq $html_element) {
1819                $html_element = pop(@html_stack) if @html_stack;
1820                last;
1821            }
1822        }
1823    } else {
1824        $html_element = pop(@html_stack) if @html_stack;
1825    }
1826}
1827
1828sub html_debug {
1829    local($what, $line) = @_;
1830    return("<!-- $line @html_stack, $html_element -->$what")
1831        if $debug & $DEBUG_HTML;
1832    return($what);
1833}
1834
1835# to debug the output...
1836sub debug {
1837    local($what, $line) = @_;
1838    return("<!-- $line -->$what")
1839        if $debug & $DEBUG_HTML;
1840    return($what);
1841}
1842
1843sub normalise_node {
1844    $_[0] =~ s/\s+/ /g;
1845    $_[0] =~ s/ $//;
1846    $_[0] =~ s/^ //;
1847}
1848
1849sub left_menu_entry {
1850    local($entry) = @_;
1851    local($_);
1852    local($href, $descr);
1853
1854    $_ = $entry;
1855    print "===>$_\n";
1856    s/^[0-9A-Z.]+ //;
1857    &normalise_node($_);
1858    $href = $node2href{$_};
1859    if ($href) {
1860        $descr =~ s/^\s+//;
1861        $descr = ": $descr" if $descr;
1862        push(@menu_lines, "<DT>" . &anchor('', $href, "Main", $entry) . "$descr</DT>\n");
1863    } else {
1864        warn "$ERROR Undefined node ($node): $_";
1865    }
1866}
1867
1868sub menu_entry {
1869    local($entry, $node, $descr) = @_;
1870    local($href);
1871
1872    &normalise_node($node);
1873    $href = $node2href{$node};
1874    if ($href) {
1875        $descr =~ s/^\s+//;
1876        $descr = ": $descr" if $descr;
1877        push(@lines2, "<LI>" . &anchor('', $href, '', $entry) . "$descr\n");
1878    } else {
1879        warn "$ERROR Undefined node ($node): $_";
1880    }
1881}
1882
1883sub do_email {
1884    my($address,$text);
1885    ($address,$text) = split(/,/, "$_[0]");
1886    $text =~ s/(^\s+)|(\s+$)//; # trim leading and trailing white space
1887    $text = $address unless $text;
1888    &anchor('', "mailto:${address}", '', "<TT>${text}</TT>")
1889}
1890
1891sub do_image {
1892    my($base,$width,$height,$image);
1893    ($base,$width,$height) = split(/,/,"$_[0]");
1894    if ( -f "${base}.jpg" ) {
1895        $image = "${base}.jpg";
1896    } elsif ( -f "${base}.gif" ) {
1897        $image = "${base}.gif";
1898    } else {
1899        $image = $base;
1900        warn "$ERROR image not found for ($base): $_";
1901    }
1902    "<BR><IMG SRC=\"${image}\"><BR>";
1903}
1904
1905sub do_uref {
1906  my($href,$text);
1907  ($href,$text) = split(/,/,"$_[0]");
1908  $text =~ s/(^\s+)|(\s+$)//;   # trim leading and trailing white space
1909  $text = $href unless $text;
1910# args to anchor() are: ($name, $href, $text, $newline)
1911  &anchor('', "$href", '', "<TT>$text</TT>")
1912}
1913
1914sub do_url {
1915    my($address,$text);
1916    ($address,$text) = split(/,/, "$_[0]");
1917    $text =~ s/(^\s+)|(\s+$)//; # trim leading and trailing white space
1918    $text = $address unless $text;
1919    $address =~ s/&#173;//g;
1920    &anchor('', "${address}", '', "<TT>${text}</TT>")
1921}
1922
1923sub do_ctrl { "^$_[0]" }
1924
1925sub do_sc { "\U$_[0]\E" }
1926
1927sub apply_style {
1928    local($texi_style, $text) = @_;
1929    local($style);
1930
1931    $style = $style_map{$texi_style};
1932    if (defined($style)) { # known style
1933        if ($style =~ /^\"/) { # add quotes
1934            $style = $';
1935            $text = "\`$text\'";
1936        }
1937        if ($style =~ /^\&/) { # custom
1938            $style = $';
1939            $text = &$style($text);
1940        } elsif ($style) { # good style
1941            $text = "<$style>$text</$style>";
1942        } else { # no style
1943        }
1944    } else { # unknown style
1945        $text = undef;
1946    }
1947    return($text);
1948}
1949
1950sub apply_l_style {
1951    local($texi_style, $text) = @_;
1952    local($style);
1953
1954    $style = $style_l_map{$texi_style};
1955    if (defined($style)) { # known style
1956        if ($style =~ /^\"/) { # add quotes
1957            $style = $';
1958            $text = "\`$text\'";
1959        }
1960        if ($style =~ /^\&/) { # custom
1961            $style = $';
1962            $text = &$style($text);
1963        } elsif ($style) { # good style
1964            $text = "<$style>$text</$style>";
1965        } else { # no style
1966        }
1967    } else { # unknown style
1968        $text = undef;
1969    }
1970    return($text);
1971}
1972
1973# remove Texinfo styles
1974sub remove_style {
1975    local($_) = @_;
1976    s/\@\w+{([^\{\}]+)}/$1/g;
1977    return($_);
1978}
1979
1980sub substitute_style {
1981    local($_) = @_;
1982    local($changed, $done, $style, $text);
1983
1984    $changed = 1;
1985    while ($changed) {
1986        $changed = 0;
1987        $done = '';
1988        while (/\@(\w+){([^\{\}]+)}/) {
1989            $text = &apply_style($1, $2);
1990            if ($text) {
1991                $_ = "$`$text$'";
1992                $changed = 1;
1993            } else {
1994                $done .= "$`\@$1";
1995                $_ = "{$2}$'";
1996            }
1997        }
1998        $_ = $done . $_;
1999    }
2000    return($_);
2001}
2002
2003sub anchor {
2004    local($name, $href, $target, $text, $newline) = @_;
2005    local($result);
2006
2007    $result = "<A";
2008    $result .= " NAME=\"$name\"" if $name;
2009    $result .= " HREF=\"$href\"" if $href;
2010    $result .= " TARGET=\"$target\"" if $target;
2011    $result .= ">$text</A>";
2012    $result .= "\n" if $newline;
2013    return($result);
2014}
2015
2016sub pretty_date {
2017    local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
2018
2019    @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
2020            'July', 'August', 'September', 'October', 'November', 'December');
2021    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
2022    $year += ($year < 70) ? 2000 : 1900;
2023    return("$mday $MoY[$mon] $year");
2024}
2025
2026sub doc_name {
2027    local($num) = @_;
2028
2029    return("${docu_name}_$num.html");
2030}
2031
2032sub next_doc {
2033    $docu_doc = &doc_name(++$doc_num);
2034}
2035
2036sub print {
2037    local(*lines, $fh) = @_;
2038    local($_);
2039
2040    while (@lines) {
2041        $_ = shift(@lines);
2042        if (/^$PROTECTTAG/o) {
2043            $_ = $tag2pro{$_};
2044        } else {
2045            &unprotect_texi;
2046        }
2047        print $fh $_;
2048    }
2049}
2050
2051sub print_ruler {
2052    print FILE "<P><HR><P>\n";
2053}
2054
2055sub print_frame {
2056    local($docu_right) = $_[0] . "_1";
2057    print FILE <<EOT;
2058<FRAMESET COLS="20%,*" BORDER=0>
2059<FRAME SRC="$docu_left" NAME="Links">
2060<FRAME SRC="$docu_right.html" NAME="Main">
2061</FRAMESET>
2062
2063EOT
2064}
2065
2066sub print_header {
2067    local($_);
2068
2069    $links = $_[1];
2070    $is_frame = $_[2];
2071    # clean the title
2072    $_ = &remove_style($_[0]);
2073    &unprotect_texi;
2074    # print the header
2075    if ($doctype eq 'html2') {
2076        print FILE $html2_doctype; # Wrong if any multitable used
2077    } elsif ($doctype) {
2078        print FILE $doctype;
2079    }
2080    print FILE <<EOT;
2081<HTML>
2082<HEAD>
2083$header
2084<TITLE>$_</TITLE>
2085$links
2086</HEAD>
2087EOT
2088    if(!$is_frame) { print FILE "<BODY background=\"/rock.gif\">\n"; }
2089}
2090
2091sub print_toplevel_header {
2092    local($_);
2093
2094    &print_header ($_[0], "", 0);
2095    print FILE $full_title;
2096    if ($value{'_subtitle'}) {
2097        $value{'_subtitle'} =~ s/\n+$//;
2098        foreach (split(/\n/, $value{'_subtitle'})) {
2099            $_ = &substitute_style($_);
2100            &unprotect_texi;
2101            print FILE "<H2>$_</H2>\n";
2102        }
2103    }
2104    if ($value{'_author'}) {
2105        $value{'_author'} =~ s/\n+$//;
2106        foreach (split(/\n/, $value{'_author'})) {
2107            $_ = &substitute_style($_);
2108            &unprotect_texi;
2109#           s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
2110            print FILE "<ADDRESS>$_</ADDRESS>\n";
2111        }
2112    }
2113    print FILE "<P>\n";
2114}
2115
2116sub print_footer {
2117    print FILE <<EOT;
2118</BODY>
2119</HTML>
2120EOT
2121}
2122
2123sub print_toplevel_footer {
2124    &print_ruler;
2125    print FILE <<EOT;
2126This document was generated on $TODAY using the
2127<A HREF=\"$HOMEPAGE\">texi2html</A>
2128translator version 1.51a.</P>
2129EOT
2130    &print_footer;
2131}
2132
2133sub protect_texi {
2134    # protect @ { } ` '
2135    s/\@\@/$;0/go;
2136    s/\@\{/$;1/go;
2137    s/\@\}/$;2/go;
2138    s/\@\`/$;3/go;
2139    s/\@\'/$;4/go;
2140}
2141
2142sub protect_html {
2143    local($what) = @_;
2144    # protect & < >
2145    $what =~ s/\&/\&\#38;/g;
2146    $what =~ s/\</\&\#60;/g;
2147    $what =~ s/\>/\&\#62;/g;
2148    # but recognize some HTML things
2149    $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g;             # </A>
2150    $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g;     # <A [^&]+>
2151    $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
2152    return($what);
2153}
2154
2155sub unprotect_texi {
2156    s/$;0/\@/go;
2157    s/$;1/\{/go;
2158    s/$;2/\}/go;
2159    s/$;3/\`/go;
2160    s/$;4/\'/go;
2161}
2162
2163sub unprotect_html {
2164    local($what) = @_;
2165    $what =~ s/\&\#38;/\&/g;
2166    $what =~ s/\&\#60;/\</g;
2167    $what =~ s/\&\#62;/\>/g;
2168    return($what);
2169}
2170
2171sub byalpha {
2172    $key2alpha{$a} cmp $key2alpha{$b};
2173}
2174
2175##############################################################################
2176
2177        # These next few lines are legal in both Perl and nroff.
2178
2179.00 ;                   # finish .ig
2180 
2181'di                     \" finish diversion--previous line must be blank
2182.nr nl 0-1              \" fake up transition to first page again
2183.nr % 0                 \" start at page 1
2184'; __END__ ############# From here on it's a standard manual page ############
2185.TH TEXI2HTML 1 "08/12/97"
2186.AT 3
2187.SH NAME
2188texi2html \- a Texinfo to HTML converter
2189.SH SYNOPSIS
2190.B texi2html [OPTION]... FILE
2191.PP
2192.B texi2html -check [-verbose] FILE...
2193.SH DESCRIPTION
2194.I Texi2html
2195converts the given Texinfo file to a set of HTML files. It tries to handle
2196most of the Texinfo commands. It creates hypertext links for cross-references,
2197footnotes...
2198.PP
2199It also tries to add links from a reference to its corresponding entry in the
2200bibliography (if any). It may also handle a glossary (see the
2201.B \-glossary
2202option).
2203.PP
2204.I Texi2html
2205creates several files depending on the contents of the Texinfo file and on
2206the chosen options (see FILES).
2207.PP
2208The HTML files created by
2209.I texi2html
2210are closer to TeX than to Info, that's why
2211.I texi2html
2212converts @iftex sections and not @ifinfo ones by default. You can reverse
2213this with the \-expandinfo option.
2214.SH OPTIONS
2215.TP 12
2216.B \-check
2217Check the given file and give the list of all things that may be Texinfo commands.
2218This may be used to check the output of
2219.I texi2html
2220to find the Texinfo commands that have been left in the HTML file.
2221.TP
2222.B \-expandinfo
2223Expand @ifinfo sections, not @iftex ones.
2224.TP
2225.B \-glossary
2226Use the section named 'Glossary' to build a list of terms and put links in the HTML
2227document from each term toward its definition.
2228.TP
2229.B \-invisible \fIname\fP
2230Use \fIname\fP to create invisible destination anchors for index links. This is a workaround
2231for a known bug of many WWW browsers, including xmosaic.
2232.TP
2233.B \-I \fIdir\fP
2234Look also in \fIdir\fP to find included files.
2235.TP
2236.B \-menu
2237Show the Texinfo menus; by default they are ignored.
2238.TP
2239.B \-monolithic
2240Output only one file, including the table of contents and footnotes.
2241.TP
2242.B \-number
2243Number the sections.
2244.TP
2245.B \-split_chapter
2246Split the output into several HTML files (one per main section:
2247chapter, appendix...).
2248.TP
2249.B \-split_node
2250Split the output into several HTML files (one per node).
2251.TP
2252.B \-usage
2253Print usage instructions, listing the current available command-line options.
2254.TP
2255.B \-verbose
2256Give a verbose output. Can be used with the
2257.B \-check
2258option.
2259.PP
2260.SH FILES
2261By default
2262.I texi2html
2263creates the following files (foo being the name of the Texinfo file):
2264.TP 16
2265.B foo_toc.html
2266The table of contents.
2267.TP
2268.B foo.html
2269The document's contents.
2270.TP
2271.B foo_foot.html
2272The footnotes (if any).
2273.PP
2274When used with the
2275.B \-split
2276option, it creates several files (one per chapter or node), named
2277.B foo_n.html
2278(n being the indice of the chapter or node), instead of the single
2279.B foo.html
2280file.
2281.PP
2282When used with the
2283.B \-monolithic
2284option, it creates only one file:
2285.B foo.html
2286.SH VARIABLES
2287.I texi2html
2288predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
2289.SH ADDITIONAL COMMANDS
2290.I texi2html
2291implements the following non-Texinfo commands:
2292.TP 16
2293.B @ifhtml
2294This indicates the start of an HTML section, this section will passed through
2295without any modofication.
2296.TP
2297.B @end ifhtml
2298This indcates the end of an HTML section.
2299.SH VERSION
2300This is \fItexi2html\fP version 1.54, 1998-01-17
2301.PP
2302The latest version of \fItexi2html\fP can be found at
2303ftp://ftp.cs.umb.edu/pub/tex/texi2html
2304.SH AUTHOR
2305The main author is Lionel Cons, CERN CN/DCI/UWS.
2306This version is maintained at ftp://ftp.cs.umb.edu/pub/tex/texi2html
2307by kb@cs.umb.edu.
2308Many other people around the net contributed to this program.
2309.SH COPYRIGHT
2310This program is the intellectual property of the European
2311Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
2312provided by CERN. No liability whatsoever is accepted for any loss or damage
2313of any kind resulting from any defect or inaccuracy in this information or
2314code.
2315.PP
2316CERN, 1211 Geneva 23, Switzerland
2317.SH "SEE ALSO"
2318GNU Texinfo Documentation Format,
2319HyperText Markup Language (HTML),
2320World Wide Web (WWW).
2321.SH BUGS
2322This program does not understand all Texinfo commands (yet).
2323.PP
2324TeX specific commands (normally enclosed in @iftex) will be
2325passed unmodified.
2326.ex
Note: See TracBrowser for help on using the repository browser.