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