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