Add `install' target.
[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.1 2004-09-26 21:06:17 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.1 2004-09-26 21:06:17 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.1 2004-09-26 21:06:17 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 # texinfo "things" (@foo{}) to HTML ones
2214 #
2215 %things_map = (
2216                'TeX', 'TeX',
2217                'br', '<P>',     # paragraph break
2218                'bullet', '*',
2219                #'copyright', '(C)',
2220                'copyright', '&copy;',
2221                'dots', '<small>...<\/small>',
2222                'enddots', '<small>....<\/small>',
2223                'equiv', '==',
2224                'error', 'error-->',
2225                'expansion', '==>',
2226                'minus', '-',
2227                'point', '-!-',
2228                'print', '-|',
2229                'result', '=>',
2230                # APA: &pretty_date requires $MONTH_NAMES and $T2H_LANG
2231                # to be initialized.  The latter gets initialized by
2232                # &SetDocumentLanguage in &main.
2233                # We set following hash entry in &main afterwards.
2234                # 'today', &pretty_date,
2235                'aa', '&aring;',
2236                'AA', '&Aring;',
2237                'ae', '&aelig;',
2238                'oe', '&#156;',
2239                'AE', '&AElig;',
2240                'OE', '&#140;',
2241                'o',  '&oslash;',
2242                'O',  '&Oslash;',
2243                'ss', '&szlig;',
2244                'l', '\/l',
2245                'L', '\/L',
2246                'exclamdown', '&iexcl;',
2247                'questiondown', '&iquest;',
2248                'pounds', '&pound;'
2249               );
2250
2251 #
2252 # texinfo styles (@foo{bar}) to HTML ones
2253 #
2254 %style_map = (
2255               'acronym', '&do_acronym',
2256               'asis', '',
2257               'b', 'B',
2258               'cite', 'CITE',
2259               'code', 'CODE',
2260               'command', 'CODE',
2261               'ctrl', '&do_ctrl', # special case
2262               'dfn', 'EM',      # DFN tag is illegal in the standard
2263               'dmn', '',        # useless
2264               'email', '&do_email', # insert a clickable email address
2265               'emph', 'EM',
2266               'env', 'CODE',
2267               'file', '"TT',    # will put quotes, cf. &apply_style
2268               'i', 'I',
2269               'kbd', 'KBD',
2270               'key', 'KBD',
2271               'math', '&do_math',
2272               'option', '"SAMP', # will put quotes, cf. &apply_style
2273               'r', '',          # unsupported
2274               'samp', '"SAMP',  # will put quotes, cf. &apply_style
2275               'sc', '&do_sc',   # special case
2276               'strong', 'STRONG',
2277               't', 'TT',
2278               'titlefont', '',  # useless
2279               'uref', '&do_uref', # insert a clickable URL
2280               'url', '&do_url', # insert a clickable URL
2281               'var', 'VAR',
2282               'w', '',          # unsupported
2283               'H', '&do_accent',
2284               'dotaccent', '&do_accent',
2285               'ringaccent','&do_accent',
2286               'tieaccent', '&do_accent',
2287               'u','&do_accent',
2288               'ubaraccent','&do_accent',
2289               'udotaccent','&do_accent',
2290               'v', '&do_accent',
2291               ',', '&do_accent',
2292               'dotless', '&do_accent'
2293              );
2294
2295 #
2296 # texinfo format (@foo/@end foo) to HTML ones
2297 #
2298 %format_map = (
2299                'quotation', 'BLOCKQUOTE',
2300                # lists
2301                'itemize', 'UL',
2302                'enumerate', 'OL',
2303                # poorly supported
2304                'flushleft', 'PRE',
2305                'flushright', 'PRE',
2306               );
2307
2308 #
2309 # an eval of these $complex_format_map->{what}->[0] yields beginning
2310 # an eval of these $complex_format_map->{what}->[1] yieleds end
2311 $complex_format_map =
2312 {
2313  example =>
2314  [
2315   q{"<TABLE><tr>$T2H_EXAMPLE_INDENT_CELL<td class=example><pre>"},
2316   q{'</pre></td></tr></table>'}
2317  ],
2318  smallexample =>
2319  [
2320   q{"<TABLE><tr>$T2H_SMALL_EXAMPLE_INDENT_CELL<td class=smallexample><pre><FONT SIZE=$T2H_SMALL_FONT_SIZE>"},
2321   q{'</FONT></pre></td></tr></table>'}
2322  ],
2323  display =>
2324  [
2325   q{"<TABLE><tr>$T2H_EXAMPLE_INDENT_CELL<td class=display><pre " . 'style="font-family: serif">'},
2326   q{'</pre></td></tr></table>'}
2327  ],
2328  smalldisplay =>
2329  [
2330   q{"<TABLE><tr>$T2H_SMALL_EXAMPLE_INDENT_CELL<td class=smalldisplay><pre " . 'style="font-family: serif"><FONT SIZE=$T2H_SMALL_FONT_SIZE>'},
2331   q{'</FONT></pre></td></tr></table>'}
2332  ]
2333 };
2334
2335 $complex_format_map->{lisp} = $complex_format_map->{example};
2336 $complex_format_map->{smalllisp} = $complex_format_map->{smallexample};
2337 $complex_format_map->{format} = $complex_format_map->{display};
2338 $complex_format_map->{smallformat} = $complex_format_map->{smalldisplay};
2339
2340 #
2341 # texinfo definition shortcuts to real ones
2342 #
2343 %def_map = (
2344             # basic commands
2345             'deffn', 0,
2346             'defvr', 0,
2347             'deftypefn', 0,
2348             'deftypeop', 0,
2349             'deftypevr', 0,
2350             'defcv', 0,
2351             'defop', 0,
2352             'deftp', 0,
2353             # basic x commands
2354             'deffnx', 0,
2355             'defvrx', 0,
2356             'deftypefnx', 0,
2357             'deftypeopx', 0,
2358             'deftypevrx', 0,
2359             'defcvx', 0,
2360             'defopx', 0,
2361             'deftpx', 0,
2362             # shortcuts
2363             'defun', 'deffn Function',
2364             'defmac', 'deffn Macro',
2365             'defspec', 'deffn {Special Form}',
2366             'defvar', 'defvr Variable',
2367             'defopt', 'defvr {User Option}',
2368             'deftypefun', 'deftypefn Function',
2369             'deftypevar', 'deftypevr Variable',
2370             'defivar', 'defcv {Instance Variable}',
2371             'deftypeivar', 'defcv {Instance Variable}', # NEW: FIXME
2372             'defmethod', 'defop Method',
2373             'deftypemethod', 'defop Method', # NEW:FIXME
2374             # x shortcuts
2375             'defunx', 'deffnx Function',
2376             'defmacx', 'deffnx Macro',
2377             'defspecx', 'deffnx {Special Form}',
2378             'defvarx', 'defvrx Variable',
2379             'defoptx', 'defvrx {User Option}',
2380             'deftypefunx', 'deftypefnx Function',
2381             'deftypevarx', 'deftypevrx Variable',
2382             'defivarx', 'defcvx {Instance Variable}',
2383             'defmethodx', 'defopx Method',
2384            );
2385
2386 #
2387 # things to skip
2388 #
2389 %to_skip = (
2390             # comments
2391             'c', 1,
2392             'comment', 1,
2393             'ifnotinfo', 1,
2394             'ifnottex', 1,
2395             'ifhtml', 1,
2396             'end ifhtml', 1,
2397             'end ifnotinfo', 1,
2398             'end ifnottex', 1,
2399             # useless
2400             'detailmenu', 1,
2401             'direntry', 1,
2402             'contents', 1,
2403             'shortcontents', 1,
2404             'summarycontents', 1,
2405             'footnotestyle', 1,
2406             'end ifclear', 1,
2407             'end ifset', 1,
2408             'titlepage', 1,
2409             'end titlepage', 1,
2410             # unsupported commands (formatting)
2411             'afourpaper', 1,
2412             'cropmarks', 1,
2413             'finalout', 1,
2414             'headings', 1,
2415             'sp', 1,
2416             'need', 1,
2417             'page', 1,
2418             'setchapternewpage', 1,
2419             'everyheading', 1,
2420             'everyfooting', 1,
2421             'evenheading', 1,
2422             'evenfooting', 1,
2423             'oddheading', 1,
2424             'oddfooting', 1,
2425             'smallbook', 1,
2426             'vskip', 1,
2427             'filbreak', 1,
2428             'paragraphindent', 1,
2429             # unsupported formats
2430             'cartouche', 1,
2431             'end cartouche', 1,
2432             'group', 1,
2433             'end group', 1,
2434            );
2435
2436 #+++############################################################################
2437 #                                                                              #
2438 # Argument parsing, initialisation                                             #
2439 #                                                                              #
2440 #---############################################################################
2441
2442 #
2443 # flush stdout and stderr after every write
2444 #
2445 select(STDERR);
2446 $| = 1;
2447 select(STDOUT);
2448 $| = 1;
2449
2450
2451 %value = ();                    # hold texinfo variables, see also -D
2452 $use_bibliography = 1;
2453 $use_acc = 1;
2454
2455 #
2456 # called on -init-file
2457 sub LoadInitFile
2458 {
2459     my $init_file = shift;
2460     # second argument is value of options
2461     $init_file = shift;
2462     if (-f $init_file)
2463     {
2464         print "# reading initialization file from $init_file\n"
2465             if ($T2H_VERBOSE);
2466         require($init_file);
2467     }
2468     else
2469     {
2470         print "$ERROR Error: can't read init file $int_file\n";
2471         $init_file = '';
2472     }
2473 }
2474
2475 #
2476 # called on -lang
2477 sub SetDocumentLanguage
2478 {
2479     my $lang = shift;
2480     if (! exists($T2H_WORDS->{$lang}))
2481     {
2482         warn "$ERROR: Language specs for '$lang' do not exists. Reverting to '" .
2483             ($T2H_LANG ? $T2H_LANG : "en") . "'\n";
2484     }
2485     else
2486     {
2487         print "# using '$lang' as document language\n" if ($T2H_VERBOSE);
2488         $T2H_LANG = $lang;
2489     }
2490 }
2491
2492 ##
2493 ## obsolete cmd line options
2494 ##
2495 $T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} =
2496 {
2497  type => '!',
2498  linkage => sub {$T2H_SECTION_NAVIGATION = 0;},
2499  verbose => 'obsolete, use -nosec_nav',
2500  noHelp => 2,
2501 };
2502 $T2H_OBSOLETE_OPTIONS -> {use_acc} =
2503 {
2504  type => '!',
2505  linkage => \$use_acc,
2506  verbose => 'obsolete',
2507  noHelp => 2
2508 };
2509 $T2H_OBSOLETE_OPTIONS -> {expandinfo} =
2510 {
2511  type => '!',
2512  linkage => sub {$T2H_EXPAND = 'info';},
2513  verbose => 'obsolete, use "-expand info" instead',
2514  noHelp => 2,
2515 };
2516 $T2H_OBSOLETE_OPTIONS -> {expandtex} =
2517 {
2518  type => '!',
2519  linkage => sub {$T2H_EXPAND = 'tex';},
2520  verbose => 'obsolete, use "-expand tex" instead',
2521  noHelp => 2,
2522 };
2523 $T2H_OBSOLETE_OPTIONS -> {monolithic} =
2524 {
2525  type => '!',
2526  linkage => sub {$T2H_SPLIT = '';},
2527  verbose => 'obsolete, use "-split no" instead',
2528  noHelp => 2
2529 };
2530 $T2H_OBSOLETE_OPTIONS -> {split_node} =
2531 {
2532  type => '!',
2533  linkage => sub{$T2H_SPLIT = 'section';},
2534  verbose => 'obsolete, use "-split section" instead',
2535  noHelp => 2,
2536 };
2537 $T2H_OBSOLETE_OPTIONS -> {split_chapter} =
2538 {
2539  type => '!',
2540  linkage => sub{$T2H_SPLIT = 'chapter';},
2541  verbose => 'obsolete, use "-split chapter" instead',
2542  noHelp => 2,
2543 };
2544 $T2H_OBSOLETE_OPTIONS -> {no_verbose} =
2545 {
2546  type => '!',
2547  linkage => sub {$T2H_VERBOSE = 0;},
2548  verbose => 'obsolete, use -noverbose instead',
2549  noHelp => 2,
2550 };
2551 $T2H_OBSOLETE_OPTIONS -> {output_file} =
2552 {
2553  type => '=s',
2554  linkage => sub {$T2H_OUT = $_[1]; $T2H_SPLIT = '';},
2555  verbose => 'obsolete, use -out_file instead',
2556  noHelp => 2
2557 };
2558
2559 $T2H_OBSOLETE_OPTIONS -> {section_navigation} =
2560 {
2561  type => '!',
2562  linkage => \$T2H_SECTION_NAVIGATION,
2563  verbose => 'obsolete, use -sec_nav instead',
2564  noHelp => 2,
2565 };
2566
2567 $T2H_OBSOLETE_OPTIONS -> {verbose} =
2568 {
2569  type => '!',
2570  linkage => \$T2H_VERBOSE,
2571  verbose => 'obsolete, use -Verbose instead',
2572  noHelp => 2
2573 };
2574
2575 # read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc
2576 my $home = $ENV{HOME};
2577 defined($home) or $home = '';
2578 foreach $i ('/etc/texi2htmlrc', "$home/.texi2htmlrc")
2579 {
2580     if (-f $i)
2581     {
2582         print "# reading initialization file from $i\n"
2583             if ($T2H_VERBOSE);
2584         require($i);
2585     }
2586 }
2587
2588
2589 #+++############################################################################
2590 #                                                                              #
2591 # parse command-line options
2592 #                                                                              #
2593 #---############################################################################
2594 $T2H_USAGE_TEXT = <<EOT;
2595 Usage: texi2html  [OPTIONS] TEXINFO-FILE
2596 Translates Texinfo source documentation to HTML.
2597 EOT
2598 $T2H_FAILURE_TEXT = <<EOT;
2599 Try 'texi2html -help' for usage instructions.
2600 EOT
2601 $options = new Getopt::MySimple;
2602
2603 # some older version of GetOpt::Long don't have
2604 # Getopt::Long::Configure("pass_through")
2605 eval {Getopt::Long::Configure("pass_through");};
2606 $Configure_failed = $@ && <<EOT;
2607 **WARNING: Parsing of obsolete command-line options could have failed.
2608            Consider to use only documented command-line options (run
2609            'texi2html -help 2' for a complete list) or upgrade to perl
2610            version 5.005 or higher.
2611 EOT
2612
2613 if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
2614 {
2615     print $Configure_failed if $Configure_failed;
2616     die $T2H_FAILURE_TEXT;
2617 }
2618
2619 if (@ARGV > 1)
2620 {
2621     eval {Getopt::Long::Configure("no_pass_through");};
2622     if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
2623     {
2624         print $Configure_failed if $Configure_failed;
2625         die $T2H_FAILURE_TEXT;
2626     }
2627 }
2628
2629 if ($T2H_CHECK)
2630 {
2631     die "Need file to check\n$T2H_FAILURE_TEXT" unless @ARGV > 0;
2632     &check;
2633     exit;
2634 }
2635
2636 #+++############################################################################
2637 #                                                                              #
2638 # evaluation of cmd line options
2639 #                                                                              #
2640 #---############################################################################
2641
2642 if ($T2H_EXPAND eq 'info')
2643 {
2644     $to_skip{'ifinfo'} = 1;
2645     $to_skip{'end ifinfo'} = 1;
2646 }
2647 elsif ($T2H_EXPAND eq 'tex')
2648 {
2649     $to_skip{'iftex'} = 1;
2650     $to_skip{'end iftex'} = 1;
2651
2652 }
2653
2654 $T2H_INVISIBLE_MARK = '<IMG SRC="invisible.xbm">' if $T2H_INVISIBLE_MARK eq 'xbm';
2655
2656 #
2657 # file name buisness
2658 #
2659 die "Need exactly one file to translate\n$T2H_FAILURE_TEXT" unless @ARGV == 1;
2660 $docu = shift(@ARGV);
2661 if ($docu =~ /.*\//)
2662 {
2663     chop($docu_dir = $&);
2664     $docu_name = $';
2665 }
2666 else
2667 {
2668     $docu_dir = '.';
2669     $docu_name = $docu;
2670 }
2671 unshift(@T2H_INCLUDE_DIRS, $docu_dir);
2672 $docu_name =~ s/\.te?x(i|info)?$//; # basename of the document
2673 $docu_name = $T2H_PREFIX if ($T2H_PREFIX);
2674
2675 # subdir
2676 if ($T2H_SUBDIR && ! $T2H_OUT)
2677 {
2678     $T2H_SUBDIR =~ s|/*$||;
2679     unless (-d "$T2H_SUBDIR" && -w "$T2H_SUBDIR")
2680     {
2681         if ( mkdir($T2H_SUBDIR, oct(755)))
2682         {
2683             print "# created directory $T2H_SUBDIR\n" if ($T2H_VERBOSE);
2684         }
2685         else
2686         {
2687             warn "$ERROR can't create directory $T2H_SUBDIR. Put results into current directory\n";
2688             $T2H_SUBDIR = '';
2689         }
2690     }
2691 }
2692
2693 if ($T2H_SUBDIR && ! $T2H_OUT)
2694 {
2695     $docu_rdir = "$T2H_SUBDIR/";
2696     print "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
2697 }
2698 else
2699 {
2700     if ($T2H_OUT && $T2H_OUT =~ m|(.*)/|)
2701     {
2702         $docu_rdir = "$1/";
2703         print "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
2704     }
2705     else
2706     {
2707         print "# putting result files into current directory \n" if ($T2H_VERBOSE);
2708         $docu_rdir = '';
2709     }
2710 }
2711
2712 # extension
2713 if ($T2H_SHORTEXTN)
2714 {
2715     $docu_ext = "htm";
2716 }
2717 else
2718 {
2719     $docu_ext = "html";
2720 }
2721 if ($T2H_TOP_FILE =~ /\..*$/)
2722 {
2723     $T2H_TOP_FILE = $`.".$docu_ext";
2724 }
2725
2726 # result files
2727 if (! $T2H_OUT && ($T2H_SPLIT =~ /section/i || $T2H_SPLIT =~ /node/i))
2728 {
2729     $T2H_SPLIT = 'section';
2730 }
2731 elsif (! $T2H_OUT && $T2H_SPLIT =~ /chapter/i)
2732 {
2733     $T2H_SPLIT = 'chapter'
2734 }
2735 else
2736 {
2737     undef $T2H_SPLIT;
2738 }
2739
2740 $docu_doc = "$docu_name.$docu_ext"; # document's contents
2741 $docu_doc_file = "$docu_rdir$docu_doc";
2742 if ($T2H_SPLIT)
2743 {
2744     $docu_toc  = $T2H_TOC_FILE || "${docu_name}_toc.$docu_ext"; # document's table of contents
2745     $docu_stoc = "${docu_name}_ovr.$docu_ext"; # document's short toc
2746     $docu_foot = "${docu_name}_fot.$docu_ext"; # document's footnotes
2747     $docu_about = "${docu_name}_abt.$docu_ext"; # about this document
2748     $docu_top  = $T2H_TOP_FILE || $docu_doc;
2749 }
2750 else
2751 {
2752     if ($T2H_OUT)
2753     {
2754         $docu_doc = $T2H_OUT;
2755         $docu_doc =~ s|.*/||;
2756     }
2757     $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_top = $docu_doc;
2758 }
2759
2760 $docu_toc_file  = "$docu_rdir$docu_toc";
2761 $docu_stoc_file = "$docu_rdir$docu_stoc";
2762 $docu_foot_file = "$docu_rdir$docu_foot";
2763 $docu_about_file = "$docu_rdir$docu_about";
2764 $docu_top_file  = "$docu_rdir$docu_top";
2765
2766 $docu_frame_file =     "$docu_rdir${docu_name}_frame.$docu_ext";
2767 $docu_toc_frame_file = "$docu_rdir${docu_name}_toc_frame.$docu_ext";
2768
2769 #
2770 # variables
2771 #
2772 $value{'html'} = 1;             # predefine html (the output format)
2773 $value{'texi2html'} = $THISVERSION; # predefine texi2html (the translator)
2774 # _foo: internal to track @foo
2775 foreach ('_author', '_title', '_subtitle',
2776          '_settitle', '_setfilename', '_shorttitle')
2777 {
2778     $value{$_} = '';            # prevent -w warnings
2779 }
2780 %node2sec = ();                 # node to section name
2781 %sec2node = ();                 # section to node name
2782 %sec2seccount = ();             # section to section count
2783 %seccount2sec = ();             # section count to section
2784 %sec2number = ();               # section to number
2785                                 # $number =~ ^[\dA-Z]+\.(\d+(\.\d+)*)?$
2786 %number2sec = ();               # number to section
2787 %idx2node = ();                 # index keys to node
2788 %node2href = ();                # node to HREF
2789 %node2next = ();                # node to next
2790 %node2prev = ();                # node to prev
2791 %node2up   = ();                # node to up
2792 %bib2href = ();                 # bibliography reference to HREF
2793 %gloss2href = ();               # glossary term to HREF
2794 @sections = ();                 # list of sections
2795 %tag2pro = ();                  # protected sections
2796
2797 #
2798 # initial indexes
2799 #
2800 $bib_num = 0;
2801 $foot_num = 0;
2802 $gloss_num = 0;
2803 $idx_num = 0;
2804 $sec_num = 0;
2805 $doc_num = 0;
2806 $html_num = 0;
2807
2808 #
2809 # can I use ISO8859 characters? (HTML+)
2810 #
2811 if ($T2H_USE_ISO)
2812 {
2813     $things_map{'bullet'} = "&bull;";
2814     $things_map{'copyright'} = "&copy;";
2815     $things_map{'dots'} = "&hellip;";
2816     $things_map{'equiv'} = "&equiv;";
2817     $things_map{'expansion'} = "&rarr;";
2818     $things_map{'point'} = "&lowast;";
2819     $things_map{'result'} = "&rArr;";
2820 }
2821
2822 #
2823 # read texi2html extensions (if any)
2824 #
2825 $extensions = 'texi2html.ext';  # extensions in working directory
2826 if (-f $extensions)
2827 {
2828     print "# reading extensions from $extensions\n" if $T2H_VERBOSE;
2829     require($extensions);
2830 }
2831 ($progdir = $0) =~ s/[^\/]+$//;
2832 if ($progdir && ($progdir ne './'))
2833 {
2834     $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
2835     if (-f $extensions)
2836     {
2837         print "# reading extensions from $extensions\n" if $T2H_VERBOSE;
2838         require($extensions);
2839     }
2840 }
2841
2842
2843 print "# reading from $docu\n" if $T2H_VERBOSE;
2844
2845 #########################################################################
2846 #
2847 # latex2html stuff
2848 #
2849 # latex2html conversions consist of three stages:
2850 # 1) ToLatex: Put "latex" code into a latex file
2851 # 2) ToHtml: Use latex2html to generate corresponding html code and images
2852 # 3) FromHtml: Extract generated code and images from latex2html run
2853 #
2854
2855 ##########################
2856 # default settings
2857 #
2858
2859 # defaults for files and names
2860
2861 sub l2h_Init
2862 {
2863     local($root) = @_;
2864     return 0 unless ($root);
2865     $l2h_name =  "${root}_l2h";
2866     $l2h_latex_file = "$docu_rdir${l2h_name}.tex";
2867     $l2h_cache_file = "${docu_rdir}l2h_cache.pm";
2868     $T2H_L2H_L2H = "latex2html" unless ($T2H_L2H_L2H);
2869     # destination dir -- generated images are put there, should be the same
2870     # as dir of enclosing html document --
2871     $l2h_html_file = "$docu_rdir${l2h_name}.html";
2872     $l2h_prefix = "${l2h_name}_";
2873     return 1;
2874 }
2875
2876
2877 ##########################
2878 #
2879 # First stage: Generation of Latex file
2880 # Initialize with: l2h_InitToLatex
2881 # Add content with: l2h_ToLatex($text) --> HTML placeholder comment
2882 # Finish with: l2h_FinishToLatex
2883 #
2884
2885 $l2h_latex_preample = <<EOT;
2886 % This document was automatically generated by the l2h extenstion of texi2html
2887 % DO NOT EDIT !!!
2888 \\documentclass{article}
2889 \\usepackage{html}
2890 \\begin{document}
2891 EOT
2892
2893 $l2h_latex_closing = <<EOT;
2894 \\end{document}
2895 EOT
2896
2897 # return used latex 1, if l2h could be initalized properly, 0 otherwise
2898 sub l2h_InitToLatex
2899 {
2900     %l2h_to_latex = ();
2901     unless ($T2H_L2H_SKIP)
2902     {
2903         unless (open(L2H_LATEX, ">$l2h_latex_file"))
2904         {
2905             warn "$ERROR Error l2h: Can't open latex file '$latex_file' for writing\n";
2906             return 0;
2907         }
2908         print "# l2h: use ${l2h_latex_file} as latex file\n" if ($T2H_VERBOSE);
2909         print L2H_LATEX $l2h_latex_preample;
2910     }
2911     # open database for caching
2912     l2h_InitCache();
2913     $l2h_latex_count = 0;
2914     $l2h_to_latex_count = 0;
2915     $l2h_cached_count = 0;
2916     return  1;
2917 }
2918
2919 # print text (1st arg) into latex file (if not already there), return
2920 # HTML commentary which can be later on replaced by the latex2html
2921 # generated text
2922 sub l2h_ToLatex
2923 {
2924     my($text) = @_;
2925     my($count);
2926     $l2h_to_latex_count++;
2927     $text =~ s/(\s*)$//;
2928     # try whether we can cache it
2929     my $cached_text = l2h_FromCache($text);
2930     if ($cached_text)
2931     {
2932         $l2h_cached_count++;
2933         return $cached_text;
2934     }
2935     # try whether we have text already on things to do
2936     unless ($count = $l2h_to_latex{$text})
2937     {
2938         $count = $l2h_latex_count;
2939         $l2h_latex_count++;
2940         $l2h_to_latex{$text} = $count;
2941         $l2h_to_latex[$count] = $text;
2942         unless ($T2H_L2H_SKIP)
2943         {
2944             print L2H_LATEX "\\begin{rawhtml}\n";
2945             print L2H_LATEX "<!-- l2h_begin ${l2h_name} ${count} -->\n";
2946             print L2H_LATEX "\\end{rawhtml}\n";
2947
2948             print L2H_LATEX "$text\n";
2949
2950             print L2H_LATEX "\\begin{rawhtml}\n";
2951             print L2H_LATEX "<!-- l2h_end ${l2h_name} ${count} -->\n";
2952             print L2H_LATEX "\\end{rawhtml}\n";
2953         }
2954     }
2955     return "<!-- l2h_replace ${l2h_name} ${count} -->";
2956 }
2957
2958 # print closing into latex file and close it
2959 sub l2h_FinishToLatex
2960 {
2961     local ($reused);
2962     $reused = $l2h_to_latex_count - $l2h_latex_count - $l2h_cached_count;
2963     unless ($T2H_L2H_SKIP)
2964     {
2965         print L2H_LATEX $l2h_latex_closing;
2966         close(L2H_LATEX);
2967     }
2968     print "# l2h: finished to latex ($l2h_cached_count cached, $reused reused, $l2h_latex_count contents)\n" if ($T2H_VERBOSE);
2969     unless ($l2h_latex_count)
2970     {
2971         l2h_Finish();
2972         return 0;
2973     }
2974     return 1;
2975 }
2976
2977 ###################################
2978 # Second stage: Use latex2html to generate corresponding html code and images
2979 #
2980 # l2h_ToHtml([$l2h_latex_file, [$l2h_html_dir]]):
2981 #   Call latex2html on $l2h_latex_file
2982 #   Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir
2983 #   Return 1, on success
2984 #          0, otherwise
2985 #
2986 sub l2h_ToHtml
2987 {
2988     local($call, $ext, $root, $dotbug);
2989     if ($T2H_L2H_SKIP)
2990     {
2991         print "# l2h: skipping latex2html run\n" if ($T2H_VERBOSE);
2992         return 1;
2993     }
2994     # Check for dot in directory where dvips will work
2995     if ($T2H_L2H_TMP)
2996     {
2997         if ($T2H_L2H_TMP =~ /\./)
2998         {
2999             warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n";
3000             $dotbug = 1;
3001         }
3002     }
3003     else
3004     {
3005         if (&getcwd =~ /\./)
3006         {
3007             warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n";
3008             $dotbug = 1;
3009         }
3010     }
3011     # fix it, if necessary and hope that it works
3012     $T2H_L2H_TMP = "/tmp" if ($dotbug);
3013
3014     $call = $T2H_L2H_L2H;
3015     # use init file, if specified
3016     $call = $call . " -init_file " . $init_file if ($init_file && -f $init_file);
3017     # set output dir
3018     $call .=  ($docu_rdir ? " -dir $docu_rdir" : " -no_subdir");
3019     # use l2h_tmp, if specified
3020     $call = $call . " -tmp $T2H_L2H_TMP" if ($T2H_L2H_TMP);
3021     # options we want to be sure of
3022     $call = $call ." -address 0 -info 0 -split 0 -no_navigation -no_auto_link";
3023     $call = $call ." -prefix ${l2h_prefix} $l2h_latex_file";
3024
3025     print "# l2h: executing '$call'\n" if ($T2H_VERBOSE);
3026     if (system($call))
3027     {
3028         warn "l2h ***Error: '${call}' did not succeed\n";
3029         return 0;
3030     }
3031     else
3032     {
3033         print "# l2h: latex2html finished successfully\n" if ($T2H_VERBOSE);
3034         return 1;
3035     }
3036 }
3037
3038 # this is directly pasted over from latex2html
3039 sub getcwd
3040 {
3041     local($_) = `pwd`;
3042
3043     die "'pwd' failed (out of memory?)\n"
3044         unless length;
3045     chop;
3046     $_;
3047 }
3048
3049
3050 ##########################
3051 # Third stage: Extract generated contents from latex2html run
3052 # Initialize with: l2h_InitFromHtml
3053 #   open $l2h_html_file for reading
3054 #   reads in contents into array indexed by numbers
3055 #   return 1,  on success -- 0, otherwise
3056 # Extract Html code with: l2h_FromHtml($text)
3057 #   replaces in $text all previosuly inserted comments by generated html code
3058 #   returns (possibly changed) $text
3059 # Finish with: l2h_FinishFromHtml
3060 #   closes $l2h_html_dir/$l2h_name.".$docu_ext"
3061
3062 sub l2h_InitFromHtml
3063 {
3064     local($h_line, $h_content, $count, %l2h_img);
3065
3066     if (! open(L2H_HTML, "<${l2h_html_file}"))
3067     {
3068         print "$ERROR Error l2h: Can't open ${l2h_html_file} for reading\n";
3069         return 0;
3070     }
3071     print "# l2h: use ${l2h_html_file} as html file\n" if ($T2H_VERBOSE);
3072
3073     $l2h_html_count = 0;
3074     while ($h_line = <L2H_HTML>)
3075     {
3076         if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/)
3077         {
3078             $count = $1;
3079             $h_content = "";
3080             while ($h_line = <L2H_HTML>)
3081             {
3082                 if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/)
3083                 {
3084                     chomp $h_content;
3085                     chomp $h_content;
3086                     $l2h_html_count++;
3087                     $h_content = l2h_ToCache($count, $h_content);
3088                     $l2h_from_html[$count] = $h_content;
3089                     $h_content = '';
3090                     last;
3091                 }
3092                 $h_content = $h_content.$h_line;
3093             }
3094             if ($hcontent)
3095             {
3096                 print "$ERROR Warning l2h: l2h_end $l2h_name $count not found\n"
3097                     if ($T2H_VERBOSE);
3098                 close(L2H_HTML);
3099                 return 0;
3100             }
3101         }
3102     }
3103     print "# l2h: Got $l2h_html_count of $l2h_latex_count html contents\n"
3104         if ($T2H_VERBOSE);
3105
3106     close(L2H_HTML);
3107     return 1;
3108 }
3109
3110 sub l2h_FromHtml
3111 {
3112     my($text) = @_;
3113     my($done, $to_do, $count);
3114     $to_do = $text;
3115     while ($to_do =~ /([^\000]*)<!-- l2h_replace $l2h_name ([0-9]+) -->([^\000]*)/)
3116     {
3117         $to_do = $1;
3118         $count = $2;
3119         $done = $3.$done;
3120         $done = "<!-- l2h_end $l2h_name $count -->".$done
3121             if ($T2H_DEBUG & $DEBUG_L2H);
3122
3123         $done = &l2h_ExtractFromHtml($count) . $done;
3124
3125         $done = "<!-- l2h_begin $l2h_name $count -->".$done
3126             if ($T2H_DEBUG & $DEBUG_L2H);
3127     }
3128     return $to_do.$done;
3129 }
3130
3131
3132 sub l2h_ExtractFromHtml
3133 {
3134     local($count) = @_;
3135     return $l2h_from_html[$count] if ($l2h_from_html[$count]);
3136     if ($count >= 0 && $count < $l2h_latex_count)
3137     {
3138         # now we are in trouble
3139         local($l_l2h, $_);
3140
3141         $l2h_extract_error++;
3142         print "$ERROR l2h: can't extract content $count from html\n"
3143             if ($T2H_VERBOSE);
3144         # try simple (ordinary) substition (without l2h)
3145         $l_l2h = $T2H_L2H;
3146         $T2H_L2H = 0;
3147         $_ = $l2h_to_latex{$count};
3148         $_ = &substitute_style($_);
3149         &unprotect_texi;
3150         $_ = "<!-- l2h: ". __LINE__ . " use texi2html -->" . $_
3151             if ($T2H_DEBUG & $DEBUG_L2H);
3152         $T2H_L2H = $l_l2h;
3153         return $_;
3154     }
3155     else
3156     {
3157         # now we have been incorrectly called
3158         $l2h_range_error++;
3159         print "$ERROR l2h: Request of $count content which is out of valide range [0,$l2h_latex_count)\n";
3160         return "<!-- l2h: ". __LINE__ . " out of range count $count -->"
3161             if ($T2H_DEBUG & $DEBUG_L2H);
3162         return "<!-- l2h: out of range count $count -->";
3163     }
3164 }
3165
3166 sub l2h_FinishFromHtml
3167 {
3168     if ($T2H_VERBOSE)
3169     {
3170         if ($l2h_extract_error + $l2h_range_error)
3171         {
3172             print "# l2h: finished from html ($l2h_extract_error extract and $l2h_range_error errors)\n";
3173         }
3174         else
3175         {
3176             print "# l2h: finished from html (no errors)\n";
3177         }
3178     }
3179 }
3180
3181 sub l2h_Finish
3182 {
3183     l2h_StoreCache();
3184     if ($T2H_L2H_CLEAN)
3185     {
3186         print "# l2h: removing temporary files generated by l2h extension\n"
3187             if $T2H_VERBOSE;
3188         while (<"$docu_rdir$l2h_name"*>)
3189         {
3190             unlink $_;
3191         }
3192     }
3193     print "# l2h: Finished\n" if $T2H_VERBOSE;
3194     return 1;
3195 }
3196
3197 ##############################
3198 # stuff for l2h caching
3199 #
3200
3201 # I tried doing this with a dbm data base, but it did not store all
3202 # keys/values. Hence, I did as latex2html does it
3203 sub l2h_InitCache
3204 {
3205     if (-r "$l2h_cache_file")
3206     {
3207         my $rdo = do "$l2h_cache_file";
3208         warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n")
3209             unless ($rdo);
3210     }
3211 }
3212
3213 sub l2h_StoreCache
3214 {
3215     return unless $l2h_latex_count;
3216     my ($key, $value);
3217     open(FH, ">$l2h_cache_file") || return warn"$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n";
3218     while (($key, $value) = each %l2h_cache)
3219     {
3220         # escape stuff
3221         $key =~ s|/|\\/|g;
3222         $key =~ s|\\\\/|\\/|g;
3223         # weird, a \ at the end of the key results in an error
3224         # maybe this also broke the dbm database stuff
3225         $key =~ s|\\$|\\\\|;
3226         $value =~ s/\|/\\\|/go;
3227         $value =~ s/\\\\\|/\\\|/go;
3228         $value =~ s|\\\\|\\\\\\\\|g;
3229         print FH "\n\$l2h_cache_key = q/$key/;\n";
3230         print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n";
3231     }
3232     print FH "1;";
3233     close(FH);
3234 }
3235
3236 # return cached html, if it exists for text, and if all pictures
3237 # are there, as well
3238 sub l2h_FromCache
3239 {
3240     my $text = shift;
3241     my $cached = $l2h_cache{$text};
3242     if ($cached)
3243     {
3244         while ($cached =~ m/SRC="(.*?)"/g)
3245         {
3246             unless (-e "$docu_rdir$1")
3247             {
3248                 return undef;
3249             }
3250         }
3251         return $cached;
3252     }
3253     return undef;
3254 }
3255
3256 # insert generated html into cache, move away images,
3257 # return transformed html
3258 $maximage = 1;
3259 sub l2h_ToCache
3260 {
3261     my $count = shift;
3262     my $content = shift;
3263     my @images = ($content =~ /SRC="(.*?)"/g);
3264     my ($src, $dest);
3265
3266     for $src (@images)
3267     {
3268         $dest = $l2h_img{$src};
3269         unless ($dest)
3270         {
3271             my $ext;
3272             if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext)
3273             {
3274                 $ext = $1;
3275             }
3276             else
3277             {
3278                 warn "$ERROR: L2h image $src has invalid extension\n";
3279                 next;
3280             }
3281             while (-e "$docu_rdir${docu_name}_$maximage.$ext")
3282             {
3283                 $maximage++;
3284             }
3285             $dest = "${docu_name}_$maximage.$ext";
3286             system("cp -f $docu_rdir$src $docu_rdir$dest");
3287             $l2h_img{$src} = $dest;
3288             unlink "$docu_rdir$src" unless ($DEBUG & $DEBUG_L2H);
3289         }
3290         $content =~ s/$src/$dest/g;
3291     }
3292     $l2h_cache{$l2h_to_latex[$count]} = $content;
3293     return $content;
3294 }
3295
3296
3297 #+++############################################################################
3298 #                                                                              #
3299 # Pass 1: read source, handle command, variable, simple substitution           #
3300 #                                                                              #
3301 #---############################################################################
3302 sub pass1
3303 {
3304     my $name;
3305     my $line;
3306     @lines = ();                # whole document
3307     @toc_lines = ();            # table of contents
3308     @stoc_lines = ();           # table of contents
3309     $curlevel = 0;              # current level in TOC
3310     $node = '';                 # current node name
3311     $node_next = '';            # current node next name
3312     $node_prev = '';            # current node prev name
3313     $node_up = '';              # current node up name
3314     $in_table = 0;              # am I inside a table
3315     $table_type = '';           # type of table ('', 'f', 'v', 'multi')
3316     @tables = ();               # nested table support
3317     $in_bibliography = 0;       # am I inside a bibliography
3318     $in_glossary = 0;           # am I inside a glossary
3319     $in_top = 0;                # am I inside the top node
3320     $has_top = 0;               # did I see a top node?
3321     $has_top_command = 0;       # did I see @top for automatic pointers?
3322     $in_pre = 0;                # am I inside a preformatted section
3323     $in_list = 0;               # am I inside a list
3324     $in_html = 0;               # am I inside an HTML section
3325     $first_line = 1;            # is it the first line
3326     $dont_html = 0;             # don't protect HTML on this line
3327     $deferred_ref = '';         # deferred reference for indexes
3328     @html_stack = ();           # HTML elements stack
3329     $html_element = '';         # current HTML element
3330     &html_reset;
3331     %macros = ();               # macros
3332     $toc_indent =               # used for identation in TOC's
3333         ($T2H_NUMBER_SECTIONS ? 'BLOCKQUOTE' : 'UL');
3334
3335     # init l2h
3336     $T2H_L2H = &l2h_Init($docu_name) if ($T2H_L2H);
3337     $T2H_L2H = &l2h_InitToLatex      if ($T2H_L2H);
3338
3339     # build code for simple substitutions
3340     # the maps used (%simple_map and %things_map) MUST be aware of this
3341     # watch out for regexps, / and escaped characters!
3342     $subst_code = '';
3343     foreach (keys(%simple_map))
3344     {
3345         ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
3346         $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
3347     }
3348     foreach (keys(%things_map))
3349     {
3350         $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
3351     }
3352     if ($use_acc)
3353     {
3354         # accentuated characters
3355         foreach (keys(%accent_map))
3356         {
3357             if ($_ eq "`")
3358             {
3359                 $subst_code .= "s/$;3";
3360             }
3361             elsif ($_ eq "'")
3362             {
3363                 $subst_code .= "s/$;4";
3364             }
3365             else
3366             {
3367                 $subst_code .= "s/\\\@\\$_";
3368             }
3369             $subst_code .= "([a-z])/&\${1}$accent_map{$_};/gi;\n";
3370         }
3371     }
3372     eval("sub simple_substitutions { $subst_code }");
3373
3374     &init_input;
3375  INPUT_LINE: while ($_ = &next_line)
3376     {
3377         #
3378         # remove \input on the first lines only
3379         #
3380         if ($first_line)
3381         {
3382             next if /^\\input/;
3383             $first_line = 0;
3384         }
3385         # non-@ substitutions cf. texinfmt.el
3386         #
3387         # parse texinfo tags
3388         #
3389         $tag = '';
3390         $end_tag = '';
3391         if (/^\s*\@end\s+(\w+)\b/)
3392         {
3393             $end_tag = $1;
3394         }
3395         elsif (/^\s*\@(\w+)\b/)
3396         {
3397             $tag = $1;
3398         }
3399         #
3400         # handle @html / @end html
3401         #
3402         if ($in_html)
3403         {
3404             if ($end_tag eq 'html')
3405             {
3406                 $in_html = 0;
3407             }
3408             else
3409             {
3410                 $tag2pro{$in_html} .= $_;
3411             }
3412             next;
3413         }
3414         elsif ($tag eq 'html')
3415         {
3416             $in_html = $PROTECTTAG . ++$html_num;
3417             push(@lines, $in_html);
3418             next;
3419         }
3420
3421         #
3422         # try to remove inlined comments
3423         # syntax from tex-mode.el comment-start-skip
3424         #
3425         s/((^|[^\@])(\@\@)*)\@(c( |\{)|comment ).*$/$1/;
3426
3427         # Sometimes I use @c right at the end of  a line ( to suppress the line feed )
3428         #    s/((^|[^\@])(\@\@)*)\@c(omment)?$/$1/;
3429         #     s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
3430         #     s/(.*)\@c{.*?}(.*)/$1$2/;
3431         #     s/(.*)\@comment{.*?}(.*)/$1$2/;
3432         #     s/^(.*)\@c /$1/;
3433         #     s/^(.*)\@comment /$1/;
3434
3435         #############################################################
3436         # value substitution before macro expansion, so that
3437         # it works in macro arguments
3438         s/\@value{($VARRE)}/$value{$1}/eg;
3439
3440         #############################################################
3441         # macro substitution
3442         while (/\@(\w+)/g)
3443         {
3444             if (exists($macros->{$1}))
3445             {
3446                 my $before = $`;
3447                 $name = $1;
3448                 my $after = $';
3449                 my @args;
3450                 my $args;
3451                 #####################################################
3452                 # Support for multi-line macro invocations and nested
3453                 # '{' and '}' within macro invocations added by
3454                 # Eric Sunshine <sunshine@sunshineco.com> 2000/09/10.
3455                 #####################################################
3456                 if ($after =~ /^\s*\{/) # Macro arguments delimited by '{' and '}'?
3457                 {
3458                     my ($protect, $start, $end, $depth, $c) = (0, 0, 0, 0, 0);
3459                     foreach $c (unpack('C*', $after))
3460                     {
3461                         if ($protect)
3462                         {       # Character protected by '\' or '@'; pass through unmolested.
3463                             $protect = 0;
3464                         }
3465                         elsif ($c == ord('\\') || $c == ord('@'))
3466                         {       # '\' and '@' remove special meaning of next character.
3467                             $protect = 1;
3468                         }
3469                         elsif ($c == ord('{')) # Allow '{' and '}' to nest.
3470                         {
3471                             $depth++;
3472                         }
3473                         elsif ($c == ord('}'))
3474                         {
3475                             $depth--;
3476                             last if $depth == 0;
3477                         }
3478                         $start++ if !$depth; # Position of opening brace.
3479                         $end++; # Position of closing brace.
3480                     }
3481
3482                     # '{' & '}' did not completely unnest; append next line; try again.
3483                     if ($depth > 0)
3484                     {
3485                         my $paste = &next_line;
3486                         die "$ERROR Missing closing brace '}' for invocation of macro " .
3487                             "\"\@$name\" on line:\n", substr($_,0,70), "...\n" unless $paste;
3488                         s/\n$/ /;
3489                         unshift @input_spool, $_ . $paste;
3490                         next INPUT_LINE;
3491                     }
3492
3493                     # Extract macro arguments from within '{' and '}'.
3494                     $len = $end - $start - 1;
3495                     $args = ($len > 0) ? substr($after, $start + 1, $len) : '';
3496                     $after = substr($after, $end + 1);
3497                 }
3498                 ############ End Sunshine Modifications #############
3499                 elsif (@{$macros->{$name}->{Args}} == 1) # Macro arg extends to EOL.
3500                 {
3501                     $args = $after;
3502                     $args =~ s/^\s*//;
3503                     $args =~ s/\s*$//;
3504                     $after = '';
3505                 }
3506                 $args =~ s|\\\\|\\|g;
3507                 $args =~ s|\\{|{|g;
3508                                 $args =~ s|\\}|}|g;
3509                 if (@{$macros->{$name}->{Args}} > 1)
3510                 {
3511                     $args =~ s/(^|[^\\]),/$1$;/g ;
3512                     $args =~ s|\\,|,|g;
3513                     @args = split(/$;\s*/, $args) if (@{$macros->{$name}->{Args}} > 1);
3514                 }
3515                 else
3516                 {
3517                     $args =~ s|\\,|,|g;
3518                     @args = ($args);
3519                 }
3520                 my $macrobody = $macros->{$name}->{Body};
3521                 for ($i=0; $i<=$#args; $i++)
3522                 {
3523                     $macrobody =~ s|\\$macros->{$name}->{Args}->[$i]\\|$args[$i]|g;
3524                 }
3525                 $macrobody =~ s|\\\\|\\|g;
3526                 $_ = $before . $macrobody . $after;
3527                 unshift @input_spool, map {$_ = $_."\n"} split(/\n/, $_);
3528                 next INPUT_LINE;
3529             }
3530         }
3531         #
3532         # try to skip the line
3533         #
3534         if ($end_tag)
3535         {
3536             $in_titlepage = 0 if $end_tag eq 'titlepage';
3537             next if $to_skip{"end $end_tag"};
3538         }
3539         elsif ($tag)
3540         {
3541             $in_titlepage = 1 if $tag eq 'titlepage';
3542             next if $to_skip{$tag};
3543             last if $tag eq 'bye';
3544         }
3545         if ($in_top)
3546         {
3547             # parsing the top node
3548             if ($tag eq 'node' ||
3549                 ($sec2level{$tag} && $tag !~ /unnumbered/ && $tag !~ /heading/))
3550             {
3551                 # no more in top
3552                 $in_top = 0;
3553                 push(@lines, $TOPEND);
3554             }
3555         }
3556         unless ($in_pre)
3557         {
3558             s/``/\"/go;
3559             s/''/\"/go;
3560             s/([\w ])---([\w ])/$1--$2/g;
3561         }
3562         #
3563         # analyze the tag
3564         #
3565         if ($tag)
3566         {
3567             # skip lines
3568             &skip_until($tag), next if $tag eq 'ignore';
3569             &skip_until($tag), next if $tag eq 'ifnothtml';
3570             if ($tag eq 'ifinfo')
3571             {
3572                 &skip_until($tag), next unless $T2H_EXPAND eq 'info';
3573             }
3574             if ($tag eq 'iftex')
3575             {
3576                 &skip_until($tag), next unless $T2H_EXPAND eq 'tex';
3577             }
3578             if ($tag eq 'tex')
3579             {
3580                 # add to latex2html file
3581                 if ($T2H_EXPAND eq 'tex' && $T2H_L2H && ! $in_pre)
3582                 {
3583                     # add space to the end -- tex(i2dvi) does this, as well
3584                     push(@lines, &l2h_ToLatex(&string_until($tag) . " "));
3585                 }
3586                 else
3587                 {
3588                     &skip_until($tag);
3589                 }
3590                 next;
3591             }
3592             if ($tag eq 'titlepage')
3593             {
3594                 next;
3595             }
3596             # handle special tables
3597             if ($tag =~ /^(|f|v|multi)table$/)
3598             {
3599                 $table_type = $1;
3600                 $tag = 'table';
3601             }
3602             # special cases
3603             # APA: Fixed regexp to ONLY match the top node, not any
3604             # node starting with the word top.
3605             if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*(,.*)?$/i))
3606             {
3607                 $in_top = 1;
3608                 $has_top = 1;
3609                 $has_top_command = 1 if $tag eq 'top';
3610                 @lines = ();    # ignore all lines before top (title page garbage)
3611                 next;
3612             }
3613             elsif ($tag eq 'node')
3614             {
3615                 if ($in_top)
3616                 {
3617                     $in_top = 0;
3618                     push(@lines, $TOPEND);
3619                 }
3620                 warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
3621                 # request of "Richard Y. Kim" <ryk@ap.com>
3622                 s/^\@node\s+//;
3623                 $_ = &protect_html($_); # if node contains '&' for instance
3624                 ($node, $node_next, $node_prev, $node_up) = split(/,/);
3625                 if ($node)
3626                 {
3627                     &normalise_node($node);
3628                 }
3629                 else
3630                 {
3631                     warn "$ERROR Node is undefined: $_ (eg. \@node NODE-NAME, NEXT, PREVIOUS, UP)";
3632                 }
3633                 if ($node_next)
3634                 {
3635                     &normalise_node($node_next);
3636                 }
3637                 if ($node_prev)
3638                 {
3639                     &normalise_node($node_prev);
3640                 }
3641                 if ($node_up)
3642                 {
3643                     &normalise_node($node_up);
3644                 }
3645                 $node =~ /\"/ ?
3646                     push @lines, &html_debug("<A NAME='".protect_html($node)."'></A>\n", __LINE__) :
3647                         push @lines, &html_debug("<A NAME=\"".protect_html($node)."\"></A>\n", __LINE__);
3648                 next;
3649             }
3650             elsif ($tag eq 'include')
3651             {
3652                 if (/^\@include\s+($FILERE)\s*$/o)
3653                 {
3654                     $file = LocateIncludeFile($1);
3655                     if ($file && -e $file)
3656                     {
3657                         &open($file);
3658                         print "# including $file\n" if $T2H_VERBOSE;
3659                     }
3660                     else
3661                     {
3662                         warn "$ERROR Can't find $1, skipping";
3663                     }
3664                 }
3665                 else
3666                 {
3667                     warn "$ERROR Bad include line: $_";
3668                 }
3669                 next;
3670             }
3671             elsif ($tag eq 'ifclear')
3672             {
3673                 if (/^\@ifclear\s+($VARRE)\s*$/o)
3674                 {
3675                     next unless defined($value{$1});
3676                     &skip_until($tag);
3677                 }
3678                 else
3679                 {
3680                     warn "$ERROR Bad ifclear line: $_";
3681                 }
3682                 next;
3683             }
3684             elsif ($tag eq 'ifset')
3685             {
3686                 if (/^\@ifset\s+($VARRE)\s*$/o)
3687                 {
3688                     next if defined($value{$1});
3689                     &skip_until($tag);
3690                 }
3691                 else
3692                 {
3693                     warn "$ERROR Bad ifset line: $_";
3694                 }
3695                 next;
3696             }
3697             elsif ($tag eq 'menu')
3698             {
3699                 unless ($T2H_SHOW_MENU)
3700                 {
3701                     &skip_until($tag);
3702                     next;
3703                 }
3704                 &html_push_if($tag);
3705                 push(@lines, &html_debug('', __LINE__));
3706             }
3707             elsif ($format_map{$tag})
3708             {
3709                 $in_pre = 1 if $format_map{$tag} eq 'PRE';
3710                 &html_push_if($format_map{$tag});
3711                 push(@lines, &html_debug('', __LINE__));
3712                 $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
3713                 #           push(@lines, &debug("<BLOCKQUOTE>\n", __LINE__))
3714                 #             if $tag =~ /example/i;
3715                 # Eric Sunshine <sunshine@sunshineco.com>: <PRE>blah</PRE> looks
3716                 # better than <PRE>\nblah</PRE> on OmniWeb2 NextStep browser.
3717                 push(@lines, &debug("<$format_map{$tag}>" .
3718                                     ($in_pre ? '' : "\n"), __LINE__));
3719                 next;
3720             }
3721             elsif (exists $complex_format_map->{$tag})
3722             {
3723                 my $start = eval $complex_format_map->{$tag}->[0];
3724                 # APA: <table> implicitly ends paragraph, so let's do it
3725                 # explicitly to keep our HTML stack in sync.
3726                 if ($start =~ /\A\s*<table>/i)
3727                 {
3728                     if ($html_element eq 'P')
3729                     {
3730                         push (@lines2, &debug("</P>\n", __LINE__));
3731                         &html_pop();
3732                     }
3733                 }
3734                 if ($@)
3735                 {
3736                     print "$ERROR: eval of complex_format_map->{$tag}->[0] $complex_format_map->{$tag}->[0]: $@";
3737                     $start = '<pre>'
3738                 }
3739                 $in_pre = 1 if $start =~ /<pre/;
3740                 push(@lines, html_debug($start. ($in_pre ? '' : "\n"), __LINE__));
3741                 next;
3742             }
3743             elsif ($tag eq 'table')
3744             {
3745                 # anorland@hem2.passagen.se
3746                 # if (/^\s*\@(|f|v|multi)table\s+\@(\w+)/) {
3747                 if (/^\s*\@(|f|v|multi)table\s+\@(\w+)|(\{[^\}]*\})/)
3748                 {
3749                     $in_table = $2;
3750                     unshift(@tables, join($;, $table_type, $in_table));
3751                     if ($table_type eq "multi")
3752                     {
3753                         # APA: <table> implicitly ends paragraph, so let's
3754                         # do it explicitly to keep our HTML stack in sync.
3755                         if ($html_element eq 'P')
3756                         {
3757                             push (@lines, &debug("</P>\n", __LINE__));
3758                             &html_pop();
3759                         }
3760                         # don't use borders -- gets confused by empty cells
3761                         push(@lines, &debug("<TABLE>\n", __LINE__));
3762                         &html_push_if('TABLE');
3763                     }
3764                     else
3765                     {
3766                         # APA: <dl> implicitly ends paragraph, so let's
3767                         # do it explicitly to keep our HTML stack in sync.
3768                         if ($html_element eq 'P')
3769                         {
3770                             push (@lines, &debug("</P>\n", __LINE__));
3771                             &html_pop();
3772                         }
3773                         push(@lines, &debug("<DL COMPACT>\n", __LINE__));
3774                         &html_push_if('DL');
3775                     }
3776                     push(@lines, &html_debug('', __LINE__));
3777                 }
3778                 else
3779                 {
3780                     warn "$ERROR Bad table line: $_";
3781                 }
3782                 next;
3783             }
3784             elsif ($tag eq 'synindex' || $tag eq 'syncodeindex')
3785             {
3786                 if (/^\@$tag\s+(\w+)\s+(\w+)\s*$/)
3787                 {
3788                     my $from = $1;
3789                     my $to = $2;
3790                     my $prefix_from = IndexName2Prefix($from);
3791                     my $prefix_to = IndexName2Prefix($to);
3792
3793                     warn("$ERROR unknown from index name $from ind syn*index line: $_"), next
3794                         unless $prefix_from;
3795                     warn("$ERROR unknown to index name $to ind syn*index line: $_"), next
3796                         unless $prefix_to;
3797
3798                     if ($tag eq 'syncodeindex')
3799                     {
3800                         $index_properties->{$prefix_to}->{'from_code'}->{$prefix_from} = 1;
3801                     }
3802                     else
3803                     {
3804                         $index_properties->{$prefix_to}->{'from'}->{$prefix_from} = 1;
3805                     }
3806                 }
3807                 else
3808                 {
3809                     warn "$ERROR Bad syn*index line: $_";
3810                 }
3811                 next;
3812             }
3813             elsif ($tag eq 'defindex' || $tag eq 'defcodeindex')
3814             {
3815                 if (/^\@$tag\s+(\w+)\s*$/)
3816                 {
3817                     $name = $1;
3818                     $index_properties->{$name}->{name} = $name;
3819                     $index_properties->{$name}->{code} = 1 if $tag eq 'defcodeindex';
3820                 }
3821                 else
3822                 {
3823                     warn "$ERROR Bad defindex line: $_";
3824                 }
3825                 next;
3826             }
3827             elsif (/^\@printindex/)
3828             {
3829                 # APA: HTML generated for @printindex contains <table>
3830                 # which implicitly ends paragraph, so let's do it
3831                 # explicitly to keep our HTML stack in sync.
3832                 if ($html_element eq 'P')
3833                 {
3834                     push(@lines, &debug("</P>\n", __LINE__));
3835                     &html_pop();
3836                 }
3837                 push (@lines, "<!--::${section}::-->$_");
3838                 next;
3839             }
3840             elsif ($tag eq 'sp')
3841             {
3842                 push(@lines, &debug("<P></P>\n", __LINE__));
3843                 next;
3844             }
3845             elsif ($tag eq 'center')
3846             {
3847                 push(@lines, &debug("<center>\n", __LINE__));
3848                 s/\@center//;
3849             }
3850             elsif ($tag eq 'setref')
3851             {
3852                 my ($setref);
3853                 &protect_html;  # if setref contains '&' for instance
3854                 if (/^\@$tag\s*{($NODERE)}\s*$/)
3855                 {
3856                     $setref = $1;
3857                     $setref =~ s/\s+/ /go; # normalize
3858                     $setref =~ s/ $//;
3859                     $node2sec{$setref} = $name;
3860                     $sec2node{$name} = $setref;
3861                     $node2href{$setref} = "$docu_doc#$docid";
3862                 }
3863                 else
3864                 {
3865                     warn "$ERROR Bad setref line: $_";
3866                 }
3867                 next;
3868             }
3869             elsif ($tag eq 'lowersections')
3870             {
3871                 my ($sec, $level);
3872                 while (($sec, $level) = each %sec2level)
3873                 {
3874                     $sec2level{$sec} = $level + 1;
3875                 }
3876                 next;
3877             }
3878             elsif ($tag eq 'raisesections')
3879             {
3880                 my ($sec, $level);
3881                 while (($sec, $level) = each %sec2level)
3882                 {
3883                     $sec2level{$sec} = $level - 1;
3884                 }
3885                 next;
3886             }
3887             elsif ($tag eq 'macro' || $tag eq 'rmacro')
3888             {
3889                 if (/^\@$tag\s*(\w+)\s*(.*)/)
3890                 {
3891                     $name = $1;
3892                     my @args;
3893                     @args = split(/\s*,\s*/ , $1)
3894                         if ($2 =~ /^\s*{(.*)}\s*/);
3895
3896                     $macros->{$name}->{Args} = \@args;
3897                     $macros->{$name}->{Body} = '';
3898                     while (($_ = &next_line) && $_ !~ /\@end $tag/)
3899                     {
3900                         $macros->{$name}->{Body} .= $_;
3901                     }
3902                     die "ERROR: No closing '\@end $tag' found for macro definition of '$name'\n"
3903                         unless (/\@end $tag/);
3904                     chomp $macros->{$name}->{Body};
3905                 }
3906                 else
3907                 {
3908                     warn "$ERROR: Bad macro defintion $_"
3909                 }
3910                 next;
3911             }
3912             elsif ($tag eq 'unmacro')
3913             {
3914                 delete $macros->{$1} if (/^\@unmacro\s*(\w+)/);
3915                 next;
3916             }
3917             elsif ($tag eq 'documentlanguage')
3918             {
3919                 SetDocumentLanguage($1) if (!$T2H_LANG && /documentlanguage\s*(\w+)/);
3920             }
3921             elsif (defined($def_map{$tag}))
3922             {
3923                 if ($def_map{$tag})
3924                 {
3925                     s/^\@$tag\s+//;
3926                     $tag = $def_map{$tag};
3927                     $_ = "\@$tag $_";
3928                     $tag =~ s/\s.*//;
3929                 }
3930             }
3931             elsif (defined($user_sub{$tag}))
3932             {
3933                 s/^\@$tag\s+//;
3934                 $sub = $user_sub{$tag};
3935                 print "# user $tag = $sub, arg: $_" if $T2H_DEBUG & $DEBUG_USER;
3936                 if (defined(&$sub))
3937                 {
3938                     chop($_);
3939                     &$sub($_);
3940                 }
3941                 else
3942                 {
3943                     warn "$ERROR Bad user sub for $tag: $sub\n";
3944                 }
3945                 next;
3946             }
3947             if (defined($def_map{$tag}))
3948             {
3949                 s/^\@$tag\s+//;
3950                 if ($tag =~ /x$/)
3951                 {
3952                     # extra definition line
3953                     $tag = $`;
3954                     $is_extra = 1;
3955                 }
3956                 else
3957                 {
3958                     $is_extra = 0;
3959                 }
3960                 while (/\{([^\{\}]*)\}/)
3961                 {
3962                     # this is a {} construct
3963                     ($before, $contents, $after) = ($`, $1, $');
3964                     # protect spaces
3965                     $contents =~ s/\s+/$;9/g;
3966                     # restore $_ protecting {}
3967                     $_ = "$before$;7$contents$;8$after";
3968                 }
3969                 @args = split(/\s+/, &protect_html($_));
3970                 foreach (@args)
3971                 {
3972                     s/$;9/ /g;  # unprotect spaces
3973                     s/$;7/\{/g; # ... {
3974                     s/$;8/\}/g; # ... }
3975                 }
3976                 $type = shift(@args);
3977                 $type =~ s/^\{(.*)\}$/$1/;
3978                 print "# def ($tag): {$type} ", join(', ', @args), "\n"
3979                     if $T2H_DEBUG & $DEBUG_DEF;
3980                 $type .= ':' if (!$T2H_DEF_TABLE); # it's nicer like this
3981                 $name = shift(@args);
3982                 $name =~ s/^\{(.*)\}$/$1/;
3983                 if ($is_extra)
3984                 {
3985                     $_ = &debug("<DT>", __LINE__) if (!$T2H_DEF_TABLE);
3986                     $_ = &debug("", __LINE__) if ($T2H_DEF_TABLE);
3987                     #$_ = &debug("<TR TEST1>\n", __LINE__) if ($T2H_DEF_TABLE);
3988                 }
3989                 else
3990                 {
3991                     # APA: <dl> implicitly ends paragraph, so let's
3992                     # do it explicitly to keep our HTML stack in sync.
3993                     if ($html_element eq 'P')
3994                     {
3995                         $_ = &debug("</P>\n", __LINE__);
3996                         &html_pop();
3997                     }
3998                     else
3999                     {
4000                         $_ = '';
4001                     }
4002                     $_ .= &debug("<DL>\n<DT>", __LINE__) if (!$T2H_DEF_TABLE);
4003                     $_ .= &debug("<TABLE WIDTH=\"100%\">\n", __LINE__) if ($T2H_DEF_TABLE);
4004                 }
4005                 if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp')
4006                 {
4007                     if ($T2H_DEF_TABLE)
4008                     {
4009                         $_ .= "<TR>\n<TD ALIGN=\"LEFT\"><B>$name</B>\n";
4010                         $_ .= " <I>@args</I>" if @args;
4011                         $_ .= "</TD>\n";
4012                         $_ .= "<TD ALIGN=\"RIGHT\">";
4013                         $_ .= "$type</TD>\n</TR>\n";
4014                     }
4015                     else
4016                     {
4017                         $_ .= "<U>$type</U> <B>$name</B>";
4018                         $_ .= " <I>@args</I>" if @args;
4019                     }
4020                 }
4021                 elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
4022                        || $tag eq 'deftypeop' || $tag eq 'defcv'
4023                        || $tag eq 'defop')
4024                 {
4025                     $ftype = $name;
4026                     $name = shift(@args);
4027                     $name =~ s/^\{(.*)\}$/$1/;
4028                     if ($T2H_DEF_TABLE)
4029                     {
4030                         $_ .= "<TR>\n<TD ALIGN=\"LEFT\"><B>$name</B>";
4031                         $_ .= " <I>@args</I>" if @args;
4032                         $_ .= "</TD>\n";
4033                         $_ .= "<TD ALIGN=\"RIGHT\">";
4034                         $_ .= "$type of $ftype</TD>\n</TR>\n";
4035                     }
4036                     else
4037                     {
4038                         $_ .= "<U>$type</U> $ftype <B>$name</B>";
4039                         $_ .= " <I>@args</I>" if @args;
4040                     }
4041                 }
4042                 else
4043                 {
4044                     warn "$ERROR Unknown definition type: $tag\n";
4045                     $_ .= "<U>$type</U> <B>$name</B>";
4046                     $_ .= " <I>@args</I>" if @args;
4047                 }
4048                 $_ .= &debug("\n<DD>", __LINE__) if (!$T2H_DEF_TABLE);
4049                 ########$_ .= &debug("\n</TABLE TEST3>\n<TABLE WIDTH=\"95%\">\n", __LINE__) if ($T2H_DEF_TABLE);
4050                 $name = &unprotect_html($name);
4051                 if ($tag eq 'deffn' || $tag eq 'deftypefn')
4052                 {
4053                     EnterIndexEntry('f', $name, $docu_doc, $section, \@lines);
4054                     #           unshift(@input_spool, "\@findex $name\n");
4055                 }
4056                 elsif ($tag eq 'defop')
4057                 {
4058                     EnterIndexEntry('f', "$name on $ftype", $docu_doc, $section, \@lines);
4059                     #           unshift(@input_spool, "\@findex $name on $ftype\n");
4060                 }
4061                 elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv')
4062                 {
4063                     EnterIndexEntry('v', $name, $docu_doc, $section, \@lines);
4064                     #           unshift(@input_spool, "\@vindex $name\n");
4065                 }
4066                 else
4067                 {
4068                     EnterIndexEntry('t', $name, $docu_doc, $section, \@lines);
4069                     #           unshift(@input_spool, "\@tindex $name\n");
4070                 }
4071                 $dont_html = 1;
4072             }
4073         }
4074         elsif ($end_tag)
4075         {
4076             if ($format_map{$end_tag})
4077             {
4078                 $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
4079                 $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
4080                 &html_pop_if('P');
4081                 &html_pop_if('LI');
4082                 &html_pop_if();
4083                 push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
4084                 push(@lines, &html_debug('', __LINE__));
4085             }
4086             elsif (exists $complex_format_map->{$end_tag})
4087             {
4088                 my $end = eval $complex_format_map->{$end_tag}->[1];
4089                 if ($@)
4090                 {
4091                     print "$ERROR: eval of complex_format_map->{$end_tag}->[1] $complex_format_map->{$end_tag}->[0]: $@";
4092                     $end = '</pre>'
4093                 }
4094                 $in_pre = 0 if $end =~ m|</pre>|;
4095                 push(@lines, html_debug($end, __LINE__));
4096             }
4097             elsif ($end_tag =~ /^(|f|v|multi)table$/)
4098             {
4099                 unless (@tables)
4100                 {
4101                     warn "$ERROR \@end $end_tag without \@*table\n";
4102                     next;
4103                 }
4104                 &html_pop_if('P');
4105                 ($table_type, $in_table) = split($;, shift(@tables));
4106                 unless ($1 eq $table_type)
4107                 {
4108                     warn "$ERROR \@end $end_tag without matching \@$end_tag\n";
4109                     next;
4110                 }
4111                 if ($table_type eq "multi")
4112                 {
4113                     push(@lines, "</TR></TABLE>\n");
4114                     &html_pop_if('TR');
4115                 }
4116                 else
4117                 {
4118                     # APA: </dl> implicitly ends paragraph, so let's
4119                     # do it explicitly to keep our HTML stack in sync.
4120                     if ($html_element eq 'P')
4121                     {
4122                         push(@lines, &debug("</P>\n", __LINE__));
4123                         &html_pop();
4124                     }
4125                     push(@lines, "</DL>\n");
4126                     &html_pop_if('DD');
4127                 }
4128                 &html_pop_if();
4129                 if (@tables)
4130                 {
4131                     ($table_type, $in_table) = split($;, $tables[0]);
4132                 }
4133                 else
4134                 {
4135                     $in_table = 0;
4136                 }
4137             }
4138             elsif (defined($def_map{$end_tag}))
4139             {
4140                 # APA: </dl> and </table> implicitly ends paragraph,
4141                 # so let's do it explicitly to keep our HTML stack in
4142                 # sync.
4143                 if ($html_element eq 'P')
4144                 {
4145                     push(@lines, &debug("</P>\n", __LINE__));
4146                     &html_pop();
4147                 }
4148                 push(@lines, &debug("</DL>\n", __LINE__)) if (!$T2H_DEF_TABLE);
4149                 push(@lines, &debug("</TABLE>\n", __LINE__)) if ($T2H_DEF_TABLE);
4150             }
4151             elsif ($end_tag eq 'menu')
4152             {
4153                 &html_pop_if();
4154                 push(@lines, $_); # must keep it for pass 2
4155             }
4156             next;
4157         }
4158         #############################################################
4159         # anchor insertion
4160         while (/\@anchor\s*\{(.*?)\}/)
4161         {
4162             $_ = $`.$';
4163             my $anchor = $1;
4164             $anchor = &normalise_node($anchor);
4165             push @lines, &html_debug("<A NAME=\"".protect_html($anchor)."\"></A>\n");
4166             $node2href{$anchor} = "$docu_doc#$anchor";
4167             next INPUT_LINE if $_ =~ /^\s*$/;
4168         }
4169         #############################################################
4170         # index entry generation, after value substitutions
4171         if (/^\@(\w+?)index\s+/)
4172         {
4173             EnterIndexEntry($1, $', $docu_doc, $section, \@lines);
4174             next;
4175         }
4176         #
4177         # protect texi and HTML things
4178         &protect_texi;
4179         $_ = &protect_html($_) unless $dont_html;
4180         $dont_html = 0;
4181         # substitution (unsupported things)
4182         s/^\@exdent\s+//go;
4183         s/\@noindent\s+//go;
4184         s/\@refill\s+//go;
4185         # other substitutions
4186         &simple_substitutions;
4187         s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
4188         #
4189         # analyze the tag again
4190         #
4191         if ($tag)
4192         {
4193             if (defined($sec2level{$tag}) && $sec2level{$tag} > 0)
4194             {
4195                 if (/^\@$tag\s+(.+)$/)
4196                 {
4197                     $name = $1;
4198                     $name = &normalise_node($name);
4199                     $level = $sec2level{$tag};
4200                     # check for index
4201                     $first_index_chapter = $name
4202                         if ($level == 1 && !$first_index_chapter &&
4203                             $name =~ /index/i);
4204                     if ($in_top && /heading/)
4205                     {
4206                         $T2H_HAS_TOP_HEADING = 1;
4207                         $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
4208                         &html_push_if('body');
4209                         print "# top heading, section $name, level $level\n"
4210                             if $T2H_DEBUG & $DEBUG_TOC;
4211                     }
4212                     else
4213                     {
4214                         unless (/^\@\w*heading/)
4215                         {
4216                             unless (/^\@unnumbered/)
4217                             {
4218                                 my $number = &update_sec_num($tag, $level);
4219                                 $name = $number . ' ' . $name if $T2H_NUMBER_SECTIONS;
4220                                 $sec2number{$name} = $number;
4221                                 $number2sec{$number} = $name;
4222                             }
4223                             if (defined($toplevel))
4224                             {
4225                                 push @lines, ($level==$toplevel ? $CHAPTEREND : $SECTIONEND);
4226                             }
4227                             else
4228                             {
4229                                 # first time we see a "section"
4230                                 unless ($level == 1)
4231                                 {
4232                                     warn "$WARN The first section found is not of level 1: $_";
4233                                 }
4234                                 $toplevel = $level;
4235                             }
4236                             push(@sections, $name);
4237                             next_doc() if (defined $T2H_SPLIT
4238                                            and
4239                                            ($T2H_SPLIT eq 'section'
4240                                             ||
4241                                             $T2H_SPLIT && $level == $toplevel));
4242                         }
4243                         $sec_num++;
4244                         $docid = "SEC$sec_num";
4245                         $tocid = (/^\@\w*heading/ ? undef : "TOC$sec_num");
4246                         # check biblio and glossary
4247                         $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
4248                         $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
4249                         # check node
4250                         if ($node)
4251                         {
4252                             warn "$ERROR Duplicate node found: $node\n"
4253                                 if ($node2sec{$node});
4254                         }
4255                         else
4256                         {
4257                             $name .= ' ' while ($node2sec{$name});
4258                             $node = $name;
4259                         }
4260                         $name .= ' ' while ($sec2node{$name});
4261                         $section = $name;
4262                         $node2sec{$node} = $name;
4263                         $sec2node{$name} = $node;
4264                         $sec2seccount{$name} = $sec_num;
4265                         $seccount2sec{$sec_num} = $name;
4266                         $node2href{$node} = "$docu_doc#$docid";
4267                         $node2next{$node} = $node_next;
4268                         $node2prev{$node} = $node_prev;
4269                         $node2up{$node} = $node_up;
4270                         print "# node $node, section $name, level $level\n"
4271                             if $T2H_DEBUG & $DEBUG_TOC;
4272
4273                         $node = '';
4274                         $node_next = '';
4275                         $node_prev = '';
4276                         $node_next = '';
4277                         if ($tocid)
4278                         {
4279                             # update TOC
4280                             while ($level > $curlevel)
4281                             {
4282                                 $curlevel++;
4283                                 push(@toc_lines, "<$toc_indent>\n");
4284                             }
4285                             while ($level < $curlevel)
4286                             {
4287                                 $curlevel--;
4288                                 push(@toc_lines, "</$toc_indent>\n");
4289                             }
4290                             $_ = &t2h_anchor($tocid, "$docu_doc#$docid", $name, 1);
4291                             $_ = &substitute_style($_);
4292                             push(@stoc_lines, "$_<BR>\n") if ($level == 1);
4293                             if ($T2H_NUMBER_SECTIONS)
4294                             {
4295                                 push(@toc_lines, $_ . "<BR>\n")
4296                             }
4297                             else
4298                             {
4299                                 push(@toc_lines, "<LI>" . $_ ."</LI>");
4300                             }
4301                         }
4302                         else
4303                         {
4304                             push(@lines, &html_debug("<A NAME=\"".protect_html($docid)."\"></A>\n",
4305                                                      __LINE__));
4306                         }
4307                         # update DOC
4308                         push(@lines, &html_debug('', __LINE__));
4309                         &html_reset;
4310                         $_ =  "<H$level> $name </H$level>\n<!--docid::${docid}::-->\n";
4311                         $_ = &debug($_, __LINE__);
4312                         push(@lines, &html_debug('', __LINE__));
4313                     }
4314                     # update DOC
4315                     foreach $line (split(/\n+/, $_))
4316                     {
4317                         push(@lines, "$line\n");
4318                     }
4319                     next;
4320                 }
4321                 else
4322                 {
4323                     warn "$ERROR Bad section line: $_";
4324                 }
4325             }
4326             else
4327             {
4328                 # track variables
4329                 $value{$1} = Unprotect_texi($2), next if /^\@set\s+($VARRE)\s+(.*)$/o;
4330                 delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
4331                 # store things
4332                 $value{'_shorttitle'} = Unprotect_texi($1), next if /^\@shorttitle\s+(.*)$/;
4333                 $value{'_setfilename'}   = Unprotect_texi($1), next if /^\@setfilename\s+(.*)$/;
4334                 $value{'_settitle'}      = Unprotect_texi($1), next if /^\@settitle\s+(.*)$/;
4335                 $value{'_author'}   .= Unprotect_texi($1)."\n", next if /^\@author\s+(.*)$/;
4336                 $value{'_subtitle'} .= Unprotect_texi($1)."\n", next if /^\@subtitle\s+(.*)$/;
4337                 $value{'_title'}    .= Unprotect_texi($1)."\n", next if /^\@title\s+(.*)$/;
4338
4339                 # list item
4340                 if (/^\s*\@itemx?\s+/)
4341                 {
4342                     $what = $';
4343                     $what =~ s/\s+$//;
4344                     if ($in_bibliography && $use_bibliography)
4345                     {
4346                         if ($what =~ /^$BIBRE$/o)
4347                         {
4348                             $id = 'BIB' . ++$bib_num;
4349                             $bib2href{$what} = "$docu_doc#$id";
4350                             print "# found bibliography for '$what' id $id\n"
4351                                 if $T2H_DEBUG & $DEBUG_BIB;
4352                             $what = &t2h_anchor($id, '', $what);
4353                         }
4354                     }
4355                     elsif ($in_glossary && $T2H_USE_GLOSSARY)
4356                     {
4357                         $id = 'GLOSS' . ++$gloss_num;
4358                         $entry = $what;
4359                         $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
4360                         $gloss2href{$entry} = "$docu_doc#$id";
4361                         print "# found glossary for '$entry' id $id\n"
4362                             if $T2H_DEBUG & $DEBUG_GLOSS;
4363                         $what = &t2h_anchor($id, '', $what);
4364                     }
4365                     elsif ($in_table && ($table_type eq 'f' || $table_type eq 'v'))
4366                     {
4367                         # APA: Insert <dt> before index anchor, if
4368                         # necessary to produce valid HTML.  Close open
4369                         # paragraph first.
4370                         if ($html_element ne 'DT')
4371                         {
4372                             # APA: End paragraph, if any.
4373                             if ($html_element eq 'P')
4374                             {
4375                                 push(@lines, &debug("</P>\n", __LINE__));
4376                                 &html_pop();
4377                             }
4378                             push(@lines, &debug("<DT>", __LINE__));
4379                             &html_push('DT');
4380                         }
4381                         EnterIndexEntry($table_type, $what, $docu_doc, $section, \@lines);
4382                     }
4383                     # APA: End paragraph, if any.
4384                     if ($html_element eq 'P')
4385                     {
4386                         push(@lines, &debug("</P>\n", __LINE__));
4387                         &html_pop();
4388                     }
4389                     if ($html_element =~ m|^D[DLT]$|)
4390                     {
4391                         unless ($html_element eq 'DT')
4392                         {
4393                             push(@lines, &debug("<DT>", __LINE__));
4394                         }
4395                         if ($things_map{$in_table} && !$what)
4396                         {
4397                             # special case to allow @table @bullet for instance
4398                             push(@lines, &debug("$things_map{$in_table}\n", __LINE__));
4399                         }
4400                         else
4401                         {
4402                             push(@lines, &debug("\@$in_table\{$what\}\n", __LINE__));
4403                         }
4404                         push(@lines, "<DD>");
4405                         &html_push('DD') unless $html_element eq 'DD';
4406                         if ($table_type)
4407                         {       # add also an index
4408                             unshift(@input_spool, "\@${table_type}index $what\n");
4409                         }
4410                     }
4411                     elsif ($html_element eq 'TABLE')
4412                     {
4413                         push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
4414                         &html_push('TR');
4415                     }
4416                     elsif ($html_element eq 'TR')
4417                     {
4418                         push(@lines, &debug("</TR>\n", __LINE__));
4419                         push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
4420                     }
4421                     else
4422                     {
4423                         push(@lines, &debug("<LI>$what\n", __LINE__));
4424                         &html_push('LI') unless $html_element eq 'LI';
4425                     }
4426                     push(@lines, &html_debug('', __LINE__));
4427                     if ($deferred_ref)
4428                     {
4429                         push(@lines, &debug("$deferred_ref\n", __LINE__));
4430                         $deferred_ref = '';
4431                     }
4432                     next;
4433                 }
4434                 elsif (/^\@tab\s+(.*)$/)
4435                 {
4436                     push(@lines, "<TD>$1</TD>\n");
4437                     next;
4438                 }
4439             }
4440         }
4441         # paragraph separator
4442         if ($_ eq "\n" && ! $in_pre)
4443         {
4444             next if $#lines >= 0 && $lines[$#lines] eq "\n";
4445             if ($html_element eq 'P')
4446             {
4447                 push (@lines, &debug("</P>\n<P>\n", __LINE__));
4448             }
4449             #   else
4450             #   {
4451             #     push(@lines, "<P></P>\n");
4452             #     $_ = &debug("<P></P>\n", __LINE__);
4453             #   }
4454             elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE' || $html_element eq 'DD' || $html_element eq 'LI')
4455             {
4456                 &html_push('P');
4457                 push(@lines, &debug("<P>\n", __LINE__));
4458             }
4459         }
4460         # otherwise
4461         push(@lines, $_) unless $in_titlepage;
4462         push(@lines, &debug("</center>\n", __LINE__))  if ($tag eq 'center');
4463     }
4464     # finish TOC
4465     $level = 0;
4466     while ($level < $curlevel)
4467     {
4468         $curlevel--;
4469         push(@toc_lines, "</$toc_indent>\n");
4470     }
4471     print "# end of pass 1\n" if $T2H_VERBOSE;
4472 }
4473
4474 #+++############################################################################
4475 #                                                                              #
4476 # Stuff related to Index generation                                            #
4477 #                                                                              #
4478 #---############################################################################
4479
4480 sub EnterIndexEntry
4481 {
4482     my $prefix = shift;
4483     my $key = shift;
4484     my $docu_doc = shift;
4485     my $section = shift;
4486     my $lines = shift;
4487     local $_;
4488
4489     warn "$ERROR Undefined index command: $_", next
4490         unless (exists ($index_properties->{$prefix}));
4491     $key =~ s/\s+$//;
4492     $_ = $key;
4493     &protect_texi;
4494     $key = $_;
4495     $_ = &protect_html($_);
4496     my $html_key = substitute_style($_);
4497     my $id;
4498     $key = remove_style($key);
4499     $key = remove_things($key);
4500     $_ = $key;
4501     &unprotect_texi;
4502     $key = $_;
4503     while (exists $index->{$prefix}->{$key})
4504     {
4505         $key .= ' ';
4506     }
4507     ;
4508     if ($lines->[$#lines] =~ /^<!--docid::(.+)::-->$/)
4509     {
4510         $id = $1;
4511     }
4512     else
4513     {
4514         $id = 'IDX' . ++$idx_num;
4515         push(@$lines, &t2h_anchor($id, '', $T2H_INVISIBLE_MARK, !$in_pre));
4516     }
4517     $index->{$prefix}->{$key}->{html_key} = $html_key;
4518     $index->{$prefix}->{$key}->{section} = $section;
4519     $index->{$prefix}->{$key}->{href} = "$docu_doc#$id";
4520     print "# found ${prefix}index  for '$key' with id $id\n"
4521         if $T2H_DEBUG & $DEBUG_INDEX;
4522 }
4523
4524 sub IndexName2Prefix
4525 {
4526     my $name = shift;
4527     my $prefix;
4528
4529     for $prefix (keys %$index_properties)
4530     {
4531         return $prefix if ($index_properties->{$prefix}->{name} eq $name);
4532     }
4533     return undef;
4534 }
4535
4536 sub GetIndexEntries
4537 {
4538     my $normal = shift;
4539     my $code = shift;
4540     my ($entries, $prefix, $key) = ({});
4541     for $prefix (keys %$normal)
4542     {
4543         for $key (keys %{$index->{$prefix}})
4544         {
4545             $entries->{$key} = {%{$index->{$prefix}->{$key}}};
4546         }
4547     }
4548
4549     if (defined($code))
4550     {
4551         for $prefix (keys %$code)
4552         {
4553             unless (exists $normal->{$prefix})
4554             {
4555                 for $key (keys %{$index->{$prefix}})
4556                 {
4557                     $entries->{$key} = {%{$index->{$prefix}->{$key}}};
4558                     $entries->{$key}->{html_key} = "<CODE>$entries->{$key}->{html_key}</CODE>";
4559                 }
4560             }
4561         }
4562     }
4563     return $entries;
4564 }
4565
4566 sub byAlpha
4567 {
4568     if ($a =~ /^[A-Za-z]/)
4569     {
4570         if ($b =~ /^[A-Za-z]/)
4571         {
4572             return lc($a) cmp lc($b);
4573         }
4574         else
4575         {
4576             return 1;
4577         }
4578     }
4579     elsif ($b =~ /^[A-Za-z]/)
4580     {
4581         return -1;
4582     }
4583     else
4584     {
4585         return lc($a) cmp lc($b);
4586     }
4587 }
4588
4589 sub GetIndexPages
4590 {
4591     my $entries = shift;
4592     my (@Letters, $key);
4593     my ($EntriesByLetter, $Pages, $page) = ({}, [], {});
4594     my @keys = sort byAlpha keys %$entries;
4595
4596     for $key (@keys)
4597     {
4598         push @{$EntriesByLetter->{uc(substr($key,0, 1))}} , $entries->{$key};
4599     }
4600     @Letters = sort byAlpha keys %$EntriesByLetter;
4601     $T2H_SPLIT_INDEX = 0 unless $T2H_SPLIT;
4602
4603     unless ($T2H_SPLIT_INDEX)
4604     {
4605         $page->{First} = $Letters[0];
4606         $page->{Last} = $Letters[$#Letters];
4607         $page->{Letters} = \@Letters;
4608         $page->{EntriesByLetter} = $EntriesByLetter;
4609         push @$Pages, $page;
4610         return $Pages;
4611     }
4612
4613     if ($T2H_SPLIT_INDEX =~ /^\d+$/)
4614     {
4615         my $i = 0;
4616         my ($prev_letter, $letter);
4617         for $letter (@Letters)
4618         {
4619             if ($i > $T2H_SPLIT_INDEX)
4620             {
4621                 $page->{Last} = $prev_letter;
4622                 push @$Pages, $page;
4623                 $i=0;
4624             }
4625             if ($i == 0)
4626             {
4627                 $page = {};
4628                 $page->{Letters} = [];
4629                 $page->{EntriesByLetter} = {};
4630                 $page->{First} = $letter;
4631             }
4632             push @{$page->{Letters}}, $letter;
4633             $page->{EntriesByLetter}->{$letter} = [@{$EntriesByLetter->{$letter}}];
4634             $i += scalar(@{$EntriesByLetter->{$letter}});
4635             $prev_letter = $letter;
4636         }
4637         $page->{Last} = $Letters[$#Letters];
4638         push @$Pages, $page;
4639     }
4640     return $Pages;
4641 }
4642
4643 sub GetIndexSummary
4644 {
4645     my $first_page = shift;
4646     my $Pages = shift;
4647     my $name = shift;
4648     my ($page, $letter, $summary, $i, $l1, $l2, $l);
4649
4650     $i = 0;
4651     $summary = '<table><tr><th valign=top>Jump to: &nbsp; </th><td>';
4652     for $page ($first_page, @$Pages)
4653     {
4654         for $letter (@{$page->{Letters}})
4655         {
4656             $l = t2h_anchor('', "$page->{href}#${name}_$letter", "<b>$letter</b>",
4657                             0, 'style="text-decoration:none"') . "\n &nbsp; \n";
4658             if ($letter =~ /^[A-Za-z]/)
4659             {
4660                 $l2 .= $l;
4661             }
4662             else
4663             {
4664                 $l1 .= $l;
4665             }
4666         }
4667     }
4668     $summary .= $l1 . "<BR>\n" if ($l1);
4669     $summary .= $l2 . '</td></tr></table>';
4670     return $summary;
4671 }
4672
4673 sub PrintIndexPage
4674 {
4675     my $lines = shift;
4676     my $summary = shift;
4677     my $page = shift;
4678     my $name = shift;
4679
4680     push @$lines, $summary;
4681
4682     push @$lines , <<EOT;
4683 <P></P>
4684 <TABLE border=0>
4685 <TR><TD></TD><TH ALIGN=LEFT>Index Entry</TH><TH ALIGN=LEFT> Section</TH></TR>
4686 <TR><TD COLSPAN=3> <HR></TD></TR>
4687 EOT
4688
4689     for $letter (@{$page->{Letters}})
4690     {
4691         push @$lines, "<TR><TH><A NAME=\"".protect_html("${name}_$letter")."\"></A>".protect_html($letter)."</TH><TD></TD><TD></TD></TR>\n";
4692         for $entry (@{$page->{EntriesByLetter}->{$letter}})
4693         {
4694             push @$lines,
4695                 "<TR><TD></TD><TD valign=top>" .
4696                     t2h_anchor('', $entry->{href}, $entry->{html_key}) .
4697                         "</TD><TD valign=top>" .
4698                             t2h_anchor('', sec_href($entry->{section}), clean_name($entry->{section})) .
4699                                 "</TD></TR>\n";
4700         }
4701         push @$lines, "<TR><TD COLSPAN=3> <HR></TD></TR>\n";
4702     }
4703     push @$lines, "</TABLE><P></P>";
4704     push @$lines, $summary;
4705 }
4706
4707 sub PrintIndex
4708 {
4709     my $lines = shift;
4710     my $name = shift;
4711     my $section = shift;
4712     $section = 'Top' unless $section;
4713     my $prefix = IndexName2Prefix($name);
4714
4715     warn ("$ERROR printindex: bad index name: $name"), return
4716         unless $prefix;
4717
4718     if ($index_properties->{$prefix}->{code})
4719     {
4720         $index_properties->{$prefix}->{from_code}->{$prefix} = 1;
4721     }
4722     else
4723     {
4724         $index_properties->{$prefix}->{from}->{$prefix}= 1;
4725     }
4726
4727     my $Entries = GetIndexEntries($index_properties->{$prefix}->{from},
4728                                   $index_properties->{$prefix}->{from_code});
4729     return unless %$Entries;
4730
4731     if ($T2H_IDX_SUMMARY)
4732     {
4733         my $key;
4734         open(FHIDX, ">$docu_rdir$docu_name" . "_$name.idx")
4735             || die "Can't open > $docu_rdir$docu_name" . "_$name.idx for writing: $!\n";
4736         print "# writing $name index summary in $docu_rdir$docu_name" . "_$name.idx...\n" if $T2H_VERBOSE;
4737
4738         for $key (sort keys %$Entries)
4739         {
4740             print FHIDX "$key\t$Entries->{$key}->{href}\n";
4741         }
4742     }
4743
4744     my $Pages = GetIndexPages($Entries);
4745     my $page;
4746     my $first_page = shift @$Pages;
4747     my $sec_name = $section;
4748
4749     # remove section number
4750     $sec_name =~ s/.*? // if $sec_name =~ /^([A-Z]|\d+)\./;
4751
4752     ($first_page->{href} = sec_href($section)) =~ s/\#.*$//;
4753     $node2prev{$section} = Sec2PrevNode($node2sec{$section});
4754     $prev_node = $section;
4755     # Update tree structure of document
4756     if (@$Pages)
4757     {
4758         my $sec;
4759         my @after;
4760
4761         while (@sections && $sections[$#sections] ne $section)
4762         {
4763             unshift @after, pop @sections;
4764         }
4765
4766         for $page (@$Pages)
4767         {
4768             my $node = ($page->{First} ne $page->{Last} ?
4769                         "$sec_name: $page->{First} -- $page->{Last}" :
4770                         "$sec_name: $page->{First}");
4771             push @sections, $node;
4772             $node2sec{$node} = $node;
4773             $sec2node{$node} = $node;
4774             $node2up{$node} = $section;
4775             $page->{href} = next_doc();
4776             $page->{name} = $node;
4777             $node2href{$node} = $page->{href};
4778             if ($prev_node)
4779             {
4780                 $node2next{$prev_node} = $node;
4781                 $node2prev{$node} = $prev_node;
4782             }
4783             $prev_node = $node;
4784         }
4785         # Full circle - Next on last index page goes to Top
4786         $node2next{$prev_node} = "Top";
4787         push @sections, @after;
4788     }
4789
4790     my $summary = GetIndexSummary($first_page, $Pages, $name);
4791     PrintIndexPage($lines, $summary, $first_page, $name);
4792     for $page (@$Pages)
4793     {
4794         push @$lines, ($T2H_SPLIT eq 'chapter' ? $CHAPTEREND : $SECTIONEND);
4795         push @$lines, "<H2 ALIGN=\"Left\">$page->{name}</H2>\n";
4796         PrintIndexPage($lines, $summary, $page, $name);
4797     }
4798 }
4799
4800
4801 #+++############################################################################
4802 #                                                                              #
4803 # Pass 2/3: handle style, menu, index, cross-reference                         #
4804 #                                                                              #
4805 #---############################################################################
4806 sub pass2
4807 {
4808     my $sec;
4809     my $href;
4810     @lines2 = ();               # whole document (2nd pass)
4811     @lines3 = ();               # whole document (3rd pass)
4812     my $in_menu = 0;            # am I inside a menu
4813     my $in_menu_listing;
4814
4815     while (@lines)
4816     {
4817         $_ = shift(@lines);
4818         #
4819         # special case (protected sections)
4820         #
4821         if (/^$PROTECTTAG/o)
4822         {
4823             push(@lines2, $_);
4824             next;
4825         }
4826         #
4827         # menu
4828         #
4829         if (/^\@menu\b/)
4830         {
4831             $in_menu = 1;
4832             $in_menu_listing = 1;
4833             # APA: <table> implicitly ends paragraph, so let's do it
4834             # explicitly to keep our HTML stack in sync.
4835             if ($html_element eq 'P')
4836             {
4837                 push (@lines2, &debug("</P>\n", __LINE__));
4838                 &html_pop();
4839             }
4840             push(@lines2, &debug("<TABLE BORDER=\"0\" CELLSPACING=\"0\">\n", __LINE__));
4841             next;
4842         }
4843         if (/^\@end\s+menu\b/)
4844         {
4845             if ($in_menu_listing)
4846             {
4847                 push(@lines2, &debug("</TABLE>\n", __LINE__));
4848             }
4849             $in_menu = 0;
4850             $in_menu_listing = 0;
4851             next;
4852         }
4853         if ($in_menu)
4854         {
4855             my ($node, $name, $descr);
4856             if (/^\*\s+($NODERE)::/o)
4857             {
4858                 $node = $1;
4859                 $descr = $';
4860             }
4861             elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/)
4862             {
4863                 $name = $1;
4864                 $node = $2;
4865                 $descr = $';
4866             }
4867             elsif (/^\*/)
4868             {
4869                 warn "$ERROR Bad menu line: $_";
4870             }
4871             else
4872             {
4873                 if ($in_menu_listing)
4874                 {
4875                     # APA: Handle menu comment lines.  These don't end the menu!
4876                     # $in_menu_listing = 0;
4877                     push(@lines2,&debug('<TR><TH COLSPAN="3" ALIGN="left" VALIGN="TOP">' . $_ . '</TH></TR>
4878 ', __LINE__));
4879                 }
4880             }
4881             if ($node)
4882             {
4883                 if (! $in_menu_listing)
4884                 {
4885                     $in_menu_listing = 1;
4886                     push(@lines2, &debug("<TABLE BORDER=0 CELLSPACING=0>\n", __LINE__));
4887                 }
4888                 # look for continuation
4889                 while ($lines[0] =~ /^\s+\w+/)
4890                 {
4891                     $descr .= shift(@lines);
4892                 }
4893                 &menu_entry($node, $name, $descr);
4894             }
4895             next;
4896         }
4897         #
4898         # printindex
4899         #
4900         PrintIndex(\@lines2, $2, $1), next
4901             if (/^<!--::(.*)::-->\@printindex\s+(\w+)/);
4902         #
4903         # simple style substitutions
4904         #
4905         $_ = &substitute_style($_);
4906         #
4907         # xref
4908         #
4909         while (/\@(x|px|info|)ref{([^{}]+)(}?)/)
4910         {
4911             # note: Texinfo may accept other characters
4912             ($type, $nodes, $full) = ($1, $2, $3);
4913             ($before, $after) = ($`, $');
4914             if (! $full && $after)
4915             {
4916                 warn "$ERROR Bad xref (no ending } on line): $_";
4917                 $_ = "$before$;0${type}ref\{$nodes$after";
4918                 next;           # while xref
4919             }
4920             if ($type eq 'x')
4921             {
4922                 $type = "$T2H_WORDS->{$T2H_LANG}->{'See'} ";
4923             }
4924             elsif ($type eq 'px')
4925             {
4926                 $type = "$T2H_WORDS->{$T2H_LANG}->{'see'} ";
4927             }
4928             elsif ($type eq 'info')
4929             {
4930                 $type = "$T2H_WORDS->{$T2H_LANG}->{'See'} Info";
4931             }
4932             else
4933             {
4934                 $type = '';
4935             }
4936             unless ($full)
4937             {
4938                 $next = shift(@lines);
4939                 $next = &substitute_style($next);
4940                 chop($nodes);   # remove final newline
4941                 if ($next =~ /\}/)
4942                 {               # split on 2 lines
4943                     $nodes .= " $`";
4944                     $after = $';
4945                 }
4946                 else
4947                 {
4948                     $nodes .= " $next";
4949                     $next = shift(@lines);
4950                     $next = &substitute_style($next);
4951                     chop($nodes);
4952                     if ($next =~ /\}/)
4953                     {           # split on 3 lines
4954                         $nodes .= " $`";
4955                         $after = $';
4956                     }
4957                     else
4958                     {
4959                         warn "$ERROR Bad xref (no ending }): $_";
4960                         $_ = "$before$;0xref\{$nodes$after";
4961                         unshift(@lines, $next);
4962                         next;   # while xref
4963                     }
4964                 }
4965             }
4966             $nodes =~ s/\s+/ /go; # remove useless spaces
4967             @args = split(/\s*,\s*/, $nodes);
4968             $node = $args[0];   # the node is always the first arg
4969             $node = &normalise_node($node);
4970             $sec = $args[2] || $args[1] || $node2sec{$node};
4971             $href = $node2href{$node};
4972             if (@args == 5)
4973             {                   # reference to another manual
4974                 $sec = $args[2] || $node;
4975                 $man = $args[4] || $args[3];
4976                 $_ = "${before}${type}$T2H_WORDS->{$T2H_LANG}->{'section'} `$sec' in \@cite{$man}$after";
4977             }
4978             elsif ($type =~ /Info/)
4979             {                   # inforef
4980                 warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
4981                 ($nn, $_, $in) = @args;
4982                 $_ = "${before}${type} file `$in', node `$nn'$after";
4983             }
4984             elsif ($sec && $href && ! $T2H_SHORT_REF)
4985             {
4986                 $_  = "${before}${type}";
4987                 $_ .= "$T2H_WORDS->{$T2H_LANG}->{'section'} " if $type;
4988                 $_ .= &t2h_anchor('', $href, $sec) . $after;
4989             }
4990             elsif ($href)
4991             {
4992                 $_ = "${before}${type} " .
4993                     &t2h_anchor('', $href, $args[2] || $args[1] || $node) .
4994                         $after;
4995             }
4996             else
4997             {
4998                 warn "$ERROR Undefined node ($node): $_";
4999                 $_ = "$before$;0xref{$nodes}$after";
5000             }
5001         }
5002
5003         # replace images
5004         s[\@image\s*{(.+?)}]
5005         {
5006          my @args = split (/\s*,\s*/, $1);
5007          my $base = $args[0];
5008          my $image =
5009          LocateIncludeFile("$base.png") ||
5010          LocateIncludeFile("$base.jpg") ||
5011          LocateIncludeFile("$base.gif");
5012          warn "$ERROR no image file for $base: $_" unless ($image && -e $image);
5013          ($T2H_CENTER_IMAGE ?
5014           "<CENTER><IMG SRC=\"$image\" ALT=\"$base\"></CENTER>" :
5015           "<IMG SRC=\"$image\" ALT=\"$base\">");
5016         }eg;
5017
5018         #
5019         # try to guess bibliography references or glossary terms
5020         #
5021         unless (/^<H\d><A NAME=\"SEC\d/)
5022         {
5023             if ($use_bibliography)
5024             {
5025                 $done = '';
5026                 while (/$BIBRE/o)
5027                 {
5028                     ($pre, $what, $post) = ($`, $&, $');
5029                     $href = $bib2href{$what};
5030                     if (defined($href) && $post !~ /^[^<]*<\/A>/)
5031                     {
5032                         $done .= $pre . &t2h_anchor('', $href, $what);
5033                     }
5034                     else
5035                     {
5036                         $done .= "$pre$what";
5037                     }
5038                     $_ = $post;
5039                 }
5040                 $_ = $done . $_;
5041             }
5042             if ($T2H_USE_GLOSSARY)
5043             {
5044                 $done = '';
5045                 while (/\b\w+\b/)
5046                 {
5047                     ($pre, $what, $post) = ($`, $&, $');
5048                     $entry = $what;
5049                     $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
5050                     $href = $gloss2href{$entry};
5051                     if (defined($href) && $post !~ /^[^<]*<\/A>/)
5052                     {
5053                         $done .= $pre . &t2h_anchor('', $href, $what);
5054                     }
5055                     else
5056                     {
5057                         $done .= "$pre$what";
5058                     }
5059                     $_ = $post;
5060                 }
5061                 $_ = $done . $_;
5062             }
5063         }
5064         # otherwise
5065         push(@lines2, $_);
5066     }
5067     print "# end of pass 2\n" if $T2H_VERBOSE;
5068 }
5069
5070 sub pass3
5071 {
5072     #
5073     # split style substitutions
5074     #
5075     my $text;
5076     while (@lines2)
5077     {
5078         $_ = shift(@lines2);
5079         #
5080         # special case (protected sections)
5081         #
5082         if (/^$PROTECTTAG/o)
5083         {
5084             push(@lines3, $_);
5085             next;
5086         }
5087         #
5088         # split style substitutions
5089         #
5090         $old = '';
5091         while ($old ne $_)
5092         {
5093             $old = $_;
5094             if (/\@(\w+)\{/)
5095             {
5096                 ($before, $style, $after) = ($`, $1, $');
5097                 if (defined($style_map{$style}))
5098                 {
5099                     $_ = $after;
5100                     $text = '';
5101                     $after = '';
5102                     $failed = 1;
5103                     while (@lines2)
5104                     {
5105                         if (/\}/)
5106                         {
5107                             $text .= $`;
5108                             $after = $';
5109                             $failed = 0;
5110                             last;
5111                         }
5112                         else
5113                         {
5114                             $text .= $_;
5115                             $_ = shift(@lines2);
5116                         }
5117                     }
5118                     if ($failed)
5119                     {
5120                         die "* Bad syntax (\@$style) after: $before\n";
5121                     }
5122                     else
5123                     {
5124                         $text = &apply_style($style, $text);
5125                         $_ = "$before$text$after";
5126                     }
5127                 }
5128             }
5129         }
5130         # otherwise
5131         push(@lines3, $_);
5132     }
5133     print "# end of pass 3\n" if $T2H_VERBOSE;
5134 }
5135
5136 #+++############################################################################
5137 #                                                                              #
5138 # Pass 4: foot notes, final cleanup                                            #
5139 #                                                                              #
5140 #---############################################################################
5141 sub pass4
5142 {
5143     my $text;
5144     my $name;
5145     @foot_lines = ();           # footnotes
5146     @doc_lines = ();            # final document
5147     $end_of_para = 0;           # true if last line is <P>
5148
5149     # APA: There aint no paragraph before the first one!
5150     # This fixes a HTML validation error.
5151     $lines3[0] =~ s|^</P>\n|\n|;
5152     while (@lines3)
5153     {
5154         $_ = shift(@lines3);
5155         #
5156         # special case (protected sections)
5157         #
5158         if (/^$PROTECTTAG/o)
5159         {
5160             push(@doc_lines, $_);
5161             $end_of_para = 0;
5162             next;
5163         }
5164         #
5165         # footnotes
5166         #
5167         while (/\@footnote([^\{\s]+)\{/)
5168         {
5169             ($before, $d, $after) = ($`, $1, $');
5170             $_ = $after;
5171             $text = '';
5172             $after = '';
5173             $failed = 1;
5174             while (@lines3)
5175             {
5176                 if (/\}/)
5177                 {
5178                     $text .= $`;
5179                     $after = $';
5180                     $failed = 0;
5181                     last;
5182                 }
5183                 else
5184                 {
5185                     $text .= $_;
5186                     $_ = shift(@lines3);
5187                 }
5188             }
5189             if ($failed)
5190             {
5191                 die "* Bad syntax (\@footnote) after: $before\n";
5192             }
5193             else
5194             {
5195                 $foot_num++;
5196                 $docid  = "DOCF$foot_num";
5197                 $footid = "FOOT$foot_num";
5198                 $foot = "($foot_num)";
5199                 push(@foot_lines, "<H3>" . &t2h_anchor($footid, "$d#$docid", $foot) . "</H3>\n");
5200                 $text = "<P>$text" unless $text =~ /^\s*<P>/;
5201                 push(@foot_lines, "$text\n");
5202                 $_ = $before . &t2h_anchor($docid, "$docu_foot#$footid", $foot) . $after;
5203             }
5204         }
5205         #
5206         # remove unnecessary <P>
5207         #
5208         if (/^\s*<P>\s*$/)
5209         {
5210             next if $end_of_para++;
5211         }
5212         else
5213         {
5214             $end_of_para = 0;
5215         }
5216         # otherwise
5217         push(@doc_lines, $_);
5218     }
5219
5220     print "# end of pass 4\n" if $T2H_VERBOSE;
5221 }
5222
5223 #+++############################################################################
5224 #                                                                              #
5225 # Pass 5: print things                                                         #
5226 #                                                                              #
5227 #---############################################################################
5228 sub pass5
5229 {
5230     $T2H_L2H = &l2h_FinishToLatex if ($T2H_L2H);
5231     $T2H_L2H = &l2h_ToHtml        if ($T2H_L2H);
5232     $T2H_L2H = &l2h_InitFromHtml  if ($T2H_L2H);
5233
5234     T2H_InitGlobals();
5235
5236     # fix node2up, node2prev, node2next, if desired
5237     if ($has_top_command)
5238     {
5239         for $section (keys %sec2number)
5240         {
5241             $node2href{$sec2node{$section}} =~ /SEC(\d+)$/;
5242             $node = $sec2node{$section};
5243             $node2up{$node} = Sec2UpNode($section) unless $node2up{$node};
5244             $node2prev{$node} = Sec2PrevNode($section) unless $node2prev{$node};
5245             $node2next{$node} = Sec2NextNode($section) unless $node2next{$node};
5246         }
5247     }
5248
5249     # prepare %T2H_THISDOC
5250     $T2H_THISDOC{fulltitle} = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
5251     $T2H_THISDOC{title} = $value{'_settitle'} || $T2H_THISDOC{fulltitle};
5252     $T2H_THISDOC{author} = $value{'_author'};
5253     $T2H_THISDOC{subtitle} = $value{'_subtitle'};
5254     $T2H_THISDOC{shorttitle} = $value{'_shorttitle'};
5255     for $key (keys %T2H_THISDOC)
5256     {
5257         $_ = &substitute_style($T2H_THISDOC{$key});
5258         &unprotect_texi;
5259         s/\s*$//;
5260         $T2H_THISDOC{$key} = $_;
5261     }
5262
5263     # if no sections, then simply print document as is
5264     unless (@sections)
5265     {
5266         print "# Writing content into $docu_top_file \n" if $T2H_VERBOSE;
5267         open(FILE, "> $docu_top_file")
5268             || die "$ERROR: Can't open $docu_top_file for writing: $!\n";
5269
5270         &$T2H_print_page_head(\*FILE);
5271         $T2H_THIS_SECTION = \@doc_lines;
5272         t2h_print_lines(\*FILE);
5273         &$T2H_print_foot_navigation(\*FILE);
5274         &$T2H_print_page_foot(\*FILE);
5275         close(FILE);
5276         goto Finish;
5277     }
5278
5279     # initialize $T2H_HREF, $T2H_NAME
5280     %T2H_HREF =
5281         (
5282          'First' ,   sec_href($sections[0]),
5283          'Last',     sec_href($sections[$#sections]),
5284          'About',     $docu_about. '#SEC_About',
5285         );
5286
5287     # prepare TOC, OVERVIEW, TOP
5288     $T2H_TOC = \@toc_lines;
5289     $T2H_OVERVIEW = \@stoc_lines;
5290     if ($has_top)
5291     {
5292         while (1)
5293         {
5294             $_ = shift @doc_lines;
5295             last if /$TOPEND/;
5296             push @$T2H_TOP, $_;
5297         }
5298         $T2H_HREF{'Top'} = $docu_top . '#SEC_Top';
5299     }
5300     else
5301     {
5302         $T2H_HREF{'Top'} = $T2H_HREF{First};
5303     }
5304
5305     $node2href{Top} = $T2H_HREF{Top};
5306     $T2H_HREF{Contents} = $docu_toc.'#SEC_Contents' if @toc_lines;
5307     $T2H_HREF{Overview} = $docu_stoc.'#SEC_OVERVIEW' if @stoc_lines;
5308
5309     # settle on index
5310     if ($T2H_INDEX_CHAPTER)
5311     {
5312         $T2H_HREF{Index} = $node2href{normalise_node($T2H_INDEX_CHAPTER)};
5313         warn "$ERROR T2H_INDEX_CHAPTER '$T2H_INDEX_CHAPTER' not found\n"
5314             unless $T2H_HREF{Index};
5315     }
5316     if (! $T2H_HREF{Index} && $first_index_chapter)
5317     {
5318         $T2H_INDEX_CHAPTER = $first_index_chapter;
5319         $T2H_HREF{Index} = $node2href{$T2H_INDEX_CHAPTER};
5320     }
5321
5322     print "# Using '" . clean_name($T2H_INDEX_CHAPTER) . "' as index page\n"
5323         if ($T2H_VERBOSE && $T2H_HREF{Index});
5324
5325     %T2H_NAME =
5326         (
5327          'First',   clean_name($sec2node{$sections[0]}),
5328          'Last',    clean_name($sec2node{$sections[$#sections]}),
5329          'About',    $T2H_WORDS->{$T2H_LANG}->{'About_Title'},
5330          'Contents', $T2H_WORDS->{$T2H_LANG}->{'ToC_Title'},
5331          'Overview', $T2H_WORDS->{$T2H_LANG}->{'Overview_Title'},
5332          'Index' ,   clean_name($T2H_INDEX_CHAPTER),
5333          'Top',      clean_name($T2H_TOP_HEADING || $T2H_THISDOC{'title'} || $T2H_THISDOC{'shorttitle'}),
5334         );
5335
5336     #############################################################################
5337     # print frame and frame toc file
5338     #
5339     if ( $T2H_FRAMES )
5340     {
5341         open(FILE, "> $docu_frame_file")
5342             || die "$ERROR: Can't open $docu_frame_file for writing: $!\n";
5343         print "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
5344         &$T2H_print_frame(\*FILE);
5345         close(FILE);
5346
5347         open(FILE, "> $docu_toc_frame_file")
5348             || die "$ERROR: Can't open $docu_toc_frame_file for writing: $!\n";
5349         print "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
5350         &$T2H_print_toc_frame(\*FILE);
5351         close(FILE);
5352     }
5353
5354
5355     #############################################################################
5356     # Monolithic beginning.
5357     #
5358     unless ($T2H_SPLIT)
5359     {
5360         open(FILE, "> $docu_doc_file")
5361             || die "$ERROR: Can't open $docu_doc_file for writing: $!\n";
5362         &$T2H_print_page_head(\*FILE);
5363     }
5364
5365
5366     #############################################################################
5367     # print Top
5368     #
5369     if ($has_top)
5370     {
5371         if ($T2H_SPLIT)
5372         {
5373             open(FILE, "> $docu_top_file")
5374                 || die "$ERROR: Can't open $docu_top_file for writing: $!\n";
5375         }
5376
5377         print "# Creating Top in $docu_top_file ...\n" if $T2H_VERBOSE;
5378         $T2H_THIS_SECTION = $T2H_TOP;
5379         $T2H_HREF{This} = $T2H_HREF{Top};
5380         $T2H_NAME{This} = $T2H_NAME{Top};
5381         &$T2H_print_Top(\*FILE);
5382
5383         if ($T2H_SPLIT)
5384         {
5385             close(FILE)
5386                 || die "$ERROR: Error occurred when closing $docu_top_file: $!\n";
5387         }
5388     }
5389
5390
5391     #############################################################################
5392     # Print sections
5393     #
5394     $T2H_NODE{Forward} = $sec2node{$sections[0]};
5395     $T2H_NAME{Forward} = &clean_name($sec2node{$sections[0]});
5396     $T2H_HREF{Forward} = sec_href($sections[0]);
5397     $T2H_NODE{This} = 'Top';
5398     $T2H_NAME{This} = $T2H_NAME{Top};
5399     $T2H_HREF{This} = $T2H_HREF{Top};
5400     if ($T2H_SPLIT)
5401     {
5402         print "# writing " . scalar(@sections) .
5403             " sections into $docu_rdir$docu_name"."_[1..$doc_num].$docu_ext"
5404                 if $T2H_VERBOSE;
5405         $previous = ($T2H_SPLIT eq 'chapter' ? $CHAPTEREND : $SECTIONEND);
5406         undef $FH;
5407         $doc_num = 0;
5408     }
5409     else
5410     {
5411         print "# writing " . scalar(@sections) . " sections in $docu_top_file ..."
5412             if $T2H_VERBOSE;
5413         $FH = \*FILE;
5414         $previous = '';
5415     }
5416
5417     $counter = 0;
5418     # loop through sections
5419     while ($section = shift(@sections))
5420     {
5421         if ($T2H_SPLIT && ($T2H_SPLIT eq 'section' || $previous eq $CHAPTEREND))
5422         {
5423             if ($FH)
5424             {
5425                 #close previous page
5426                 &$T2H_print_chapter_footer($FH) if $T2H_SPLIT eq 'chapter';
5427                 &$T2H_print_page_foot($FH);
5428                 close($FH);
5429                 undef $FH;
5430             }
5431         }
5432         $T2H_NAME{Back} = $T2H_NAME{This};
5433         $T2H_HREF{Back} = $T2H_HREF{This};
5434         $T2H_NODE{Back} = $T2H_NODE{This};
5435         $T2H_NAME{This} = $T2H_NAME{Forward};
5436         $T2H_HREF{This} = $T2H_HREF{Forward};
5437         $T2H_NODE{This} = $T2H_NODE{Forward};
5438         if ($sections[0])
5439         {
5440             $T2H_NODE{Forward} = $sec2node{$sections[0]};
5441             $T2H_NAME{Forward} = &clean_name($T2H_NODE{Forward});
5442             $T2H_HREF{Forward} = sec_href($sections[0]);
5443         }
5444         else
5445         {
5446             delete $T2H_HREF{Forward};
5447             delete $T2H_NODE{Forward};
5448             delete $T2H_NAME{Forward};
5449         }
5450
5451         $node = $node2up{$T2H_NODE{This}};
5452         $T2H_HREF{Up} = $node2href{$node};
5453         if ($T2H_HREF{Up} eq $T2H_HREF{This} || ! $T2H_HREF{Up})
5454         {
5455             $T2H_NAME{Up} = $T2H_NAME{Top};
5456             $T2H_HREF{Up} = $T2H_HREF{Top};
5457             $T2H_NODE{Up} = 'Up';
5458         }
5459         else
5460         {
5461             $T2H_NAME{Up} = &clean_name($node);
5462             $T2H_NODE{Up} = $node;
5463         }
5464
5465         $node = $node2prev{$T2H_NODE{This}};
5466         $T2H_NAME{Prev} = &clean_name($node);
5467         $T2H_HREF{Prev} = $node2href{$node};
5468         $T2H_NODE{Prev} = $node;
5469
5470         $node = Node2FastBack($T2H_NODE{This});
5471         $T2H_NAME{FastBack} = &clean_name($node);
5472         $T2H_HREF{FastBack} = $node2href{$node};
5473         $T2H_NODE{FastBack} = $node;
5474
5475         $node = $node2next{$T2H_NODE{This}};
5476         $T2H_NAME{Next} = &clean_name($node);
5477         $T2H_HREF{Next} = $node2href{$node};
5478         $T2H_NODE{Next} = $node;
5479
5480         $node = Node2FastForward($T2H_NODE{This});
5481         $T2H_NAME{FastForward} = &clean_name($node);
5482         $T2H_HREF{FastForward} = $node2href{$node};
5483         $T2H_NODE{FastForward} = $node;
5484
5485         if (! defined($FH))
5486         {
5487             my $file = $T2H_HREF{This};
5488             $file =~ s/\#.*$//;
5489             open(FILE, "> $docu_rdir$file") ||
5490                 die "$ERROR: Can't open $docu_rdir$file for writing: $!\n";
5491             $FH = \*FILE;
5492             &$T2H_print_page_head($FH);
5493             t2h_print_label($FH);
5494             &$T2H_print_chapter_header($FH) if $T2H_SPLIT eq 'chapter';
5495         }
5496         else
5497         {
5498             t2h_print_label($FH);
5499         }
5500
5501         $T2H_THIS_SECTION = [];
5502         while (@doc_lines)
5503         {
5504             $_ = shift(@doc_lines);
5505             last if ($_ eq $SECTIONEND || $_ eq $CHAPTEREND);
5506             push(@$T2H_THIS_SECTION, $_);
5507         }
5508         $previous = $_;
5509         &$T2H_print_section($FH);
5510
5511         if ($T2H_VERBOSE)
5512         {
5513             $counter++;
5514             print "." if $counter =~ /00$/;
5515         }
5516     }
5517     if ($T2H_SPLIT)
5518     {
5519         &$T2H_print_chapter_footer($FH) if $T2H_SPLIT eq 'chapter';
5520         &$T2H_print_page_foot($FH);
5521         close($FH);
5522     }
5523     print "\n" if $T2H_VERBOSE;
5524
5525     #############################################################################
5526     # Print ToC, Overview, Footnotes
5527     #
5528     delete $T2H_HREF{Prev};
5529     delete $T2H_HREF{Next};
5530     delete $T2H_HREF{Back};
5531     delete $T2H_HREF{Forward};
5532     delete $T2H_HREF{Up};
5533
5534     if (@foot_lines)
5535     {
5536         print "# writing Footnotes in $docu_foot_file...\n" if $T2H_VERBOSE;
5537         open (FILE, "> $docu_foot_file") || die "$ERROR: Can't open $docu_foot_file for writing: $!\n"
5538             if $T2H_SPLIT;
5539         $T2H_HREF{This} = $docu_foot;
5540         $T2H_NAME{This} = $T2H_WORDS->{$T2H_LANG}->{'Footnotes_Title'};
5541         $T2H_THIS_SECTION = \@foot_lines;
5542         &$T2H_print_Footnotes(\*FILE);
5543         close(FILE) if $T2H_SPLIT;
5544     }
5545
5546     if (@toc_lines)
5547     {
5548         print "# writing Toc in $docu_toc_file...\n" if $T2H_VERBOSE;
5549         open (FILE, "> $docu_toc_file") || die "$ERROR: Can't open $docu_toc_file for writing: $!\n"
5550             if $T2H_SPLIT;
5551         $T2H_HREF{This} = $T2H_HREF{Contents};
5552         $T2H_NAME{This} = $T2H_NAME{Contents};
5553         $T2H_THIS_SECTION = \@toc_lines;
5554         &$T2H_print_Toc(\*FILE);
5555         close(FILE) if $T2H_SPLIT;
5556     }
5557
5558     if (@stoc_lines)
5559     {
5560         print "# writing Overview in $docu_stoc_file...\n" if $T2H_VERBOSE;
5561         open (FILE, "> $docu_stoc_file") || die "$ERROR: Can't open $docu_stoc_file for writing: $!\n"
5562             if $T2H_SPLIT;
5563         $T2H_HREF{This} = $T2H_HREF{Overview};
5564         $T2H_NAME{This} = $T2H_NAME{Overview};
5565         $T2H_THIS_SECTION = \@stoc_lines;
5566         unshift @$T2H_THIS_SECTION, "<BLOCKQUOTE>\n";
5567         push @$T2H_THIS_SECTION, "\n</BLOCKQUOTE>\n";
5568         &$T2H_print_Overview(\*FILE);
5569         close(FILE) if $T2H_SPLIT;
5570     }
5571
5572     if ($about_body = &$T2H_about_body())
5573     {
5574         print "# writing About in $docu_about_file...\n" if $T2H_VERBOSE;
5575         open (FILE, "> $docu_about_file") || die "$ERROR: Can't open $docu_about_file for writing: $!\n"
5576             if $T2H_SPLIT;
5577
5578         $T2H_HREF{This} = $T2H_HREF{About};
5579         $T2H_NAME{This} = $T2H_NAME{About};
5580         $T2H_THIS_SECTION = [$about_body];
5581         &$T2H_print_About(\*FILE);
5582         close(FILE) if $T2H_SPLIT;
5583     }
5584
5585     unless ($T2H_SPLIT)
5586     {
5587         &$T2H_print_page_foot(\*FILE);
5588         close (FILE);
5589     }
5590
5591  Finish:
5592     &l2h_FinishFromHtml if ($T2H_L2H);
5593     &l2h_Finish if($T2H_L2H);
5594     print "# that's all folks\n" if $T2H_VERBOSE;
5595
5596     exit(0);
5597 }
5598
5599 #+++############################################################################
5600 #                                                                              #
5601 # Low level functions                                                          #
5602 #                                                                              #
5603 #---############################################################################
5604
5605 sub LocateIncludeFile
5606 {
5607     my $file = shift;
5608     my $dir;
5609
5610     # APA: Don't implicitely search ., to conform with the docs!
5611     # return $file if (-e $file && -r $file);
5612     foreach $dir (@T2H_INCLUDE_DIRS)
5613     {
5614         return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file");
5615     }
5616     return undef;
5617 }
5618
5619 sub clean_name
5620 {
5621     local ($_);
5622     $_ = &remove_style($_[0]);
5623     &unprotect_texi;
5624     return $_;
5625 }
5626
5627 sub update_sec_num
5628 {
5629     my($name, $level) = @_;
5630     my $ret;
5631
5632     $level--;                   # here we start at 0
5633     if ($name =~ /^appendix/ || defined(@appendix_sec_num))
5634     {
5635         # appendix style
5636         if (defined(@appendix_sec_num))
5637         {
5638             &incr_sec_num($level, @appendix_sec_num);
5639         }
5640         else
5641         {
5642             @appendix_sec_num = ('A', 0, 0, 0);
5643         }
5644         $ret = join('.', @appendix_sec_num[0..$level]);
5645     }
5646     else
5647     {
5648         # normal style
5649         if (defined(@normal_sec_num))
5650         {
5651             &incr_sec_num($level, @normal_sec_num);
5652         }
5653         else
5654         {
5655             @normal_sec_num = (1, 0, 0, 0);
5656         }
5657         $ret = join('.', @normal_sec_num[0..$level]);
5658     }
5659     $ret .= "." if $level == 0;
5660     return $ret;
5661 }
5662
5663 sub incr_sec_num
5664 {
5665     local($level, $l);
5666     $level = shift(@_);
5667     $_[$level]++;
5668     foreach $l ($level+1 .. 3)
5669     {
5670         $_[$l] = 0;
5671     }
5672 }
5673
5674 sub Sec2UpNode
5675 {
5676     my $sec = shift;
5677     my $num = $sec2number{$sec};
5678
5679     return '' unless $num;
5680     return 'Top' unless $num =~ /\.\d+/;
5681     $num =~ s/\.[^\.]*$//;
5682     $num = $num . '.' unless $num =~ /\./;
5683     return $sec2node{$number2sec{$num}};
5684 }
5685
5686 # Return previous node or "Top"
5687 sub Sec2PrevNode
5688 {
5689     my $sec = shift;
5690     my $sec_num = $sec2seccount{$sec} - 1;
5691     return "Top" if !$sec_num || $sec_num < 1;
5692     return $sec2node{$seccount2sec{$sec_num}};
5693 }
5694
5695 # Return next node or "Top"
5696 sub Sec2NextNode
5697 {
5698     my $sec = shift;
5699     my $sec_num = $sec2seccount{$sec} + 1;
5700     return "Top" unless exists $seccount2sec{$sec_num};
5701     return $sec2node{$seccount2sec{$sec_num}};
5702 }
5703
5704 #
5705 # sub Node2FastBack NODE
5706 #
5707 # INPUTS
5708 #    NODE       A node
5709 #
5710 # RETURNS
5711 #    The beginning of this chapter, or if already there, the beginning of the
5712 #    previous chapter.
5713 #
5714 sub Node2FastBack
5715 {
5716     my $node = shift;
5717     my $num = $sec2number{$node2sec{$node}};
5718     my $n;
5719
5720     # Index Pages  have no section number and 1. should go back to Top
5721     return $node2prev{$node} if !$num or $num eq "1.";
5722
5723     # Get the current chapter
5724     $num =~ /^([A-Z\d]+)\./;
5725     $n = $1;
5726
5727     # If the first section of this chapter, decrement chapter
5728     $n = $n eq 'A' ? $normal_sec_num[0] : $n =~ /^\d+$/ ? --$n : chr(ord($n)-1)
5729         if $n . '.' eq $num;
5730
5731     # Return node name for section number "$n."
5732     return $sec2node{$number2sec{$n . '.'}} || $node2prev{$node};
5733 }
5734
5735 #
5736 # sub Node2FastForward NODE
5737 #
5738 # INPUTS
5739 #    NODE       A node
5740 #
5741 # RETURNS
5742 #    The beginning of the next chapter.
5743 #
5744 sub Node2FastForward
5745 {
5746     my $node = shift;
5747     my $num = $sec2number{$node2sec{$node}};
5748     my $n;
5749
5750     # Index pages
5751     return $node2next{$node} if !$num;
5752
5753     # Get current chapter
5754     $num =~ /^([A-Z\d]+)\./;
5755     $n = $1;
5756
5757     # Increment chapter
5758     $n = $n eq $normal_sec_num[0] ? 'A' : ++$n;
5759
5760     # Return node name
5761     return $sec2node{$number2sec{$n . '.'}} || $node2next{$node};
5762 }
5763
5764 sub check
5765 {
5766     local($_, %seen, %context, $before, $match, $after);
5767
5768     while (<>)
5769     {
5770         if (/\@(\*|\.|\:|\@|\{|\})/)
5771         {
5772             $seen{$&}++;
5773             $context{$&} .= "> $_" if $T2H_VERBOSE;
5774             $_ = "$`XX$'";
5775             redo;
5776         }
5777         if (/\@(\w+)/)
5778         {
5779             ($before, $match, $after) = ($`, $&, $');
5780             if ($before =~ /\b[-\w]+$/ && $after =~ /^[-\w.]*\b/)
5781             {                   # e-mail address
5782                 $seen{'e-mail address'}++;
5783                 $context{'e-mail address'} .= "> $_" if $T2H_VERBOSE;
5784             }
5785             else
5786             {
5787                 $seen{$match}++;
5788                 $context{$match} .= "> $_" if $T2H_VERBOSE;
5789             }
5790             $match =~ s/^\@/X/;
5791             $_ = "$before$match$after";
5792             redo;
5793         }
5794     }
5795
5796     foreach (sort(keys(%seen)))
5797     {
5798         if ($T2H_VERBOSE)
5799         {
5800             print "$_\n";
5801             print $context{$_};
5802         }
5803         else
5804         {
5805             print "$_ ($seen{$_})\n";
5806         }
5807     }
5808 }
5809
5810 sub open
5811 {
5812     my($name) = @_;
5813
5814     ++$fh_name;
5815     no strict "refs";
5816     if (open($fh_name, $name))
5817     {
5818         unshift(@fhs, $fh_name);
5819     }
5820     else
5821     {
5822         warn "$ERROR Can't read file $name: $!\n";
5823     }
5824     use strict "refs";
5825 }
5826
5827 sub init_input
5828 {
5829     @fhs = ();                  # hold the file handles to read
5830     @input_spool = ();          # spooled lines to read
5831     $fh_name = 'FH000';
5832     &open($docu);
5833 }
5834
5835 sub next_line
5836 {
5837     my($fh, $line);
5838
5839     if (@input_spool)
5840     {
5841         $line = shift(@input_spool);
5842         return($line);
5843     }
5844     while (@fhs)
5845     {
5846         $fh = $fhs[0];
5847         $line = <$fh>;
5848         return($line) if $line;
5849         close($fh);
5850         shift(@fhs);
5851     }
5852     return(undef);
5853 }
5854
5855 # used in pass 1, use &next_line
5856 sub skip_until
5857 {
5858     local($tag) = @_;
5859     local($_);
5860
5861     while ($_ = &next_line)
5862     {
5863         return if /^\@end\s+$tag\s*$/;
5864     }
5865     die "* Failed to find '$tag' after: " . $lines[$#lines];
5866 }
5867
5868 # used in pass 1 for l2h use &next_line
5869 sub string_until
5870 {
5871     local($tag) = @_;
5872     local($_, $string);
5873
5874     while ($_ = &next_line)
5875     {
5876         return $string if /^\@end\s+$tag\s*$/;
5877         #       $_ =~ s/hbox/mbox/g;
5878         $string = $string.$_;
5879     }
5880     die "* Failed to find '$tag' after: " . $lines[$#lines];
5881 }
5882
5883 #
5884 # HTML stacking to have a better HTML output
5885 #
5886
5887 sub html_reset
5888 {
5889     @html_stack = ('html');
5890     $html_element = 'body';
5891 }
5892
5893 sub html_push
5894 {
5895     local($what) = @_;
5896     push(@html_stack, $html_element);
5897     $html_element = $what;
5898 }
5899
5900 sub html_push_if
5901 {
5902     local($what) = @_;
5903     push(@html_stack, $html_element)
5904         if ($html_element && $html_element ne 'P');
5905     $html_element = $what;
5906 }
5907
5908 sub html_pop
5909 {
5910     $html_element = pop(@html_stack);
5911 }
5912
5913 sub html_pop_if
5914 {
5915     local($elt);
5916
5917     if (@_)
5918     {
5919         foreach $elt (@_)
5920         {
5921             if ($elt eq $html_element)
5922             {
5923                 $html_element = pop(@html_stack) if @html_stack;
5924                 last;
5925             }
5926         }
5927     }
5928     else
5929     {
5930         $html_element = pop(@html_stack) if @html_stack;
5931     }
5932 }
5933
5934 sub html_debug
5935 {
5936     my($what, $line) = @_;
5937     if ($T2H_DEBUG & $DEBUG_HTML)
5938     {
5939         $what = "\n" unless $what;
5940         return("<!-- $line @html_stack, $html_element -->$what")
5941     }
5942     return($what);
5943 }
5944
5945 # to debug the output...
5946 sub debug
5947 {
5948     my($what, $line) = @_;
5949     return("<!-- $line -->$what")
5950         if $T2H_DEBUG & $DEBUG_HTML;
5951     return($what);
5952 }
5953
5954 sub SimpleTexi2Html
5955 {
5956     local $_ = $_[0];
5957     &protect_texi;
5958     &protect_html;
5959     $_ = substitute_style($_);
5960     $_[0]  = $_;
5961 }
5962
5963 sub normalise_node
5964 {
5965     local $_ = $_[0];
5966     s/\s+/ /go;
5967     s/ $//;
5968     s/^ //;
5969     &protect_texi;
5970     &protect_html;
5971     $_ = substitute_style($_);
5972     $_[0]  = $_;
5973 }
5974
5975 sub menu_entry
5976 {
5977     my ($node, $name, $descr) = @_;
5978     my ($href, $entry);
5979
5980     &normalise_node($node);
5981     $href = $node2href{$node};
5982     if ($href)
5983     {
5984         $descr =~ s/^\s+//;
5985         $descr =~ s/\s*$//;
5986         $descr = SimpleTexi2Html($descr);
5987         if ($T2H_NUMBER_SECTIONS && !$T2H_NODE_NAME_IN_MENU && $node2sec{$node})
5988         {
5989             $entry = $node2sec{$node};
5990             $name = '';
5991         }
5992         else
5993         {
5994             &normalise_node($name);
5995             $entry = ($name && ($name ne $node || ! $T2H_AVOID_MENU_REDUNDANCY)
5996                       ? "$name : $node" : $node);
5997         }
5998
5999         if ($T2H_AVOID_MENU_REDUNDANCY && $descr)
6000         {
6001             my $clean_entry = $entry;
6002             $clean_entry =~ s/^.*? // if ($clean_entry =~ /^([A-Z]|\d+)\.[\d\.]* /);
6003             $clean_entry =~ s/[^\w]//g;
6004             my $clean_descr = $descr;
6005             $clean_descr =~ s/[^\w]//g;
6006             $descr = '' if ($clean_entry eq $clean_descr)
6007         }
6008         push(@lines2,&debug('<TR><TD ALIGN="left" VALIGN="TOP">' .
6009                             &t2h_anchor('', $href, $entry) .
6010                             '</TD><TD>&nbsp;&nbsp;</TD><TD ALIGN="left" VALIGN="TOP">' .
6011                             $descr .
6012                             "</TD></TR>\n", __LINE__));
6013     }
6014     elsif ($node =~ /^\(.*\)\w+/)
6015     {
6016         push(@lines2,&debug('<TR><TD ALIGN="left" VALIGN="TOP">' .
6017                             $entry .
6018                             '</TD><TD ALIGN="left" VALIGN="TOP">' . $descr .
6019                             "</TD></TR>\n", __LINE__))
6020     }
6021     else
6022     {
6023         warn "$ERROR Undefined node of menu_entry ($node): $_";
6024     }
6025 }
6026
6027 sub do_ctrl { "^$_[0]" }
6028
6029 sub do_email
6030 {
6031     my($addr, $text) = split(/,\s*/, $_[0]);
6032
6033     $text = $addr unless $text;
6034     &t2h_anchor('', "mailto:$addr", $text);
6035 }
6036
6037 sub do_sc
6038 {
6039     # l2h does this much better
6040     return &l2h_ToLatex("{\\sc ".&unprotect_html($_[0])."}") if ($T2H_L2H);
6041     return "\U$_[0]\E";
6042 }
6043
6044 sub do_math
6045 {
6046     # APA: FIXME
6047     # This sub doesn't seem to be used.
6048     # What are $_[0] and $text?
6049     my $text;
6050     return &l2h_ToLatex("\$".&unprotect_html($_[0])."\$") if ($T2H_L2H);
6051     return "<EM>".$text."</EM>";
6052 }
6053
6054 sub do_uref
6055 {
6056     my($url, $text, $only_text) = split(/,\s*/, $_[0]);
6057     # APA: Don't markup obviously bad links.
6058     # e.g. texinfo.texi 4.0 has this, which would lead to a broken
6059     # link:
6060     # @section @code{@@uref@{@var{url}[, @var{text}][, @var{replacement}]@}}
6061     return if $url =~ /[<>]/;
6062     $text = $only_text if $only_text;
6063     $text = $url unless $text;
6064     &t2h_anchor('', $url, $text);
6065 }
6066
6067 sub do_url { &t2h_anchor('', $_[0], $_[0]) }
6068
6069 sub do_acronym
6070 {
6071     return '<FONT SIZE="-1">' . $_[0] . '</FONT>';
6072 }
6073
6074 sub do_accent
6075 {
6076     return "&$_[0]acute;" if $_[1] eq 'H';
6077     return "$_[0]." if $_[1] eq 'dotaccent';
6078     return "$_[0]*" if $_[1] eq 'ringaccent';
6079     return "$_[0]".'[' if $_[1] eq 'tieaccent';
6080     return "$_[0]".'(' if $_[1] eq 'u';
6081     return "$_[0]_" if $_[1] eq 'ubaraccent';
6082     return ".$_[0]" if $_[1] eq 'udotaccent';
6083     return "$_[0]&lt;" if $_[1] eq 'v';
6084     return "&$_[0]cedil;" if $_[1] eq ',';
6085     return "$_[0]" if $_[1] eq 'dotless';
6086     return undef;
6087 }
6088
6089 sub apply_style
6090 {
6091     my($texi_style, $text) = @_;
6092     my($style);
6093
6094     $style = $style_map{$texi_style};
6095     if (defined($style))
6096     {                           # known style
6097         my $do_quotes = 0;
6098         if ($style =~ /^\"/)
6099         {                       # add quotes
6100             $style = $';
6101             $do_quotes = 1;
6102         }
6103         if ($style =~ /^\&/)
6104         {                       # custom
6105             $style = $';
6106             no strict "refs";
6107             $text = &$style($text, $texi_style);
6108             use strict "refs";
6109         }
6110         elsif ($style)
6111         {                       # good style
6112             $text = "<$style>$text</$style>";
6113         }
6114         else
6115         {                       # no style
6116         }
6117         $text = "\`$text\'" if $do_quotes;
6118     }
6119     else
6120     {                           # unknown style
6121         $text = undef;
6122     }
6123     return($text);
6124 }
6125
6126 # remove Texinfo styles
6127 sub remove_style
6128 {
6129     local($_) = @_;
6130     1 while(s/\@\w+{([^\{\}]+)}/$1/g);
6131     return($_);
6132 }
6133
6134 sub remove_things
6135 {
6136     local ($_) = @_;
6137     s|\@(\w+)\{\}|$1|g;
6138     return $_;
6139 }
6140
6141 sub substitute_style
6142 {
6143     local($_) = @_;
6144     my($changed, $done, $style, $text);
6145
6146     &simple_substitutions;
6147     $changed = 1;
6148     while ($changed)
6149     {
6150         $changed = 0;
6151         $done = '';
6152         while (/\@(\w+){([^\{\}]+)}/ || /\@(,){([^\{\}]+)}/)
6153         {
6154             $text = &apply_style($1, $2);
6155             if ($text)
6156             {
6157                 $_ = "$`$text$'";
6158                 $changed = 1;
6159             }
6160             else
6161             {
6162                 $done .= "$`\@$1";
6163                 $_ = "{$2}$'";
6164             }
6165         }
6166         $_ = $done . $_;
6167     }
6168     return($_);
6169 }
6170
6171 sub t2h_anchor
6172 {
6173     my($name, $href, $text, $newline, $extra_attribs) = @_;
6174     my($result);
6175
6176     $result = "<A";
6177     $result .= " NAME=\"".protect_html($name)."\"" if $name;
6178     if ($href)
6179     {
6180         $href =~ s|^$T2H_HREF_DIR_INSTEAD_FILE|./|
6181             if ($T2H_HREF_DIR_INSTEAD_FILE);
6182         $result .= " HREF=\"".protect_html($href)."\"";
6183     }
6184     $result .= " $extra_attribs" if $extra_attribs;
6185     $result .= ">$text</A>";
6186     $result .= "\n" if $newline;
6187     return($result);
6188 }
6189
6190 sub doc_href
6191 {
6192     local($num) = @_;
6193
6194     return("${docu_name}_$num.$docu_ext");
6195 }
6196
6197 sub sec_href
6198 {
6199     return $node2href{$sec2node{$_[0]}};
6200 }
6201
6202 sub next_doc
6203 {
6204     ++$doc_num;
6205     if ("$docu_rdir${docu_name}_$doc_num.$docu_ext" eq "$docu_top_file") {
6206         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";
6207         $doc_num++;
6208     }
6209     $docu_doc = &doc_href($doc_num);
6210 }
6211
6212 sub t2h_print_lines
6213 {
6214     my ($fh, $lines) = @_;
6215     local($_);
6216     $lines = $T2H_THIS_SECTION unless $lines;
6217     my $cnt = 0;
6218     my @cnt;
6219     for (@$lines)
6220     {
6221         $_ = l2h_FromHtml($_) if ($T2H_L2H);
6222         if (/^$PROTECTTAG/o)
6223         {
6224             $_ = $tag2pro{$_};
6225         }
6226         else
6227         {
6228             &unprotect_texi;
6229         }
6230         print $fh $_;
6231         @cnt = split(/\W*\s+\W*/);
6232         $cnt += scalar(@cnt);
6233     }
6234     return $cnt;
6235 }
6236
6237 sub protect_texi
6238 {
6239     # protect @ { } ` '
6240     s/\@\@/$;0/go;
6241     s/\@\{/$;1/go;
6242     s/\@\}/$;2/go;
6243     s/\@\`/$;3/go;
6244     s/\@\'/$;4/go;
6245 }
6246
6247 sub protect_html
6248 {
6249     local($what) = @_;
6250     # protect &, ", <, and >.
6251     # APA: Keep it simple.  This is what perl's CGI::espaceHTML does.
6252     # We may consider using that instead.
6253     # If raw HTML is used outside @ifhtml or @html it's an error
6254     # anyway.
6255     $what =~ s/\&/\&amp;/go;
6256     $what =~ s/\"/\&quot;/go;
6257     $what =~ s/\</\&lt;/go;
6258     $what =~ s/\>/\&gt;/go;
6259     return($what);
6260 }
6261
6262 sub unprotect_texi
6263 {
6264     s/$;0/\@/go;
6265     s/$;1/\{/go;
6266     s/$;2/\}/go;
6267     s/$;3/\`/go;
6268     s/$;4/\'/go;
6269 }
6270
6271 sub Unprotect_texi
6272 {
6273     local $_ = shift;
6274     &unprotect_texi;
6275     return($_);
6276 }
6277
6278 sub unprotect_html
6279 {
6280     local($what) = @_;
6281     # APA: Use
6282     # Character entity references (eg. &lt;)
6283     # instead of
6284     # Numeric character references (eg. &#60)
6285     $what =~ s/\&amp;/\&/go;
6286     $what =~ s/\&quot;/\"/go;
6287     $what =~ s/\&lt;/\</go;
6288     $what =~ s/\&gt;/\>/go;
6289     return($what);
6290 }
6291
6292 sub t2h_print_label
6293 {
6294     my $fh = shift;
6295     my $href = shift || $T2H_HREF{This};
6296     $href =~ s/.*#(.*)$/$1/;
6297     print $fh qq{<A NAME="$href"></A>\n};
6298 }
6299
6300 sub main
6301 {
6302     SetDocumentLanguage('en') unless ($T2H_LANG);
6303     # APA: There's got to be a better way:
6304     $things_map{'today'} = &pretty_date;
6305     # Identity:
6306     $T2H_TODAY = &pretty_date;  # like "20 September 1993"
6307     # the eval prevents this from breaking on system which do not have
6308     # a proper getpwuid implemented
6309     eval { ($T2H_USER = (getpwuid ($<))[6]) =~ s/,.*//;}; # Who am i
6310     # APA: Provide Windows NT workaround until getpwuid gets
6311     # implemented there.
6312     $T2H_USER = $ENV{'USERNAME'} unless defined $T2H_USER;
6313     &pass1();
6314     &pass2();
6315     &pass3();
6316     &pass4();
6317     &pass5();
6318 }
6319
6320 &main();
6321
6322 ##############################################################################
6323
6324 # These next few lines are legal in both Perl and nroff.
6325
6326 .00 ;                           # finish .ig
6327
6328 'di                     \" finish diversion--previous line must be blank
6329 .nr nl 0-1              \" fake up transition to first page again
6330 .nr % 0                 \" start at page 1
6331 '; __END__ ############# From here on it's a standard manual page ############
6332     .so /usr/share/man/man1/texi2html.1