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