Use macros for 8259A PIC registers, instead of writing them literally.
[pintos-anon] / doc / texi2html
1 #! /usr/bin/env perl
2 'di ';
3 'ig 00 ';
4 #+##############################################################################
5 #
6 # texi2html: Program to transform Texinfo documents to HTML
7 #
8 #    Copyright (C) 1999, 2000  Free Software Foundation, Inc.
9 #
10 #    This program is free software; you can redistribute it and/or modify
11 #    it under the terms of the GNU General Public License as published by
12 #    the Free Software Foundation; either version 2 of the License, or
13 #    (at your option) any later version.
14 #
15 #    This program is distributed in the hope that it will be useful,
16 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 #    GNU General Public License for more details.
19 #
20 #    You should have received a copy of the GNU General Public License
21 #    along with this program; if not, write to the Free Software
22 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 #
24 #-##############################################################################
25
26 # This requires perl version 5 or higher
27 require 5.0;
28
29 # Perl pragma to restrict unsafe constructs
30 use strict;
31 #
32 # According to
33 # larry.jones@sdrc.com (Larry Jones)
34 # this pragma is not present in perl5.004_02:
35 #
36 # Perl pragma to control optional warnings
37 # use warnings;
38
39 # Declarations
40 use vars qw(
41             $ADDRESS
42             $ANTI_ALIAS
43             $ANTI_ALIAS_TEXT
44             $ASCII_MODE
45             $AUTO_LINK
46             $AUTO_PREFIX
47             $BIBRE
48             $CHAPTEREND
49             $CHILDLINE
50             $Configure_failed
51             $DEBUG
52             $DEBUG_BIB
53             $DEBUG_DEF
54             $DEBUG_GLOSS
55             $DEBUG_HTML
56             $DEBUG_INDEX
57             $DEBUG_L2H
58             $DEBUG_TOC
59             $DEBUG_USER
60             $DESTDIR
61             $ERROR
62             $EXTERNAL_FILE
63             $EXTERNAL_IMAGES
64             $EXTERNAL_UP_LINK
65             $EXTERNAL_UP_TITLE
66             $FH
67             $FIGURE_SCALE_FACTOR
68             $FILERE
69             $HTML_VERSION
70             $IMAGES_ONLY
71             $INFO
72             $LINE_WIDTH
73             $LOCAL_ICONS
74             $LONG_TITLES
75             $MATH_SCALE_FACTOR
76             $MAX_LINK_DEPTH
77             $MAX_SPLIT_DEPTH
78             $NETSCAPE_HTML
79             $NODERE
80             $NODESRE
81             $NOLATEX
82             $NO_FOOTNODE
83             $NO_IMAGES
84             $NO_NAVIGATION
85             $NO_SIMPLE_MATH
86             $NO_SUBDIR
87             $PAPERSIZE
88             $PREFIX
89             $PROTECTTAG
90             $PS_IMAGES
91             $REUSE
92             $SCALABLE_FONTS
93             $SECTIONEND
94             $SHORTEXTN
95             $SHORT_INDEX
96             $SHOW_SECTION_NUMBERS
97             $SPLIT
98             $T2H_ADDRESS
99             $T2H_AFTER_ABOUT
100             $T2H_AFTER_BODY_OPEN
101             $T2H_AUTHORS
102             $T2H_BODYTEXT
103             $T2H_BUTTONS
104             $T2H_EXTRA_HEAD
105             $T2H_FAILURE_TEXT
106             $T2H_HAS_TOP_HEADING
107             $T2H_HOMEPAGE
108             $T2H_ICONS
109             $T2H_OBSOLETE_OPTIONS
110             $T2H_OVERVIEW
111             $T2H_PRE_BODY_CLOSE
112             $T2H_THIS_SECTION
113             $T2H_TOC
114             $T2H_TODAY
115             $T2H_TOP
116             $T2H_USAGE_TEXT
117             $T2H_USER
118             $TEXDEFS
119             $THISPROG
120             $THISVERSION
121             $TITLE
122             $TITLES_LANGUAGE
123             $TMP
124             $TOPEND
125             $VARRE
126             $VERBOSE
127             $WARN
128             $WORDS_IN_NAVIGATION_PANEL_TITLES
129             $WORDS_IN_PAGE
130             $about_body
131             $addr
132             $after
133             $before
134             $bib_num
135             $button
136             $call
137             $changed
138             $complex_format_map
139             $contents
140             $count
141             $counter
142             $curlevel
143             $d
144             $default_language
145             $deferred_ref
146             $doc_num
147             $docid
148             $docu
149             $docu_about
150             $docu_about_file
151             $docu_dir
152             $docu_doc
153             $docu_doc_file
154             $docu_ext
155             $docu_foot
156             $docu_foot_file
157             $docu_frame_file
158             $docu_name
159             $docu_rdir
160             $docu_stoc
161             $docu_stoc_file
162             $docu_toc
163             $docu_toc_file
164             $docu_toc_frame_file
165             $docu_top
166             $docu_top_file
167             $done
168             $dont_html
169             $dotbug
170             $elt
171             $end_of_para
172             $end_tag
173             $entry
174             $ext
175             $extensions
176             $failed
177             $fh_name
178             $file
179             $first_index_chapter
180             $first_line
181             $foot
182             $foot_num
183             $footid
184             $ftype
185             $full
186             $gloss_num
187             $h_content
188             $h_line
189             $has_top
190             $has_top_command
191             $hcontent
192             $html_element
193             $html_num
194             $i
195             $id
196             $idx_num
197             $in
198             $in_bibliography
199             $in_glossary
200             $in_html
201             $in_list
202             $in_pre
203             $in_table
204             $in_titlepage
205             $in_top
206             $index
207             $index_properties
208             $init_file
209             $int_file
210             $is_extra
211             $key
212             $keys
213             $l
214             $l2h_cache_file
215             $l2h_cached_count
216             $l2h_extract_error
217             $l2h_html_count
218             $l2h_html_file
219             $l2h_latex_closing
220             $l2h_latex_count
221             $l2h_latex_file
222             $l2h_latex_preample
223             $l2h_name
224             $l2h_prefix
225             $l2h_range_error
226             $l2h_to_latex_count
227             $l_l2h
228             $latex_file
229             $len
230             $letter
231             $level
232             $macros
233             $man
234             $match
235             $maximage
236             $next
237             $nn
238             $node
239             $node_next
240             $node_prev
241             $node_up
242             $nodes
243             $num
244             $old
245             $only_text
246             $options
247             $post
248             $pre
249             $prev_node
250             $previous
251             $progdir
252             $re
253             $reused
254             $root
255             $sec_num
256             $section
257             $string
258             $style
259             $sub
260             $subst_code
261             $table_type
262             $tag
263             $texi_style
264             $to_do
265             $toc_indent
266             $tocid
267             $toplevel
268             $type
269             $url
270             $use_acc
271             $use_bibliography
272             $what
273             %T2H_ACTIVE_ICONS
274             %T2H_BUTTONS_EXAMPLE
275             %T2H_BUTTONS_GOTO
276             %T2H_HREF
277             %T2H_NAME
278             %T2H_NAVIGATION_TEXT
279             %T2H_NODE
280             %T2H_PASSIVE_ICONS
281             %T2H_THISDOC
282             %accent_map
283             %bib2href
284             %context
285             %def_map
286             %format_map
287             %gloss2href
288             %idx2node
289             %l2h_cache
290             %l2h_img
291             %l2h_to_latex
292             %macros
293             %node2href
294             %node2next
295             %node2prev
296             %node2sec
297             %node2up
298             %number2sec
299             %predefined_index
300             %sec2level
301             %sec2node
302             %sec2seccount
303             %seccount2sec
304             %sec2number
305             %seen
306             %simple_map
307             %style_map
308             %tag2pro
309             %things_map
310             %to_skip
311             %user_sub
312             %valid_index
313             %value
314             @T2H_CHAPTER_BUTTONS
315             @T2H_MISC_BUTTONS
316             @T2H_SECTION_BUTTONS
317             @appendix_sec_num
318             @args
319             @doc_lines
320             @fhs
321             @foot_lines
322             @html_stack
323             @input_spool
324             @l2h_from_html
325             @l2h_to_latex
326             @lines
327             @lines2
328             @lines3
329             @normal_sec_num
330             @sections
331             @stoc_lines
332             @tables
333             @toc_lines
334            );
335
336 #++##############################################################################
337 #
338 # NOTE FOR DEBUGGING THIS SCRIPT:
339 # You can run 'perl texi2html.pl' directly, provided you have
340 # the environment variable T2H_HOME set to the directory containing
341 # the texi2html.init file
342 #
343 #--##############################################################################
344
345 # CVS version:
346 # $Id: texi2html,v 1.3 2005-06-19 03:20:26 blp Exp $
347
348 # Homepage:
349 $T2H_HOMEPAGE = "http://texi2html.cvshome.org";
350
351 # Authors:
352 $T2H_AUTHORS = <<EOT;
353 Written by: Lionel Cons <Lionel.Cons\@cern.ch> (original author)
354             Karl Berry  <karl\@freefriends.org>
355             Olaf Bachmann <obachman\@mathematik.uni-kl.de>
356             and many others.
357 Maintained by: Many creative people <dev\@texi2html.cvshome.org>
358 Send bugs and suggestions to <users\@texi2html.cvshome.org>
359 EOT
360
361 # Version: set in configure.in
362 $THISVERSION = '1.66';
363 $THISPROG = "texi2html $THISVERSION"; # program name and version
364
365 # The man page for this program is included at the end of this file and can be
366 # viewed using the command 'nroff -man texi2html'.
367
368 #+++############################################################################
369 #                                                                              #
370 # Initialization                                                               #
371 # Pasted content of File $(srcdir)/texi2html.init: Default initializations     #
372 #                                                                              #
373 #---############################################################################
374
375 # leave this within comments, and keep the require statement
376 # This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/texi2html.init
377 # exists.
378
379
380 # -*-perl-*-
381 ######################################################################
382 # File: texi2html.init
383 #
384 # Sets default values for command-line arguments and for various customizable
385 # procedures
386 #
387 # A copy of this file is pasted into the beginning of texi2html by
388 # 'make texi2html'
389 #
390 # Copy this file and make changes to it, if you like.
391 # Afterwards, either, load it with command-line option -init_file <your_init_file>
392 #
393 # $Id: texi2html,v 1.3 2005-06-19 03:20:26 blp Exp $
394
395 ######################################################################
396 # stuff which can also be set by command-line options
397 #
398 #
399 # Note: values set here, overwrite values set by the command-line
400 # options before -init_file and might still be overwritten by
401 # command-line arguments following the -init_file option
402 #
403
404 # T2H_OPTIONS is a hash whose keys are the (long) names of valid
405 # command-line options and whose values are a hash with the following keys:
406 # type    ==> one of !|=i|:i|=s|:s (see GetOpt::Long for more info)
407 # linkage ==> ref to scalar, array, or subroutine (see GetOpt::Long for more info)
408 # verbose ==> short description of option (displayed by -h)
409 # noHelp  ==> if 1 -> for "not so important options": only print description on -h 1
410 #                2 -> for obsolete options: only print description on -h 2
411
412 my $T2H_DEBUG = 0;
413 my $T2H_OPTIONS;
414 $T2H_OPTIONS -> {debug} =
415 {
416  type => '=i',
417  linkage => \$T2H_DEBUG,
418  verbose => 'output HTML with debuging information',
419 };
420
421 # APA: Add SystemLiteral to identify the canonical DTD.
422 # [Definition:] The SystemLiteral is called the entity's system
423 # identifier. It is a URI, which may be used to retrieve the entity.
424 # See http://www.xml.com/axml/target.html#NT-ExternalID
425 my $T2H_DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
426                       "http://www.w3.org/TR/html40/loose.dtd">';
427 $T2H_OPTIONS -> {doctype} =
428 {
429  type => '=s',
430  linkage => \$T2H_DOCTYPE,
431  verbose => 'document type which is output in header of HTML files',
432  noHelp => 1
433 };
434
435 my $T2H_CHECK = 0;
436 $T2H_OPTIONS -> {check} =
437 {
438  type => '!',
439  linkage => \$T2H_CHECK,
440  verbose => 'if set, only check files and output all things that may be Texinfo commands',
441  noHelp => 1
442 };
443
444 # -expand
445 # if set to "tex" (or, "info") expand @iftex and @tex (or, @ifinfo) sections
446 # else, neither expand @iftex, @tex, nor @ifinfo sections
447 my $T2H_EXPAND = "info";
448 $T2H_OPTIONS -> {expand} =
449 {
450  type => '=s',
451  linkage => \$T2H_EXPAND,
452  verbose => 'Expand info|tex|none section of texinfo source',
453 };
454
455 # - glossary
456 # If set, uses section named `Footnotes' for glossary.
457 my $T2H_USE_GLOSSARY = 0;
458 $T2H_OPTIONS -> {glossary} =
459 {
460  type => '!',
461  linkage => \$T2H_USE_GLOSSARY,
462  verbose => "if set, uses section named `Footnotes' for glossary",
463  noHelp  => 1,
464 };
465
466
467 # -invisible
468 # $T2H_INVISIBLE_MARK is the text used to create invisible destination
469 # anchors for index links (you can for instance use the invisible.xbm
470 # file shipped with this program). This is a workaround for a known
471 # bug of many WWW browsers, including netscape.
472 # For me, it works fine without it -- on the contrary: if there, it
473 # inserts space between headers and start of text (obachman 3/99)
474 my $T2H_INVISIBLE_MARK = '';
475 # $T2H_INVISIBLE_MARK = '&#160;';
476 $T2H_OPTIONS -> {invisible} =
477 {
478  type => '=s',
479  linkage => \$T2H_INVISIBLE_MARK,
480  verbose => 'use text in invisble anchot',
481  noHelp  => 1,
482 };
483
484 # -iso
485 # if set, ISO8859 characters are used for special symbols (like copyright, etc)
486 my $T2H_USE_ISO = 0;
487 $T2H_OPTIONS -> {iso} =
488 {
489  type => 'iso',
490  linkage => \$T2H_USE_ISO,
491  verbose => 'if set, ISO8859 characters are used for special symbols (like copyright, etc)',
492  noHelp => 1,
493 };
494
495 # -I
496 # list directories where @include files are searched for (besides the
497 # directory of the doc file) additional '-I' args add to this list
498 # APA: Don't implicitely search ., to conform with the docs!
499 # my @T2H_INCLUDE_DIRS = (".");
500 my @T2H_INCLUDE_DIRS = ();
501 $T2H_OPTIONS -> {I} =
502 {
503  type => '=s',
504  linkage => \@T2H_INCLUDE_DIRS,
505  verbose => 'append $s to the @include search path',
506 };
507
508 # -top_file
509 # uses file of this name for top-level file
510 # extension is manipulated appropriately, if necessary.
511 # If empty, <basename of document>.html is used.
512 # Typically, you would set this to "index.html".
513 my $T2H_TOP_FILE = '';
514 $T2H_OPTIONS -> {top_file} =
515 {
516  type => '=s',
517  linkage => \$T2H_TOP_FILE,
518  verbose => 'use $s as top file, instead of <docname>.html',
519 };
520
521
522 # -toc_file
523 # uses file of this name for table of contents.  File
524 # extension is manipulated appropriately, if necessary.
525 # If empty, <basename of document>_toc.html is used.
526 my $T2H_TOC_FILE = '';
527 $T2H_OPTIONS -> {toc_file} =
528 {
529  type => '=s',
530  linkage => \$T2H_TOC_FILE,
531  verbose => 'use $s as ToC file, instead of <docname>_toc.html',
532 };
533
534 # -frames
535 # if set, output two additional files which use HTML 4.0 "frames".
536 my $T2H_FRAMES = 0;
537 $T2H_OPTIONS -> {frames} =
538 {
539  type => '!',
540  linkage => \$T2H_FRAMES,
541  verbose => 'output files which use HTML 4.0 frames (experimental)',
542  noHelp => 1,
543 };
544
545
546 # -menu | -nomenu
547 # if set, show the Texinfo menus
548 my $T2H_SHOW_MENU = 1;
549 $T2H_OPTIONS -> {menu} =
550 {
551  type => '!',
552  linkage => \$T2H_SHOW_MENU,
553  verbose => 'ouput Texinfo menus',
554 };
555
556 # -number | -nonumber
557 # if set, number sections and show section names and numbers in references
558 # and menus
559 my $T2H_NUMBER_SECTIONS = 1;
560 $T2H_OPTIONS -> {number} =
561 {
562  type => '!',
563  linkage => \$T2H_NUMBER_SECTIONS,
564  verbose => 'use numbered sections'
565 };
566
567 # if set, and T2H_NUMBER_SECTIONS is set, then use node names in menu
568 # entries, instead of section names
569 my $T2H_NODE_NAME_IN_MENU = 0;
570
571 # if set and menu entry equals menu descr, then do not print menu descr.
572 # Likewise, if node name equals entry name, do not print entry name.
573 my $T2H_AVOID_MENU_REDUNDANCY = 1;
574
575 # -split section|chapter|none
576 # if set to 'section' (resp. 'chapter') create one html file per (sub)section
577 # (resp. chapter) and separate pages for Top, ToC, Overview, Index,
578 # Glossary, About.
579 # Otherwise, create a monolithic html file that contains the whole document.
580 #$T2H_SPLIT = 'section';
581 my $T2H_SPLIT = '';
582 $T2H_OPTIONS -> {split} =
583 {
584  type => '=s',
585  linkage => \$T2H_SPLIT,
586  verbose => 'split document on section|chapter else no splitting',
587 };
588
589 # -section_navigation|-no-section_navigation
590 # if set, then navigation panels are printed at the beginning of each section
591 # and, possibly at the end (depending on whether or not there were more than
592 # $T2H_WORDS_IN_PAGE  words on page
593 # This is most useful if you do not want to have section navigation
594 # on -split chapter
595 my $T2H_SECTION_NAVIGATION = 1;
596 $T2H_OPTIONS -> {sec_nav} =
597 {
598  type => '!',
599  linkage => \$T2H_SECTION_NAVIGATION,
600  verbose => 'output navigation panels for each section',
601 };
602
603 # -subdir
604 # If set, then put result files into the specified directory.
605 # If not set, then result files are put into the current directory.
606 #$T2H_SUBDIR = 'html';
607 my $T2H_SUBDIR = '';
608 $T2H_OPTIONS -> {subdir} =
609 {
610  type => '=s',
611  linkage => \$T2H_SUBDIR,
612  verbose => 'put HTML files in directory $s, instead of $cwd',
613 };
614
615 # -short_extn
616 # If this is set, then all HTML files will have extension ".htm" instead of
617 # ".html". This is helpful when shipping the document to DOS-based systems.
618 my $T2H_SHORTEXTN = 0;
619 $T2H_OPTIONS -> {short_ext} =
620 {
621  type => '!',
622  linkage => \$T2H_SHORTEXTN,
623  verbose => 'use "htm" extension for output HTML files',
624 };
625
626
627 # -prefix
628 # Set the output file prefix, prepended to all .html, .gif and .pl files.
629 # By default, this is the basename of the document
630 my $T2H_PREFIX = '';
631 $T2H_OPTIONS -> {prefix} =
632 {
633  type => '=s',
634  linkage => \$T2H_PREFIX,
635  verbose => 'use as prefix for output files, instead of <docname>',
636 };
637
638 # -o filename
639 # If set, generate monolithic document output html into $filename
640 my $T2H_OUT = '';
641 $T2H_OPTIONS -> {out_file} =
642 {
643  type => '=s',
644  linkage => sub {$T2H_OUT = $_[1]; $T2H_SPLIT = '';},
645  verbose => 'if set, all HTML output goes into file $s',
646 };
647
648 # -short_ref
649 #if set cross-references are given without section numbers
650 my $T2H_SHORT_REF = '';
651 $T2H_OPTIONS -> {short_ref} =
652 {
653  type => '!',
654  linkage => \$T2H_SHORT_REF,
655  verbose => 'if set, references are without section numbers',
656 };
657
658 # -idx_sum
659 # if value is set, then for each @prinindex $what
660 # $docu_name_$what.idx is created which contains lines of the form
661 # $key\t$ref sorted alphabetically (case matters)
662 my $T2H_IDX_SUMMARY = 0;
663 $T2H_OPTIONS -> {idx_sum} =
664 {
665  type => '!',
666  linkage => \$T2H_IDX_SUMMARY,
667  verbose => 'if set, also output index summary',
668  noHelp  => 1,
669 };
670
671 # -def_table
672 # Use a table construction for @def .... stuff instead
673 # New Option: 27.07.2000 Karl Heinz Marbaise
674 my $T2H_DEF_TABLE = 0;
675 $T2H_OPTIONS -> {def_table} =
676 {
677  type => '!',
678  linkage => \$T2H_DEF_TABLE,
679  verbose => 'if set, \@def.. are converted using tables.',
680  noHelp  => 1,
681 };
682
683 # -verbose
684 # if set, chatter about what we are doing
685 my $T2H_VERBOSE = '';
686 $T2H_OPTIONS -> {Verbose} =
687 {
688  type => '!',
689  linkage => \$T2H_VERBOSE,
690  verbose => 'print progress info to stdout',
691 };
692
693 # -lang
694 # For page titles use $T2H_WORDS->{$T2H_LANG}->{...} as title.
695 # To add a new language, supply list of titles (see $T2H_WORDS below).
696 # and use ISO 639 language codes (see e.g. perl module Locale-Codes-1.02
697 # for  definitions)
698 # Default's to 'en' if not set or no @documentlanguage is specified
699 my $T2H_LANG = '';
700 $T2H_OPTIONS -> {lang} =
701 {
702  type => '=s',
703  linkage => sub {SetDocumentLanguage($_[1])},
704  verbose => 'use $s as document language (ISO 639 encoding)',
705 };
706
707 # -l2h
708 # if set, uses latex2html for generation of math content
709 my $T2H_L2H = '';
710 $T2H_OPTIONS -> {l2h} =
711 {
712  type => '!',
713  linkage => \$T2H_L2H,
714  verbose => 'if set, uses latex2html for @math and @tex',
715 };
716
717 ######################
718 # The following options are only relevant if $T2H_L2H is set
719 #
720 # -l2h_l2h
721 # name/location of latex2html program
722 my $T2H_L2H_L2H = "latex2html";
723 $T2H_OPTIONS -> {l2h_l2h} =
724 {
725  type => '=s',
726  linkage => \$T2H_L2H_L2H,
727  verbose => 'program to use for latex2html translation',
728  noHelp => 1,
729 };
730
731 # -l2h_skip
732 # If set, skips actual call to latex2html: tries to reuse previously generated
733 # content, instead.
734 my $T2H_L2H_SKIP = '';
735 $T2H_OPTIONS -> {l2h_skip} =
736 {
737  type => '!',
738  linkage => \$T2H_L2H_SKIP,
739  verbose => 'if set, tries to reuse previously latex2html output',
740  noHelp => 1,
741 };
742
743 # -l2h_tmp
744 # If set, l2h uses the specified directory for temporary files.  The path
745 # leading to this directory may not contain a dot (i.e., a ".");
746 # otherwise, l2h will fail.
747 my $T2H_L2H_TMP = '';
748 $T2H_OPTIONS -> {l2h_tmp} =
749 {
750  type => '=s',
751  linkage => \$T2H_L2H_TMP,
752  verbose => 'if set, uses $s as temporary latex2html directory',
753  noHelp => 1,
754 };
755
756 # if set, cleans intermediate files (they all have the prefix $doc_l2h_)
757 # of l2h
758 my $T2H_L2H_CLEAN = 1;
759 $T2H_OPTIONS -> {l2h_clean} =
760 {
761  type => '!',
762  linkage => \$T2H_L2H_CLEAN,
763  verbose => 'if set, do not keep intermediate latex2html files for later reuse',
764  noHelp => 1,
765 };
766
767 $T2H_OPTIONS -> {D} =
768 {
769  type => '=s',
770  linkage => sub {$main::value{$_[1]} = 1;},
771  verbose => 'equivalent to Texinfo "@set $s 1"',
772  noHelp => 1,
773 };
774
775 $T2H_OPTIONS -> {init_file} =
776 {
777  type => '=s',
778  linkage => \&LoadInitFile,
779  verbose => 'load init file $s'
780 };
781
782
783 ##############################################################################
784 #
785 # The following can only be set in the init file
786 #
787 ##############################################################################
788
789 # if set, center @image by default
790 # otherwise, do not center by default
791 my $T2H_CENTER_IMAGE = 1;
792
793 # used as identation for block enclosing command @example, etc
794 # If not empty, must be enclosed in <td></td>
795 my $T2H_EXAMPLE_INDENT_CELL = '<td>&nbsp;</td>';
796 # same as above, only for @small
797 my $T2H_SMALL_EXAMPLE_INDENT_CELL = '<td>&nbsp;</td>';
798 # font size for @small
799 my $T2H_SMALL_FONT_SIZE = '-1';
800
801 # if non-empty, and no @..heading appeared in Top node, then
802 # use this as header for top node/section, otherwise use value of
803 # @settitle or @shorttitle (in that order)
804 my $T2H_TOP_HEADING = '';
805
806 # if set, use this chapter for 'Index' button, else
807 # use first chapter whose name matches 'index' (case insensitive)
808 my $T2H_INDEX_CHAPTER = '';
809
810 # if set and $T2H_SPLIT is set, then split index pages at the next letter
811 # after they have more than that many entries
812 my $T2H_SPLIT_INDEX = 100;
813
814 # if set (e.g., to index.html) replace hrefs to this file
815 # (i.e., to index.html) by ./
816 my $T2H_HREF_DIR_INSTEAD_FILE = '';
817
818 ########################################################################
819 # Language dependencies:
820 # To add a new language extend T2H_WORDS hash and create $T2H_<...>_WORDS hash
821 # To redefine one word, simply do:
822 # $T2H_WORDS->{<language>}->{<word>} = 'whatever' in your personal init file.
823 #
824 my $T2H_WORDS_EN =
825 {
826  # titles  of pages
827  'ToC_Title' => 'Table of Contents',
828  'Overview_Title' => 'Short Table of Contents',
829  'Index_Title' => 'Index',
830  'About_Title' => 'About this document',
831  'Footnotes_Title' => 'Footnotes',
832  'See' => 'See',
833  'see' => 'see',
834  'section' => 'section',
835  # If necessary, we could extend this as follows:
836  #  # text for buttons
837  #  'Top_Button' => 'Top',
838  #  'ToC_Button' => 'Contents',
839  #  'Overview_Button' => 'Overview',
840  #  'Index_button' => 'Index',
841  #  'Back_Button' => 'Back',
842  #  'FastBack_Button' => 'FastBack',
843  #  'Prev_Button' => 'Prev',
844  #  'Up_Button' => 'Up',
845  #  'Next_Button' => 'Next',
846  #  'Forward_Button' =>'Forward',
847  #  'FastWorward_Button' => 'FastForward',
848  #  'First_Button' => 'First',
849  #  'Last_Button' => 'Last',
850  #  'About_Button' => 'About'
851 };
852
853 my $T2H_WORDS_DE =
854 {
855  'ToC_Title' => 'Inhaltsverzeichniss',
856  'Overview_Title' => 'Kurzes Inhaltsverzeichniss',
857  'Index_Title' => 'Index',
858  'About_Title' => '&Uuml;ber dieses Dokument',
859  'Footnotes_Title' => 'Fu&szlig;noten',
860  'See' => 'Siehe',
861  'see' => 'siehe',
862  'section' => 'Abschnitt',
863 };
864
865 my $T2H_WORDS_NL =
866 {
867  'ToC_Title' => 'Inhoudsopgave',
868  'Overview_Title' => 'Korte inhoudsopgave',
869  'Index_Title' => 'Index',      #Not sure ;-)
870  'About_Title' => 'No translation available!', #No translation available!
871  'Footnotes_Title' => 'No translation available!', #No translation available!
872  'See' => 'Zie',
873  'see' => 'zie',
874  'section' => 'sectie',
875 };
876
877 my $T2H_WORDS_ES =
878 {
879  'ToC_Title' => '&iacute;ndice General',
880  'Overview_Title' => 'Resumen del Contenido',
881  'Index_Title' => 'Index',      #Not sure ;-)
882  'About_Title' => 'No translation available!', #No translation available!
883  'Footnotes_Title' => 'Fu&szlig;noten',
884  'See' => 'V&eacute;ase',
885  'see' => 'v&eacute;ase',
886  'section' => 'secci&oacute;n',
887 };
888
889 my $T2H_WORDS_NO =
890 {
891  'ToC_Title' => 'Innholdsfortegnelse',
892  'Overview_Title' => 'Kort innholdsfortegnelse',
893  'Index_Title' => 'Indeks',     #Not sure ;-)
894  'About_Title' => 'No translation available!', #No translation available!
895  'Footnotes_Title' => 'No translation available!',
896  'See' => 'Se',
897  'see' => 'se',
898  'section' => 'avsnitt',
899 };
900
901 my $T2H_WORDS_PT =
902 {
903  'ToC_Title' => 'Sum&aacute;rio',
904  'Overview_Title' => 'Breve Sum&aacute;rio',
905  'Index_Title' => '&Iacute;ndice', #Not sure ;-)
906  'About_Title' => 'No translation available!', #No translation available!
907  'Footnotes_Title' => 'No translation available!',
908  'See' => 'Veja',
909  'see' => 'veja',
910  'section' => 'Se&ccedil;&atilde;o',
911 };
912
913 my $T2H_WORDS_FR =
914 {
915  'ToC_Title' => 'Table des mati&egrav;res',
916  'Overview_Title' => 'R&eacute;sum&eacute;e du contenu',
917  'Index_Title' => 'Index',
918  'About_Title' => 'A propos de ce document',
919  'Footnotes_Title' => 'Notes de bas de page',
920  'See' => 'Voir',
921  'see' => 'voir',
922  'section' => 'section',
923 };
924
925 my $T2H_WORDS =
926 {
927  'en' => $T2H_WORDS_EN,
928  'de' => $T2H_WORDS_DE,
929  'nl' => $T2H_WORDS_NL,
930  'es' => $T2H_WORDS_ES,
931  'no' => $T2H_WORDS_NO,
932  'pt' => $T2H_WORDS_PT,
933  'fr' => $T2H_WORDS_FR
934 };
935
936 my @MONTH_NAMES_EN =
937     (
938      'January', 'February', 'March', 'April', 'May',
939      'June', 'July', 'August', 'September', 'October',
940      'November', 'December'
941     );
942
943 my @MONTH_NAMES_DE =
944     (
945      'Januar', 'Februar', 'M&auml;rz', 'April', 'Mai',
946      'Juni', 'Juli', 'August', 'September', 'Oktober',
947      'November', 'Dezember'
948     );
949
950 my @MONTH_NAMES_NL =
951     (
952      'Januari', 'Februari', 'Maart', 'April', 'Mei',
953      'Juni', 'Juli', 'Augustus', 'September', 'Oktober',
954      'November', 'December'
955     );
956
957 my @MONTH_NAMES_ES =
958     (
959      'enero', 'febrero', 'marzo', 'abril', 'mayo',
960      'junio', 'julio', 'agosto', 'septiembre', 'octubre',
961      'noviembre', 'diciembre'
962     );
963
964 my @MONTH_NAMES_NO =
965     (
966
967      'januar', 'februar', 'mars', 'april', 'mai',
968      'juni', 'juli', 'august', 'september', 'oktober',
969      'november', 'desember'
970     );
971
972 my @MONTH_NAMES_PT =
973     (
974      'Janeiro', 'Fevereiro', 'Mar&ccedil;o', 'Abril', 'Maio',
975      'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro',
976      'Novembro', 'Dezembro'
977     );
978
979 my @MONTH_NAMES_FR =
980 (
981  'Janvier', 'F&eacute;vrier', 'Mars', 'Avril', 'Mai',
982  'Juin', 'Juillet', 'Ao&ucirc;t', 'Septembre', 'Octobre',
983  'Novembre', 'D&eacute;cembre'
984 );
985
986
987
988 my $MONTH_NAMES =
989 {
990  'en' => \@MONTH_NAMES_EN,
991  'de' => \@MONTH_NAMES_DE,
992  'es' => \@MONTH_NAMES_ES,
993  'nl' => \@MONTH_NAMES_NL,
994  'no' => \@MONTH_NAMES_NO,
995  'pt' => \@MONTH_NAMES_PT,
996  'fr' => \@MONTH_NAMES_FR
997 };
998
999 ########################################################################
1000 # Control of Page layout:
1001 # You can make changes of the Page layout at two levels:
1002 # 1.) For small changes, it is often enough to change the value of
1003 #     some global string/hash/array variables
1004 # 2.) For larger changes, reimplement one of the T2H_DEFAULT_<fnc>* routines,
1005 #     give them another name, and assign them to the respective
1006 #     $T2H_<fnc> variable.
1007
1008 # As a general interface, the hashes T2H_HREF, T2H_NAME, T2H_NODE hold
1009 # href, html-name, node-name of
1010 # This     -- current section (resp. html page)
1011 # Top      -- top page ($T2H_TOP_FILE)
1012 # Contents -- Table of contents
1013 # Overview -- Short table of contents
1014 # Index    -- Index page
1015 # About    -- page which explain "navigation buttons"
1016 # First    -- first node
1017 # Last     -- last node
1018 #
1019 # Whether or not the following hash values are set, depends on the context
1020 # (all values are w.r.t. 'This' section)
1021 # Next        -- next node of texinfo
1022 # Prev        -- previous node of texinfo
1023 # Up          -- up node of texinfo
1024 # Forward     -- next node in reading order
1025 # Back        -- previous node in reading order
1026 # FastForward -- if leave node, up and next, else next node
1027 # FastBackward-- if leave node, up and prev, else prev node
1028 #
1029 # Furthermore, the following global variabels are set:
1030 # $T2H_THISDOC{title}     -- title as set by @setttile
1031 # $T2H_THISDOC{fulltitle} -- full title as set by @title...
1032 # $T2H_THISDOC{subtitle}  -- subtitle as set by @subtitle
1033 # $T2H_THISDOC{author}    -- author as set by @author
1034 #
1035 # and pointer to arrays of lines which need to be printed by t2h_print_lines
1036 # $T2H_OVERVIEW      -- lines of short table of contents
1037 # $T2H_TOC           -- lines of table of contents
1038 # $T2H_TOP           -- lines of Top texinfo node
1039 # $T2H_THIS_SECTION  -- lines of 'This' section
1040
1041 #
1042 # There are the following subs which control the layout:
1043 #
1044 my $T2H_print_section            = \&T2H_DEFAULT_print_section;
1045 my $T2H_print_Top_header         = \&T2H_DEFAULT_print_Top_header;
1046 my $T2H_print_Top_footer              = \&T2H_DEFAULT_print_Top_footer;
1047 my $T2H_print_Top                     = \&T2H_DEFAULT_print_Top;
1048 my $T2H_print_Toc                     = \&T2H_DEFAULT_print_Toc;
1049 my $T2H_print_Overview        = \&T2H_DEFAULT_print_Overview;
1050 my $T2H_print_Footnotes       = \&T2H_DEFAULT_print_Footnotes;
1051 my $T2H_print_About           = \&T2H_DEFAULT_print_About;
1052 my $T2H_print_misc_header             = \&T2H_DEFAULT_print_misc_header;
1053 my $T2H_print_misc_footer             = \&T2H_DEFAULT_print_misc_footer;
1054 my $T2H_print_misc                    = \&T2H_DEFAULT_print_misc;
1055 my $T2H_print_chapter_header     = \&T2H_DEFAULT_print_chapter_header;
1056 my $T2H_print_chapter_footer     = \&T2H_DEFAULT_print_chapter_footer;
1057 my $T2H_print_page_head       = \&T2H_DEFAULT_print_page_head;
1058 my $T2H_print_page_foot       = \&T2H_DEFAULT_print_page_foot;
1059 my $T2H_print_head_navigation    = \&T2H_DEFAULT_print_head_navigation;
1060 my $T2H_print_foot_navigation    = \&T2H_DEFAULT_print_foot_navigation;
1061 my $T2H_button_icon_img       = \&T2H_DEFAULT_button_icon_img;
1062 my $T2H_print_navigation              = \&T2H_DEFAULT_print_navigation;
1063 my $T2H_about_body                    = \&T2H_DEFAULT_about_body;
1064 my $T2H_print_frame              = \&T2H_DEFAULT_print_frame;
1065 my $T2H_print_toc_frame          = \&T2H_DEFAULT_print_toc_frame;
1066
1067 ########################################################################
1068 # Layout for html for every sections
1069 #
1070 sub T2H_DEFAULT_print_section
1071 {
1072     my $fh = shift;
1073     local $T2H_BUTTONS = \@T2H_SECTION_BUTTONS;
1074     &$T2H_print_head_navigation($fh) if $T2H_SECTION_NAVIGATION;
1075     my $nw = t2h_print_lines($fh);
1076     if (defined $T2H_SPLIT
1077         and ($T2H_SPLIT eq 'section' && $T2H_SECTION_NAVIGATION))
1078     {
1079         &$T2H_print_foot_navigation($fh, $nw);
1080     }
1081     else
1082     {
1083         print $fh '<HR SIZE="6">' . "\n";
1084     }
1085 }
1086
1087 ###################################################################
1088 # Layout of top-page I recommend that you use @ifnothtml, @ifhtml,
1089 # @html within the Top texinfo node to specify content of top-level
1090 # page.
1091 #
1092 # If you enclose everything in @ifnothtml, then title, subtitle,
1093 # author and overview is printed
1094 # T2H_HREF of Next, Prev, Up, Forward, Back are not defined
1095 # if $T2H_SPLIT then Top page is in its own html file
1096 sub T2H_DEFAULT_print_Top_header
1097 {
1098     &$T2H_print_page_head(@_) if $T2H_SPLIT;
1099     t2h_print_label(@_);        # this needs to be called, otherwise no label set
1100     &$T2H_print_head_navigation(@_);
1101 }
1102 sub T2H_DEFAULT_print_Top_footer
1103 {
1104     &$T2H_print_foot_navigation(@_);
1105     &$T2H_print_page_foot(@_) if $T2H_SPLIT;
1106 }
1107 sub T2H_DEFAULT_print_Top
1108 {
1109     my $fh = shift;
1110
1111     # for redefining navigation buttons use:
1112     # local $T2H_BUTTONS = [...];
1113     # as it is, 'Top', 'Contents', 'Index', 'About' are printed
1114     local $T2H_BUTTONS = \@T2H_MISC_BUTTONS;
1115     &$T2H_print_Top_header($fh);
1116     if ($T2H_THIS_SECTION)
1117     {
1118         # if top-level node has content, then print it with extra header
1119         print $fh "<H1>$T2H_NAME{Top}</H1>\n"
1120             unless ($T2H_HAS_TOP_HEADING);
1121         t2h_print_lines($fh, $T2H_THIS_SECTION)
1122     }
1123     else
1124     {
1125         # top-level node is fully enclosed in @ifnothtml
1126         # print fulltitle, subtitle, author, Overview
1127         print $fh
1128             "<CENTER>\n<H1>" .
1129                 join("</H1>\n<H1>", split(/\n/,  $T2H_THISDOC{fulltitle})) .
1130                     "</H1>\n";
1131         print $fh "<H2>$T2H_THISDOC{subtitle}</H2>\n" if $T2H_THISDOC{subtitle};
1132         print $fh "$T2H_THISDOC{author}\n" if $T2H_THISDOC{author};
1133         print $fh <<EOT;
1134 </CENTER>
1135 <HR>
1136 <P></P>
1137 <H2> Overview: </H2>
1138 <BLOCKQUOTE>
1139 EOT
1140         t2h_print_lines($fh, $T2H_OVERVIEW);
1141         print $fh "</BLOCKQUOTE>\n";
1142     }
1143     &$T2H_print_Top_footer($fh);
1144 }
1145
1146 ###################################################################
1147 # Layout of Toc, Overview, and Footnotes pages
1148 # By default, we use "normal" layout
1149 # T2H_HREF of Next, Prev, Up, Forward, Back, etc are not defined
1150 # use: local $T2H_BUTTONS = [...] to redefine navigation buttons
1151 sub T2H_DEFAULT_print_Toc
1152 {
1153     return &$T2H_print_misc(@_);
1154 }
1155 sub T2H_DEFAULT_print_Overview
1156 {
1157     return &$T2H_print_misc(@_);
1158 }
1159 sub T2H_DEFAULT_print_Footnotes
1160 {
1161     return &$T2H_print_misc(@_);
1162 }
1163 sub T2H_DEFAULT_print_About
1164 {
1165     return &$T2H_print_misc(@_);
1166 }
1167
1168 sub T2H_DEFAULT_print_misc_header
1169 {
1170     &$T2H_print_page_head(@_) if $T2H_SPLIT;
1171     # this needs to be called, otherwise, no labels are set
1172     t2h_print_label(@_);
1173     &$T2H_print_head_navigation(@_);
1174 }
1175 sub T2H_DEFAULT_print_misc_footer
1176 {
1177     &$T2H_print_foot_navigation(@_);
1178     &$T2H_print_page_foot(@_) if $T2H_SPLIT;
1179 }
1180 sub T2H_DEFAULT_print_misc
1181 {
1182     my $fh = shift;
1183     local $T2H_BUTTONS = \@T2H_MISC_BUTTONS;
1184     &$T2H_print_misc_header($fh);
1185     print $fh "<H1>$T2H_NAME{This}</H1>\n";
1186     t2h_print_lines($fh);
1187     &$T2H_print_misc_footer($fh);
1188 }
1189
1190 ###################################################################
1191 # chapter_header and chapter_footer are only called if
1192 # T2H_SPLIT eq 'chapter'
1193 # chapter_header: after print_page_head, before print_section
1194 # chapter_footer: after print_section of last section, before print_page_foot
1195 #
1196 # If you want to get rid of navigation stuff after each section,
1197 # redefine print_section such that it does not call print_navigation,
1198 # and put print_navigation into print_chapter_header
1199 @T2H_CHAPTER_BUTTONS =
1200     (
1201      'FastBack', 'FastForward', ' ',
1202      ' ', ' ', ' ', ' ',
1203      'Top', 'Contents', 'Index', 'About',
1204     );
1205
1206 sub T2H_DEFAULT_print_chapter_header
1207 {
1208     # nothing to do there, by default
1209     if (! $T2H_SECTION_NAVIGATION)
1210     {
1211         my $fh = shift;
1212         local $T2H_BUTTONS = \@T2H_CHAPTER_BUTTONS;
1213         &$T2H_print_navigation($fh);
1214         print $fh "\n<HR SIZE=2>\n";
1215     }
1216 }
1217
1218 sub T2H_DEFAULT_print_chapter_footer
1219 {
1220     local $T2H_BUTTONS = \@T2H_CHAPTER_BUTTONS;
1221     &$T2H_print_navigation(@_);
1222 }
1223 ###################################################################
1224
1225 sub pretty_date {
1226     my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
1227
1228     ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
1229     $year += ($year < 70) ? 2000 : 1900;
1230     # obachman: Let's do it as the Americans do
1231     return($MONTH_NAMES->{$T2H_LANG}[$mon] . ", " . $mday . " " . $year);
1232 }
1233
1234
1235 ###################################################################
1236 # Layout of standard header and footer
1237 #
1238
1239 # This init routine is called at the beginning of pass5 before first
1240 # output is generated.
1241 sub T2H_InitGlobals
1242 {
1243     # Set the default body text, inserted between <BODY ... >
1244     $T2H_BODYTEXT = 'LANG="' . $T2H_LANG . '" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000"';
1245     # text inserted after <BODY ...>
1246     $T2H_AFTER_BODY_OPEN = '';
1247     #text inserted before </BODY>
1248     $T2H_PRE_BODY_CLOSE = '';
1249     # this is used in footer
1250     $T2H_ADDRESS = "<I>$T2H_USER</I> " if $T2H_USER;
1251     $T2H_ADDRESS .= "on <I>$T2H_TODAY</I>";
1252     # this is added inside <HEAD></HEAD> after <TITLE> and some META NAME stuff
1253     # can be used for <style> <script>, <meta> tags
1254     $T2H_EXTRA_HEAD = '';
1255 }
1256
1257 sub T2H_DEFAULT_print_page_head
1258 {
1259     my $fh = shift;
1260     my $longtitle = "$T2H_THISDOC{title}";
1261     $longtitle .= ": $T2H_NAME{This}" if exists $T2H_NAME{This};
1262     print $fh <<EOT;
1263 $T2H_DOCTYPE
1264 <HTML>
1265 <!-- Created on $T2H_TODAY by $THISPROG -->
1266 <!--
1267 $T2H_AUTHORS
1268 -->
1269 <HEAD>
1270 <TITLE>$longtitle</TITLE>
1271
1272 <META NAME="description" CONTENT="$longtitle">
1273 <META NAME="keywords" CONTENT="$longtitle">
1274 <META NAME="resource-type" CONTENT="document">
1275 <META NAME="distribution" CONTENT="global">
1276 <META NAME="Generator" CONTENT="$THISPROG">
1277 $T2H_EXTRA_HEAD
1278 </HEAD>
1279
1280 <BODY $T2H_BODYTEXT>
1281 $T2H_AFTER_BODY_OPEN
1282 EOT
1283 }
1284
1285 sub T2H_DEFAULT_print_page_foot
1286 {
1287     my $fh = shift;
1288     print $fh <<EOT;
1289 <BR>
1290 <FONT SIZE="-1">
1291 This document was generated
1292 by $T2H_ADDRESS
1293 using <A HREF="$T2H_HOMEPAGE"><I>texi2html</I></A>
1294 </FONT>
1295 $T2H_PRE_BODY_CLOSE
1296 </BODY>
1297 </HTML>
1298 EOT
1299 }
1300
1301 ###################################################################
1302 # Layout of navigation panel
1303
1304 # if this is set, then a vertical navigation panel is used
1305 my $T2H_VERTICAL_HEAD_NAVIGATION = 0;
1306 sub T2H_DEFAULT_print_head_navigation
1307 {
1308     my $fh = shift;
1309     if ($T2H_VERTICAL_HEAD_NAVIGATION)
1310     {
1311         print $fh <<EOT;
1312 <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
1313 <TR VALIGN="TOP">
1314 <TD ALIGN="LEFT">
1315 EOT
1316     }
1317     &$T2H_print_navigation($fh, $T2H_VERTICAL_HEAD_NAVIGATION);
1318     if ($T2H_VERTICAL_HEAD_NAVIGATION)
1319     {
1320         print $fh <<EOT;
1321 </TD>
1322 <TD ALIGN="LEFT">
1323 EOT
1324     }
1325     elsif (defined $T2H_SPLIT
1326            and ($T2H_SPLIT eq 'section'))
1327     {
1328         print $fh "<HR SIZE=1>\n";
1329     }
1330 }
1331
1332 # Specifies the minimum page length required before a navigation panel
1333 # is placed at the bottom of a page (the default is that of latex2html)
1334 # T2H_THIS_WORDS_IN_PAGE holds number of words of current page
1335 my $T2H_WORDS_IN_PAGE = 300;
1336 sub T2H_DEFAULT_print_foot_navigation
1337 {
1338     my $fh = shift;
1339     my $nwords = shift;
1340     if ($T2H_VERTICAL_HEAD_NAVIGATION)
1341     {
1342         print $fh <<EOT;
1343 </TD>
1344 </TR>
1345 </TABLE>
1346 EOT
1347     }
1348     print $fh "<HR SIZE=1>\n";
1349     &$T2H_print_navigation($fh) if (defined $nwords
1350                                     and $nwords >= $T2H_WORDS_IN_PAGE)
1351 }
1352
1353 ######################################################################
1354 # navigation panel
1355 #
1356 # specify in this array which "buttons" should appear in which order
1357 # in the navigation panel for sections; use ' ' for empty buttons (space)
1358 @T2H_SECTION_BUTTONS =
1359     (
1360      'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1361      ' ', ' ', ' ', ' ',
1362      'Top', 'Contents', 'Index', 'About',
1363     );
1364
1365 # buttons for misc stuff
1366 @T2H_MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About');
1367
1368 # insert here name of icon images for buttons
1369 # Icons are used, if $T2H_ICONS and resp. value are set
1370 %T2H_ACTIVE_ICONS =
1371     (
1372      'Top',      '',
1373      'Contents', '',
1374      'Overview', '',
1375      'Index',    '',
1376      'Back',     '',
1377      'FastBack', '',
1378      'Prev',     '',
1379      'Up',       '',
1380      'Next',     '',
1381      'Forward',  '',
1382      'FastForward', '',
1383      'About' ,    '',
1384      'First',    '',
1385      'Last',     '',
1386      ' ',        ''
1387     );
1388
1389 # insert here name of icon images for these, if button is inactive
1390 %T2H_PASSIVE_ICONS =
1391     (
1392      'Top',      '',
1393      'Contents', '',
1394      'Overview', '',
1395      'Index',    '',
1396      'Back',     '',
1397      'FastBack', '',
1398      'Prev',     '',
1399      'Up',       '',
1400      'Next',     '',
1401      'Forward',  '',
1402      'FastForward', '',
1403      'About',     '',
1404      'First',    '',
1405      'Last',     '',
1406     );
1407
1408 # how to create IMG tag
1409 sub T2H_DEFAULT_button_icon_img
1410 {
1411     my $button = shift;
1412     my $icon = shift;
1413     my $name = shift;
1414     return qq{<IMG SRC="$icon" BORDER="0" ALT="$button: $name" ALIGN="MIDDLE">};
1415 }
1416
1417 # Names of text as alternative for icons
1418 %T2H_NAVIGATION_TEXT =
1419     (
1420      'Top',      'Top',
1421      'Contents', 'Contents',
1422      'Overview', 'Overview',
1423      'Index',    'Index',
1424      ' ',        ' &nbsp; ',
1425      'Back',     ' &lt; ',
1426      'FastBack', ' &lt;&lt; ',
1427      'Prev',     'Prev',
1428      'Up',       ' Up ',
1429      'Next',     'Next',
1430      'Forward',  ' &gt; ',
1431      'FastForward',  ' &gt;&gt; ',
1432      'About',     ' ? ',
1433      'First',    ' |&lt; ',
1434      'Last',     ' &gt;| '
1435     );
1436
1437 sub T2H_DEFAULT_print_navigation
1438 {
1439     my $fh = shift;
1440     my $vertical = shift;
1441     my $spacing = 1;
1442     print $fh "<TABLE CELLPADDING=$spacing CELLSPACING=$spacing BORDER=0>\n";
1443
1444     print $fh "<TR>" unless $vertical;
1445     for $button (@$T2H_BUTTONS)
1446     {
1447         print $fh qq{<TR VALIGN="TOP" ALIGN="LEFT">\n} if $vertical;
1448         print $fh qq{<TD VALIGN="MIDDLE" ALIGN="LEFT">};
1449
1450         if (ref($button) eq 'CODE')
1451         {
1452             &$button($fh, $vertical);
1453         }
1454         elsif ($button eq ' ')
1455         {                       # handle space button
1456             print $fh
1457                 $T2H_ICONS && $T2H_ACTIVE_ICONS{' '} ?
1458                     &$T2H_button_icon_img($button, $T2H_ACTIVE_ICONS{' '}) :
1459                         $T2H_NAVIGATION_TEXT{' '};
1460             next;
1461         }
1462         elsif ($T2H_HREF{$button})
1463         {                       # button is active
1464             print $fh
1465                 $T2H_ICONS && $T2H_ACTIVE_ICONS{$button} ? # use icon ?
1466                     t2h_anchor('', $T2H_HREF{$button}, # yes
1467                                &$T2H_button_icon_img($button,
1468                                                      $T2H_ACTIVE_ICONS{$button},
1469                                                      $T2H_NAME{$button}))
1470                         :       # use text
1471                             "[" .
1472                                 t2h_anchor('', $T2H_HREF{$button}, $T2H_NAVIGATION_TEXT{$button}) .
1473                                     "]";
1474         }
1475         else
1476         {                       # button is passive
1477             print $fh
1478                 $T2H_ICONS && $T2H_PASSIVE_ICONS{$button} ?
1479                     &$T2H_button_icon_img($button,
1480                                           $T2H_PASSIVE_ICONS{$button},
1481                                           $T2H_NAME{$button}) :
1482
1483                                               "[" . $T2H_NAVIGATION_TEXT{$button} . "]";
1484         }
1485         print $fh "</TD>\n";
1486         print $fh "</TR>\n" if $vertical;
1487     }
1488     print $fh "</TR>" unless $vertical;
1489     print $fh "</TABLE>\n";
1490 }
1491
1492 ######################################################################
1493 # Frames: this is from "Richard Y. Kim" <ryk@coho.net>
1494 # Should be improved to be more conforming to other _print* functions
1495
1496 sub T2H_DEFAULT_print_frame
1497 {
1498     my $fh = shift;
1499     print $fh <<EOT;
1500 <HTML>
1501 <HEAD><TITLE>$T2H_THISDOC{title}</TITLE></HEAD>
1502 <FRAMESET cols="140,*">
1503   <FRAME name=toc  src="$docu_toc_frame_file">
1504   <FRAME name=main src="$docu_doc">
1505 </FRAMESET>
1506 </HTML>
1507 EOT
1508 }
1509
1510 sub T2H_DEFAULT_print_toc_frame
1511 {
1512     my $fh = shift;
1513     &$T2H_print_page_head($fh);
1514     print $fh <<EOT;
1515 <H2>Content</H2>
1516 EOT
1517     print $fh map {s/HREF=/target=\"main\" HREF=/; $_;} @stoc_lines;
1518     print $fh "</BODY></HTML>\n";
1519 }
1520
1521 ######################################################################
1522 # About page
1523 #
1524
1525 # T2H_PRE_ABOUT might be a function
1526 my $T2H_PRE_ABOUT = <<EOT;
1527 This document was generated
1528 by $T2H_ADDRESS
1529 using <A HREF=\"$T2H_HOMEPAGE\"><I>texi2html</I></A>
1530 <P></P>
1531 EOT
1532 my $T2H_AFTER_ABOUT = '';
1533
1534 sub T2H_DEFAULT_about_body
1535 {
1536     my $about;
1537     if (ref($T2H_PRE_ABOUT) eq 'CODE')
1538     {
1539         $about = &$T2H_PRE_ABOUT();
1540     }
1541     else
1542     {
1543         $about = $T2H_PRE_ABOUT;
1544     }
1545     $about .= <<EOT;
1546 The buttons in the navigation panels have the following meaning:
1547 <P></P>
1548 <table border = "1">
1549 <TR>
1550 <TH> Button </TH>
1551 <TH> Name </TH>
1552 <TH> Go to </TH>
1553 <TH> From 1.2.3 go to</TH>
1554 </TR>
1555 EOT
1556
1557     for $button (@T2H_SECTION_BUTTONS)
1558     {
1559         next if $button eq ' ' || ref($button) eq 'CODE';
1560         $about .= <<EOT;
1561 <TR>
1562 <TD ALIGN="CENTER">
1563 EOT
1564         $about .=
1565             ($T2H_ICONS && $T2H_ACTIVE_ICONS{$button} ?
1566              &$T2H_button_icon_img($button, $T2H_ACTIVE_ICONS{$button}) :
1567              " [" . $T2H_NAVIGATION_TEXT{$button} . "] ");
1568         $about .= <<EOT;
1569 </TD>
1570 <TD ALIGN="CENTER">
1571 $button
1572 </TD>
1573 <TD>
1574 $T2H_BUTTONS_GOTO{$button}
1575 </TD>
1576 <TD>
1577 $T2H_BUTTONS_EXAMPLE{$button}
1578 </TD>
1579 </TR>
1580 EOT
1581     }
1582
1583     $about .= <<EOT;
1584 </TABLE>
1585     <P>
1586       where the <STRONG> Example </STRONG> assumes that the current position
1587       is at <STRONG> Subsubsection One-Two-Three </STRONG> of a document of
1588       the following structure:</P>
1589     <UL>
1590       <LI> 1. Section One
1591         <UL>
1592           <LI>1.1 Subsection One-One
1593             <UL>
1594               <LI>...</LI>
1595             </UL>
1596           <LI>1.2 Subsection One-Two
1597             <UL>
1598               <LI>1.2.1 Subsubsection One-Two-One</LI>
1599               <LI>1.2.2 Subsubsection One-Two-Two</LI>
1600               <LI>1.2.3 Subsubsection One-Two-Three &nbsp; &nbsp;
1601                 <STRONG>&lt;== Current Position </STRONG></LI>
1602               <LI>1.2.4 Subsubsection One-Two-Four</LI>
1603             </UL>
1604           </LI>
1605           <LI>1.3 Subsection One-Three
1606             <UL>
1607               <LI>...</LI>
1608             </UL>
1609           </LI>
1610           <LI>1.4 Subsection One-Four</LI>
1611         </UL>
1612       </LI>
1613     </UL>
1614 $T2H_AFTER_ABOUT
1615 EOT
1616     return $about;
1617 }
1618
1619
1620 %T2H_BUTTONS_GOTO =
1621     (
1622      'Top',      'cover (top) of document',
1623      'Contents', 'table of contents',
1624      'Overview', 'short table of contents',
1625      'Index',    'concept index',
1626      'Back',     'previous section in reading order',
1627      'FastBack', 'beginning of this chapter or previous chapter',
1628      'Prev',     'previous section same level',
1629      'Up',       'up section',
1630      'Next',     'next section same level',
1631      'Forward',  'next section in reading order',
1632      'FastForward', 'next chapter',
1633      'About' ,    'this page',
1634      'First',    'first section in reading order',
1635      'Last',     'last section in reading order',
1636     );
1637
1638 %T2H_BUTTONS_EXAMPLE =
1639     (
1640      'Top',      ' &nbsp; ',
1641      'Contents', ' &nbsp; ',
1642      'Overview', ' &nbsp; ',
1643      'Index',    ' &nbsp; ',
1644      'Back',     '1.2.2',
1645      'FastBack', '1',
1646      'Prev',     '1.2.2',
1647      'Up',       '1.2',
1648      'Next',     '1.2.4',
1649      'Forward',  '1.2.4',
1650      'FastForward', '2',
1651      'About',     ' &nbsp; ',
1652      'First',    '1.',
1653      'Last',     '1.2.4',
1654     );
1655
1656
1657 ######################################################################
1658 # from here on, its l2h init stuff
1659 #
1660
1661 ## initialization for latex2html as for Singular manual generation
1662 ## obachman 3/99
1663
1664 #
1665 # Options controlling Titles, File-Names, Tracing and Sectioning
1666 #
1667 $TITLE = '';
1668
1669 $SHORTEXTN = 0;
1670
1671 $LONG_TITLES = 0;
1672
1673 $DESTDIR = '';                  # should be overwritten by cmd-line argument
1674
1675 $NO_SUBDIR = 0;                 # should be overwritten by cmd-line argument
1676
1677 $PREFIX = '';                   # should be overwritten by cmd-line argument
1678
1679 $AUTO_PREFIX = 0;               # this is needed, so that prefix settings are used
1680
1681 $AUTO_LINK = 0;
1682
1683 $SPLIT = 0;
1684
1685 $MAX_LINK_DEPTH = 0;
1686
1687 $TMP = '';                      # should be overwritten by cmd-line argument
1688
1689 $DEBUG = 0;
1690
1691 $VERBOSE = 1;
1692
1693 #
1694 # Options controlling Extensions and Special Features
1695 #
1696 $HTML_VERSION = "3.2";
1697
1698 $TEXDEFS = 1;                   # we absolutely need that
1699
1700 $EXTERNAL_FILE = '';
1701
1702 $SCALABLE_FONTS = 1;
1703
1704 $NO_SIMPLE_MATH = 1;
1705
1706 $LOCAL_ICONS = 1;
1707
1708 $SHORT_INDEX = 0;
1709
1710 $NO_FOOTNODE = 1;
1711
1712 $ADDRESS = '';
1713
1714 $INFO = '';
1715
1716 #
1717 # Switches controlling Image Generation
1718 #
1719 $ASCII_MODE = 0;
1720
1721 $NOLATEX = 0;
1722
1723 $EXTERNAL_IMAGES = 0;
1724
1725 $PS_IMAGES = 0;
1726
1727 $NO_IMAGES = 0;
1728
1729 $IMAGES_ONLY = 0;
1730
1731 $REUSE = 2;
1732
1733 $ANTI_ALIAS = 1;
1734
1735 $ANTI_ALIAS_TEXT = 1;
1736
1737 #
1738 #Switches controlling Navigation Panels
1739 #
1740 $NO_NAVIGATION = 1;
1741 $ADDRESS = '';
1742 $INFO = 0;                      # 0 = do not make a "About this document..." section
1743
1744 #
1745 #Switches for Linking to other documents
1746 #
1747 # currently -- we don't care
1748
1749 $MAX_SPLIT_DEPTH = 0;           # Stop making separate files at this depth
1750
1751 $MAX_LINK_DEPTH = 0;            # Stop showing child nodes at this depth
1752
1753 $NOLATEX = 0;                   # 1 = do not pass unknown environments to Latex
1754
1755 $EXTERNAL_IMAGES = 0;           # 1 = leave the images outside the document
1756
1757 $ASCII_MODE = 0;                # 1 = do not use any icons or internal images
1758
1759 # 1 =  use links to external postscript images rather than inlined bitmap
1760 # images.
1761 $PS_IMAGES = 0;
1762 $SHOW_SECTION_NUMBERS = 0;
1763
1764 ### Other global variables ###############################################
1765 $CHILDLINE = "";
1766
1767 # This is the line width measured in pixels and it is used to right justify
1768 # equations and equation arrays;
1769 $LINE_WIDTH = 500;
1770
1771 # Used in conjunction with AUTO_NAVIGATION
1772 $WORDS_IN_PAGE = 300;
1773
1774 # Affects ONLY the way accents are processed
1775 $default_language = 'english';
1776
1777 # The value of this variable determines how many words to use in each
1778 # title that is added to the navigation panel (see below)
1779 #
1780 $WORDS_IN_NAVIGATION_PANEL_TITLES = 0;
1781
1782 # This number will determine the size of the equations, special characters,
1783 # and anything which will be converted into an inlined image
1784 # *except* "image generating environments" such as "figure", "table"
1785 # or "minipage".
1786 # Effective values are those greater than 0.
1787 # Sensible values are between 0.1 - 4.
1788 $MATH_SCALE_FACTOR = 1.5;
1789
1790 # This number will determine the size of
1791 # image generating environments such as "figure", "table" or "minipage".
1792 # Effective values are those greater than 0.
1793 # Sensible values are between 0.1 - 4.
1794 $FIGURE_SCALE_FACTOR = 1.6;
1795
1796
1797 #  If both of the following two variables are set then the "Up" button
1798 #  of the navigation panel in the first node/page of a converted document
1799 #  will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set
1800 #  to some text which describes this external link.
1801 $EXTERNAL_UP_LINK = "";
1802 $EXTERNAL_UP_TITLE = "";
1803
1804 # If this is set then the resulting HTML will look marginally better if viewed
1805 # with Netscape.
1806 $NETSCAPE_HTML = 1;
1807
1808 # Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0"
1809 # Paper sizes has no effect other than in the time it takes to create inlined
1810 # images and in whether large images can be created at all ie
1811 #  - larger paper sizes *MAY* help with large image problems
1812 #  - smaller paper sizes are quicker to handle
1813 $PAPERSIZE = "a4";
1814
1815 # Replace "english" with another language in order to tell LaTeX2HTML that you
1816 # want some generated section titles (eg "Table of Contents" or "References")
1817 # to appear in a different language. Currently only "english" and "french"
1818 # is supported but it is very easy to add your own. See the example in the
1819 # file "latex2html.config"
1820 $TITLES_LANGUAGE = "english";
1821
1822 1;                              # This must be the last non-comment line
1823
1824 # End File texi2html.init
1825 ######################################################################
1826
1827
1828 require "$ENV{T2H_HOME}/texi2html.init"
1829     if ($0 =~ /\.pl$/ &&
1830         -e "$ENV{T2H_HOME}/texi2html.init" && -r "$ENV{T2H_HOME}/texi2html.init");
1831
1832 #+++############################################################################
1833 #                                                                              #
1834 # Initialization                                                               #
1835 # Pasted content of File $(srcdir)/MySimple.pm: Command-line processing        #
1836 #                                                                              #
1837 #---############################################################################
1838
1839 # leave this within comments, and keep the require statement
1840 # This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/texi2html.init
1841 # exists.
1842
1843
1844 package Getopt::MySimple;
1845
1846 # Name:
1847 #       Getopt::MySimple.
1848 #
1849 # Documentation:
1850 #       POD-style (incomplete) documentation is in file MySimple.pod
1851 #
1852 # Tabs:
1853 #       4 spaces || die.
1854 #
1855 # Author:
1856 #       Ron Savage      rpsavage@ozemail.com.au.
1857 #       1.00    19-Aug-97       Initial version.
1858 #       1.10    13-Oct-97       Add arrays of switches (eg '=s@').
1859 #       1.20     3-Dec-97       Add 'Help' on a per-switch basis.
1860 #       1.30    11-Dec-97       Change 'Help' to 'verbose'. Make all hash keys lowercase.
1861 #       1.40    10-Nov-98       Change width of help report. Restructure tests.
1862 #               1-Jul-00        Modifications for Texi2html
1863
1864 # --------------------------------------------------------------------------
1865 # Locally modified by obachman (Display type instead of env, order by cmp)
1866 # $Id: texi2html,v 1.3 2005-06-19 03:20:26 blp Exp $
1867
1868 # use strict;
1869 # no strict 'refs';
1870
1871 use vars qw(@EXPORT @EXPORT_OK @ISA);
1872 use vars qw($fieldWidth $opt $VERSION);
1873
1874 use Exporter();
1875 use Getopt::Long;
1876
1877 @ISA            = qw(Exporter);
1878 @EXPORT         = qw();
1879 @EXPORT_OK      = qw($opt);     # An alias for $self -> {'opt'}.
1880
1881 # --------------------------------------------------------------------------
1882
1883 $fieldWidth     = 20;
1884 $VERSION        = '1.41';
1885
1886 # --------------------------------------------------------------------------
1887
1888 sub byOrder
1889 {
1890         my($self) = @_;
1891         
1892         return uc($a) cmp (uc($b));
1893 }
1894
1895 # --------------------------------------------------------------------------
1896
1897 sub dumpOptions
1898 {
1899         my($self) = @_;
1900
1901         print 'Option', ' ' x ($fieldWidth - length('Option') ), "Value\n";
1902
1903         for (sort byOrder keys(%{$self -> {'opt'} }) )
1904         {
1905           print "-$_", ' ' x ($fieldWidth - (1 + length) ), "${$self->{'opt'} }{$_}\n";
1906         }
1907
1908         print "\n";
1909
1910 }       # End of dumpOptions.
1911
1912 # --------------------------------------------------------------------------
1913 # Return:
1914 #       0 -> Error.
1915 #       1 -> Ok.
1916
1917 sub getOptions
1918 {
1919         push(@_, 0) if ($#_ == 2);      # Default for $ignoreCase is 0.
1920         push(@_, 1) if ($#_ == 3);      # Default for $helpThenExit is 1.
1921
1922         my($self, $default, $helpText, $versionText, 
1923            $helpThenExit, $versionThenExit, $ignoreCase) = @_;
1924         
1925         $helpThenExit = 1 unless (defined($helpThenExit));
1926         $versionThenExit = 1 unless (defined($versionThenExit));
1927         $ignoreCase = 0 unless (defined($ignoreCase));
1928
1929         $self -> {'default'}            = $default;
1930         $self -> {'helpText'}           = $helpText;
1931         $self -> {'versionText'}        = $versionText;
1932         $Getopt::Long::ignorecase       = $ignoreCase;
1933
1934         unless (defined($self -> {'default'}{'help'}))
1935         {
1936           $self -> {'default'}{'help'} = 
1937           { 
1938            type => ':i', 
1939            default => '',
1940            linkage => sub {$self->helpOptions($_[1]); exit (0) if $helpThenExit;},
1941            verbose => "print help and exit"
1942           };
1943         }
1944
1945         unless (defined($self -> {'default'}{'version'}))
1946         {
1947           $self -> {'default'}{'version'} = 
1948           { 
1949            type => '', 
1950            default => '',
1951            linkage => sub {print $self->{'versionText'};  exit (0) if $versionThenExit;},
1952            verbose => "print version and exit"
1953           };
1954         }
1955
1956         for (keys(%{$self -> {'default'} }) )
1957         {
1958           my $type = ${$self -> {'default'} }{$_}{'type'};
1959           push(@{$self -> {'type'} }, "$_$type");
1960           $self->{'opt'}->{$_} =  ${$self -> {'default'} }{$_}{'linkage'}
1961             if ${$self -> {'default'} }{$_}{'linkage'};
1962         }
1963
1964         my($result) = &GetOptions($self -> {'opt'}, @{$self -> {'type'} });
1965
1966         return $result unless $result;
1967
1968         for (keys(%{$self -> {'default'} }) )
1969         {
1970            if (! defined(${$self -> {'opt'} }{$_})) #{
1971             {
1972              ${$self -> {'opt'} }{$_} = ${$self -> {'default'} }{$_}{'default'};
1973             }
1974         }
1975
1976         $result;
1977 }       # End of getOptions.
1978
1979 # --------------------------------------------------------------------------
1980
1981 sub helpOptions
1982 {
1983         my($self) = shift;
1984         my($noHelp) = shift;
1985         $noHelp = 0 unless $noHelp;
1986         my($optwidth, $typewidth, $defaultwidth, $maxlinewidth, $valind, $valwidth) 
1987           = (10, 5, 9, 78, 4, 11);
1988
1989         print "$self->{'helpText'}" if ($self -> {'helpText'});
1990
1991         print ' Option', ' ' x ($optwidth - length('Option') -1 ),
1992                 'Type', ' ' x ($typewidth - length('Type') + 1),
1993                 'Default', ' ' x ($defaultwidth - length('Default') ),
1994                 "Description\n";
1995
1996         for (sort byOrder keys(%{$self -> {'default'} }) )
1997         {
1998           my($line, $help, $option, $val);
1999           $option = $_;
2000           next if ${$self->{'default'} }{$_}{'noHelp'} && ${$self->{'default'} }{$_}{'noHelp'} > $noHelp;
2001           #$line = " -$_" . ' ' x ($optwidth - (2 + length) ) .
2002           #             "${$self->{'default'} }{$_}{'type'} ".
2003           #             ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) ));
2004                 $line = " -$_" . "${$self->{'default'} }{$_}{'type'}".
2005                         ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) ));
2006
2007                  $val = ${$self->{'default'} }{$_}{'linkage'};
2008                 if ($val)
2009                 {
2010                   if (ref($val) eq 'SCALAR')
2011                   {
2012                     $val = $$val; 
2013                   }
2014                   else
2015                   {
2016                     $val = '';
2017                   }
2018                 }
2019                 else
2020                 {
2021                   $val = ${$self->{'default'} }{$_}{'default'};
2022                 }
2023                 $line .= "$val  ";
2024                 $line .= ' ' x ($optwidth + $typewidth + $defaultwidth + 1 - length($line));
2025                 
2026                 if (defined(${$self -> {'default'} }{$_}{'verbose'}) &&
2027                   ${$self -> {'default'} }{$_}{'verbose'} ne '')
2028               {
2029                 $help = "${$self->{'default'} }{$_}{'verbose'}";
2030               }
2031               else
2032               {
2033                 $help = ' ';
2034               }
2035               if ((length("$line") + length($help)) < $maxlinewidth)
2036               {
2037                 print $line , $help, "\n";
2038               }
2039               else
2040               {
2041                 print $line, "\n", ' ' x $valind, $help, "\n";
2042               }
2043               for $val (sort byOrder keys(%{${$self->{'default'}}{$option}{'values'}}))
2044               {
2045                 print ' ' x ($valind + 2);
2046                 print $val, '  ', ' ' x ($valwidth - length($val) - 2);
2047                 print ${$self->{'default'}}{$option}{'values'}{$val}, "\n";
2048               }
2049         }
2050
2051         print <<EOT;
2052 Note: 'Options' may be abbreviated. 'Type' specifications mean:
2053  <none>| !    no argument: variable is set to 1 on -foo (or, to 0 on -nofoo)
2054     =s | :s   mandatory (or, optional)  string argument
2055     =i | :i   mandatory (or, optional)  integer argument
2056 EOT
2057 }       # End of helpOptions.
2058
2059 #-------------------------------------------------------------------
2060
2061 sub new
2062 {
2063         my($class)                              = @_;
2064         my($self)                               = {};
2065         $self -> {'default'}    = {};
2066         $self -> {'helpText'}   = '';
2067         $self -> {'opt'}                = {};
2068         $opt                                    = $self -> {'opt'};      # An alias for $self -> {'opt'}.
2069         $self -> {'type'}               = ();
2070
2071         return bless $self, $class;
2072
2073 }       # End of new.
2074
2075 # --------------------------------------------------------------------------
2076
2077 1;
2078
2079 # End MySimple.pm
2080
2081 require "$ENV{T2H_HOME}/MySimple.pm"
2082     if ($0 =~ /\.pl$/ &&
2083         -e "$ENV{T2H_HOME}/MySimple.pm" && -r "$ENV{T2H_HOME}/MySimple.pm");
2084
2085 package main;
2086
2087 #+++############################################################################
2088 #                                                                              #
2089 # Constants                                                                    #
2090 #                                                                              #
2091 #---############################################################################
2092
2093 $DEBUG_TOC   =  1;
2094 $DEBUG_INDEX =  2;
2095 $DEBUG_BIB   =  4;
2096 $DEBUG_GLOSS =  8;
2097 $DEBUG_DEF   = 16;
2098 $DEBUG_HTML  = 32;
2099 $DEBUG_USER  = 64;
2100 $DEBUG_L2H   = 128;
2101
2102
2103 $BIBRE = '\[[\w\/-]+\]';        # RE for a bibliography reference
2104 $FILERE = '[\/\w.+-]+';         # RE for a file name
2105 $VARRE = '[^\s\{\}]+';          # RE for a variable name
2106 $NODERE = '[^,:]+';             # RE for a node name
2107 $NODESRE = '[^:]+';             # RE for a list of node names
2108
2109 $ERROR = "***";                 # prefix for errors
2110 $WARN  = "**";                  # prefix for warnings
2111
2112                                 # program home page
2113 $PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections
2114
2115 $CHAPTEREND = "<!-- End chapter -->\n"; # to know where a chpater ends
2116 $SECTIONEND = "<!-- End section -->\n"; # to know where section ends
2117 $TOPEND     = "<!-- End top     -->\n"; # to know where top ends
2118
2119
2120
2121 #
2122 # pre-defined indices
2123 #
2124 $index_properties =
2125 {
2126  'c' => { name => 'cp'},
2127  'f' => { name => 'fn', code => 1},
2128  'v' => { name => 'vr', code => 1},
2129  'k' => { name => 'ky', code => 1},
2130  'p' => { name => 'pg', code => 1},
2131  't' => { name => 'tp', code => 1}
2132 };
2133
2134
2135 %predefined_index = (
2136                      'cp', 'c',
2137                      'fn', 'f',
2138                      'vr', 'v',
2139                      'ky', 'k',
2140                      'pg', 'p',
2141                      'tp', 't',
2142                     );
2143
2144 #
2145 # valid indices
2146 #
2147 %valid_index = (
2148                 'c', 1,
2149                 'f', 1,
2150                 'v', 1,
2151                 'k', 1,
2152                 'p', 1,
2153                 't', 1,
2154                );
2155
2156 #
2157 # texinfo section names to level
2158 #
2159 %sec2level = (
2160               'top', 0,
2161               'chapter', 1,
2162               'unnumbered', 1,
2163               'majorheading', 1,
2164               'chapheading', 1,
2165               'appendix', 1,
2166               'section', 2,
2167               'unnumberedsec', 2,
2168               'heading', 2,
2169               'appendixsec', 2,
2170               'appendixsection', 2,
2171               'subsection', 3,
2172               'unnumberedsubsec', 3,
2173               'subheading', 3,
2174               'appendixsubsec', 3,
2175               'subsubsection', 4,
2176               'unnumberedsubsubsec', 4,
2177               'subsubheading', 4,
2178               'appendixsubsubsec', 4,
2179              );
2180
2181 #
2182 # accent map, TeX command to ISO name
2183 #
2184 %accent_map = (
2185                '"',  'uml',
2186                '~',  'tilde',
2187                '^',  'circ',
2188                '`',  'grave',
2189                '\'', 'acute',
2190               );
2191
2192 #
2193 # texinfo "simple things" (@foo) to HTML ones
2194 #
2195 %simple_map = (
2196                # cf. makeinfo.c
2197                "*", "<BR>",     # HTML+
2198                " ", "&nbsp;",
2199                "\t", "&nbsp;",
2200                "-", "&#173;",    # soft hyphen
2201                "\n", "&nbsp;",
2202                "|", "",
2203                'tab', '<\/TD><TD>',
2204                # spacing commands
2205                ":", "",
2206                "!", "!",
2207                "?", "?",
2208                ".", ".",
2209                "-", "",
2210                "/", "",
2211               );
2212
2213 #
2214 # texinfo "things" (@foo{}) to HTML ones
2215 #
2216 %things_map = (
2217                'TeX', 'TeX',
2218                'br', '<P>',     # paragraph break
2219                'bullet', '*',
2220                #'copyright', '(C)',
2221                'copyright', '&copy;',
2222                'dots', '<small>...<\/small>',
2223                'enddots', '<small>....<\/small>',
2224                'equiv', '==',
2225                'error', 'error-->',
2226                'expansion', '==>',
2227                'minus', '-',
2228                'point', '-!-',
2229                'print', '-|',
2230                'result', '=>',
2231                # APA: &pretty_date requires $MONTH_NAMES and $T2H_LANG
2232                # to be initialized.  The latter gets initialized by
2233                # &SetDocumentLanguage in &main.
2234                # We set following hash entry in &main afterwards.
2235                # 'today', &pretty_date,
2236                'aa', '&aring;',
2237                'AA', '&Aring;',
2238                'ae', '&aelig;',
2239                'oe', '&#156;',
2240                'AE', '&AElig;',
2241                'OE', '&#140;',
2242                'o',  '&oslash;',
2243                'O',  '&Oslash;',
2244                'ss', '&szlig;',
2245                'l', '\/l',
2246                'L', '\/L',
2247                'exclamdown', '&iexcl;',
2248                'questiondown', '&iquest;',
2249                'pounds', '&pound;'
2250               );
2251
2252 #
2253 # texinfo styles (@foo{bar}) to HTML ones
2254 #
2255 %style_map = (
2256               'acronym', 'ACRONYM',
2257               'asis', '',
2258               'b', 'B',
2259               'cite', 'CITE',
2260               'code', 'CODE',
2261               'command', 'CODE',
2262               'ctrl', '&do_ctrl', # special case
2263               'dfn', 'EM',      # DFN tag is illegal in the standard
2264               'dmn', '',        # useless
2265               'email', '&do_email', # insert a clickable email address
2266               'emph', 'EM',
2267               'env', 'CODE',
2268               'file', '"TT',    # will put quotes, cf. &apply_style
2269               'i', 'I',
2270               'kbd', 'KBD',
2271               'key', 'KBD',
2272               'math', '&do_math',
2273               'option', '"SAMP', # will put quotes, cf. &apply_style
2274               'r', '',          # unsupported
2275               'samp', '"SAMP',  # will put quotes, cf. &apply_style
2276               'sc', '&do_sc',   # special case
2277               'strong', 'STRONG',
2278               't', 'TT',
2279               'titlefont', '',  # useless
2280               'uref', '&do_uref', # insert a clickable URL
2281               'url', '&do_url', # insert a clickable URL
2282               'var', 'VAR',
2283               'w', '',          # unsupported
2284               'H', '&do_accent',
2285               'dotaccent', '&do_accent',
2286               'ringaccent','&do_accent',
2287               'tieaccent', '&do_accent',
2288               'u','&do_accent',
2289               'ubaraccent','&do_accent',
2290               'udotaccent','&do_accent',
2291               'v', '&do_accent',
2292               ',', '&do_accent',
2293               'dotless', '&do_accent'
2294              );
2295
2296 #
2297 # texinfo format (@foo/@end foo) to HTML ones
2298 #
2299 %format_map = (
2300                'quotation', 'BLOCKQUOTE',
2301                # lists
2302                'itemize', 'UL',
2303                'enumerate', 'OL',
2304                # poorly supported
2305                'flushleft', 'PRE',
2306                'flushright', 'PRE',
2307               );
2308
2309 #
2310 # an eval of these $complex_format_map->{what}->[0] yields beginning
2311 # an eval of these $complex_format_map->{what}->[1] yieleds end
2312 $complex_format_map =
2313 {
2314  verbatim =>
2315  [
2316   q{"<TABLE><tr>$T2H_EXAMPLE_INDENT_CELL<td class=example><pre>"},
2317   q{'</pre></td></tr></table>'}
2318  ],
2319  example =>
2320  [
2321   q{"<TABLE><tr>$T2H_EXAMPLE_INDENT_CELL<td class=example><pre>"},
2322   q{'</pre></td></tr></table>'}
2323  ],
2324  smallexample =>
2325  [
2326   q{"<TABLE><tr>$T2H_SMALL_EXAMPLE_INDENT_CELL<td class=smallexample><pre><FONT SIZE=$T2H_SMALL_FONT_SIZE>"},
2327   q{'</FONT></pre></td></tr></table>'}
2328  ],
2329  display =>
2330  [
2331   q{"<TABLE><tr>$T2H_EXAMPLE_INDENT_CELL<td class=display><pre " . 'style="font-family: serif">'},
2332   q{'</pre></td></tr></table>'}
2333  ],
2334  smalldisplay =>
2335  [
2336   q{"<TABLE><tr>$T2H_SMALL_EXAMPLE_INDENT_CELL<td class=smalldisplay><pre " . 'style="font-family: serif"><FONT SIZE=$T2H_SMALL_FONT_SIZE>'},
2337   q{'</FONT></pre></td></tr></table>'}
2338  ]
2339 };
2340
2341 $complex_format_map->{lisp} = $complex_format_map->{example};
2342 $complex_format_map->{smalllisp} = $complex_format_map->{smallexample};
2343 $complex_format_map->{format} = $complex_format_map->{display};
2344 $complex_format_map->{smallformat} = $complex_format_map->{smalldisplay};
2345
2346 #
2347 # texinfo definition shortcuts to real ones
2348 #
2349 %def_map = (
2350             # basic commands
2351             'deffn', 0,
2352             'defvr', 0,
2353             'deftypefn', 0,
2354             'deftypeop', 0,
2355             'deftypevr', 0,
2356             'deftypecv', 0,
2357             'defcv', 0,
2358             'defop', 0,
2359             'deftp', 0,
2360             # basic x commands
2361             'deffnx', 0,
2362             'defvrx', 0,
2363             'deftypefnx', 0,
2364             'deftypeopx', 0,
2365             'deftypevrx', 0,
2366             'deftypecvx', 0,
2367             'defcvx', 0,
2368             'defopx', 0,
2369             'deftpx', 0,
2370             # shortcuts
2371             'defun', 'deffn Function',
2372             'defmac', 'deffn Macro',
2373             'defspec', 'deffn {Special Form}',
2374             'defvar', 'defvr Variable',
2375             'defopt', 'defvr {User Option}',
2376             'deftypefun', 'deftypefn Function',
2377             'deftypevar', 'deftypevr Variable',
2378             'defivar', 'defcv {Instance Variable}',
2379             'deftypeivar', 'defcv {Instance Variable}', # NEW: FIXME
2380             'defmethod', 'defop Method',
2381             'deftypemethod', 'defop Method', # NEW:FIXME
2382             # x shortcuts
2383             'defunx', 'deffnx Function',
2384             'defmacx', 'deffnx Macro',
2385             'defspecx', 'deffnx {Special Form}',
2386             'defvarx', 'defvrx Variable',
2387             'defoptx', 'defvrx {User Option}',
2388             'deftypefunx', 'deftypefnx Function',
2389             'deftypevarx', 'deftypevrx Variable',
2390             'defivarx', 'defcvx {Instance Variable}',
2391             'defmethodx', 'defopx Method',
2392            );
2393
2394 #
2395 # things to skip
2396 #
2397 %to_skip = (
2398             # comments
2399             'c', 1,
2400             'comment', 1,
2401             'ifnotinfo', 1,
2402             'ifnottex', 1,
2403             'ifhtml', 1,
2404             'end ifhtml', 1,
2405             'end ifnotinfo', 1,
2406             'end ifnottex', 1,
2407             # useless
2408             'detailmenu', 1,
2409             'direntry', 1,
2410             'contents', 1,
2411             'shortcontents', 1,
2412             'summarycontents', 1,
2413             'footnotestyle', 1,
2414             'end ifclear', 1,
2415             'end ifset', 1,
2416             'titlepage', 1,
2417             'end titlepage', 1,
2418             # unsupported commands (formatting)
2419             'afourpaper', 1,
2420             'cropmarks', 1,
2421             'finalout', 1,
2422             'headings', 1,
2423             'sp', 1,
2424             'need', 1,
2425             'page', 1,
2426             'setchapternewpage', 1,
2427             'everyheading', 1,
2428             'everyfooting', 1,
2429             'evenheading', 1,
2430             'evenfooting', 1,
2431             'oddheading', 1,
2432             'oddfooting', 1,
2433             'smallbook', 1,
2434             'vskip', 1,
2435             'filbreak', 1,
2436             'paragraphindent', 1,
2437             # unsupported formats
2438             'cartouche', 1,
2439             'end cartouche', 1,
2440             'group', 1,
2441             'end group', 1,
2442            );
2443
2444 #+++############################################################################
2445 #                                                                              #
2446 # Argument parsing, initialisation                                             #
2447 #                                                                              #
2448 #---############################################################################
2449
2450 #
2451 # flush stdout and stderr after every write
2452 #
2453 select(STDERR);
2454 $| = 1;
2455 select(STDOUT);
2456 $| = 1;
2457
2458
2459 %value = ();                    # hold texinfo variables, see also -D
2460 $use_bibliography = 1;
2461 $use_acc = 1;
2462
2463 #
2464 # called on -init-file
2465 sub LoadInitFile
2466 {
2467     my $init_file = shift;
2468     # second argument is value of options
2469     $init_file = shift;
2470     if (-f $init_file)
2471     {
2472         print "# reading initialization file from $init_file\n"
2473             if ($T2H_VERBOSE);
2474         require($init_file);
2475     }
2476     else
2477     {
2478         print "$ERROR Error: can't read init file $int_file\n";
2479         $init_file = '';
2480     }
2481 }
2482
2483 #
2484 # called on -lang
2485 sub SetDocumentLanguage
2486 {
2487     my $lang = shift;
2488     if (! exists($T2H_WORDS->{$lang}))
2489     {
2490         warn "$ERROR: Language specs for '$lang' do not exists. Reverting to '" .
2491             ($T2H_LANG ? $T2H_LANG : "en") . "'\n";
2492     }
2493     else
2494     {
2495         print "# using '$lang' as document language\n" if ($T2H_VERBOSE);
2496         $T2H_LANG = $lang;
2497     }
2498 }
2499
2500 ##
2501 ## obsolete cmd line options
2502 ##
2503 $T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} =
2504 {
2505  type => '!',
2506  linkage => sub {$T2H_SECTION_NAVIGATION = 0;},
2507  verbose => 'obsolete, use -nosec_nav',
2508  noHelp => 2,
2509 };
2510 $T2H_OBSOLETE_OPTIONS -> {use_acc} =
2511 {
2512  type => '!',
2513  linkage => \$use_acc,
2514  verbose => 'obsolete',
2515  noHelp => 2
2516 };
2517 $T2H_OBSOLETE_OPTIONS -> {expandinfo} =
2518 {
2519  type => '!',
2520  linkage => sub {$T2H_EXPAND = 'info';},
2521  verbose => 'obsolete, use "-expand info" instead',
2522  noHelp => 2,
2523 };
2524 $T2H_OBSOLETE_OPTIONS -> {expandtex} =
2525 {
2526  type => '!',
2527  linkage => sub {$T2H_EXPAND = 'tex';},
2528  verbose => 'obsolete, use "-expand tex" instead',
2529  noHelp => 2,
2530 };
2531 $T2H_OBSOLETE_OPTIONS -> {monolithic} =
2532 {
2533  type => '!',
2534  linkage => sub {$T2H_SPLIT = '';},
2535  verbose => 'obsolete, use "-split no" instead',
2536  noHelp => 2
2537 };
2538 $T2H_OBSOLETE_OPTIONS -> {split_node} =
2539 {
2540  type => '!',
2541  linkage => sub{$T2H_SPLIT = 'section';},
2542  verbose => 'obsolete, use "-split section" instead',
2543  noHelp => 2,
2544 };
2545 $T2H_OBSOLETE_OPTIONS -> {split_chapter} =
2546 {
2547  type => '!',
2548  linkage => sub{$T2H_SPLIT = 'chapter';},
2549  verbose => 'obsolete, use "-split chapter" instead',
2550  noHelp => 2,
2551 };
2552 $T2H_OBSOLETE_OPTIONS -> {no_verbose} =
2553 {
2554  type => '!',
2555  linkage => sub {$T2H_VERBOSE = 0;},
2556  verbose => 'obsolete, use -noverbose instead',
2557  noHelp => 2,
2558 };
2559 $T2H_OBSOLETE_OPTIONS -> {output_file} =
2560 {
2561  type => '=s',
2562  linkage => sub {$T2H_OUT = $_[1]; $T2H_SPLIT = '';},
2563  verbose => 'obsolete, use -out_file instead',
2564  noHelp => 2
2565 };
2566
2567 $T2H_OBSOLETE_OPTIONS -> {section_navigation} =
2568 {
2569  type => '!',
2570  linkage => \$T2H_SECTION_NAVIGATION,
2571  verbose => 'obsolete, use -sec_nav instead',
2572  noHelp => 2,
2573 };
2574
2575 $T2H_OBSOLETE_OPTIONS -> {verbose} =
2576 {
2577  type => '!',
2578  linkage => \$T2H_VERBOSE,
2579  verbose => 'obsolete, use -Verbose instead',
2580  noHelp => 2
2581 };
2582
2583 # read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc
2584 my $home = $ENV{HOME};
2585 defined($home) or $home = '';
2586 foreach $i ('/etc/texi2htmlrc', "$home/.texi2htmlrc")
2587 {
2588     if (-f $i)
2589     {
2590         print "# reading initialization file from $i\n"
2591             if ($T2H_VERBOSE);
2592         require($i);
2593     }
2594 }
2595
2596
2597 #+++############################################################################
2598 #                                                                              #
2599 # parse command-line options
2600 #                                                                              #
2601 #---############################################################################
2602 $T2H_USAGE_TEXT = <<EOT;
2603 Usage: texi2html  [OPTIONS] TEXINFO-FILE
2604 Translates Texinfo source documentation to HTML.
2605 EOT
2606 $T2H_FAILURE_TEXT = <<EOT;
2607 Try 'texi2html -help' for usage instructions.
2608 EOT
2609 $options = new Getopt::MySimple;
2610
2611 # some older version of GetOpt::Long don't have
2612 # Getopt::Long::Configure("pass_through")
2613 eval {Getopt::Long::Configure("pass_through");};
2614 $Configure_failed = $@ && <<EOT;
2615 **WARNING: Parsing of obsolete command-line options could have failed.
2616            Consider to use only documented command-line options (run
2617            'texi2html -help 2' for a complete list) or upgrade to perl
2618            version 5.005 or higher.
2619 EOT
2620
2621 if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
2622 {
2623     print $Configure_failed if $Configure_failed;
2624     die $T2H_FAILURE_TEXT;
2625 }
2626
2627 if (@ARGV > 1)
2628 {
2629     eval {Getopt::Long::Configure("no_pass_through");};
2630     if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
2631     {
2632         print $Configure_failed if $Configure_failed;
2633         die $T2H_FAILURE_TEXT;
2634     }
2635 }
2636
2637 if ($T2H_CHECK)
2638 {
2639     die "Need file to check\n$T2H_FAILURE_TEXT" unless @ARGV > 0;
2640     &check;
2641     exit;
2642 }
2643
2644 #+++############################################################################
2645 #                                                                              #
2646 # evaluation of cmd line options
2647 #                                                                              #
2648 #---############################################################################
2649
2650 if ($T2H_EXPAND eq 'info')
2651 {
2652     $to_skip{'ifinfo'} = 1;
2653     $to_skip{'end ifinfo'} = 1;
2654 }
2655 elsif ($T2H_EXPAND eq 'tex')
2656 {
2657     $to_skip{'iftex'} = 1;
2658     $to_skip{'end iftex'} = 1;
2659
2660 }
2661
2662 $T2H_INVISIBLE_MARK = '<IMG SRC="invisible.xbm">' if $T2H_INVISIBLE_MARK eq 'xbm';
2663
2664 #
2665 # file name buisness
2666 #
2667 die "Need exactly one file to translate\n$T2H_FAILURE_TEXT" unless @ARGV == 1;
2668 $docu = shift(@ARGV);
2669 if ($docu =~ /.*\//)
2670 {
2671     chop($docu_dir = $&);
2672     $docu_name = $';
2673 }
2674 else
2675 {
2676     $docu_dir = '.';
2677     $docu_name = $docu;
2678 }
2679 unshift(@T2H_INCLUDE_DIRS, $docu_dir);
2680 $docu_name =~ s/\.te?x(i|info)?$//; # basename of the document
2681 $docu_name = $T2H_PREFIX if ($T2H_PREFIX);
2682
2683 # subdir
2684 if ($T2H_SUBDIR && ! $T2H_OUT)
2685 {
2686     $T2H_SUBDIR =~ s|/*$||;
2687     unless (-d "$T2H_SUBDIR" && -w "$T2H_SUBDIR")
2688     {
2689         if ( mkdir($T2H_SUBDIR, oct(755)))
2690         {
2691             print "# created directory $T2H_SUBDIR\n" if ($T2H_VERBOSE);
2692         }
2693         else
2694         {
2695             warn "$ERROR can't create directory $T2H_SUBDIR. Put results into current directory\n";
2696             $T2H_SUBDIR = '';
2697         }
2698     }
2699 }
2700
2701 if ($T2H_SUBDIR && ! $T2H_OUT)
2702 {
2703     $docu_rdir = "$T2H_SUBDIR/";
2704     print "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
2705 }
2706 else
2707 {
2708     if ($T2H_OUT && $T2H_OUT =~ m|(.*)/|)
2709     {
2710         $docu_rdir = "$1/";
2711         print "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
2712     }
2713     else
2714     {
2715         print "# putting result files into current directory \n" if ($T2H_VERBOSE);
2716         $docu_rdir = '';
2717     }
2718 }
2719
2720 # extension
2721 if ($T2H_SHORTEXTN)
2722 {
2723     $docu_ext = "htm";
2724 }
2725 else
2726 {
2727     $docu_ext = "html";
2728 }
2729 if ($T2H_TOP_FILE =~ /\..*$/)
2730 {
2731     $T2H_TOP_FILE = $`.".$docu_ext";
2732 }
2733
2734 # result files
2735 if (! $T2H_OUT && ($T2H_SPLIT =~ /section/i || $T2H_SPLIT =~ /node/i))
2736 {
2737     $T2H_SPLIT = 'section';
2738 }
2739 elsif (! $T2H_OUT && $T2H_SPLIT =~ /chapter/i)
2740 {
2741     $T2H_SPLIT = 'chapter'
2742 }
2743 else
2744 {
2745     undef $T2H_SPLIT;
2746 }
2747
2748 $docu_doc = "$docu_name.$docu_ext"; # document's contents
2749 $docu_doc_file = "$docu_rdir$docu_doc";
2750 if ($T2H_SPLIT)
2751 {
2752     $docu_toc  = $T2H_TOC_FILE || "${docu_name}_toc.$docu_ext"; # document's table of contents
2753     $docu_stoc = "${docu_name}_ovr.$docu_ext"; # document's short toc
2754     $docu_foot = "${docu_name}_fot.$docu_ext"; # document's footnotes
2755     $docu_about = "${docu_name}_abt.$docu_ext"; # about this document
2756     $docu_top  = $T2H_TOP_FILE || $docu_doc;
2757 }
2758 else
2759 {
2760     if ($T2H_OUT)
2761     {
2762         $docu_doc = $T2H_OUT;
2763         $docu_doc =~ s|.*/||;
2764     }
2765     $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_top = $docu_doc;
2766 }
2767
2768 $docu_toc_file  = "$docu_rdir$docu_toc";
2769 $docu_stoc_file = "$docu_rdir$docu_stoc";
2770 $docu_foot_file = "$docu_rdir$docu_foot";
2771 $docu_about_file = "$docu_rdir$docu_about";
2772 $docu_top_file  = "$docu_rdir$docu_top";
2773
2774 $docu_frame_file =     "$docu_rdir${docu_name}_frame.$docu_ext";
2775 $docu_toc_frame_file = "$docu_rdir${docu_name}_toc_frame.$docu_ext";
2776
2777 #
2778 # variables
2779 #
2780 $value{'html'} = 1;             # predefine html (the output format)
2781 $value{'texi2html'} = $THISVERSION; # predefine texi2html (the translator)
2782 # _foo: internal to track @foo
2783 foreach ('_author', '_title', '_subtitle',
2784          '_settitle', '_setfilename', '_shorttitle')
2785 {
2786     $value{$_} = '';            # prevent -w warnings
2787 }
2788 %node2sec = ();                 # node to section name
2789 %sec2node = ();                 # section to node name
2790 %sec2seccount = ();             # section to section count
2791 %seccount2sec = ();             # section count to section
2792 %sec2number = ();               # section to number
2793                                 # $number =~ ^[\dA-Z]+\.(\d+(\.\d+)*)?$
2794 %number2sec = ();               # number to section
2795 %idx2node = ();                 # index keys to node
2796 %node2href = ();                # node to HREF
2797 %node2next = ();                # node to next
2798 %node2prev = ();                # node to prev
2799 %node2up   = ();                # node to up
2800 %bib2href = ();                 # bibliography reference to HREF
2801 %gloss2href = ();               # glossary term to HREF
2802 @sections = ();                 # list of sections
2803 %tag2pro = ();                  # protected sections
2804
2805 #
2806 # initial indexes
2807 #
2808 $bib_num = 0;
2809 $foot_num = 0;
2810 $gloss_num = 0;
2811 $idx_num = 0;
2812 $sec_num = 0;
2813 $doc_num = 0;
2814 $html_num = 0;
2815
2816 #
2817 # can I use ISO8859 characters? (HTML+)
2818 #
2819 if ($T2H_USE_ISO)
2820 {
2821     $things_map{'bullet'} = "&bull;";
2822     $things_map{'copyright'} = "&copy;";
2823     $things_map{'dots'} = "&hellip;";
2824     $things_map{'equiv'} = "&equiv;";
2825     $things_map{'expansion'} = "&rarr;";
2826     $things_map{'point'} = "&lowast;";
2827     $things_map{'result'} = "&rArr;";
2828 }
2829
2830 #
2831 # read texi2html extensions (if any)
2832 #
2833 $extensions = 'texi2html.ext';  # extensions in working directory
2834 if (-f $extensions)
2835 {
2836     print "# reading extensions from $extensions\n" if $T2H_VERBOSE;
2837     require($extensions);
2838 }
2839 ($progdir = $0) =~ s/[^\/]+$//;
2840 if ($progdir && ($progdir ne './'))
2841 {
2842     $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
2843     if (-f $extensions)
2844     {
2845         print "# reading extensions from $extensions\n" if $T2H_VERBOSE;
2846         require($extensions);
2847     }
2848 }
2849
2850
2851 print "# reading from $docu\n" if $T2H_VERBOSE;
2852
2853 #########################################################################
2854 #
2855 # latex2html stuff
2856 #
2857 # latex2html conversions consist of three stages:
2858 # 1) ToLatex: Put "latex" code into a latex file
2859 # 2) ToHtml: Use latex2html to generate corresponding html code and images
2860 # 3) FromHtml: Extract generated code and images from latex2html run
2861 #
2862
2863 ##########################
2864 # default settings
2865 #
2866
2867 # defaults for files and names
2868
2869 sub l2h_Init
2870 {
2871     local($root) = @_;
2872     return 0 unless ($root);
2873     $l2h_name =  "${root}_l2h";
2874     $l2h_latex_file = "$docu_rdir${l2h_name}.tex";
2875     $l2h_cache_file = "${docu_rdir}l2h_cache.pm";
2876     $T2H_L2H_L2H = "latex2html" unless ($T2H_L2H_L2H);
2877     # destination dir -- generated images are put there, should be the same
2878     # as dir of enclosing html document --
2879     $l2h_html_file = "$docu_rdir${l2h_name}.html";
2880     $l2h_prefix = "${l2h_name}_";
2881     return 1;
2882 }
2883
2884
2885 ##########################
2886 #
2887 # First stage: Generation of Latex file
2888 # Initialize with: l2h_InitToLatex
2889 # Add content with: l2h_ToLatex($text) --> HTML placeholder comment
2890 # Finish with: l2h_FinishToLatex
2891 #
2892
2893 $l2h_latex_preample = <<EOT;
2894 % This document was automatically generated by the l2h extenstion of texi2html
2895 % DO NOT EDIT !!!
2896 \\documentclass{article}
2897 \\usepackage{html}
2898 \\begin{document}
2899 EOT
2900
2901 $l2h_latex_closing = <<EOT;
2902 \\end{document}
2903 EOT
2904
2905 # return used latex 1, if l2h could be initalized properly, 0 otherwise
2906 sub l2h_InitToLatex
2907 {
2908     %l2h_to_latex = ();
2909     unless ($T2H_L2H_SKIP)
2910     {
2911         unless (open(L2H_LATEX, ">$l2h_latex_file"))
2912         {
2913             warn "$ERROR Error l2h: Can't open latex file '$latex_file' for writing\n";
2914             return 0;
2915         }
2916         print "# l2h: use ${l2h_latex_file} as latex file\n" if ($T2H_VERBOSE);
2917         print L2H_LATEX $l2h_latex_preample;
2918     }
2919     # open database for caching
2920     l2h_InitCache();
2921     $l2h_latex_count = 0;
2922     $l2h_to_latex_count = 0;
2923     $l2h_cached_count = 0;
2924     return  1;
2925 }
2926
2927 # print text (1st arg) into latex file (if not already there), return
2928 # HTML commentary which can be later on replaced by the latex2html
2929 # generated text
2930 sub l2h_ToLatex
2931 {
2932     my($text) = @_;
2933     my($count);
2934     $l2h_to_latex_count++;
2935     $text =~ s/(\s*)$//;
2936     # try whether we can cache it
2937     my $cached_text = l2h_FromCache($text);
2938     if ($cached_text)
2939     {
2940         $l2h_cached_count++;
2941         return $cached_text;
2942     }
2943     # try whether we have text already on things to do
2944     unless ($count = $l2h_to_latex{$text})
2945     {
2946         $count = $l2h_latex_count;
2947         $l2h_latex_count++;
2948         $l2h_to_latex{$text} = $count;
2949         $l2h_to_latex[$count] = $text;
2950         unless ($T2H_L2H_SKIP)
2951         {
2952             print L2H_LATEX "\\begin{rawhtml}\n";
2953             print L2H_LATEX "<!-- l2h_begin ${l2h_name} ${count} -->\n";
2954             print L2H_LATEX "\\end{rawhtml}\n";
2955
2956             print L2H_LATEX "$text\n";
2957
2958             print L2H_LATEX "\\begin{rawhtml}\n";
2959             print L2H_LATEX "<!-- l2h_end ${l2h_name} ${count} -->\n";
2960             print L2H_LATEX "\\end{rawhtml}\n";
2961         }
2962     }
2963     return "<!-- l2h_replace ${l2h_name} ${count} -->";
2964 }
2965
2966 # print closing into latex file and close it
2967 sub l2h_FinishToLatex
2968 {
2969     local ($reused);
2970     $reused = $l2h_to_latex_count - $l2h_latex_count - $l2h_cached_count;
2971     unless ($T2H_L2H_SKIP)
2972     {
2973         print L2H_LATEX $l2h_latex_closing;
2974         close(L2H_LATEX);
2975     }
2976     print "# l2h: finished to latex ($l2h_cached_count cached, $reused reused, $l2h_latex_count contents)\n" if ($T2H_VERBOSE);
2977     unless ($l2h_latex_count)
2978     {
2979         l2h_Finish();
2980         return 0;
2981     }
2982     return 1;
2983 }
2984
2985 ###################################
2986 # Second stage: Use latex2html to generate corresponding html code and images
2987 #
2988 # l2h_ToHtml([$l2h_latex_file, [$l2h_html_dir]]):
2989 #   Call latex2html on $l2h_latex_file
2990 #   Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir
2991 #   Return 1, on success
2992 #          0, otherwise
2993 #
2994 sub l2h_ToHtml
2995 {
2996     local($call, $ext, $root, $dotbug);
2997     if ($T2H_L2H_SKIP)
2998     {
2999         print "# l2h: skipping latex2html run\n" if ($T2H_VERBOSE);
3000         return 1;
3001     }
3002     # Check for dot in directory where dvips will work
3003     if ($T2H_L2H_TMP)
3004     {
3005         if ($T2H_L2H_TMP =~ /\./)
3006         {
3007             warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n";
3008             $dotbug = 1;
3009         }
3010     }
3011     else
3012     {
3013         if (&getcwd =~ /\./)
3014         {
3015             warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n";
3016             $dotbug = 1;
3017         }
3018     }
3019     # fix it, if necessary and hope that it works
3020     $T2H_L2H_TMP = "/tmp" if ($dotbug);
3021
3022     $call = $T2H_L2H_L2H;
3023     # use init file, if specified
3024     $call = $call . " -init_file " . $init_file if ($init_file && -f $init_file);
3025     # set output dir
3026     $call .=  ($docu_rdir ? " -dir $docu_rdir" : " -no_subdir");
3027     # use l2h_tmp, if specified
3028     $call = $call . " -tmp $T2H_L2H_TMP" if ($T2H_L2H_TMP);
3029     # options we want to be sure of
3030     $call = $call ." -address 0 -info 0 -split 0 -no_navigation -no_auto_link";
3031     $call = $call ." -prefix ${l2h_prefix} $l2h_latex_file";
3032
3033     print "# l2h: executing '$call'\n" if ($T2H_VERBOSE);
3034     if (system($call))
3035     {
3036         warn "l2h ***Error: '${call}' did not succeed\n";
3037         return 0;
3038     }
3039     else
3040     {
3041         print "# l2h: latex2html finished successfully\n" if ($T2H_VERBOSE);
3042         return 1;
3043     }
3044 }
3045
3046 # this is directly pasted over from latex2html
3047 sub getcwd
3048 {
3049     local($_) = `pwd`;
3050
3051     die "'pwd' failed (out of memory?)\n"
3052         unless length;
3053     chop;
3054     $_;
3055 }
3056
3057
3058 ##########################
3059 # Third stage: Extract generated contents from latex2html run
3060 # Initialize with: l2h_InitFromHtml
3061 #   open $l2h_html_file for reading
3062 #   reads in contents into array indexed by numbers
3063 #   return 1,  on success -- 0, otherwise
3064 # Extract Html code with: l2h_FromHtml($text)
3065 #   replaces in $text all previosuly inserted comments by generated html code
3066 #   returns (possibly changed) $text
3067 # Finish with: l2h_FinishFromHtml
3068 #   closes $l2h_html_dir/$l2h_name.".$docu_ext"
3069
3070 sub l2h_InitFromHtml
3071 {
3072     local($h_line, $h_content, $count, %l2h_img);
3073
3074     if (! open(L2H_HTML, "<${l2h_html_file}"))
3075     {
3076         print "$ERROR Error l2h: Can't open ${l2h_html_file} for reading\n";
3077         return 0;
3078     }
3079     print "# l2h: use ${l2h_html_file} as html file\n" if ($T2H_VERBOSE);
3080
3081     $l2h_html_count = 0;
3082     while ($h_line = <L2H_HTML>)
3083     {
3084         if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/)
3085         {
3086             $count = $1;
3087             $h_content = "";
3088             while ($h_line = <L2H_HTML>)
3089             {
3090                 if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/)
3091                 {
3092                     chomp $h_content;
3093                     chomp $h_content;
3094                     $l2h_html_count++;
3095                     $h_content = l2h_ToCache($count, $h_content);
3096                     $l2h_from_html[$count] = $h_content;
3097                     $h_content = '';
3098                     last;
3099                 }
3100                 $h_content = $h_content.$h_line;
3101             }
3102             if ($hcontent)
3103             {
3104                 print "$ERROR Warning l2h: l2h_end $l2h_name $count not found\n"
3105                     if ($T2H_VERBOSE);
3106                 close(L2H_HTML);
3107                 return 0;
3108             }
3109         }
3110     }
3111     print "# l2h: Got $l2h_html_count of $l2h_latex_count html contents\n"
3112         if ($T2H_VERBOSE);
3113
3114     close(L2H_HTML);
3115     return 1;
3116 }
3117
3118 sub l2h_FromHtml
3119 {
3120     my($text) = @_;
3121     my($done, $to_do, $count);
3122     $to_do = $text;
3123     while ($to_do =~ /([^\000]*)<!-- l2h_replace $l2h_name ([0-9]+) -->([^\000]*)/)
3124     {
3125         $to_do = $1;
3126         $count = $2;
3127         $done = $3.$done;
3128         $done = "<!-- l2h_end $l2h_name $count -->".$done
3129             if ($T2H_DEBUG & $DEBUG_L2H);
3130
3131         $done = &l2h_ExtractFromHtml($count) . $done;
3132
3133         $done = "<!-- l2h_begin $l2h_name $count -->".$done
3134             if ($T2H_DEBUG & $DEBUG_L2H);
3135     }
3136     return $to_do.$done;
3137 }
3138
3139
3140 sub l2h_ExtractFromHtml
3141 {
3142     local($count) = @_;
3143     return $l2h_from_html[$count] if ($l2h_from_html[$count]);
3144     if ($count >= 0 && $count < $l2h_latex_count)
3145     {
3146         # now we are in trouble
3147         local($l_l2h, $_);
3148
3149         $l2h_extract_error++;
3150         print "$ERROR l2h: can't extract content $count from html\n"
3151             if ($T2H_VERBOSE);
3152         # try simple (ordinary) substition (without l2h)
3153         $l_l2h = $T2H_L2H;
3154         $T2H_L2H = 0;
3155         $_ = $l2h_to_latex{$count};
3156         $_ = &substitute_style($_);
3157         &unprotect_texi;
3158         $_ = "<!-- l2h: ". __LINE__ . " use texi2html -->" . $_
3159             if ($T2H_DEBUG & $DEBUG_L2H);
3160         $T2H_L2H = $l_l2h;
3161         return $_;
3162     }
3163     else
3164     {
3165         # now we have been incorrectly called
3166         $l2h_range_error++;
3167         print "$ERROR l2h: Request of $count content which is out of valide range [0,$l2h_latex_count)\n";
3168         return "<!-- l2h: ". __LINE__ . " out of range count $count -->"
3169             if ($T2H_DEBUG & $DEBUG_L2H);
3170         return "<!-- l2h: out of range count $count -->";
3171     }
3172 }
3173
3174 sub l2h_FinishFromHtml
3175 {
3176     if ($T2H_VERBOSE)
3177     {
3178         if ($l2h_extract_error + $l2h_range_error)
3179         {
3180             print "# l2h: finished from html ($l2h_extract_error extract and $l2h_range_error errors)\n";
3181         }
3182         else
3183         {
3184             print "# l2h: finished from html (no errors)\n";
3185         }
3186     }
3187 }
3188
3189 sub l2h_Finish
3190 {
3191     l2h_StoreCache();
3192     if ($T2H_L2H_CLEAN)
3193     {
3194         print "# l2h: removing temporary files generated by l2h extension\n"
3195             if $T2H_VERBOSE;
3196         while (<"$docu_rdir$l2h_name"*>)
3197         {
3198             unlink $_;
3199         }
3200     }
3201     print "# l2h: Finished\n" if $T2H_VERBOSE;
3202     return 1;
3203 }
3204
3205 ##############################
3206 # stuff for l2h caching
3207 #
3208
3209 # I tried doing this with a dbm data base, but it did not store all
3210 # keys/values. Hence, I did as latex2html does it
3211 sub l2h_InitCache
3212 {
3213     if (-r "$l2h_cache_file")
3214     {
3215         my $rdo = do "$l2h_cache_file";
3216         warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n")
3217             unless ($rdo);
3218     }
3219 }
3220
3221 sub l2h_StoreCache
3222 {
3223     return unless $l2h_latex_count;
3224     my ($key, $value);
3225     open(FH, ">$l2h_cache_file") || return warn"$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n";
3226     while (($key, $value) = each %l2h_cache)
3227     {
3228         # escape stuff
3229         $key =~ s|/|\\/|g;
3230         $key =~ s|\\\\/|\\/|g;
3231         # weird, a \ at the end of the key results in an error
3232         # maybe this also broke the dbm database stuff
3233         $key =~ s|\\$|\\\\|;
3234         $value =~ s/\|/\\\|/go;
3235         $value =~ s/\\\\\|/\\\|/go;
3236         $value =~ s|\\\\|\\\\\\\\|g;
3237         print FH "\n\$l2h_cache_key = q/$key/;\n";
3238         print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n";
3239     }
3240     print FH "1;";
3241     close(FH);
3242 }
3243
3244 # return cached html, if it exists for text, and if all pictures
3245 # are there, as well
3246 sub l2h_FromCache
3247 {
3248     my $text = shift;
3249     my $cached = $l2h_cache{$text};
3250     if ($cached)
3251     {
3252         while ($cached =~ m/SRC="(.*?)"/g)
3253         {
3254             unless (-e "$docu_rdir$1")
3255             {
3256                 return undef;
3257             }
3258         }
3259         return $cached;
3260     }
3261     return undef;
3262 }
3263
3264 # insert generated html into cache, move away images,
3265 # return transformed html
3266 $maximage = 1;
3267 sub l2h_ToCache
3268 {
3269     my $count = shift;
3270     my $content = shift;
3271     my @images = ($content =~ /SRC="(.*?)"/g);
3272     my ($src, $dest);
3273
3274     for $src (@images)
3275     {
3276         $dest = $l2h_img{$src};
3277         unless ($dest)
3278         {
3279             my $ext;
3280             if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext)
3281             {
3282                 $ext = $1;
3283             }
3284             else
3285             {
3286                 warn "$ERROR: L2h image $src has invalid extension\n";
3287                 next;
3288             }
3289             while (-e "$docu_rdir${docu_name}_$maximage.$ext")
3290             {
3291                 $maximage++;
3292             }
3293             $dest = "${docu_name}_$maximage.$ext";
3294             system("cp -f $docu_rdir$src $docu_rdir$dest");
3295             $l2h_img{$src} = $dest;
3296             unlink "$docu_rdir$src" unless ($DEBUG & $DEBUG_L2H);
3297         }
3298         $content =~ s/$src/$dest/g;
3299     }
3300     $l2h_cache{$l2h_to_latex[$count]} = $content;
3301     return $content;
3302 }
3303
3304
3305 #+++############################################################################
3306 #                                                                              #
3307 # Pass 1: read source, handle command, variable, simple substitution           #
3308 #                                                                              #
3309 #---############################################################################
3310 sub pass1
3311 {
3312     my $name;
3313     my $line;
3314     @lines = ();                # whole document
3315     @toc_lines = ();            # table of contents
3316     @stoc_lines = ();           # table of contents
3317     $curlevel = 0;              # current level in TOC
3318     $node = '';                 # current node name
3319     $node_next = '';            # current node next name
3320     $node_prev = '';            # current node prev name
3321     $node_up = '';              # current node up name
3322     $in_table = 0;              # am I inside a table
3323     $table_type = '';           # type of table ('', 'f', 'v', 'multi')
3324     @tables = ();               # nested table support
3325     $in_bibliography = 0;       # am I inside a bibliography
3326     $in_glossary = 0;           # am I inside a glossary
3327     $in_top = 0;                # am I inside the top node
3328     $has_top = 0;               # did I see a top node?
3329     $has_top_command = 0;       # did I see @top for automatic pointers?
3330     $in_pre = 0;                # am I inside a preformatted section
3331     $in_list = 0;               # am I inside a list
3332     $in_html = 0;               # am I inside an HTML section
3333     $first_line = 1;            # is it the first line
3334     $dont_html = 0;             # don't protect HTML on this line
3335     $deferred_ref = '';         # deferred reference for indexes
3336     @html_stack = ();           # HTML elements stack
3337     $html_element = '';         # current HTML element
3338     &html_reset;
3339     %macros = ();               # macros
3340     $toc_indent =               # used for identation in TOC's
3341         ($T2H_NUMBER_SECTIONS ? 'BLOCKQUOTE' : 'UL');
3342
3343     # init l2h
3344     $T2H_L2H = &l2h_Init($docu_name) if ($T2H_L2H);
3345     $T2H_L2H = &l2h_InitToLatex      if ($T2H_L2H);
3346
3347     # build code for simple substitutions
3348     # the maps used (%simple_map and %things_map) MUST be aware of this
3349     # watch out for regexps, / and escaped characters!
3350     $subst_code = '';
3351     foreach (keys(%simple_map))
3352     {
3353         ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
3354         $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
3355     }
3356     foreach (keys(%things_map))
3357     {
3358         $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
3359     }
3360     if ($use_acc)
3361     {
3362         # accentuated characters
3363         foreach (keys(%accent_map))
3364         {
3365             if ($_ eq "`")
3366             {
3367                 $subst_code .= "s/$;3";
3368             }
3369             elsif ($_ eq "'")
3370             {
3371                 $subst_code .= "s/$;4";
3372             }
3373             else
3374             {
3375                 $subst_code .= "s/\\\@\\$_";
3376             }
3377             $subst_code .= "([a-z])/&\${1}$accent_map{$_};/gi;\n";
3378         }
3379     }
3380     eval("sub simple_substitutions { $subst_code }");
3381
3382     &init_input;
3383  INPUT_LINE: while ($_ = &next_line)
3384     {
3385         #
3386         # remove \input on the first lines only
3387         #
3388         if ($first_line)
3389         {
3390             next if /^\\input/;
3391             $first_line = 0;
3392         }
3393         # non-@ substitutions cf. texinfmt.el
3394         #
3395         # parse texinfo tags
3396         #
3397         $tag = '';
3398         $end_tag = '';
3399         if (/^\s*\@end\s+(\w+)\b/)
3400         {
3401             $end_tag = $1;
3402         }
3403         elsif (/^\s*\@(\w+)\b/)
3404         {
3405             $tag = $1;
3406         }
3407         #
3408         # handle @html / @end html
3409         #
3410         if ($in_html)
3411         {
3412             if ($end_tag eq 'html')
3413             {
3414                 $in_html = 0;
3415             }
3416             else
3417             {
3418                 $tag2pro{$in_html} .= $_;
3419             }
3420             next;
3421         }
3422         elsif ($tag eq 'html')
3423         {
3424             $in_html = $PROTECTTAG . ++$html_num;
3425             push(@lines, $in_html);
3426             next;
3427         }
3428
3429         #
3430         # try to remove inlined comments
3431         # syntax from tex-mode.el comment-start-skip
3432         #
3433         s/((^|[^\@])(\@\@)*)\@(c( |\{)|comment ).*$/$1/;
3434
3435         # Sometimes I use @c right at the end of  a line ( to suppress the line feed )
3436         #    s/((^|[^\@])(\@\@)*)\@c(omment)?$/$1/;
3437         #     s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
3438         #     s/(.*)\@c{.*?}(.*)/$1$2/;
3439         #     s/(.*)\@comment{.*?}(.*)/$1$2/;
3440         #     s/^(.*)\@c /$1/;
3441         #     s/^(.*)\@comment /$1/;
3442
3443         #############################################################
3444         # value substitution before macro expansion, so that
3445         # it works in macro arguments
3446         s/\@value{($VARRE)}/$value{$1}/eg;
3447
3448         #############################################################
3449         # macro substitution
3450         while (/\@(\w+)/g)
3451         {
3452             if (exists($macros->{$1}))
3453             {
3454                 my $before = $`;
3455                 $name = $1;
3456                 my $after = $';
3457                 my @args;
3458                 my $args;
3459                 #####################################################
3460                 # Support for multi-line macro invocations and nested
3461                 # '{' and '}' within macro invocations added by
3462                 # Eric Sunshine <sunshine@sunshineco.com> 2000/09/10.
3463                 #####################################################
3464                 if ($after =~ /^\s*\{/) # Macro arguments delimited by '{' and '}'?
3465                 {
3466                     my ($protect, $start, $end, $depth, $c) = (0, 0, 0, 0, 0);
3467                     foreach $c (unpack('C*', $after))
3468                     {
3469                         if ($protect)
3470                         {       # Character protected by '\' or '@'; pass through unmolested.
3471                             $protect = 0;
3472                         }
3473                         elsif ($c == ord('\\') || $c == ord('@'))
3474                         {       # '\' and '@' remove special meaning of next character.
3475                             $protect = 1;
3476                         }
3477                         elsif ($c == ord('{')) # Allow '{' and '}' to nest.
3478                         {
3479                             $depth++;
3480                         }
3481                         elsif ($c == ord('}'))
3482                         {
3483                             $depth--;
3484                             last if $depth == 0;
3485                         }
3486                         $start++ if !$depth; # Position of opening brace.
3487                         $end++; # Position of closing brace.
3488                     }
3489
3490                     # '{' & '}' did not completely unnest; append next line; try again.
3491                     if ($depth > 0)
3492                     {
3493                         my $paste = &next_line;
3494                         die "$ERROR Missing closing brace '}' for invocation of macro " .
3495                             "\"\@$name\" on line:\n", substr($_,0,70), "...\n" unless $paste;
3496                         s/\n$/ /;
3497                         unshift @input_spool, $_ . $paste;
3498                         next INPUT_LINE;
3499                     }
3500
3501                     # Extract macro arguments from within '{' and '}'.
3502                     $len = $end - $start - 1;
3503                     $args = ($len > 0) ? substr($after, $start + 1, $len) : '';
3504                     $after = substr($after, $end + 1);
3505                 }
3506                 ############ End Sunshine Modifications #############
3507                 elsif (@{$macros->{$name}->{Args}} == 1) # Macro arg extends to EOL.
3508                 {
3509                     $args = $after;
3510                     $args =~ s/^\s*//;
3511                     $args =~ s/\s*$//;
3512                     $after = '';
3513                 }
3514                 $args =~ s|\\\\|\\|g;
3515                 $args =~ s|\\{|{|g;
3516                                 $args =~ s|\\}|}|g;
3517                 if (@{$macros->{$name}->{Args}} > 1)
3518                 {
3519                     $args =~ s/(^|[^\\]),/$1$;/g ;
3520                     $args =~ s|\\,|,|g;
3521                     @args = split(/$;\s*/, $args) if (@{$macros->{$name}->{Args}} > 1);
3522                 }
3523                 else
3524                 {
3525                     $args =~ s|\\,|,|g;
3526                     @args = ($args);
3527                 }
3528                 my $macrobody = $macros->{$name}->{Body};
3529                 for ($i=0; $i<=$#args; $i++)
3530                 {
3531                     $macrobody =~ s|\\$macros->{$name}->{Args}->[$i]\\|$args[$i]|g;
3532                 }
3533                 $macrobody =~ s|\\\\|\\|g;
3534                 $_ = $before . $macrobody . $after;
3535                 unshift @input_spool, map {$_ = $_."\n"} split(/\n/, $_);
3536                 next INPUT_LINE;
3537             }
3538         }
3539         #
3540         # try to skip the line
3541         #
3542         if ($end_tag)
3543         {
3544             $in_titlepage = 0 if $end_tag eq 'titlepage';
3545             next if $to_skip{"end $end_tag"};
3546         }
3547         elsif ($tag)
3548         {
3549             $in_titlepage = 1 if $tag eq 'titlepage';
3550             next if $to_skip{$tag};
3551             last if $tag eq 'bye';
3552         }
3553         if ($in_top)
3554         {
3555             # parsing the top node
3556             if ($tag eq 'node' ||
3557                 ($sec2level{$tag} && $tag !~ /unnumbered/ && $tag !~ /heading/))
3558             {
3559                 # no more in top
3560                 $in_top = 0;
3561                 push(@lines, $TOPEND);
3562             }
3563         }
3564         unless ($in_pre)
3565         {
3566             s/``/\"/go;
3567             s/''/\"/go;
3568             s/([\w ])---([\w ])/$1--$2/g;
3569         }
3570         #
3571         # analyze the tag
3572         #
3573         if ($tag)
3574         {
3575             # skip lines
3576             &skip_until($tag), next if $tag eq 'ignore';
3577             &skip_until($tag), next if $tag eq 'ifnothtml';
3578             if ($tag eq 'ifinfo')
3579             {
3580                 &skip_until($tag), next unless $T2H_EXPAND eq 'info';
3581             }
3582             if ($tag eq 'iftex')
3583             {
3584                 &skip_until($tag), next unless $T2H_EXPAND eq 'tex';
3585             }
3586             if ($tag eq 'tex')
3587             {
3588                 # add to latex2html file
3589                 if ($T2H_EXPAND eq 'tex' && $T2H_L2H && ! $in_pre)
3590                 {
3591                     # add space to the end -- tex(i2dvi) does this, as well
3592                     push(@lines, &l2h_ToLatex(&string_until($tag) . " "));
3593                 }
3594                 else
3595                 {
3596                     &skip_until($tag);
3597                 }
3598                 next;
3599             }
3600             if ($tag eq 'titlepage')
3601             {
3602                 next;
3603             }
3604             # handle special tables
3605             if ($tag =~ /^(|f|v|multi)table$/)
3606             {
3607                 $table_type = $1;
3608                 $tag = 'table';
3609             }
3610             # special cases
3611             # APA: Fixed regexp to ONLY match the top node, not any
3612             # node starting with the word top.
3613             if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*(,.*)?$/i))
3614             {
3615                 $in_top = 1;
3616                 $has_top = 1;
3617                 $has_top_command = 1 if $tag eq 'top';
3618                 @lines = ();    # ignore all lines before top (title page garbage)
3619                 next;
3620             }
3621             elsif ($tag eq 'node')
3622             {
3623                 if ($in_top)
3624                 {
3625                     $in_top = 0;
3626                     push(@lines, $TOPEND);
3627                 }
3628                 warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
3629                 # request of "Richard Y. Kim" <ryk@ap.com>
3630                 s/^\@node\s+//;
3631                 $_ = &protect_html($_); # if node contains '&' for instance
3632                 ($node, $node_next, $node_prev, $node_up) = split(/,/);
3633                 if ($node)
3634                 {
3635                     &normalise_node($node);
3636                 }
3637                 else
3638                 {
3639                     warn "$ERROR Node is undefined: $_ (eg. \@node NODE-NAME, NEXT, PREVIOUS, UP)";
3640                 }
3641                 if ($node_next)
3642                 {
3643                     &normalise_node($node_next);
3644                 }
3645                 if ($node_prev)
3646                 {
3647                     &normalise_node($node_prev);
3648                 }
3649                 if ($node_up)
3650                 {
3651                     &normalise_node($node_up);
3652                 }
3653                 $node =~ /\"/ ?
3654                     push @lines, &html_debug("<A NAME='".protect_html($node)."'></A>\n", __LINE__) :
3655                         push @lines, &html_debug("<A NAME=\"".protect_html($node)."\"></A>\n", __LINE__);
3656                 next;
3657             }
3658             elsif ($tag eq 'include')
3659             {
3660                 if (/^\@include\s+($FILERE)\s*$/o)
3661                 {
3662                     $file = LocateIncludeFile($1);
3663                     if ($file && -e $file)
3664                     {
3665                         &open($file);
3666                         print "# including $file\n" if $T2H_VERBOSE;
3667                     }
3668                     else
3669                     {
3670                         warn "$ERROR Can't find $1, skipping";
3671                     }
3672                 }
3673                 else
3674                 {
3675                     warn "$ERROR Bad include line: $_";
3676                 }
3677                 next;
3678             }
3679             elsif ($tag eq 'ifclear')
3680             {
3681                 if (/^\@ifclear\s+($VARRE)\s*$/o)
3682                 {
3683                     next unless defined($value{$1});
3684                     &skip_until($tag);
3685                 }
3686                 else
3687                 {
3688                     warn "$ERROR Bad ifclear line: $_";
3689                 }
3690                 next;
3691             }
3692             elsif ($tag eq 'ifset')
3693             {
3694                 if (/^\@ifset\s+($VARRE)\s*$/o)
3695                 {
3696                     next if defined($value{$1});
3697                     &skip_until($tag);
3698                 }
3699                 else
3700                 {
3701                     warn "$ERROR Bad ifset line: $_";
3702                 }
3703                 next;
3704             }
3705             elsif ($tag eq 'menu')
3706             {
3707                 unless ($T2H_SHOW_MENU)
3708                 {
3709                     &skip_until($tag);
3710                     next;
3711                 }
3712                 &html_push_if($tag);
3713                 push(@lines, &html_debug('', __LINE__));
3714             }
3715             elsif ($format_map{$tag})
3716             {
3717                 $in_pre = 1 if $format_map{$tag} eq 'PRE';
3718                 &html_push_if($format_map{$tag});
3719                 push(@lines, &html_debug('', __LINE__));
3720                 $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
3721                 #           push(@lines, &debug("<BLOCKQUOTE>\n", __LINE__))
3722                 #             if $tag =~ /example/i;
3723                 # Eric Sunshine <sunshine@sunshineco.com>: <PRE>blah</PRE> looks
3724                 # better than <PRE>\nblah</PRE> on OmniWeb2 NextStep browser.
3725                 push(@lines, &debug("<$format_map{$tag}>" .
3726                                     ($in_pre ? '' : "\n"), __LINE__));
3727                 next;
3728             }
3729             elsif (exists $complex_format_map->{$tag})
3730             {
3731                 my $start = eval $complex_format_map->{$tag}->[0];
3732                 # APA: <table> implicitly ends paragraph, so let's do it
3733                 # explicitly to keep our HTML stack in sync.
3734                 if ($start =~ /\A\s*<table>/i)
3735                 {
3736                     if ($html_element eq 'P')
3737                     {
3738                         push (@lines2, &debug("</P>\n", __LINE__));
3739                         &html_pop();
3740                     }
3741                 }
3742                 if ($@)
3743                 {
3744                     print "$ERROR: eval of complex_format_map->{$tag}->[0] $complex_format_map->{$tag}->[0]: $@";
3745                     $start = '<pre>'
3746                 }
3747                 $in_pre = 1 if $start =~ /<pre/;
3748                 push(@lines, html_debug($start. ($in_pre ? '' : "\n"), __LINE__));
3749                 next;
3750             }
3751             elsif ($tag eq 'table')
3752             {
3753                 # anorland@hem2.passagen.se
3754                 # if (/^\s*\@(|f|v|multi)table\s+\@(\w+)/) {
3755                 if (/^\s*\@(|f|v|multi)table\s+\@(\w+)|(\{[^\}]*\})/)
3756                 {
3757                     $in_table = $2;
3758                     unshift(@tables, join($;, $table_type, $in_table));
3759                     if ($table_type eq "multi")
3760                     {
3761                         # APA: <table> implicitly ends paragraph, so let's
3762                         # do it explicitly to keep our HTML stack in sync.
3763                         if ($html_element eq 'P')
3764                         {
3765                             push (@lines, &debug("</P>\n", __LINE__));
3766                             &html_pop();
3767                         }
3768                         # don't use borders -- gets confused by empty cells
3769                         push(@lines, &debug("<TABLE>\n", __LINE__));
3770                         &html_push_if('TABLE');
3771                     }
3772                     else
3773                     {
3774                         # APA: <dl> implicitly ends paragraph, so let's
3775                         # do it explicitly to keep our HTML stack in sync.
3776                         if ($html_element eq 'P')
3777                         {
3778                             push (@lines, &debug("</P>\n", __LINE__));
3779                             &html_pop();
3780                         }
3781                         push(@lines, &debug("<DL COMPACT>\n", __LINE__));
3782                         &html_push_if('DL');
3783                     }
3784                     push(@lines, &html_debug('', __LINE__));
3785                 }
3786                 else
3787                 {
3788                     warn "$ERROR Bad table line: $_";
3789                 }
3790                 next;
3791             }
3792             elsif ($tag eq 'synindex' || $tag eq 'syncodeindex')
3793             {
3794                 if (/^\@$tag\s+(\w+)\s+(\w+)\s*$/)
3795                 {
3796                     my $from = $1;
3797                     my $to = $2;
3798                     my $prefix_from = IndexName2Prefix($from);
3799                     my $prefix_to = IndexName2Prefix($to);
3800
3801                     warn("$ERROR unknown from index name $from ind syn*index line: $_"), next
3802                         unless $prefix_from;
3803                     warn("$ERROR unknown to index name $to ind syn*index line: $_"), next
3804                         unless $prefix_to;
3805
3806                     if ($tag eq 'syncodeindex')
3807                     {
3808                         $index_properties->{$prefix_to}->{'from_code'}->{$prefix_from} = 1;
3809                     }
3810                     else
3811                     {
3812                         $index_properties->{$prefix_to}->{'from'}->{$prefix_from} = 1;
3813                     }
3814                 }
3815                 else
3816                 {
3817                     warn "$ERROR Bad syn*index line: $_";
3818                 }
3819                 next;
3820             }
3821             elsif ($tag eq 'defindex' || $tag eq 'defcodeindex')
3822             {
3823                 if (/^\@$tag\s+(\w+)\s*$/)
3824                 {
3825                     $name = $1;
3826                     $index_properties->{$name}->{name} = $name;
3827                     $index_properties->{$name}->{code} = 1 if $tag eq 'defcodeindex';
3828                 }
3829                 else
3830                 {
3831                     warn "$ERROR Bad defindex line: $_";
3832                 }
3833                 next;
3834             }
3835             elsif (/^\@printindex/)
3836             {
3837                 # APA: HTML generated for @printindex contains <table>
3838                 # which implicitly ends paragraph, so let's do it
3839                 # explicitly to keep our HTML stack in sync.
3840                 if ($html_element eq 'P')
3841                 {
3842                     push(@lines, &debug("</P>\n", __LINE__));
3843                     &html_pop();
3844                 }
3845                 push (@lines, "<!--::${section}::-->$_");
3846                 next;
3847             }
3848             elsif ($tag eq 'sp')
3849             {
3850                 push(@lines, &debug("<P></P>\n", __LINE__));
3851                 next;
3852             }
3853             elsif ($tag eq 'center')
3854             {
3855                 push(@lines, &debug("<center>\n", __LINE__));
3856                 s/\@center//;
3857             }
3858             elsif ($tag eq 'setref')
3859             {
3860                 my ($setref);
3861                 &protect_html;  # if setref contains '&' for instance
3862                 if (/^\@$tag\s*{($NODERE)}\s*$/)
3863                 {
3864                     $setref = $1;
3865                     $setref =~ s/\s+/ /go; # normalize
3866                     $setref =~ s/ $//;
3867                     $node2sec{$setref} = $name;
3868                     $sec2node{$name} = $setref;
3869                     $node2href{$setref} = "$docu_doc#$docid";
3870                 }
3871                 else
3872                 {
3873                     warn "$ERROR Bad setref line: $_";
3874                 }
3875                 next;
3876             }
3877             elsif ($tag eq 'lowersections')
3878             {
3879                 my ($sec, $level);
3880                 while (($sec, $level) = each %sec2level)
3881                 {
3882                     $sec2level{$sec} = $level + 1;
3883                 }
3884                 next;
3885             }
3886             elsif ($tag eq 'raisesections')
3887             {
3888                 my ($sec, $level);
3889                 while (($sec, $level) = each %sec2level)
3890                 {
3891                     $sec2level{$sec} = $level - 1;
3892                 }
3893                 next;
3894             }
3895             elsif ($tag eq 'macro' || $tag eq 'rmacro')
3896             {
3897                 if (/^\@$tag\s*(\w+)\s*(.*)/)
3898                 {
3899                     $name = $1;
3900                     my @args;
3901                     @args = split(/\s*,\s*/ , $1)
3902                         if ($2 =~ /^\s*{(.*)}\s*/);
3903
3904                     $macros->{$name}->{Args} = \@args;
3905                     $macros->{$name}->{Body} = '';
3906                     while (($_ = &next_line) && $_ !~ /\@end $tag/)
3907                     {
3908                         $macros->{$name}->{Body} .= $_;
3909                     }
3910                     die "ERROR: No closing '\@end $tag' found for macro definition of '$name'\n"
3911                         unless (/\@end $tag/);
3912                     chomp $macros->{$name}->{Body};
3913                 }
3914                 else
3915                 {
3916                     warn "$ERROR: Bad macro defintion $_"
3917                 }
3918                 next;
3919             }
3920             elsif ($tag eq 'unmacro')
3921             {
3922                 delete $macros->{$1} if (/^\@unmacro\s*(\w+)/);
3923                 next;
3924             }
3925             elsif ($tag eq 'documentlanguage')
3926             {
3927                 SetDocumentLanguage($1) if (!$T2H_LANG && /documentlanguage\s*(\w+)/);
3928             }
3929             elsif (defined($def_map{$tag}))
3930             {
3931                 if ($def_map{$tag})
3932                 {
3933                     s/^\@$tag\s+//;
3934                     $tag = $def_map{$tag};
3935                     $_ = "\@$tag $_";
3936                     $tag =~ s/\s.*//;
3937                 }
3938             }
3939             elsif (defined($user_sub{$tag}))
3940             {
3941                 s/^\@$tag\s+//;
3942                 $sub = $user_sub{$tag};
3943                 print "# user $tag = $sub, arg: $_" if $T2H_DEBUG & $DEBUG_USER;
3944                 if (defined(&$sub))
3945                 {
3946                     chop($_);
3947                     &$sub($_);
3948                 }
3949                 else
3950                 {
3951                     warn "$ERROR Bad user sub for $tag: $sub\n";
3952                 }
3953                 next;
3954             }
3955             if (defined($def_map{$tag}))
3956             {
3957                 s/^\@$tag\s+//;
3958                 if ($tag =~ /x$/)
3959                 {
3960                     # extra definition line
3961                     $tag = $`;
3962                     $is_extra = 1;
3963                 }
3964                 else
3965                 {
3966                     $is_extra = 0;
3967                 }
3968                 while (/\{([^\{\}]*)\}/)
3969                 {
3970                     # this is a {} construct
3971                     ($before, $contents, $after) = ($`, $1, $');
3972                     # protect spaces
3973                     $contents =~ s/\s+/$;9/g;
3974                     # restore $_ protecting {}
3975                     $_ = "$before$;7$contents$;8$after";
3976                 }
3977                 @args = split(/\s+/, &protect_html($_));
3978                 foreach (@args)
3979                 {
3980                     s/$;9/ /g;  # unprotect spaces
3981                     s/$;7/\{/g; # ... {
3982                     s/$;8/\}/g; # ... }
3983                 }
3984                 $type = shift(@args);
3985                 $type =~ s/^\{(.*)\}$/$1/;
3986                 print "# def ($tag): {$type} ", join(', ', @args), "\n"
3987                     if $T2H_DEBUG & $DEBUG_DEF;
3988                 if ($tag eq 'deftypecv') {
3989                     my $class = shift (@args);
3990                     $class =~ s/^\{(.*)\}$/$1/;
3991                     $type .= " of $class";
3992                 }
3993                 $type .= ':' if (!$T2H_DEF_TABLE); # it's nicer like this
3994                 $name = shift(@args);
3995                 $name =~ s/^\{(.*)\}$/$1/;
3996                 if ($is_extra)
3997                 {
3998                     $_ = &debug("<DT>", __LINE__) if (!$T2H_DEF_TABLE);
3999                     $_ = &debug("", __LINE__) if ($T2H_DEF_TABLE);
4000                     #$_ = &debug("<TR TEST1>\n", __LINE__) if ($T2H_DEF_TABLE);
4001                 }
4002                 else
4003                 {
4004                     # APA: <dl> implicitly ends paragraph, so let's
4005                     # do it explicitly to keep our HTML stack in sync.
4006                     if ($html_element eq 'P')
4007                     {
4008                         $_ = &debug("</P>\n", __LINE__);
4009                         &html_pop();
4010                     }
4011                     else
4012                     {
4013                         $_ = '';
4014                     }
4015                     $_ .= &debug("<DL>\n<DT>", __LINE__) if (!$T2H_DEF_TABLE);
4016                     $_ .= &debug("<TABLE WIDTH=\"100%\">\n", __LINE__) if ($T2H_DEF_TABLE);
4017                 }
4018                 if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp')
4019                 {
4020                     if ($T2H_DEF_TABLE)
4021                     {
4022                         $_ .= "<TR>\n<TD ALIGN=\"LEFT\"><B>$name</B>\n";
4023                         $_ .= " <I>@args</I>" if @args;
4024                         $_ .= "</TD>\n";
4025                         $_ .= "<TD ALIGN=\"RIGHT\">";
4026                         $_ .= "$type</TD>\n</TR>\n";
4027                     }
4028                     else
4029                     {
4030                         $_ .= "<U>$type</U> <B>$name</B>";
4031                         $_ .= " <I>@args</I>" if @args;
4032                     }
4033                 }
4034                 elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
4035                        || $tag eq 'deftypeop' || $tag eq 'defcv'
4036                        || $tag eq 'defop' || $tag eq 'deftypecv')
4037                 {
4038                     $ftype = $name;
4039                     $name = shift(@args);
4040                     $name =~ s/^\{(.*)\}$/$1/;
4041                     if ($T2H_DEF_TABLE)
4042                     {
4043                         $_ .= "<TR>\n<TD ALIGN=\"LEFT\"><B>$name</B>";
4044                         $_ .= " <I>@args</I>" if @args;
4045                         $_ .= "</TD>\n";
4046                         $_ .= "<TD ALIGN=\"RIGHT\">";
4047                         $_ .= "$type of $ftype</TD>\n</TR>\n";
4048                     }
4049                     else
4050                     {
4051                         my $sep = $ftype =~ /\*$/ ? '' : ' ';
4052                         $_ .= "<U>$type</U> $ftype$sep<B>$name</B>";
4053                         $_ .= " @args" if @args;
4054                     }
4055                 }
4056                 else
4057                 {
4058                     warn "$ERROR Unknown definition type: $tag\n";
4059                     $_ .= "<U>$type</U> <B>$name</B>";
4060                     $_ .= " <I>@args</I>" if @args;
4061                 }
4062                 $_ .= &debug("\n<DD>", __LINE__) if (!$T2H_DEF_TABLE);
4063                 ########$_ .= &debug("\n</TABLE TEST3>\n<TABLE WIDTH=\"95%\">\n", __LINE__) if ($T2H_DEF_TABLE);
4064                 $name = &unprotect_html($name);
4065                 if ($tag eq 'deffn' || $tag eq 'deftypefn')
4066                 {
4067                     EnterIndexEntry('f', $name, $docu_doc, $section, \@lines);
4068                     #           unshift(@input_spool, "\@findex $name\n");
4069                 }
4070                 elsif ($tag eq 'defop')
4071                 {
4072                     EnterIndexEntry('f', "$name on $ftype", $docu_doc, $section, \@lines);
4073                     #           unshift(@input_spool, "\@findex $name on $ftype\n");
4074                 }
4075                 elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv')
4076                 {
4077                     EnterIndexEntry('v', $name, $docu_doc, $section, \@lines);
4078                     #           unshift(@input_spool, "\@vindex $name\n");
4079                 }
4080                 else
4081                 {
4082                     EnterIndexEntry('t', $name, $docu_doc, $section, \@lines);
4083                     #           unshift(@input_spool, "\@tindex $name\n");
4084                 }
4085                 $dont_html = 1;
4086             }
4087         }
4088         elsif ($end_tag)
4089         {
4090             if ($format_map{$end_tag})
4091             {
4092                 $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
4093                 $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
4094                 &html_pop_if('P');
4095                 &html_pop_if('LI');
4096                 &html_pop_if();
4097                 push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
4098                 push(@lines, &html_debug('', __LINE__));
4099             }
4100             elsif (exists $complex_format_map->{$end_tag})
4101             {
4102                 my $end = eval $complex_format_map->{$end_tag}->[1];
4103                 if ($@)
4104                 {
4105                     print "$ERROR: eval of complex_format_map->{$end_tag}->[1] $complex_format_map->{$end_tag}->[0]: $@";
4106                     $end = '</pre>'
4107                 }
4108                 $in_pre = 0 if $end =~ m|</pre>|;
4109                 push(@lines, html_debug($end, __LINE__));
4110             }
4111             elsif ($end_tag =~ /^(|f|v|multi)table$/)
4112             {
4113                 unless (@tables)
4114                 {
4115                     warn "$ERROR \@end $end_tag without \@*table\n";
4116                     next;
4117                 }
4118                 &html_pop_if('P');
4119                 ($table_type, $in_table) = split($;, shift(@tables));
4120                 unless ($1 eq $table_type)
4121                 {
4122                     warn "$ERROR \@end $end_tag without matching \@$end_tag\n";
4123                     next;
4124                 }
4125                 if ($table_type eq "multi")
4126                 {
4127                     push(@lines, "</TR></TABLE>\n");
4128                     &html_pop_if('TR');
4129                 }
4130                 else
4131                 {
4132                     # APA: </dl> implicitly ends paragraph, so let's
4133                     # do it explicitly to keep our HTML stack in sync.
4134                     if ($html_element eq 'P')
4135                     {
4136                         push(@lines, &debug("</P>\n", __LINE__));
4137                         &html_pop();
4138                     }
4139                     push(@lines, "</DL>\n");
4140                     &html_pop_if('DD');
4141                 }
4142                 &html_pop_if();
4143                 if (@tables)
4144                 {
4145                     ($table_type, $in_table) = split($;, $tables[0]);
4146                 }
4147                 else
4148                 {
4149                     $in_table = 0;
4150                 }
4151             }
4152             elsif (defined($def_map{$end_tag}))
4153             {
4154                 # APA: </dl> and </table> implicitly ends paragraph,
4155                 # so let's do it explicitly to keep our HTML stack in
4156                 # sync.
4157                 if ($html_element eq 'P')
4158                 {
4159                     push(@lines, &debug("</P>\n", __LINE__));
4160                     &html_pop();
4161                 }
4162                 push(@lines, &debug("</DL>\n", __LINE__)) if (!$T2H_DEF_TABLE);
4163                 push(@lines, &debug("</TABLE>\n", __LINE__)) if ($T2H_DEF_TABLE);
4164             }
4165             elsif ($end_tag eq 'menu')
4166             {
4167                 &html_pop_if();
4168                 push(@lines, $_); # must keep it for pass 2
4169             }
4170             next;
4171         }
4172         #############################################################
4173         # anchor insertion
4174         while (/\@anchor\s*\{(.*?)\}/)
4175         {
4176             $_ = $`.$';
4177             my $anchor = $1;
4178             $anchor = &normalise_node($anchor);
4179             push @lines, &html_debug("<A NAME=\"".protect_html($anchor)."\"></A>\n");
4180             $node2href{$anchor} = "$docu_doc#$anchor";
4181             next INPUT_LINE if $_ =~ /^\s*$/;
4182         }
4183         #############################################################
4184         # index entry generation, after value substitutions
4185         if (/^\@(\w+?)index\s+/)
4186         {
4187             EnterIndexEntry($1, $', $docu_doc, $section, \@lines);
4188             next;
4189         }
4190         #
4191         # protect texi and HTML things
4192         &protect_texi;
4193         $_ = &protect_html($_) unless $dont_html;
4194         $dont_html = 0;
4195         # substitution (unsupported things)
4196         s/^\@exdent\s+//go;
4197         s/\@noindent\s+//go;
4198         s/\@refill\s+//go;
4199         # other substitutions
4200         &simple_substitutions;
4201         s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
4202         #
4203         # analyze the tag again
4204         #
4205         if ($tag)
4206         {
4207             if (defined($sec2level{$tag}) && $sec2level{$tag} > 0)
4208             {
4209                 if (/^\@$tag\s+(.+)$/)
4210                 {
4211                     $name = $1;
4212                     $name = &normalise_node($name);
4213                     $level = $sec2level{$tag};
4214                     # check for index
4215                     $first_index_chapter = $name
4216                         if ($level == 1 && !$first_index_chapter &&
4217                             $name =~ /index/i);
4218                     if ($in_top && /heading/)
4219                     {
4220                         $T2H_HAS_TOP_HEADING = 1;
4221                         $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
4222                         &html_push_if('body');
4223                         print "# top heading, section $name, level $level\n"
4224                             if $T2H_DEBUG & $DEBUG_TOC;
4225                     }
4226                     else
4227                     {
4228                         unless (/^\@\w*heading/)
4229                         {
4230                             unless (/^\@unnumbered/)
4231                             {
4232                                 my $number = &update_sec_num($tag, $level);
4233                                 $name = $number . ' ' . $name if $T2H_NUMBER_SECTIONS;
4234                                 $sec2number{$name} = $number;
4235                                 $number2sec{$number} = $name;
4236                             }
4237                             if (defined($toplevel))
4238                             {
4239                                 push @lines, ($level==$toplevel ? $CHAPTEREND : $SECTIONEND);
4240                             }
4241                             else
4242                             {
4243                                 # first time we see a "section"
4244                                 unless ($level == 1)
4245                                 {
4246                                     warn "$WARN The first section found is not of level 1: $_";
4247                                 }
4248                                 $toplevel = $level;
4249                             }
4250                             push(@sections, $name);
4251                             next_doc() if (defined $T2H_SPLIT
4252                                            and
4253                                            ($T2H_SPLIT eq 'section'
4254                                             ||
4255                                             $T2H_SPLIT && $level == $toplevel));
4256                         }
4257                         $sec_num++;
4258                         $docid = "SEC$sec_num";
4259                         $tocid = (/^\@\w*heading/ ? undef : "TOC$sec_num");
4260                         # check biblio and glossary
4261                         $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
4262                         $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
4263                         # check node
4264                         if ($node)
4265                         {
4266                             warn "$ERROR Duplicate node found: $node\n"
4267                                 if ($node2sec{$node});
4268                         }
4269                         else
4270                         {
4271                             $name .= ' ' while ($node2sec{$name});
4272                             $node = $name;
4273                         }
4274                         $name .= ' ' while ($sec2node{$name});
4275                         $section = $name;
4276                         $node2sec{$node} = $name;
4277                         $sec2node{$name} = $node;
4278                         $sec2seccount{$name} = $sec_num;
4279                         $seccount2sec{$sec_num} = $name;
4280                         $node2href{$node} = "$docu_doc#$docid";
4281                         $node2next{$node} = $node_next;
4282                         $node2prev{$node} = $node_prev;
4283                         $node2up{$node} = $node_up;
4284                         print "# node $node, section $name, level $level\n"
4285                             if $T2H_DEBUG & $DEBUG_TOC;
4286
4287                         $node = '';
4288                         $node_next = '';
4289                         $node_prev = '';
4290                         $node_next = '';
4291                         if ($tocid)
4292                         {
4293                             # update TOC
4294                             while ($level > $curlevel)
4295                             {
4296                                 $curlevel++;
4297                                 push(@toc_lines, "<$toc_indent>\n");
4298                             }
4299                             while ($level < $curlevel)
4300                             {
4301                                 $curlevel--;
4302                                 push(@toc_lines, "</$toc_indent>\n");
4303                             }
4304                             $_ = &t2h_anchor($tocid, "$docu_doc#$docid", $name, 1);
4305                             $_ = &substitute_style($_);
4306                             push(@stoc_lines, "$_<BR>\n") if ($level == 1);
4307                             if ($T2H_NUMBER_SECTIONS)
4308                             {
4309                                 push(@toc_lines, $_ . "<BR>\n")
4310                             }
4311                             else
4312                             {
4313                                 push(@toc_lines, "<LI>" . $_ ."</LI>");
4314                             }
4315                         }
4316                         else
4317                         {
4318                             push(@lines, &html_debug("<A NAME=\"".protect_html($docid)."\"></A>\n",
4319                                                      __LINE__));
4320                         }
4321                         # update DOC
4322                         push(@lines, &html_debug('', __LINE__));
4323                         &html_reset;
4324                         $_ =  "<H$level> $name </H$level>\n<!--docid::${docid}::-->\n";
4325                         $_ = &debug($_, __LINE__);
4326                         push(@lines, &html_debug('', __LINE__));
4327                     }
4328                     # update DOC
4329                     foreach $line (split(/\n+/, $_))
4330                     {
4331                         push(@lines, "$line\n");
4332                     }
4333                     next;
4334                 }
4335                 else
4336                 {
4337                     warn "$ERROR Bad section line: $_";
4338                 }
4339             }
4340             else
4341             {
4342                 # track variables
4343                 $value{$1} = Unprotect_texi($2), next if /^\@set\s+($VARRE)\s+(.*)$/o;
4344                 delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
4345                 # store things
4346                 $value{'_shorttitle'} = Unprotect_texi($1), next if /^\@shorttitle\s+(.*)$/;
4347                 $value{'_setfilename'}   = Unprotect_texi($1), next if /^\@setfilename\s+(.*)$/;
4348                 $value{'_settitle'}      = Unprotect_texi($1), next if /^\@settitle\s+(.*)$/;
4349                 $value{'_author'}   .= Unprotect_texi($1)."\n", next if /^\@author\s+(.*)$/;
4350                 $value{'_subtitle'} .= Unprotect_texi($1)."\n", next if /^\@subtitle\s+(.*)$/;
4351                 $value{'_title'}    .= Unprotect_texi($1)."\n", next if /^\@title\s+(.*)$/;
4352
4353                 # list item
4354                 if (/^\s*\@itemx?\s+/)
4355                 {
4356                     $what = $';
4357                     $what =~ s/\s+$//;
4358                     if ($in_bibliography && $use_bibliography)
4359                     {
4360                         if ($what =~ /^$BIBRE$/o)
4361                         {
4362                             $id = 'BIB' . ++$bib_num;
4363                             $bib2href{$what} = "$docu_doc#$id";
4364                             print "# found bibliography for '$what' id $id\n"
4365                                 if $T2H_DEBUG & $DEBUG_BIB;
4366                             $what = &t2h_anchor($id, '', $what);
4367                         }
4368                     }
4369                     elsif ($in_glossary && $T2H_USE_GLOSSARY)
4370                     {
4371                         $id = 'GLOSS' . ++$gloss_num;
4372                         $entry = $what;
4373                         $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
4374                         $gloss2href{$entry} = "$docu_doc#$id";
4375                         print "# found glossary for '$entry' id $id\n"
4376                             if $T2H_DEBUG & $DEBUG_GLOSS;
4377                         $what = &t2h_anchor($id, '', $what);
4378                     }
4379                     elsif ($in_table && ($table_type eq 'f' || $table_type eq 'v'))
4380                     {
4381                         # APA: Insert <dt> before index anchor, if
4382                         # necessary to produce valid HTML.  Close open
4383                         # paragraph first.
4384                         if ($html_element ne 'DT')
4385                         {
4386                             # APA: End paragraph, if any.
4387                             if ($html_element eq 'P')
4388                             {
4389                                 push(@lines, &debug("</P>\n", __LINE__));
4390                                 &html_pop();
4391                             }
4392                             push(@lines, &debug("<DT>", __LINE__));
4393                             &html_push('DT');
4394                         }
4395                         EnterIndexEntry($table_type, $what, $docu_doc, $section, \@lines);
4396                     }
4397                     # APA: End paragraph, if any.
4398                     if ($html_element eq 'P')
4399                     {
4400                         push(@lines, &debug("</P>\n", __LINE__));
4401                         &html_pop();
4402                     }
4403                     if ($html_element =~ m|^D[DLT]$|)
4404                     {
4405                         unless ($html_element eq 'DT')
4406                         {
4407                             push(@lines, &debug("<DT>", __LINE__));
4408                         }
4409                         if ($things_map{$in_table} && !$what)
4410                         {
4411                             # special case to allow @table @bullet for instance
4412                             push(@lines, &debug("$things_map{$in_table}\n", __LINE__));
4413                         }
4414                         else
4415                         {
4416                             push(@lines, &debug("\@$in_table\{$what\}\n", __LINE__));
4417                         }
4418                         push(@lines, "<DD>");
4419                         &html_push('DD') unless $html_element eq 'DD';
4420                         if ($table_type)
4421                         {       # add also an index
4422                             unshift(@input_spool, "\@${table_type}index $what\n");
4423                         }
4424                     }
4425                     elsif ($html_element eq 'TABLE')
4426                     {
4427                         push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
4428                         &html_push('TR');
4429                     }
4430                     elsif ($html_element eq 'TR')
4431                     {
4432                         push(@lines, &debug("</TR>\n", __LINE__));
4433                         push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
4434                     }
4435                     else
4436                     {
4437                         push(@lines, &debug("<LI>$what\n", __LINE__));
4438                         &html_push('LI') unless $html_element eq 'LI';
4439                     }
4440                     push(@lines, &html_debug('', __LINE__));
4441                     if ($deferred_ref)
4442                     {
4443                         push(@lines, &debug("$deferred_ref\n", __LINE__));
4444                         $deferred_ref = '';
4445                     }
4446                     next;
4447                 }
4448                 elsif (/^\@tab\s+(.*)$/)
4449                 {
4450                     push(@lines, "<TD>$1</TD>\n");
4451                     next;
4452                 }
4453             }
4454         }
4455         # paragraph separator
4456         if ($_ eq "\n" && ! $in_pre)
4457         {
4458             next if $#lines >= 0 && $lines[$#lines] eq "\n";
4459             if ($html_element eq 'P')
4460             {
4461                 push (@lines, &debug("</P>\n<P>\n", __LINE__));
4462             }
4463             #   else
4464             #   {
4465             #     push(@lines, "<P></P>\n");
4466             #     $_ = &debug("<P></P>\n", __LINE__);
4467             #   }
4468             elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE' || $html_element eq 'DD' || $html_element eq 'LI')
4469             {
4470                 &html_push('P');
4471                 push(@lines, &debug("<P>\n", __LINE__));
4472             }
4473         }
4474         # otherwise
4475         push(@lines, $_) unless $in_titlepage;
4476         push(@lines, &debug("</center>\n", __LINE__))  if ($tag eq 'center');
4477     }
4478     # finish TOC
4479     $level = 0;
4480     while ($level < $curlevel)
4481     {
4482         $curlevel--;
4483         push(@toc_lines, "</$toc_indent>\n");
4484     }
4485     print "# end of pass 1\n" if $T2H_VERBOSE;
4486 }
4487
4488 #+++############################################################################
4489 #                                                                              #
4490 # Stuff related to Index generation                                            #
4491 #                                                                              #
4492 #---############################################################################
4493
4494 sub EnterIndexEntry
4495 {
4496     my $prefix = shift;
4497     my $key = shift;
4498     my $docu_doc = shift;
4499     my $section = shift;
4500     my $lines = shift;
4501     local $_;
4502
4503     warn "$ERROR Undefined index command: $_", next
4504         unless (exists ($index_properties->{$prefix}));
4505     $key =~ s/\s+$//;
4506     $_ = $key;
4507     &protect_texi;
4508     $key = $_;
4509     $_ = &protect_html($_);
4510     my $html_key = substitute_style($_);
4511     my $id;
4512     $key = remove_style($key);
4513     $key = remove_things($key);
4514     $_ = $key;
4515     &unprotect_texi;
4516     $key = $_;
4517     while (exists $index->{$prefix}->{$key})
4518     {
4519         $key .= ' ';
4520     }
4521     ;
4522     if ($lines->[$#lines] =~ /^<!--docid::(.+)::-->$/)
4523     {
4524         $id = $1;
4525     }
4526     else
4527     {
4528         $id = 'IDX' . ++$idx_num;
4529         push(@$lines, &t2h_anchor($id, '', $T2H_INVISIBLE_MARK, !$in_pre));
4530     }
4531     $index->{$prefix}->{$key}->{html_key} = $html_key;
4532     $index->{$prefix}->{$key}->{section} = $section;
4533     $index->{$prefix}->{$key}->{href} = "$docu_doc#$id";
4534     print "# found ${prefix}index  for '$key' with id $id\n"
4535         if $T2H_DEBUG & $DEBUG_INDEX;
4536 }
4537
4538 sub IndexName2Prefix
4539 {
4540     my $name = shift;
4541     my $prefix;
4542
4543     for $prefix (keys %$index_properties)
4544     {
4545         return $prefix if ($index_properties->{$prefix}->{name} eq $name);
4546     }
4547     return undef;
4548 }
4549
4550 sub GetIndexEntries
4551 {
4552     my $normal = shift;
4553     my $code = shift;
4554     my ($entries, $prefix, $key) = ({});
4555     for $prefix (keys %$normal)
4556     {
4557         for $key (keys %{$index->{$prefix}})
4558         {
4559             $entries->{$key} = {%{$index->{$prefix}->{$key}}};
4560         }
4561     }
4562
4563     if (defined($code))
4564     {
4565         for $prefix (keys %$code)
4566         {
4567             unless (exists $normal->{$prefix})
4568             {
4569                 for $key (keys %{$index->{$prefix}})
4570                 {
4571                     $entries->{$key} = {%{$index->{$prefix}->{$key}}};
4572                     $entries->{$key}->{html_key} = "<CODE>$entries->{$key}->{html_key}</CODE>";
4573                 }
4574             }
4575         }
4576     }
4577     return $entries;
4578 }
4579
4580 sub byAlpha
4581 {
4582     if ($a =~ /^[A-Za-z]/)
4583     {
4584         if ($b =~ /^[A-Za-z]/)
4585         {
4586             return lc($a) cmp lc($b);
4587         }
4588         else
4589         {
4590             return 1;
4591         }
4592     }
4593     elsif ($b =~ /^[A-Za-z]/)
4594     {
4595         return -1;
4596     }
4597     else
4598     {
4599         return lc($a) cmp lc($b);
4600     }
4601 }
4602
4603 sub GetIndexPages
4604 {
4605     my $entries = shift;
4606     my (@Letters, $key);
4607     my ($EntriesByLetter, $Pages, $page) = ({}, [], {});
4608     my @keys = sort byAlpha keys %$entries;
4609
4610     for $key (@keys)
4611     {
4612         push @{$EntriesByLetter->{uc(substr($key,0, 1))}} , $entries->{$key};
4613     }
4614     @Letters = sort byAlpha keys %$EntriesByLetter;
4615     $T2H_SPLIT_INDEX = 0 unless $T2H_SPLIT;
4616
4617     unless ($T2H_SPLIT_INDEX)
4618     {
4619         $page->{First} = $Letters[0];
4620         $page->{Last} = $Letters[$#Letters];
4621         $page->{Letters} = \@Letters;
4622         $page->{EntriesByLetter} = $EntriesByLetter;
4623         push @$Pages, $page;
4624         return $Pages;
4625     }
4626
4627     if ($T2H_SPLIT_INDEX =~ /^\d+$/)
4628     {
4629         my $i = 0;
4630         my ($prev_letter, $letter);
4631         for $letter (@Letters)
4632         {
4633             if ($i > $T2H_SPLIT_INDEX)
4634             {
4635                 $page->{Last} = $prev_letter;
4636                 push @$Pages, $page;
4637                 $i=0;
4638             }
4639             if ($i == 0)
4640             {
4641                 $page = {};
4642                 $page->{Letters} = [];
4643                 $page->{EntriesByLetter} = {};
4644                 $page->{First} = $letter;
4645             }
4646             push @{$page->{Letters}}, $letter;
4647             $page->{EntriesByLetter}->{$letter} = [@{$EntriesByLetter->{$letter}}];
4648             $i += scalar(@{$EntriesByLetter->{$letter}});
4649             $prev_letter = $letter;
4650         }
4651         $page->{Last} = $Letters[$#Letters];
4652         push @$Pages, $page;
4653     }
4654     return $Pages;
4655 }
4656
4657 sub GetIndexSummary
4658 {
4659     my $first_page = shift;
4660     my $Pages = shift;
4661     my $name = shift;
4662     my ($page, $letter, $summary, $i, $l1, $l2, $l);
4663
4664     $i = 0;
4665     $summary = '<table><tr><th valign=top>Jump to: &nbsp; </th><td>';
4666     for $page ($first_page, @$Pages)
4667     {
4668         for $letter (@{$page->{Letters}})
4669         {
4670             $l = t2h_anchor('', "$page->{href}#${name}_$letter", "<b>$letter</b>",
4671                             0, 'style="text-decoration:none"') . "\n &nbsp; \n";
4672             if ($letter =~ /^[A-Za-z]/)
4673             {
4674                 $l2 .= $l;
4675             }
4676             else
4677             {
4678                 $l1 .= $l;
4679             }
4680         }
4681     }
4682     $summary .= $l1 . "<BR>\n" if ($l1);
4683     $summary .= $l2 . '</td></tr></table>';
4684     return $summary;
4685 }
4686
4687 sub PrintIndexPage
4688 {
4689     my $lines = shift;
4690     my $summary = shift;
4691     my $page = shift;
4692     my $name = shift;
4693
4694     push @$lines, $summary;
4695
4696     push @$lines , <<EOT;
4697 <P></P>
4698 <TABLE border=0>
4699 <TR><TD></TD><TH ALIGN=LEFT>Index Entry</TH><TH ALIGN=LEFT> Section</TH></TR>
4700 <TR><TD COLSPAN=3> <HR></TD></TR>
4701 EOT
4702
4703     for $letter (@{$page->{Letters}})
4704     {
4705         push @$lines, "<TR><TH><A NAME=\"".protect_html("${name}_$letter")."\"></A>".protect_html($letter)."</TH><TD></TD><TD></TD></TR>\n";
4706         for $entry (@{$page->{EntriesByLetter}->{$letter}})
4707         {
4708             push @$lines,
4709                 "<TR><TD></TD><TD valign=top>" .
4710                     t2h_anchor('', $entry->{href}, $entry->{html_key}) .
4711                         "</TD><TD valign=top>" .
4712                             t2h_anchor('', sec_href($entry->{section}), clean_name($entry->{section})) .
4713                                 "</TD></TR>\n";
4714         }
4715         push @$lines, "<TR><TD COLSPAN=3> <HR></TD></TR>\n";
4716     }
4717     push @$lines, "</TABLE><P></P>";
4718     push @$lines, $summary;
4719 }
4720
4721 sub PrintIndex
4722 {
4723     my $lines = shift;
4724     my $name = shift;
4725     my $section = shift;
4726     $section = 'Top' unless $section;
4727     my $prefix = IndexName2Prefix($name);
4728
4729     warn ("$ERROR printindex: bad index name: $name"), return
4730         unless $prefix;
4731
4732     if ($index_properties->{$prefix}->{code})
4733     {
4734         $index_properties->{$prefix}->{from_code}->{$prefix} = 1;
4735     }
4736     else
4737     {
4738         $index_properties->{$prefix}->{from}->{$prefix}= 1;
4739     }
4740
4741     my $Entries = GetIndexEntries($index_properties->{$prefix}->{from},
4742                                   $index_properties->{$prefix}->{from_code});
4743     return unless %$Entries;
4744
4745     if ($T2H_IDX_SUMMARY)
4746     {
4747         my $key;
4748         open(FHIDX, ">$docu_rdir$docu_name" . "_$name.idx")
4749             || die "Can't open > $docu_rdir$docu_name" . "_$name.idx for writing: $!\n";
4750         print "# writing $name index summary in $docu_rdir$docu_name" . "_$name.idx...\n" if $T2H_VERBOSE;
4751
4752         for $key (sort keys %$Entries)
4753         {
4754             print FHIDX "$key\t$Entries->{$key}->{href}\n";
4755         }
4756     }
4757
4758     my $Pages = GetIndexPages($Entries);
4759     my $page;
4760     my $first_page = shift @$Pages;
4761     my $sec_name = $section;
4762
4763     # remove section number
4764     $sec_name =~ s/.*? // if $sec_name =~ /^([A-Z]|\d+)\./;
4765
4766     ($first_page->{href} = sec_href($section)) =~ s/\#.*$//;
4767     $node2prev{$section} = Sec2PrevNode($node2sec{$section});
4768     $prev_node = $section;
4769     # Update tree structure of document
4770     if (@$Pages)
4771     {
4772         my $sec;
4773         my @after;
4774
4775         while (@sections && $sections[$#sections] ne $section)
4776         {
4777             unshift @after, pop @sections;
4778         }
4779
4780         for $page (@$Pages)
4781         {
4782             my $node = ($page->{First} ne $page->{Last} ?
4783                         "$sec_name: $page->{First} -- $page->{Last}" :
4784                         "$sec_name: $page->{First}");
4785             push @sections, $node;
4786             $node2sec{$node} = $node;
4787             $sec2node{$node} = $node;
4788             $node2up{$node} = $section;
4789             $page->{href} = next_doc();
4790             $page->{name} = $node;
4791             $node2href{$node} = $page->{href};
4792             if ($prev_node)
4793             {
4794                 $node2next{$prev_node} = $node;
4795                 $node2prev{$node} = $prev_node;
4796             }
4797             $prev_node = $node;
4798         }
4799         # Full circle - Next on last index page goes to Top
4800         $node2next{$prev_node} = "Top";
4801         push @sections, @after;
4802     }
4803
4804     my $summary = GetIndexSummary($first_page, $Pages, $name);
4805     PrintIndexPage($lines, $summary, $first_page, $name);
4806     for $page (@$Pages)
4807     {
4808         push @$lines, ($T2H_SPLIT eq 'chapter' ? $CHAPTEREND : $SECTIONEND);
4809         push @$lines, "<H2 ALIGN=\"Left\">$page->{name}</H2>\n";
4810         PrintIndexPage($lines, $summary, $page, $name);
4811     }
4812 }
4813
4814
4815 #+++############################################################################
4816 #                                                                              #
4817 # Pass 2/3: handle style, menu, index, cross-reference                         #
4818 #                                                                              #
4819 #---############################################################################
4820 sub pass2
4821 {
4822     my $sec;
4823     my $href;
4824     @lines2 = ();               # whole document (2nd pass)
4825     @lines3 = ();               # whole document (3rd pass)
4826     my $in_menu = 0;            # am I inside a menu
4827     my $in_menu_listing;
4828
4829     while (@lines)
4830     {
4831         $_ = shift(@lines);
4832         #
4833         # special case (protected sections)
4834         #
4835         if (/^$PROTECTTAG/o)
4836         {
4837             push(@lines2, $_);
4838             next;
4839         }
4840         #
4841         # menu
4842         #
4843         if (/^\@menu\b/)
4844         {
4845             $in_menu = 1;
4846             $in_menu_listing = 1;
4847             # APA: <table> implicitly ends paragraph, so let's do it
4848             # explicitly to keep our HTML stack in sync.
4849             if ($html_element eq 'P')
4850             {
4851                 push (@lines2, &debug("</P>\n", __LINE__));
4852                 &html_pop();
4853             }
4854             push(@lines2, &debug("<TABLE BORDER=\"0\" CELLSPACING=\"0\">\n", __LINE__));
4855             next;
4856         }
4857         if (/^\@end\s+menu\b/)
4858         {
4859             if ($in_menu_listing)
4860             {
4861                 push(@lines2, &debug("</TABLE>\n", __LINE__));
4862             }
4863             $in_menu = 0;
4864             $in_menu_listing = 0;
4865             next;
4866         }
4867         if ($in_menu)
4868         {
4869             my ($node, $name, $descr);
4870             if (/^\*\s+($NODERE)::/o)
4871             {
4872                 $node = $1;
4873                 $descr = $';
4874             }
4875             elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/)
4876             {
4877                 $name = $1;
4878                 $node = $2;
4879                 $descr = $';
4880             }
4881             elsif (/^\*/)
4882             {
4883                 warn "$ERROR Bad menu line: $_";
4884             }
4885             else
4886             {
4887                 if ($in_menu_listing)
4888                 {
4889                     # APA: Handle menu comment lines.  These don't end the menu!
4890                     # $in_menu_listing = 0;
4891                     push(@lines2,&debug('<TR><TH COLSPAN="3" ALIGN="left" VALIGN="TOP">' . $_ . '</TH></TR>
4892 ', __LINE__));
4893                 }
4894             }
4895             if ($node)
4896             {
4897                 if (! $in_menu_listing)
4898                 {
4899                     $in_menu_listing = 1;
4900                     push(@lines2, &debug("<TABLE BORDER=0 CELLSPACING=0>\n", __LINE__));
4901                 }
4902                 # look for continuation
4903                 while ($lines[0] =~ /^\s+\w+/)
4904                 {
4905                     $descr .= shift(@lines);
4906                 }
4907                 &menu_entry($node, $name, $descr);
4908             }
4909             next;
4910         }
4911         #
4912         # printindex
4913         #
4914         PrintIndex(\@lines2, $2, $1), next
4915             if (/^<!--::(.*)::-->\@printindex\s+(\w+)/);
4916         #
4917         # simple style substitutions
4918         #
4919         $_ = &substitute_style($_);
4920         #
4921         # xref
4922         #
4923         while (/\@(x|px|info|)ref{([^{}]+)(}?)/)
4924         {
4925             # note: Texinfo may accept other characters
4926             ($type, $nodes, $full) = ($1, $2, $3);
4927             ($before, $after) = ($`, $');
4928             if (! $full && $after)
4929             {
4930                 warn "$ERROR Bad xref (no ending } on line): $_";
4931                 $_ = "$before$;0${type}ref\{$nodes$after";
4932                 next;           # while xref
4933             }
4934             if ($type eq 'x')
4935             {
4936                 $type = "$T2H_WORDS->{$T2H_LANG}->{'See'} ";
4937             }
4938             elsif ($type eq 'px')
4939             {
4940                 $type = "$T2H_WORDS->{$T2H_LANG}->{'see'} ";
4941             }
4942             elsif ($type eq 'info')
4943             {
4944                 $type = "$T2H_WORDS->{$T2H_LANG}->{'See'} Info";
4945             }
4946             else
4947             {
4948                 $type = '';
4949             }
4950             unless ($full)
4951             {
4952                 $next = shift(@lines);
4953                 $next = &substitute_style($next);
4954                 chop($nodes);   # remove final newline
4955                 if ($next =~ /\}/)
4956                 {               # split on 2 lines
4957                     $nodes .= " $`";
4958                     $after = $';
4959                 }
4960                 else
4961                 {
4962                     $nodes .= " $next";
4963                     $next = shift(@lines);
4964                     $next = &substitute_style($next);
4965                     chop($nodes);
4966                     if ($next =~ /\}/)
4967                     {           # split on 3 lines
4968                         $nodes .= " $`";
4969                         $after = $';
4970                     }
4971                     else
4972                     {
4973                         warn "$ERROR Bad xref (no ending }): $_";
4974                         $_ = "$before$;0xref\{$nodes$after";
4975                         unshift(@lines, $next);
4976                         next;   # while xref
4977                     }
4978                 }
4979             }
4980             $nodes =~ s/\s+/ /go; # remove useless spaces
4981             @args = split(/\s*,\s*/, $nodes);
4982             $node = $args[0];   # the node is always the first arg
4983             $node = &normalise_node($node);
4984             $sec = $args[2] || $args[1] || $node2sec{$node};
4985             $href = $node2href{$node};
4986             if (@args == 5)
4987             {                   # reference to another manual
4988                 $sec = $args[2] || $node;
4989                 $man = $args[4] || $args[3];
4990                 $_ = "${before}${type}$T2H_WORDS->{$T2H_LANG}->{'section'} `$sec' in \@cite{$man}$after";
4991             }
4992             elsif ($type =~ /Info/)
4993             {                   # inforef
4994                 warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
4995                 ($nn, $_, $in) = @args;
4996                 $_ = "${before}${type} file `$in', node `$nn'$after";
4997             }
4998             elsif ($sec && $href && ! $T2H_SHORT_REF)
4999             {
5000                 $_  = "${before}${type}";
5001                 $_ .= "$T2H_WORDS->{$T2H_LANG}->{'section'} " if $type;
5002                 $_ .= &t2h_anchor('', $href, $sec) . $after;
5003             }
5004             elsif ($href)
5005             {
5006                 $_ = "${before}${type} " .
5007                     &t2h_anchor('', $href, $args[2] || $args[1] || $node) .
5008                         $after;
5009             }
5010             else
5011             {
5012                 warn "$ERROR Undefined node ($node): $_";
5013                 $_ = "$before$;0xref{$nodes}$after";
5014             }
5015         }
5016
5017         # replace images
5018         s[\@image\s*{(.+?)}]
5019         {
5020          my @args = split (/\s*,\s*/, $1);
5021          my $base = $args[0];
5022          my $image =
5023          LocateIncludeFile("$base.png") ||
5024          LocateIncludeFile("$base.jpg") ||
5025          LocateIncludeFile("$base.gif");
5026          warn "$ERROR no image file for $base: $_" unless ($image && -e $image);
5027          ($T2H_CENTER_IMAGE ?
5028           "<CENTER><IMG SRC=\"$image\" ALT=\"$base\"></CENTER>" :
5029           "<IMG SRC=\"$image\" ALT=\"$base\">");
5030         }eg;
5031
5032         #
5033         # try to guess bibliography references or glossary terms
5034         #
5035         unless (/^<H\d><A NAME=\"SEC\d/)
5036         {
5037             if ($use_bibliography)
5038             {
5039                 $done = '';
5040                 while (/$BIBRE/o)
5041                 {
5042                     ($pre, $what, $post) = ($`, $&, $');
5043                     $href = $bib2href{$what};
5044                     if (defined($href) && $post !~ /^[^<]*<\/A>/)
5045                     {
5046                         $done .= $pre . &t2h_anchor('', $href, $what);
5047                     }
5048                     else
5049                     {
5050                         $done .= "$pre$what";
5051                     }
5052                     $_ = $post;
5053                 }
5054                 $_ = $done . $_;
5055             }
5056             if ($T2H_USE_GLOSSARY)
5057             {
5058                 $done = '';
5059                 while (/\b\w+\b/)
5060                 {
5061                     ($pre, $what, $post) = ($`, $&, $');
5062                     $entry = $what;
5063                     $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
5064                     $href = $gloss2href{$entry};
5065                     if (defined($href) && $post !~ /^[^<]*<\/A>/)
5066                     {
5067                         $done .= $pre . &t2h_anchor('', $href, $what);
5068                     }
5069                     else
5070                     {
5071                         $done .= "$pre$what";
5072                     }
5073                     $_ = $post;
5074                 }
5075                 $_ = $done . $_;
5076             }
5077         }
5078         # otherwise
5079         push(@lines2, $_);
5080     }
5081     print "# end of pass 2\n" if $T2H_VERBOSE;
5082 }
5083
5084 sub pass3
5085 {
5086     #
5087     # split style substitutions
5088     #
5089     my $text;
5090     while (@lines2)
5091     {
5092         $_ = shift(@lines2);
5093         #
5094         # special case (protected sections)
5095         #
5096         if (/^$PROTECTTAG/o)
5097         {
5098             push(@lines3, $_);
5099             next;
5100         }
5101         #
5102         # split style substitutions
5103         #
5104         $old = '';
5105         while ($old ne $_)
5106         {
5107             $old = $_;
5108             if (/\@(\w+)\{/)
5109             {
5110                 ($before, $style, $after) = ($`, $1, $');
5111                 if (defined($style_map{$style}))
5112                 {
5113                     $_ = $after;
5114                     $text = '';
5115                     $after = '';
5116                     $failed = 1;
5117                     while (@lines2)
5118                     {
5119                         if (/\}/)
5120                         {
5121                             $text .= $`;
5122                             $after = $';
5123                             $failed = 0;
5124                             last;
5125                         }
5126                         else
5127                         {
5128                             $text .= $_;
5129                             $_ = shift(@lines2);
5130                         }
5131                     }
5132                     if ($failed)
5133                     {
5134                         die "* Bad syntax (\@$style) after: $before\n";
5135                     }
5136                     else
5137                     {
5138                         $text = &apply_style($style, $text);
5139                         $_ = "$before$text$after";
5140                     }
5141                 }
5142             }
5143         }
5144         # otherwise
5145         push(@lines3, $_);
5146     }
5147     print "# end of pass 3\n" if $T2H_VERBOSE;
5148 }
5149
5150 #+++############################################################################
5151 #                                                                              #
5152 # Pass 4: foot notes, final cleanup                                            #
5153 #                                                                              #
5154 #---############################################################################
5155 sub pass4
5156 {
5157     my $text;
5158     my $name;
5159     @foot_lines = ();           # footnotes
5160     @doc_lines = ();            # final document
5161     $end_of_para = 0;           # true if last line is <P>
5162
5163     # APA: There aint no paragraph before the first one!
5164     # This fixes a HTML validation error.
5165     $lines3[0] =~ s|^</P>\n|\n|;
5166     while (@lines3)
5167     {
5168         $_ = shift(@lines3);
5169         #
5170         # special case (protected sections)
5171         #
5172         if (/^$PROTECTTAG/o)
5173         {
5174             push(@doc_lines, $_);
5175             $end_of_para = 0;
5176             next;
5177         }
5178         #
5179         # footnotes
5180         #
5181         while (/\@footnote([^\{\s]+)\{/)
5182         {
5183             ($before, $d, $after) = ($`, $1, $');
5184             $_ = $after;
5185             $text = '';
5186             $after = '';
5187             $failed = 1;
5188             while (@lines3)
5189             {
5190                 if (/\}/)
5191                 {
5192                     $text .= $`;
5193                     $after = $';
5194                     $failed = 0;
5195                     last;
5196                 }
5197                 else
5198                 {
5199                     $text .= $_;
5200                     $_ = shift(@lines3);
5201                 }
5202             }
5203             if ($failed)
5204             {
5205                 die "* Bad syntax (\@footnote) after: $before\n";
5206             }
5207             else
5208             {
5209                 $foot_num++;
5210                 $docid  = "DOCF$foot_num";
5211                 $footid = "FOOT$foot_num";
5212                 $foot = "($foot_num)";
5213                 push(@foot_lines, "<H3>" . &t2h_anchor($footid, "$d#$docid", $foot) . "</H3>\n");
5214                 $text = "<P>$text" unless $text =~ /^\s*<P>/;
5215                 push(@foot_lines, "$text\n");
5216                 $_ = $before . &t2h_anchor($docid, "$docu_foot#$footid", $foot) . $after;
5217             }
5218         }
5219         #
5220         # remove unnecessary <P>
5221         #
5222         if (/^\s*<P>\s*$/)
5223         {
5224             next if $end_of_para++;
5225         }
5226         else
5227         {
5228             $end_of_para = 0;
5229         }
5230         # otherwise
5231         push(@doc_lines, $_);
5232     }
5233
5234     print "# end of pass 4\n" if $T2H_VERBOSE;
5235 }
5236
5237 #+++############################################################################
5238 #                                                                              #
5239 # Pass 5: print things                                                         #
5240 #                                                                              #
5241 #---############################################################################
5242 sub pass5
5243 {
5244     $T2H_L2H = &l2h_FinishToLatex if ($T2H_L2H);
5245     $T2H_L2H = &l2h_ToHtml        if ($T2H_L2H);
5246     $T2H_L2H = &l2h_InitFromHtml  if ($T2H_L2H);
5247
5248     T2H_InitGlobals();
5249
5250     # fix node2up, node2prev, node2next, if desired
5251     if ($has_top_command)
5252     {
5253         for $section (keys %sec2number)
5254         {
5255             $node2href{$sec2node{$section}} =~ /SEC(\d+)$/;
5256             $node = $sec2node{$section};
5257             $node2up{$node} = Sec2UpNode($section) unless $node2up{$node};
5258             $node2prev{$node} = Sec2PrevNode($section) unless $node2prev{$node};
5259             $node2next{$node} = Sec2NextNode($section) unless $node2next{$node};
5260         }
5261     }
5262
5263     # prepare %T2H_THISDOC
5264     $T2H_THISDOC{fulltitle} = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
5265     $T2H_THISDOC{title} = $value{'_settitle'} || $T2H_THISDOC{fulltitle};
5266     $T2H_THISDOC{author} = $value{'_author'};
5267     $T2H_THISDOC{subtitle} = $value{'_subtitle'};
5268     $T2H_THISDOC{shorttitle} = $value{'_shorttitle'};
5269     for $key (keys %T2H_THISDOC)
5270     {
5271         $_ = &substitute_style($T2H_THISDOC{$key});
5272         &unprotect_texi;
5273         s/\s*$//;
5274         $T2H_THISDOC{$key} = $_;
5275     }
5276
5277     # if no sections, then simply print document as is
5278     unless (@sections)
5279     {
5280         print "# Writing content into $docu_top_file \n" if $T2H_VERBOSE;
5281         open(FILE, "> $docu_top_file")
5282             || die "$ERROR: Can't open $docu_top_file for writing: $!\n";
5283
5284         &$T2H_print_page_head(\*FILE);
5285         $T2H_THIS_SECTION = \@doc_lines;
5286         t2h_print_lines(\*FILE);
5287         &$T2H_print_foot_navigation(\*FILE);
5288         &$T2H_print_page_foot(\*FILE);
5289         close(FILE);
5290         goto Finish;
5291     }
5292
5293     # initialize $T2H_HREF, $T2H_NAME
5294     %T2H_HREF =
5295         (
5296          'First' ,   sec_href($sections[0]),
5297          'Last',     sec_href($sections[$#sections]),
5298          'About',     $docu_about. '#SEC_About',
5299         );
5300
5301     # prepare TOC, OVERVIEW, TOP
5302     $T2H_TOC = \@toc_lines;
5303     $T2H_OVERVIEW = \@stoc_lines;
5304     if ($has_top)
5305     {
5306         while (1)
5307         {
5308             $_ = shift @doc_lines;
5309             last if /$TOPEND/;
5310             push @$T2H_TOP, $_;
5311         }
5312         $T2H_HREF{'Top'} = $docu_top . '#SEC_Top';
5313     }
5314     else
5315     {
5316         $T2H_HREF{'Top'} = $T2H_HREF{First};
5317     }
5318
5319     $node2href{Top} = $T2H_HREF{Top};
5320     $T2H_HREF{Contents} = $docu_toc.'#SEC_Contents' if @toc_lines;
5321     $T2H_HREF{Overview} = $docu_stoc.'#SEC_OVERVIEW' if @stoc_lines;
5322
5323     # settle on index
5324     if ($T2H_INDEX_CHAPTER)
5325     {
5326         $T2H_HREF{Index} = $node2href{normalise_node($T2H_INDEX_CHAPTER)};
5327         warn "$ERROR T2H_INDEX_CHAPTER '$T2H_INDEX_CHAPTER' not found\n"
5328             unless $T2H_HREF{Index};
5329     }
5330     if (! $T2H_HREF{Index} && $first_index_chapter)
5331     {
5332         $T2H_INDEX_CHAPTER = $first_index_chapter;
5333         $T2H_HREF{Index} = $node2href{$T2H_INDEX_CHAPTER};
5334     }
5335
5336     print "# Using '" . clean_name($T2H_INDEX_CHAPTER) . "' as index page\n"
5337         if ($T2H_VERBOSE && $T2H_HREF{Index});
5338
5339     %T2H_NAME =
5340         (
5341          'First',   clean_name($sec2node{$sections[0]}),
5342          'Last',    clean_name($sec2node{$sections[$#sections]}),
5343          'About',    $T2H_WORDS->{$T2H_LANG}->{'About_Title'},
5344          'Contents', $T2H_WORDS->{$T2H_LANG}->{'ToC_Title'},
5345          'Overview', $T2H_WORDS->{$T2H_LANG}->{'Overview_Title'},
5346          'Index' ,   clean_name($T2H_INDEX_CHAPTER),
5347          'Top',      clean_name($T2H_TOP_HEADING || $T2H_THISDOC{'title'} || $T2H_THISDOC{'shorttitle'}),
5348         );
5349
5350     #############################################################################
5351     # print frame and frame toc file
5352     #
5353     if ( $T2H_FRAMES )
5354     {
5355         open(FILE, "> $docu_frame_file")
5356             || die "$ERROR: Can't open $docu_frame_file for writing: $!\n";
5357         print "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
5358         &$T2H_print_frame(\*FILE);
5359         close(FILE);
5360
5361         open(FILE, "> $docu_toc_frame_file")
5362             || die "$ERROR: Can't open $docu_toc_frame_file for writing: $!\n";
5363         print "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
5364         &$T2H_print_toc_frame(\*FILE);
5365         close(FILE);
5366     }
5367
5368
5369     #############################################################################
5370     # Monolithic beginning.
5371     #
5372     unless ($T2H_SPLIT)
5373     {
5374         open(FILE, "> $docu_doc_file")
5375             || die "$ERROR: Can't open $docu_doc_file for writing: $!\n";
5376         &$T2H_print_page_head(\*FILE);
5377     }
5378
5379
5380     #############################################################################
5381     # print Top
5382     #
5383     if ($has_top)
5384     {
5385         if ($T2H_SPLIT)
5386         {
5387             open(FILE, "> $docu_top_file")
5388                 || die "$ERROR: Can't open $docu_top_file for writing: $!\n";
5389         }
5390
5391         print "# Creating Top in $docu_top_file ...\n" if $T2H_VERBOSE;
5392         $T2H_THIS_SECTION = $T2H_TOP;
5393         $T2H_HREF{This} = $T2H_HREF{Top};
5394         $T2H_NAME{This} = $T2H_NAME{Top};
5395         &$T2H_print_Top(\*FILE);
5396
5397         if ($T2H_SPLIT)
5398         {
5399             close(FILE)
5400                 || die "$ERROR: Error occurred when closing $docu_top_file: $!\n";
5401         }
5402     }
5403
5404
5405     #############################################################################
5406     # Print sections
5407     #
5408     $T2H_NODE{Forward} = $sec2node{$sections[0]};
5409     $T2H_NAME{Forward} = &clean_name($sec2node{$sections[0]});
5410     $T2H_HREF{Forward} = sec_href($sections[0]);
5411     $T2H_NODE{This} = 'Top';
5412     $T2H_NAME{This} = $T2H_NAME{Top};
5413     $T2H_HREF{This} = $T2H_HREF{Top};
5414     if ($T2H_SPLIT)
5415     {
5416         print "# writing " . scalar(@sections) .
5417             " sections into $docu_rdir$docu_name"."_[1..$doc_num].$docu_ext"
5418                 if $T2H_VERBOSE;
5419         $previous = ($T2H_SPLIT eq 'chapter' ? $CHAPTEREND : $SECTIONEND);
5420         undef $FH;
5421         $doc_num = 0;
5422     }
5423     else
5424     {
5425         print "# writing " . scalar(@sections) . " sections in $docu_top_file ..."
5426             if $T2H_VERBOSE;
5427         $FH = \*FILE;
5428         $previous = '';
5429     }
5430
5431     $counter = 0;
5432     # loop through sections
5433     while ($section = shift(@sections))
5434     {
5435         if ($T2H_SPLIT && ($T2H_SPLIT eq 'section' || $previous eq $CHAPTEREND))
5436         {
5437             if ($FH)
5438             {
5439                 #close previous page
5440                 &$T2H_print_chapter_footer($FH) if $T2H_SPLIT eq 'chapter';
5441                 &$T2H_print_page_foot($FH);
5442                 close($FH);
5443                 undef $FH;
5444             }
5445         }
5446         $T2H_NAME{Back} = $T2H_NAME{This};
5447         $T2H_HREF{Back} = $T2H_HREF{This};
5448         $T2H_NODE{Back} = $T2H_NODE{This};
5449         $T2H_NAME{This} = $T2H_NAME{Forward};
5450         $T2H_HREF{This} = $T2H_HREF{Forward};
5451         $T2H_NODE{This} = $T2H_NODE{Forward};
5452         if ($sections[0])
5453         {
5454             $T2H_NODE{Forward} = $sec2node{$sections[0]};
5455             $T2H_NAME{Forward} = &clean_name($T2H_NODE{Forward});
5456             $T2H_HREF{Forward} = sec_href($sections[0]);
5457         }
5458         else
5459         {
5460             delete $T2H_HREF{Forward};
5461             delete $T2H_NODE{Forward};
5462             delete $T2H_NAME{Forward};
5463         }
5464
5465         $node = $node2up{$T2H_NODE{This}};
5466         $T2H_HREF{Up} = $node2href{$node};
5467         if ($T2H_HREF{Up} eq $T2H_HREF{This} || ! $T2H_HREF{Up})
5468         {
5469             $T2H_NAME{Up} = $T2H_NAME{Top};
5470             $T2H_HREF{Up} = $T2H_HREF{Top};
5471             $T2H_NODE{Up} = 'Up';
5472         }
5473         else
5474         {
5475             $T2H_NAME{Up} = &clean_name($node);
5476             $T2H_NODE{Up} = $node;
5477         }
5478
5479         $node = $node2prev{$T2H_NODE{This}};
5480         $T2H_NAME{Prev} = &clean_name($node);
5481         $T2H_HREF{Prev} = $node2href{$node};
5482         $T2H_NODE{Prev} = $node;
5483
5484         $node = Node2FastBack($T2H_NODE{This});
5485         $T2H_NAME{FastBack} = &clean_name($node);
5486         $T2H_HREF{FastBack} = $node2href{$node};
5487         $T2H_NODE{FastBack} = $node;
5488
5489         $node = $node2next{$T2H_NODE{This}};
5490         $T2H_NAME{Next} = &clean_name($node);
5491         $T2H_HREF{Next} = $node2href{$node};
5492         $T2H_NODE{Next} = $node;
5493
5494         $node = Node2FastForward($T2H_NODE{This});
5495         $T2H_NAME{FastForward} = &clean_name($node);
5496         $T2H_HREF{FastForward} = $node2href{$node};
5497         $T2H_NODE{FastForward} = $node;
5498
5499         if (! defined($FH))
5500         {
5501             my $file = $T2H_HREF{This};
5502             $file =~ s/\#.*$//;
5503             open(FILE, "> $docu_rdir$file") ||
5504                 die "$ERROR: Can't open $docu_rdir$file for writing: $!\n";
5505             $FH = \*FILE;
5506             &$T2H_print_page_head($FH);
5507             t2h_print_label($FH);
5508             &$T2H_print_chapter_header($FH) if $T2H_SPLIT eq 'chapter';
5509         }
5510         else
5511         {
5512             t2h_print_label($FH);
5513         }
5514
5515         $T2H_THIS_SECTION = [];
5516         while (@doc_lines)
5517         {
5518             $_ = shift(@doc_lines);
5519             last if ($_ eq $SECTIONEND || $_ eq $CHAPTEREND);
5520             push(@$T2H_THIS_SECTION, $_);
5521         }
5522         $previous = $_;
5523         &$T2H_print_section($FH);
5524
5525         if ($T2H_VERBOSE)
5526         {
5527             $counter++;
5528             print "." if $counter =~ /00$/;
5529         }
5530     }
5531     if ($T2H_SPLIT)
5532     {
5533         &$T2H_print_chapter_footer($FH) if $T2H_SPLIT eq 'chapter';
5534         &$T2H_print_page_foot($FH);
5535         close($FH);
5536     }
5537     print "\n" if $T2H_VERBOSE;
5538
5539     #############################################################################
5540     # Print ToC, Overview, Footnotes
5541     #
5542     delete $T2H_HREF{Prev};
5543     delete $T2H_HREF{Next};
5544     delete $T2H_HREF{Back};
5545     delete $T2H_HREF{Forward};
5546     delete $T2H_HREF{Up};
5547
5548     if (@foot_lines)
5549     {
5550         print "# writing Footnotes in $docu_foot_file...\n" if $T2H_VERBOSE;
5551         open (FILE, "> $docu_foot_file") || die "$ERROR: Can't open $docu_foot_file for writing: $!\n"
5552             if $T2H_SPLIT;
5553         $T2H_HREF{This} = $docu_foot;
5554         $T2H_NAME{This} = $T2H_WORDS->{$T2H_LANG}->{'Footnotes_Title'};
5555         $T2H_THIS_SECTION = \@foot_lines;
5556         &$T2H_print_Footnotes(\*FILE);
5557         close(FILE) if $T2H_SPLIT;
5558     }
5559
5560     if (@toc_lines)
5561     {
5562         print "# writing Toc in $docu_toc_file...\n" if $T2H_VERBOSE;
5563         open (FILE, "> $docu_toc_file") || die "$ERROR: Can't open $docu_toc_file for writing: $!\n"
5564             if $T2H_SPLIT;
5565         $T2H_HREF{This} = $T2H_HREF{Contents};
5566         $T2H_NAME{This} = $T2H_NAME{Contents};
5567         $T2H_THIS_SECTION = \@toc_lines;
5568         &$T2H_print_Toc(\*FILE);
5569         close(FILE) if $T2H_SPLIT;
5570     }
5571
5572     if (@stoc_lines)
5573     {
5574         print "# writing Overview in $docu_stoc_file...\n" if $T2H_VERBOSE;
5575         open (FILE, "> $docu_stoc_file") || die "$ERROR: Can't open $docu_stoc_file for writing: $!\n"
5576             if $T2H_SPLIT;
5577         $T2H_HREF{This} = $T2H_HREF{Overview};
5578         $T2H_NAME{This} = $T2H_NAME{Overview};
5579         $T2H_THIS_SECTION = \@stoc_lines;
5580         unshift @$T2H_THIS_SECTION, "<BLOCKQUOTE>\n";
5581         push @$T2H_THIS_SECTION, "\n</BLOCKQUOTE>\n";
5582         &$T2H_print_Overview(\*FILE);
5583         close(FILE) if $T2H_SPLIT;
5584     }
5585
5586     if ($about_body = &$T2H_about_body())
5587     {
5588         print "# writing About in $docu_about_file...\n" if $T2H_VERBOSE;
5589         open (FILE, "> $docu_about_file") || die "$ERROR: Can't open $docu_about_file for writing: $!\n"
5590             if $T2H_SPLIT;
5591
5592         $T2H_HREF{This} = $T2H_HREF{About};
5593         $T2H_NAME{This} = $T2H_NAME{About};
5594         $T2H_THIS_SECTION = [$about_body];
5595         &$T2H_print_About(\*FILE);
5596         close(FILE) if $T2H_SPLIT;
5597     }
5598
5599     unless ($T2H_SPLIT)
5600     {
5601         &$T2H_print_page_foot(\*FILE);
5602         close (FILE);
5603     }
5604
5605  Finish:
5606     &l2h_FinishFromHtml if ($T2H_L2H);
5607     &l2h_Finish if($T2H_L2H);
5608     print "# that's all folks\n" if $T2H_VERBOSE;
5609
5610     exit(0);
5611 }
5612
5613 #+++############################################################################
5614 #                                                                              #
5615 # Low level functions                                                          #
5616 #                                                                              #
5617 #---############################################################################
5618
5619 sub LocateIncludeFile
5620 {
5621     my $file = shift;
5622     my $dir;
5623
5624     # APA: Don't implicitely search ., to conform with the docs!
5625     # return $file if (-e $file && -r $file);
5626     foreach $dir (@T2H_INCLUDE_DIRS)
5627     {
5628         return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file");
5629     }
5630     return undef;
5631 }
5632
5633 sub clean_name
5634 {
5635     local ($_);
5636     $_ = &remove_style($_[0]);
5637     &unprotect_texi;
5638     return $_;
5639 }
5640
5641 sub update_sec_num
5642 {
5643     my($name, $level) = @_;
5644     my $ret;
5645
5646     $level--;                   # here we start at 0
5647     if ($name =~ /^appendix/ || defined(@appendix_sec_num))
5648     {
5649         # appendix style
5650         if (defined(@appendix_sec_num))
5651         {
5652             &incr_sec_num($level, @appendix_sec_num);
5653         }
5654         else
5655         {
5656             @appendix_sec_num = ('A', 0, 0, 0);
5657         }
5658         $ret = join('.', @appendix_sec_num[0..$level]);
5659     }
5660     else
5661     {
5662         # normal style
5663         if (defined(@normal_sec_num))
5664         {
5665             &incr_sec_num($level, @normal_sec_num);
5666         }
5667         else
5668         {
5669             @normal_sec_num = (1, 0, 0, 0);
5670         }
5671         $ret = join('.', @normal_sec_num[0..$level]);
5672     }
5673     $ret .= "." if $level == 0;
5674     return $ret;
5675 }
5676
5677 sub incr_sec_num
5678 {
5679     local($level, $l);
5680     $level = shift(@_);
5681     $_[$level]++;
5682     foreach $l ($level+1 .. 3)
5683     {
5684         $_[$l] = 0;
5685     }
5686 }
5687
5688 sub Sec2UpNode
5689 {
5690     my $sec = shift;
5691     my $num = $sec2number{$sec};
5692
5693     return '' unless $num;
5694     return 'Top' unless $num =~ /\.\d+/;
5695     $num =~ s/\.[^\.]*$//;
5696     $num = $num . '.' unless $num =~ /\./;
5697     return $sec2node{$number2sec{$num}};
5698 }
5699
5700 # Return previous node or "Top"
5701 sub Sec2PrevNode
5702 {
5703     my $sec = shift;
5704     my $sec_num = $sec2seccount{$sec} - 1;
5705     return "Top" if !$sec_num || $sec_num < 1;
5706     return $sec2node{$seccount2sec{$sec_num}};
5707 }
5708
5709 # Return next node or "Top"
5710 sub Sec2NextNode
5711 {
5712     my $sec = shift;
5713     my $sec_num = $sec2seccount{$sec} + 1;
5714     return "Top" unless exists $seccount2sec{$sec_num};
5715     return $sec2node{$seccount2sec{$sec_num}};
5716 }
5717
5718 #
5719 # sub Node2FastBack NODE
5720 #
5721 # INPUTS
5722 #    NODE       A node
5723 #
5724 # RETURNS
5725 #    The beginning of this chapter, or if already there, the beginning of the
5726 #    previous chapter.
5727 #
5728 sub Node2FastBack
5729 {
5730     my $node = shift;
5731     my $num = $sec2number{$node2sec{$node}};
5732     my $n;
5733
5734     # Index Pages  have no section number and 1. should go back to Top
5735     return $node2prev{$node} if !$num or $num eq "1.";
5736
5737     # Get the current chapter
5738     $num =~ /^([A-Z\d]+)\./;
5739     $n = $1;
5740
5741     # If the first section of this chapter, decrement chapter
5742     $n = $n eq 'A' ? $normal_sec_num[0] : $n =~ /^\d+$/ ? --$n : chr(ord($n)-1)
5743         if $n . '.' eq $num;
5744
5745     # Return node name for section number "$n."
5746     return $sec2node{$number2sec{$n . '.'}} || $node2prev{$node};
5747 }
5748
5749 #
5750 # sub Node2FastForward NODE
5751 #
5752 # INPUTS
5753 #    NODE       A node
5754 #
5755 # RETURNS
5756 #    The beginning of the next chapter.
5757 #
5758 sub Node2FastForward
5759 {
5760     my $node = shift;
5761     my $num = $sec2number{$node2sec{$node}};
5762     my $n;
5763
5764     # Index pages
5765     return $node2next{$node} if !$num;
5766
5767     # Get current chapter
5768     $num =~ /^([A-Z\d]+)\./;
5769     $n = $1;
5770
5771     # Increment chapter
5772     $n = $n eq $normal_sec_num[0] ? 'A' : ++$n;
5773
5774     # Return node name
5775     return $sec2node{$number2sec{$n . '.'}} || $node2next{$node};
5776 }
5777
5778 sub check
5779 {
5780     local($_, %seen, %context, $before, $match, $after);
5781
5782     while (<>)
5783     {
5784         if (/\@(\*|\.|\:|\@|\{|\})/)
5785         {
5786             $seen{$&}++;
5787             $context{$&} .= "> $_" if $T2H_VERBOSE;
5788             $_ = "$`XX$'";
5789             redo;
5790         }
5791         if (/\@(\w+)/)
5792         {
5793             ($before, $match, $after) = ($`, $&, $');
5794             if ($before =~ /\b[-\w]+$/ && $after =~ /^[-\w.]*\b/)
5795             {                   # e-mail address
5796                 $seen{'e-mail address'}++;
5797                 $context{'e-mail address'} .= "> $_" if $T2H_VERBOSE;
5798             }
5799             else
5800             {
5801                 $seen{$match}++;
5802                 $context{$match} .= "> $_" if $T2H_VERBOSE;
5803             }
5804             $match =~ s/^\@/X/;
5805             $_ = "$before$match$after";
5806             redo;
5807         }
5808     }
5809
5810     foreach (sort(keys(%seen)))
5811     {
5812         if ($T2H_VERBOSE)
5813         {
5814             print "$_\n";
5815             print $context{$_};
5816         }
5817         else
5818         {
5819             print "$_ ($seen{$_})\n";
5820         }
5821     }
5822 }
5823
5824 sub open
5825 {
5826     my($name) = @_;
5827
5828     ++$fh_name;
5829     no strict "refs";
5830     if (open($fh_name, $name))
5831     {
5832         unshift(@fhs, $fh_name);
5833     }
5834     else
5835     {
5836         warn "$ERROR Can't read file $name: $!\n";
5837     }
5838     use strict "refs";
5839 }
5840
5841 sub init_input
5842 {
5843     @fhs = ();                  # hold the file handles to read
5844     @input_spool = ();          # spooled lines to read
5845     $fh_name = 'FH000';
5846     &open($docu);
5847 }
5848
5849 sub next_line
5850 {
5851     my($fh, $line);
5852
5853     if (@input_spool)
5854     {
5855         $line = shift(@input_spool);
5856         return($line);
5857     }
5858     while (@fhs)
5859     {
5860         $fh = $fhs[0];
5861         $line = <$fh>;
5862         return($line) if $line;
5863         close($fh);
5864         shift(@fhs);
5865     }
5866     return(undef);
5867 }
5868
5869 # used in pass 1, use &next_line
5870 sub skip_until
5871 {
5872     local($tag) = @_;
5873     local($_);
5874
5875     while ($_ = &next_line)
5876     {
5877         return if /^\@end\s+$tag\s*$/;
5878     }
5879     die "* Failed to find '$tag' after: " . $lines[$#lines];
5880 }
5881
5882 # used in pass 1 for l2h use &next_line
5883 sub string_until
5884 {
5885     local($tag) = @_;
5886     local($_, $string);
5887
5888     while ($_ = &next_line)
5889     {
5890         return $string if /^\@end\s+$tag\s*$/;
5891         #       $_ =~ s/hbox/mbox/g;
5892         $string = $string.$_;
5893     }
5894     die "* Failed to find '$tag' after: " . $lines[$#lines];
5895 }
5896
5897 #
5898 # HTML stacking to have a better HTML output
5899 #
5900
5901 sub html_reset
5902 {
5903     @html_stack = ('html');
5904     $html_element = 'body';
5905 }
5906
5907 sub html_push
5908 {
5909     local($what) = @_;
5910     push(@html_stack, $html_element);
5911     $html_element = $what;
5912 }
5913
5914 sub html_push_if
5915 {
5916     local($what) = @_;
5917     push(@html_stack, $html_element)
5918         if ($html_element && $html_element ne 'P');
5919     $html_element = $what;
5920 }
5921
5922 sub html_pop
5923 {
5924     $html_element = pop(@html_stack);
5925 }
5926
5927 sub html_pop_if
5928 {
5929     local($elt);
5930
5931     if (@_)
5932     {
5933         foreach $elt (@_)
5934         {
5935             if ($elt eq $html_element)
5936             {
5937                 $html_element = pop(@html_stack) if @html_stack;
5938                 last;
5939             }
5940         }
5941     }
5942     else
5943     {
5944         $html_element = pop(@html_stack) if @html_stack;
5945     }
5946 }
5947
5948 sub html_debug
5949 {
5950     my($what, $line) = @_;
5951     if ($T2H_DEBUG & $DEBUG_HTML)
5952     {
5953         $what = "\n" unless $what;
5954         return("<!-- $line @html_stack, $html_element -->$what")
5955     }
5956     return($what);
5957 }
5958
5959 # to debug the output...
5960 sub debug
5961 {
5962     my($what, $line) = @_;
5963     return("<!-- $line -->$what")
5964         if $T2H_DEBUG & $DEBUG_HTML;
5965     return($what);
5966 }
5967
5968 sub SimpleTexi2Html
5969 {
5970     local $_ = $_[0];
5971     &protect_texi;
5972     &protect_html;
5973     $_ = substitute_style($_);
5974     $_[0]  = $_;
5975 }
5976
5977 sub normalise_node
5978 {
5979     local $_ = $_[0];
5980     s/\s+/ /go;
5981     s/ $//;
5982     s/^ //;
5983     &protect_texi;
5984     &protect_html;
5985     $_ = substitute_style($_);
5986     $_[0]  = $_;
5987 }
5988
5989 sub menu_entry
5990 {
5991     my ($node, $name, $descr) = @_;
5992     my ($href, $entry);
5993
5994     &normalise_node($node);
5995     $href = $node2href{$node};
5996     if ($href)
5997     {
5998         $descr =~ s/^\s+//;
5999         $descr =~ s/\s*$//;
6000         $descr = SimpleTexi2Html($descr);
6001         if ($T2H_NUMBER_SECTIONS && !$T2H_NODE_NAME_IN_MENU && $node2sec{$node})
6002         {
6003             $entry = $node2sec{$node};
6004             $name = '';
6005         }
6006         else
6007         {
6008             &normalise_node($name);
6009             $entry = ($name && ($name ne $node || ! $T2H_AVOID_MENU_REDUNDANCY)
6010                       ? "$name : $node" : $node);
6011         }
6012
6013         if ($T2H_AVOID_MENU_REDUNDANCY && $descr)
6014         {
6015             my $clean_entry = $entry;
6016             $clean_entry =~ s/^.*? // if ($clean_entry =~ /^([A-Z]|\d+)\.[\d\.]* /);
6017             $clean_entry =~ s/[^\w]//g;
6018             my $clean_descr = $descr;
6019             $clean_descr =~ s/[^\w]//g;
6020             $descr = '' if ($clean_entry eq $clean_descr)
6021         }
6022         push(@lines2,&debug('<TR><TD ALIGN="left" VALIGN="TOP">' .
6023                             &t2h_anchor('', $href, $entry) .
6024                             '</TD><TD>&nbsp;&nbsp;</TD><TD ALIGN="left" VALIGN="TOP">' .
6025                             $descr .
6026                             "</TD></TR>\n", __LINE__));
6027     }
6028     elsif ($node =~ /^\(.*\)\w+/)
6029     {
6030         push(@lines2,&debug('<TR><TD ALIGN="left" VALIGN="TOP">' .
6031                             $entry .
6032                             '</TD><TD ALIGN="left" VALIGN="TOP">' . $descr .
6033                             "</TD></TR>\n", __LINE__))
6034     }
6035     else
6036     {
6037         warn "$ERROR Undefined node of menu_entry ($node): $_";
6038     }
6039 }
6040
6041 sub do_ctrl { "^$_[0]" }
6042
6043 sub do_email
6044 {
6045     my($addr, $text) = split(/,\s*/, $_[0]);
6046
6047     $text = $addr unless $text;
6048     &t2h_anchor('', "mailto:$addr", $text);
6049 }
6050
6051 sub do_sc
6052 {
6053     # l2h does this much better
6054     return &l2h_ToLatex("{\\sc ".&unprotect_html($_[0])."}") if ($T2H_L2H);
6055     return "\U$_[0]\E";
6056 }
6057
6058 sub do_math
6059 {
6060     # APA: FIXME
6061     # This sub doesn't seem to be used.
6062     # What are $_[0] and $text?
6063     my $text;
6064     return &l2h_ToLatex("\$".&unprotect_html($_[0])."\$") if ($T2H_L2H);
6065     return "<EM>".$text."</EM>";
6066 }
6067
6068 sub do_uref
6069 {
6070     my($url, $text, $only_text) = split(/,\s*/, $_[0]);
6071     # APA: Don't markup obviously bad links.
6072     # e.g. texinfo.texi 4.0 has this, which would lead to a broken
6073     # link:
6074     # @section @code{@@uref@{@var{url}[, @var{text}][, @var{replacement}]@}}
6075     return if $url =~ /[<>]/;
6076     $text = $only_text if $only_text;
6077     $text = $url unless $text;
6078     &t2h_anchor('', $url, $text);
6079 }
6080
6081 sub do_url { &t2h_anchor('', $_[0], $_[0]) }
6082
6083 sub do_acronym
6084 {
6085     return '<FONT SIZE="-1">' . $_[0] . '</FONT>';
6086 }
6087
6088 sub do_accent
6089 {
6090     return "&$_[0]acute;" if $_[1] eq 'H';
6091     return "$_[0]." if $_[1] eq 'dotaccent';
6092     return "$_[0]*" if $_[1] eq 'ringaccent';
6093     return "$_[0]".'[' if $_[1] eq 'tieaccent';
6094     return "$_[0]".'(' if $_[1] eq 'u';
6095     return "$_[0]_" if $_[1] eq 'ubaraccent';
6096     return ".$_[0]" if $_[1] eq 'udotaccent';
6097     return "$_[0]&lt;" if $_[1] eq 'v';
6098     return "&$_[0]cedil;" if $_[1] eq ',';
6099     return "$_[0]" if $_[1] eq 'dotless';
6100     return undef;
6101 }
6102
6103 sub apply_style
6104 {
6105     my($texi_style, $text) = @_;
6106     my($style);
6107
6108     $style = $style_map{$texi_style};
6109     if (defined($style))
6110     {                           # known style
6111         my $do_quotes = 0;
6112         if ($style =~ /^\"/)
6113         {                       # add quotes
6114             $style = $';
6115             $do_quotes = 1;
6116         }
6117         if ($style =~ /^\&/)
6118         {                       # custom
6119             $style = $';
6120             no strict "refs";
6121             $text = &$style($text, $texi_style);
6122             use strict "refs";
6123         }
6124         elsif ($style)
6125         {                       # good style
6126             $text = "<$style>$text</$style>";
6127         }
6128         else
6129         {                       # no style
6130         }
6131         $text = "<Q>$text</Q>" if $do_quotes;
6132     }
6133     else
6134     {                           # unknown style
6135         $text = undef;
6136     }
6137     return($text);
6138 }
6139
6140 # remove Texinfo styles
6141 sub remove_style
6142 {
6143     local($_) = @_;
6144     1 while(s/\@\w+{([^\{\}]+)}/$1/g);
6145     return($_);
6146 }
6147
6148 sub remove_things
6149 {
6150     local ($_) = @_;
6151     s|\@(\w+)\{\}|$1|g;
6152     return $_;
6153 }
6154
6155 sub substitute_style
6156 {
6157     local($_) = @_;
6158     my($changed, $done, $style, $text);
6159
6160     &simple_substitutions;
6161     $changed = 1;
6162     while ($changed)
6163     {
6164         $changed = 0;
6165         $done = '';
6166         while (/\@(\w+){([^\{\}]+)}/ || /\@(,){([^\{\}]+)}/)
6167         {
6168             $text = &apply_style($1, $2);
6169             if ($text)
6170             {
6171                 $_ = "$`$text$'";
6172                 $changed = 1;
6173             }
6174             else
6175             {
6176                 $done .= "$`\@$1";
6177                 $_ = "{$2}$'";
6178             }
6179         }
6180         $_ = $done . $_;
6181     }
6182     return($_);
6183 }
6184
6185 sub t2h_anchor
6186 {
6187     my($name, $href, $text, $newline, $extra_attribs) = @_;
6188     my($result);
6189
6190     $result = "<A";
6191     $result .= " NAME=\"".protect_html($name)."\"" if $name;
6192     if ($href)
6193     {
6194         $href =~ s|^$T2H_HREF_DIR_INSTEAD_FILE|./|
6195             if ($T2H_HREF_DIR_INSTEAD_FILE);
6196         $result .= " HREF=\"".protect_html($href)."\"";
6197     }
6198     $result .= " $extra_attribs" if $extra_attribs;
6199     $result .= ">$text</A>";
6200     $result .= "\n" if $newline;
6201     return($result);
6202 }
6203
6204 sub doc_href
6205 {
6206     local($num) = @_;
6207
6208     return("${docu_name}_$num.$docu_ext");
6209 }
6210
6211 sub sec_href
6212 {
6213     return $node2href{$sec2node{$_[0]}};
6214 }
6215
6216 sub next_doc
6217 {
6218     ++$doc_num;
6219     if ("$docu_rdir${docu_name}_$doc_num.$docu_ext" eq "$docu_top_file") {
6220         warn "$WARN Section $docu_rdir${docu_name}_$doc_num.$docu_ext would overwrite Top, continuing at $docu_rdir${docu_name}_".($doc_num+1).".$docu_ext";
6221         $doc_num++;
6222     }
6223     $docu_doc = &doc_href($doc_num);
6224 }
6225
6226 sub t2h_print_lines
6227 {
6228     my ($fh, $lines) = @_;
6229     local($_);
6230     $lines = $T2H_THIS_SECTION unless $lines;
6231     my $cnt = 0;
6232     my @cnt;
6233     for (@$lines)
6234     {
6235         $_ = l2h_FromHtml($_) if ($T2H_L2H);
6236         if (/^$PROTECTTAG/o)
6237         {
6238             $_ = $tag2pro{$_};
6239         }
6240         else
6241         {
6242             &unprotect_texi;
6243         }
6244         print $fh $_;
6245         @cnt = split(/\W*\s+\W*/);
6246         $cnt += scalar(@cnt);
6247     }
6248     return $cnt;
6249 }
6250
6251 sub protect_texi
6252 {
6253     # protect @ { } ` '
6254     s/\@\@/$;0/go;
6255     s/\@\{/$;1/go;
6256     s/\@\}/$;2/go;
6257     s/\@\`/$;3/go;
6258     s/\@\'/$;4/go;
6259 }
6260
6261 sub protect_html
6262 {
6263     local($what) = @_;
6264     # protect &, ", <, and >.
6265     # APA: Keep it simple.  This is what perl's CGI::espaceHTML does.
6266     # We may consider using that instead.
6267     # If raw HTML is used outside @ifhtml or @html it's an error
6268     # anyway.
6269     $what =~ s/\&/\&amp;/go;
6270     $what =~ s/\"/\&quot;/go;
6271     $what =~ s/\</\&lt;/go;
6272     $what =~ s/\>/\&gt;/go;
6273     return($what);
6274 }
6275
6276 sub unprotect_texi
6277 {
6278     s/$;0/\@/go;
6279     s/$;1/\{/go;
6280     s/$;2/\}/go;
6281     s/$;3/\`/go;
6282     s/$;4/\'/go;
6283 }
6284
6285 sub Unprotect_texi
6286 {
6287     local $_ = shift;
6288     &unprotect_texi;
6289     return($_);
6290 }
6291
6292 sub unprotect_html
6293 {
6294     local($what) = @_;
6295     # APA: Use
6296     # Character entity references (eg. &lt;)
6297     # instead of
6298     # Numeric character references (eg. &#60)
6299     $what =~ s/\&amp;/\&/go;
6300     $what =~ s/\&quot;/\"/go;
6301     $what =~ s/\&lt;/\</go;
6302     $what =~ s/\&gt;/\>/go;
6303     return($what);
6304 }
6305
6306 sub t2h_print_label
6307 {
6308     my $fh = shift;
6309     my $href = shift || $T2H_HREF{This};
6310     $href =~ s/.*#(.*)$/$1/;
6311     print $fh qq{<A NAME="$href"></A>\n};
6312 }
6313
6314 sub main
6315 {
6316     SetDocumentLanguage('en') unless ($T2H_LANG);
6317     # APA: There's got to be a better way:
6318     $things_map{'today'} = &pretty_date;
6319     # Identity:
6320     $T2H_TODAY = &pretty_date;  # like "20 September 1993"
6321     # the eval prevents this from breaking on system which do not have
6322     # a proper getpwuid implemented
6323     eval { ($T2H_USER = (getpwuid ($<))[6]) =~ s/,.*//;}; # Who am i
6324     # APA: Provide Windows NT workaround until getpwuid gets
6325     # implemented there.
6326     $T2H_USER = $ENV{'USERNAME'} unless defined $T2H_USER;
6327     &pass1();
6328     &pass2();
6329     &pass3();
6330     &pass4();
6331     &pass5();
6332 }
6333
6334 &main();
6335
6336 ##############################################################################
6337
6338 # These next few lines are legal in both Perl and nroff.
6339
6340 .00 ;                           # finish .ig
6341
6342 'di                     \" finish diversion--previous line must be blank
6343 .nr nl 0-1              \" fake up transition to first page again
6344 .nr % 0                 \" start at page 1
6345 '; __END__ ############# From here on it's a standard manual page ############
6346     .so /usr/share/man/man1/texi2html.1