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