4 #+##############################################################################
8 # Description: Program to transform most Texinfo documents to HTML #
10 #-##############################################################################
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.
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.
23 #+++############################################################################
27 #---############################################################################
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)
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">';
53 # language dependent constants
56 #$LDC_SECTION = 'section';
58 #$LDC_TOC = 'Table of Contents';
59 #$LDC_GOTO = 'Go to the';
60 #$LDC_FOOT = 'Footnotes';
61 # TODO: @def* shortcuts
88 # texinfo section names to level
101 'appendixsection', 2,
103 'unnumberedsubsec', 3,
107 'unnumberedsubsubsec', 4,
109 'appendixsubsubsec', 4,
113 # accent map, TeX command to ISO name
124 # texinfo "simple things" (@foo) to HTML ones
141 # texinfo "things" (@foo{}) to HTML ones
145 'br', '<P>', # paragraph break
164 'exclamdown', '¡',
165 'questiondown', '¿',
170 # texinfo styles (@foo{bar}) to HTML ones
177 'ctrl', '&do_ctrl', # special case
178 'dfn', 'EM', # DFN tag is illegal in the standard
180 'email', '&do_email', # insert a clickable email address
182 'file', '"TT', # will put quotes, cf. &apply_style
187 'r', '', # unsupported
188 'samp', '"SAMP', # will put quotes, cf. &apply_style
189 'sc', '&do_sc', # special case
192 'titlefont', '', # useless
193 'uref', '&do_uref', # insert a clickable URL
194 'url', '&do_url', # insert a clickable URL
196 'w', '', # unsupported
197 '"', '&do_diaeresis',
198 '\'', '&do_acuteaccent', # doesn't work??
199 '\`', '&do_graveaccent', # doesn't work??
200 '~', '&do_tildeaccent',
202 '^', '&do_circumflex',
206 # texinfo format (@foo/@end foo) to HTML ones
213 'quotation', 'BLOCKQUOTE',
214 'smallexample', 'PRE',
225 # texinfo definition shortcuts to real ones
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',
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',
276 'summarycontents', 1,
282 # unsupported commands (formatting)
289 'setchapternewpage', 1,
299 'paragraphindent', 1,
300 # unsupported formats
307 #+++############################################################################
309 # Argument parsing, initialisation #
311 #---############################################################################
313 %value = (); # hold texinfo variables, see also -D
315 $use_bibliography = 1;
323 $invisible_mark = '';
327 $number_sections = 0;
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'
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
352 while (@ARGV && $ARGV[0] =~ /^-/) {
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)?)?$/) {
376 if (/^-v(erbose)?$/) { $verbose = 1; next; }
380 die $usage unless @ARGV > 0;
385 if (($split_node || $split_chapter) && $monolithic) {
386 warn "Can't use -monolithic with -split, -monolithic ignored.\n";
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'}++;
400 $to_skip{'end iftex'}++;
401 $to_skip{'ifnothtml'}++;
402 $to_skip{'end ifnothtml'}++;
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'}++;
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 = $&);
421 unshift(@include_dirs, $docu_dir);
422 $docu_name =~ s/\.te?x(i|info)?$//; # basename of the document
424 $docu_doc = "$docu_name.html"; # document's contents
426 $docu_toc = $docu_foot = $docu_doc;
428 $docu_toc = "${docu_name}_toc.html"; # document's table of contents
429 $docu_foot = "${docu_name}_foot.html"; # document's footnotes
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
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
461 # can I use ISO8879 characters? (HTML+)
464 $things_map{'bullet'} = "•";
465 $things_map{'copyright'} = "©";
466 $things_map{'dots'} = "…";
467 $things_map{'equiv'} = "≡";
468 $things_map{'expansion'} = "→";
469 $things_map{'point'} = "∗";
470 $things_map{'result'} = "⇒";
474 # read texi2html extensions (if any)
476 $extensions = 'texi2html.ext'; # extensions in working directory
477 if (-f $extensions) {
478 print "# reading extensions from $extensions\n" if $verbose;
479 require($extensions);
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);
490 print "# reading from $docu\n" if $verbose;
492 #+++############################################################################
494 # Pass 1: read source, handle command, variable, simple substitution #
496 #---############################################################################
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
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!
524 foreach (keys(%simple_map)) {
525 ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
526 $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
528 foreach (keys(%things_map)) {
529 $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
532 # accentuated characters
533 foreach (keys(%accent_map)) {
535 $subst_code .= "s/$;3";
536 } elsif ($_ eq "'") {
537 $subst_code .= "s/$;4";
539 $subst_code .= "s/\\\@\\$_";
541 $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
544 eval("sub simple_substitutions { $subst_code }");
547 while ($_ = &next_line) {
549 # remove \input on the first lines only
560 if (/^\@end\s+(\w+)\b/) {
562 } elsif (/^\@(\w+)\b/) {
566 # handle @ifhtml / @end ifhtml
569 if ($end_tag eq 'ifhtml') {
572 $tag2pro{$in_html} .= $_;
575 } elsif ($tag eq 'ifhtml') {
576 $in_html = $PROTECTTAG . ++$html_num;
577 push(@lines, $in_html);
581 # try to skip the line
584 next if $to_skip{"end $end_tag"};
586 next if $to_skip{$tag};
587 last if $tag eq 'bye';
590 # parsing the top node
591 if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) {
600 # try to remove inlined comments
601 # syntax from tex-mode.el comment-start-skip
603 s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
604 # non-@ substitutions cf. texinfmt.el
608 s/([\w ])---([\w ])/$1--$2/g;
615 &skip_until($tag), next if $tag eq 'ignore';
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';
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';
629 &skip_until($tag), next if $tag eq 'tex';
630 # handle special tables
631 if ($tag =~ /^(|f|v|multi)table$/) {
636 if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*,/i)) {
638 @lines = (); # ignore all lines before top (title page garbage)
640 } elsif ($tag eq 'node') {
642 warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
643 $_ = &protect_html($_); # if node contains '&' for instance
645 ($node) = split(/,/);
646 &normalise_node($node);
649 push(@lines, $SPLITTAG) if $split_num++;
650 push(@sections, $node);
653 } elsif ($tag eq 'include') {
654 if (/^\@include\s+($FILERE)\s*$/o) {
657 foreach $dir (@include_dirs) {
664 print "# including $file\n" if $verbose;
666 warn "$ERROR Can't find $file, skipping";
669 warn "$ERROR Bad include line: $_";
672 } elsif ($tag eq 'ifclear') {
673 if (/^\@ifclear\s+($VARRE)\s*$/o) {
674 next unless defined($value{$1});
677 warn "$ERROR Bad ifclear line: $_";
680 } elsif ($tag eq 'ifset') {
681 if (/^\@ifset\s+($VARRE)\s*$/o) {
682 next if defined($value{$1});
685 warn "$ERROR Bad ifset line: $_";
688 } elsif ($tag eq 'menu') {
689 unless ($show_menu) {
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__));
702 } elsif ($tag eq 'table') {
703 if (/^\@(|f|v|multi)table\s+\@(\w+)/) {
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');
710 push(@lines, &debug("<DL COMPACT>\n", __LINE__));
713 push(@lines, &html_debug("\n", __LINE__));
715 warn "$ERROR Bad table line: $_";
718 } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
719 if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
720 eval("*${1}index = *${2}index");
722 warn "$ERROR Bad syn*index line: $_";
725 } elsif ($tag eq 'sp') {
726 push(@lines, &debug("<P>\n", __LINE__));
728 } elsif ($tag eq 'setref') {
729 &protect_html; # if setref contains '&' for instance
730 if (/^\@$tag\s*{($NODERE)}\s*$/) {
732 $setref =~ s/\s+/ /g; # normalize
734 $node2sec{$setref} = $name;
735 $node2href{$setref} = "$docu_doc#$docid";
737 warn "$ERROR Bad setref line: $_";
740 } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
741 if (/^\@$tag\s+(\w\w)\s*$/) {
742 $valid_index{$1} = 1;
744 warn "$ERROR Bad defindex line: $_";
747 } elsif (defined($def_map{$tag})) {
748 if ($def_map{$tag}) {
750 $tag = $def_map{$tag};
754 } elsif (defined($user_sub{$tag})) {
756 $sub = $user_sub{$tag};
757 print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER;
758 if (defined(&$sub)) {
762 warn "$ERROR Bad user sub for $tag: $sub\n";
766 if (defined($def_map{$tag})) {
769 # extra definition line
775 while (/\{([^\{\}]*)\}/) {
776 # this is a {} construct
777 ($before, $contents, $after) = ($`, $1, $');
779 $contents =~ s/\s+/$;9/g;
780 # restore $_ protecting {}
781 $_ = "$before$;7$contents$;8$after";
783 @args = split(/\s+/, &protect_html($_));
785 s/$;9/ /g; # unprotect spaces
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/;
797 $_ = &debug("<DT>", __LINE__);
799 $_ = &debug("<DL>\n<DT>", __LINE__);
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') {
807 $name = shift(@args);
808 $name =~ s/^\{(.*)\}$/$1/;
809 $_ .= "<U>$type</U> $ftype <B>$name</B>";
810 $_ .= " <I>@args</I>" if @args;
812 warn "$ERROR Unknown definition type: $tag\n";
813 $_ .= "<U>$type</U> <B>$name</B>";
814 $_ .= " <I>@args</I>" if @args;
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");
825 unshift(@input_spool, "\@tindex $name\n");
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');
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$/) {
839 warn "$ERROR \@end $end_tag without \@*table\n";
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";
847 if ($table_type eq "multi") {
848 push(@lines, "</TR></TABLE>\n");
851 push(@lines, "</DL>\n");
856 ($table_type, $in_table) = split($;, $tables[0]);
860 } elsif (defined($def_map{$end_tag})) {
861 push(@lines, &debug("</DL>\n", __LINE__));
862 } elsif ($end_tag eq 'menu') {
864 push(@lines, $_); # must keep it for pass 2
871 # protect texi and HTML things
873 $_ = &protect_html($_) unless $dont_html;
875 # substitution (unsupported things)
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
885 # analyze the tag again
888 if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
889 if (/^\@$tag\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__);
903 $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
904 &html_push_if('body');
906 print "# heading, section $name, level $level\n"
907 if $debug & $DEBUG_TOC;
909 if ($split_chapter) {
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";
918 if ($level == $toplevel) {
920 push(@lines, $SPLITTAG) if $split_num++;
921 push(@sections, $name);
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);
932 if ($node2sec{$node}) {
933 warn "$ERROR Duplicate node found: $node\n";
935 $node2sec{$node} = $name;
936 $node2href{$node} = "$docu_doc#$docid";
937 print "# node $node, section $name, level $level\n"
938 if $debug & $DEBUG_TOC;
942 print "# no node, section $name, level $level\n"
943 if $debug & $DEBUG_TOC;
946 while ($level > $curlevel) {
948 push(@toc_lines, "<UL>\n");
950 while ($level < $curlevel) {
952 push(@toc_lines, "</UL>\n");
954 $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", $name, 1);
955 push(@toc_lines, &substitute_style($_));
957 push(@lines, &html_debug("\n", __LINE__));
959 $_ = "<H$level>".&anchor($docid, "$docu_toc#$tocid", $name)."</H$level>\n";
960 $_ = &debug($_, __LINE__);
961 push(@lines, &html_debug("\n", __LINE__));
964 foreach $line (split(/\n+/, $_)) {
965 push(@lines, "$line\n");
969 warn "$ERROR Bad section line: $_";
973 $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o;
974 delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
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+(.*)$/;
982 if (/^\@(..?)index\s+/) {
983 unless ($valid_index{$1}) {
984 warn "$ERROR Undefined index command: $_";
987 $id = 'IDX' . ++$idx_num;
988 $index = $1 . 'index';
989 $what = &substitute_style($');
991 print "# found $index for '$what' id $id\n"
992 if $debug & $DEBUG_INDEX;
994 if (defined(\$$index\{\$what\})) {
995 \$$index\{\$what\} .= "$;$docu_doc#$id";
997 \$$index\{\$what\} = "$docu_doc#$id";
1001 # dirty hack to see if I can put an invisible anchor...
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));
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) . " ";
1025 if (/^\@itemx?\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);
1036 } elsif ($in_glossary && $use_glossary) {
1037 $id = 'GLOSS' . ++$gloss_num;
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);
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__));
1051 push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
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");
1058 } elsif ($html_element eq 'TABLE') {
1059 push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
1061 } elsif ($html_element eq 'TR') {
1062 push(@lines, &debug("</TR>\n", __LINE__));
1063 push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
1065 push(@lines, &debug("<LI>$what\n", __LINE__));
1066 &html_push('LI') unless $html_element eq 'LI';
1068 push(@lines, &html_debug("\n", __LINE__));
1069 if ($deferred_ref) {
1070 push(@lines, &debug("$deferred_ref\n", __LINE__));
1074 } elsif (/^\@tab\s+(.*)$/) {
1075 push(@lines, "<TD>$1</TD>\n");
1080 # paragraph separator
1082 next if $#lines >= 0 && $lines[$#lines] eq "\n";
1083 if ($html_element eq 'P') {
1085 $_ = &debug("</P>\n", __LINE__);
1088 } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') {
1089 push(@lines, "<P>\n");
1091 $_ = &debug($_, __LINE__);
1099 while ($level < $curlevel) {
1101 push(@toc_lines, "</UL>\n");
1104 print "# end of pass 1\n" if $verbose;
1106 #+++############################################################################
1108 # Pass 2/3: handle style, menu, index, cross-reference #
1110 #---############################################################################
1112 @lines2 = (); # whole document (2nd pass)
1113 @lines3 = (); # whole document (3rd pass)
1114 $in_menu = 0; # am I inside a menu
1119 # special case (protected sections)
1121 if (/^$PROTECTTAG/o) {
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/;
1131 if (/^\*\s+($NODERE)::/o) {
1134 &menu_entry($1, $1, $descr);
1135 } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
1138 &menu_entry($1, $2, $descr);
1140 warn "$ERROR Bad menu line: $_";
1141 } else { # description continued?
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';
1154 $index = $1 . 'index';
1156 eval("*ary = *$index");
1158 foreach $key (@keys) {
1160 1 while s/<(\w+)>\`(.*)\´<\/\1>/$2/; # remove HTML tags with quotes
1161 1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags
1162 $_ = &unprotect_html($_);
1164 tr/A-Z/a-z/; # lowercase
1165 $key2alpha{$key} = $_;
1166 print "# index $key sorted as $_\n"
1167 if $key ne $_ && $debug & $DEBUG_INDEX;
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;
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;
1192 foreach (split(/$;/, $ary{$key})) {
1193 push(@refs, &anchor('', $_, $key, 0));
1195 push(@lines2, "<LI>" . join(", ", @refs) . "\n");
1197 push(@lines2, "</DIR>\n") if defined($last_letter);
1201 # simple style substitutions
1203 $_ = &substitute_style($_);
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";
1218 } elsif ($type eq 'px') {
1220 } elsif ($type eq 'info') {
1226 $next = shift(@lines);
1227 $next = &substitute_style($next);
1228 chop($nodes); # remove final newline
1229 if ($next =~ /\}/) { # split on 2 lines
1234 $next = shift(@lines);
1235 $next = &substitute_style($next);
1237 if ($next =~ /\}/) { # split on 3 lines
1241 warn "$ERROR Bad xref (no ending }): $_";
1242 $_ = "$before$;0xref\{$nodes$after";
1243 unshift(@lines, $next);
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";
1262 $href = $node2href{$node};
1263 $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after;
1265 warn "$ERROR Undefined node ($node): $_";
1266 $_ = "$before$;0xref{$nodes}$after";
1270 # try to guess bibliography references or glossary terms
1272 unless (/^<H\d><A NAME=\"SEC\d/) {
1273 if ($use_bibliography) {
1276 ($pre, $what, $post) = ($`, $&, $');
1277 $href = $bib2href{$what};
1278 if (defined($href) && $post !~ /^[^<]*<\/A>/) {
1279 $done .= $pre . &anchor('', $href, $what);
1281 $done .= "$pre$what";
1287 if ($use_glossary) {
1290 ($pre, $what, $post) = ($`, $&, $');
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);
1297 $done .= "$pre$what";
1307 print "# end of pass 2\n" if $verbose;
1310 # split style substitutions
1313 $_ = shift(@lines2);
1315 # special case (protected sections)
1317 if (/^$PROTECTTAG/o) {
1322 # split style substitutions
1325 while ($old ne $_) {
1327 if (/\@(\w+|"|\~|,|\^)\{/) {
1328 ($before, $style, $after) = ($`, $1, $');
1329 if (defined($style_map{$style})) {
1342 $_ = shift(@lines2);
1346 die "* Bad syntax (\@$style) after: $before\n";
1348 $text = &apply_style($style, $text);
1349 $_ = "$before$text$after";
1357 print "# end of pass 3\n" if $verbose;
1359 #+++############################################################################
1361 # Pass 4: foot notes, final cleanup #
1363 #---############################################################################
1365 @foot_lines = (); # footnotes
1366 @doc_lines = (); # final document
1367 $end_of_para = 0; # true if last line is <P>
1370 $_ = shift(@lines3);
1372 # special case (protected sections)
1374 if (/^$PROTECTTAG/o) {
1375 push(@doc_lines, $_);
1382 while (/\@footnote([^\{\s]+)\{/) {
1383 ($before, $d, $after) = ($`, $1, $');
1396 $_ = shift(@lines3);
1400 die "* Bad syntax (\@footnote) after: $before\n";
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;
1413 # remove unnecessary <P>
1415 if (/^\s*<P>\s*$/) {
1416 next if $end_of_para++;
1421 push(@doc_lines, $_);
1423 print "# end of pass 4\n" if $verbose;
1425 #+++############################################################################
1427 # Pass 5: print things #
1429 #---############################################################################
1432 <!-- This HTML file has been created by $THISPROG
1433 from $docu on $TODAY -->
1436 $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
1437 $title = $value{'_settitle'} || $full_title;
1438 $_ = &substitute_style($full_title);
1440 s/\n$//; # rmv last \n (if any)
1441 $full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
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");
1451 &print(*toc_lines, FILE);
1452 &print_toplevel_footer;
1455 warn "$ERROR Can't write to $docu_toc: $!\n";
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");
1467 &print(*foot_lines, FILE);
1468 &print_toplevel_footer;
1471 warn "$ERROR Can't write to $docu_foot: $!\n";
1478 if ($split_chapter || $split_node) { # split
1480 $last_num = scalar(@sections);
1481 $first_doc = &doc_name(1);
1482 $last_doc = &doc_name($last_num);
1484 $section = shift(@sections);
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;
1502 # find corresponding lines
1504 while (@doc_lines) {
1505 $_ = shift(@doc_lines);
1506 last if ($_ eq $SPLITTAG);
1507 push(@tmp_lines, $_);
1509 &print(*tmp_lines, FILE);
1511 print FILE $navigation;
1515 warn "$ERROR Can't write to $docu_doc: $!\n";
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);
1524 &print_header($title);
1525 print FILE $full_title;
1527 if ($monolithic && @toc_lines) {
1529 print FILE "<H1>Table of Contents</H1>\n";
1530 &print(*toc_lines, FILE);
1533 &print(*doc_lines, FILE);
1534 if ($monolithic && @foot_lines) {
1536 print FILE "<H1>Footnotes</H1>\n";
1537 &print(*foot_lines, FILE);
1539 if ($monolithic || !@toc_lines) {
1540 &print_toplevel_footer;
1546 warn "$ERROR Can't write to $docu_doc: $!\n";
1550 print "# that's all folks\n" if $verbose;
1552 #+++############################################################################
1554 # Low level functions #
1556 #---############################################################################
1558 sub update_sec_num {
1559 local($name, $level) = @_;
1561 $level--; # here we start at 0
1562 if ($name =~ /^appendix/) {
1564 if (@appendix_sec_num) {
1565 &incr_sec_num($level, @appendix_sec_num);
1567 @appendix_sec_num = ('A', 0, 0, 0);
1569 return(join('.', @appendix_sec_num[0..$level]));
1572 if (@normal_sec_num) {
1573 &incr_sec_num($level, @normal_sec_num);
1575 @normal_sec_num = (1, 0, 0, 0);
1577 return(join('.', @normal_sec_num[0..$level]));
1585 foreach $l ($level+1 .. 3) {
1591 local($_, %seen, %context, $before, $match, $after);
1594 if (/\@(\*|\.|\:|\@|\{|\})/) {
1596 $context{$&} .= "> $_" if $verbose;
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;
1607 $context{$match} .= "> $_" if $verbose;
1610 $_ = "$before$match$after";
1615 foreach (sort(keys(%seen))) {
1620 print "$_ ($seen{$_})\n";
1629 if (open($fh_name, $name)) {
1630 unshift(@fhs, $fh_name);
1632 warn "$ERROR Can't read file $name: $!\n";
1637 @fhs = (); # hold the file handles to read
1638 @input_spool = (); # spooled lines to read
1647 $line = shift(@input_spool);
1653 return($line) if $line;
1660 # used in pass 1, use &next_line
1665 while ($_ = &next_line) {
1666 return if /^\@end\s+$tag\s*$/;
1668 die "* Failed to find '$tag' after: " . $lines[$#lines];
1672 # HTML stacking to have a better HTML output
1676 @html_stack = ('html');
1677 $html_element = 'body';
1682 push(@html_stack, $html_element);
1683 $html_element = $what;
1688 push(@html_stack, $html_element)
1689 if ($html_element && $html_element ne 'P');
1690 $html_element = $what;
1694 $html_element = pop(@html_stack);
1702 if ($elt eq $html_element) {
1703 $html_element = pop(@html_stack) if @html_stack;
1708 $html_element = pop(@html_stack) if @html_stack;
1713 local($what, $line) = @_;
1714 return("<!-- $line @html_stack, $html_element -->$what")
1715 if $debug & $DEBUG_HTML;
1719 # to debug the output...
1721 local($what, $line) = @_;
1722 return("<!-- $line -->$what")
1723 if $debug & $DEBUG_HTML;
1727 sub normalise_node {
1734 local($entry, $node, $descr) = @_;
1737 &normalise_node($node);
1738 $href = $node2href{$node};
1741 $descr = ": $descr" if $descr;
1742 push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n");
1744 warn "$ERROR Undefined node ($node): $_";
1748 sub do_ctrl { "^$_[0]" }
1751 local($addr, $text) = split(/,\s*/, $_[0]);
1753 $text = $addr unless $text;
1754 &anchor('', "mailto:$addr", $text);
1757 sub do_sc { "\U$_[0]\E" }
1760 local($url, $text) = split(/,\s*/, $_[0]);
1762 $text = $url unless $text;
1763 &anchor('', $url, $text);
1766 sub do_url { &anchor('', $_[0], $_[0]) }
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;"; }
1776 local($texi_style, $text) = @_;
1779 $style = $style_map{$texi_style};
1780 if (defined($style)) { # known style
1781 if ($style =~ /^\"/) { # add quotes
1783 $text = "\‘$text\’";
1785 if ($style =~ /^\&/) { # custom
1787 $text = &$style($text);
1788 } elsif ($style) { # good style
1789 $text = "<$style>$text</$style>";
1792 } else { # unknown style
1798 # remove Texinfo styles
1801 s/\@\w+{([^\{\}]+)}/$1/g;
1805 sub substitute_style {
1807 local($changed, $done, $style, $text);
1813 while (/\@(\w+|"|\~|,|\^){([^\{\}]+)}/) {
1814 $text = &apply_style($1, $2);
1829 local($name, $href, $text, $newline) = @_;
1833 $result .= " NAME=\"$name\"" if $name;
1834 $result .= " HREF=\"$href\"" if $href;
1835 $result .= ">$text</A>";
1836 $result .= "\n" if $newline;
1841 local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
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");
1853 return("${docu_name}_$num.html");
1857 $docu_doc = &doc_name(++$doc_num);
1861 local(*lines, $fh) = @_;
1866 if (/^$PROTECTTAG/o) {
1876 print FILE "<P><HR><P>\n";
1883 $_ = &remove_style($_[0]);
1886 if ($doctype eq 'html2') {
1887 print FILE $html2_doctype;
1888 } elsif ($doctype) {
1889 print FILE $doctype;
1895 <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8">
1902 sub print_toplevel_header {
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($_);
1912 print FILE "<H2>$_</H2>\n";
1915 if ($value{'_author'}) {
1916 $value{'_author'} =~ s/\n+$//;
1917 foreach (split(/\n/, $value{'_author'})) {
1918 $_ = &substitute_style($_);
1920 s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
1921 print FILE "<ADDRESS>$_</ADDRESS>\n";
1934 sub print_toplevel_footer {
1937 This document was generated on $TODAY using the
1938 <A HREF=\"$HOMEPAGE\">texi2html</A>
1939 translator version 1.52b.</P>
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 [^&]+>
1966 sub unprotect_texi {
1974 sub unprotect_html {
1976 $what =~ s/\&\#38;/\&/g;
1977 $what =~ s/\&\#60;/\</g;
1978 $what =~ s/\&\#62;/\>/g;
1983 $key2alpha{$a} cmp $key2alpha{$b};
1986 ##############################################################################
1988 # These next few lines are legal in both Perl and nroff.
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"
1999 texi2html \- a Texinfo to HTML converter
2001 .B texi2html [options] file
2003 .B texi2html -check [-verbose] files
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,
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
2016 creates several files depending on the contents of the Texinfo file and on
2017 the chosen options (see FILES).
2019 The HTML files created by
2021 are closer to TeX than to Info, that's why
2023 converts @ifhtml sections and not @ifinfo or @iftex ones by default. You can
2024 change this with the \-expandinfo or \-expandtex options.
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
2031 to find the Texinfo commands that have been left in the HTML file.
2034 Expand @ifinfo sections, not @ifhtml ones.
2037 Expand @iftex sections, not @ifhtml ones.
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.
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.
2049 Look also in \fIdir\fP to find included files.
2052 Show the Texinfo menus; by default they are ignored.
2055 Output only one file, including the table of contents and footnotes.
2058 Number the sections.
2061 Split the output into several HTML files (one per main section:
2062 chapter, appendix...).
2065 Split the output into several HTML files (one per node).
2068 Print usage instructions, listing the current available command-line options.
2071 Give a verbose output. Can be used with the
2078 creates the following files (foo being the name of the Texinfo file):
2081 The table of contents.
2084 The document's contents.
2087 The footnotes (if any).
2091 option, it creates several files (one per chapter or node), named
2093 (n being the indice of the chapter or node), instead of the single
2099 option, it creates only one file:
2103 predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
2104 .SH ADDITIONAL COMMANDS
2106 implements the following non-Texinfo commands (maybe they are in Texinfo now...):
2109 This indicates the start of an HTML section, this section will passed through
2110 without any modification.
2113 This indicates the end of an HTML section.
2115 This is \fItexi2html\fP version 1.52b, 01/05/98.
2117 The latest version of \fItexi2html\fP can be found in WWW, cf. URL
2118 http://wwwinfo.cern.ch/dis/texi2html/
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.
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
2129 CERN, 1211 Geneva 23, Switzerland
2131 GNU Texinfo Documentation Format,
2132 HyperText Markup Language (HTML),
2133 World Wide Web (WWW).
2135 This program does not understand all Texinfo commands (yet).