source: git/doc/texi2html @ 4e425a

spielwiese
Last change on this file since 4e425a was 4e425a, checked in by Olaf Bachmann <obachman@…>, 25 years ago
* lib2doc * new parsing of help strings git-svn-id: file:///usr/local/Singular/svn/trunk@3387 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 80.2 KB
RevLine 
[4e425a]1#!/usr/local/bin/perl
[5d13bc]2'di ';
3'ig 00 ';
[4e425a]4#+##############################################################################
5#                                                                              #
6# File: texi2html                                                              #
7#                                                                              #
8# Description: Program to transform most Texinfo documents to HTML             #
9#                                                                              #
10#-##############################################################################
[5d13bc]11
[4e425a]12# From @(#)texi2html    1.52 01/05/98   
13# $Id: texi2html,v 1.8 1999-07-30 10:37:05 obachman Exp $
14# Homepage:
15$T2H_HOMEPAGE = <<EOT;
16http://www.mathematik.uni-kl.de/~obachman/Texi2html
17EOT
18# Authors: 
19$T2H_AUTHORS = <<EOT;
20Written (mainly) by: Lionel Cons, Lionel.Cons\@cern.ch
21Currently maintained by : Olaf Bachmann, obachman\@mathematik.uni-kl.de
22EOT
23# Version:
24$THISVERSION = "1.58";
25$THISPROG = "texi2html $THISVERSION";   # program name and version
26 
[5d13bc]27# The man page for this program is included at the end of this file and can be
28# viewed using the command 'nroff -man texi2html'.
29# Please read the copyright at the end of the man page.
30
[4e425a]31$T2H_TODAY = &pretty_date;              # like "20 September 1993"
32($T2H_USER = (getpwuid ($<))[6]) =~ s/,.*//; # Who am i
33
34#+++############################################################################
35#                                                                              #
36# Initialization                                                               #
37# Pasted content of File $T2H_HOME/texi2html.init                              #
38#                                                                              #
39#---############################################################################
40
41require "$ENV{T2H_HOME}/texi2html.init"; # Makefile:include
[5d13bc]42
43#+++############################################################################
44#                                                                              #
45# Constants                                                                    #
46#                                                                              #
47#---############################################################################
48
49$DEBUG_TOC   =  1;
50$DEBUG_INDEX =  2;
51$DEBUG_BIB   =  4;
52$DEBUG_GLOSS =  8;
53$DEBUG_DEF   = 16;
54$DEBUG_HTML  = 32;
55$DEBUG_USER  = 64;
[4e425a]56$DEBUG_L2H   = 128;
57
[5d13bc]58
[4e425a]59$BIBRE = '\[[\w\/-]+\]';                # RE for a bibliography reference
[5d13bc]60$FILERE = '[\/\w.+-]+';                 # RE for a file name
61$VARRE = '[^\s\{\}]+';                  # RE for a variable name
62$NODERE = '[^@{}:\'`",]+';              # RE for a node name
63$NODESRE = '[^@{}:\'`"]+';              # RE for a list of node names
64$XREFRE = '[^@{}]+';                    # RE for a xref (should use NODERE)
65
66$ERROR = "***";                         # prefix for errors and warnings
[4e425a]67                                        # program home page
[5d13bc]68$PROTECTTAG = "_ThisIsProtected_";      # tag to recognize protected sections
69
[4e425a]70$CHAPTEREND = "<!-- End chapter -->\n"; # to know where a chpater ends
71$SECTIONEND = "<!-- End section -->\n"; # to know where section ends
72$TOPEND     = "<!-- End top     -->\n"; # to know where top ends
73
74 
[5d13bc]75#
76# language dependent constants
77#
78#$LDC_SEE = 'see';
79#$LDC_SECTION = 'section';
80#$LDC_IN = 'in';
81#$LDC_TOC = 'Table of Contents';
82#$LDC_GOTO = 'Go to the';
83#$LDC_FOOT = 'Footnotes';
[4e425a]84#TODO: @def* shortcuts
[5d13bc]85
86#
87# pre-defined indices
88#
89%predefined_index = (
90                    'cp', 'c',
91                    'fn', 'f',
92                    'vr', 'v',
93                    'ky', 'k',
94                    'pg', 'p',
95                    'tp', 't',
96                    );
97
98#
99# valid indices
100#
101%valid_index = (
102                    'c', 1,
103                    'f', 1,
104                    'v', 1,
105                    'k', 1,
106                    'p', 1,
107                    't', 1,
108                );
109
110#
111# texinfo section names to level
112#
113%sec2level = (
114              'top', 0,
115              'chapter', 1,
116              'unnumbered', 1,
117              'majorheading', 1,
118              'chapheading', 1,
119              'appendix', 1,
120              'section', 2,
121              'unnumberedsec', 2,
122              'heading', 2,
123              'appendixsec', 2,
124              'appendixsection', 2,
125              'subsection', 3,
126              'unnumberedsubsec', 3,
127              'subheading', 3,
128              'appendixsubsec', 3,
129              'subsubsection', 4,
130              'unnumberedsubsubsec', 4,
131              'subsubheading', 4,
132              'appendixsubsubsec', 4,
133              );
134
135#
136# accent map, TeX command to ISO name
137#
138%accent_map = (
139               '"',  'uml',
140               '~',  'tilde',
141               '^',  'circ',
142               '`',  'grave',
143               '\'', 'acute',
144               );
145
146#
147# texinfo "simple things" (@foo) to HTML ones
148#
149%simple_map = (
150               # cf. makeinfo.c
151               "*", "<BR>",             # HTML+
[4e425a]152               " ", " ",
153               "\t", " ",
154               "-", "&#173;",   # soft hyphen
[5d13bc]155               "\n", "\n",
156               "|", "",
[4e425a]157               'tab', '<\/TD><TD>',
[5d13bc]158               # spacing commands
159               ":", "",
160               "!", "!",
161               "?", "?",
162               ".", ".",
[4e425a]163               "-", "",
[5d13bc]164               );
165
166#
167# texinfo "things" (@foo{}) to HTML ones
168#
169%things_map = (
170               'TeX', 'TeX',
[4e425a]171               'br', '<P>',             # paragraph break
[5d13bc]172               'bullet', '*',
[4e425a]173               'copyright', '(C)',
[5d13bc]174               'dots', '...',
175               'equiv', '==',
176               'error', 'error-->',
177               'expansion', '==>',
178               'minus', '-',
179               'point', '-!-',
180               'print', '-|',
181               'result', '=>',
[4e425a]182               'today', $T2H_TODAY,
183               'aa', '&aring;',
184               'AA', '&Aring;',
185               'ae', '&aelig;',
186               'AE', '&AElig;',
187               'o',  '&oslash;',
188               'O',  '&Oslash;',
189               'ss', '&szlig;',
[5d13bc]190               );
191
192#
193# texinfo styles (@foo{bar}) to HTML ones
194#
195%style_map = (
[4e425a]196              'asis', '',
[5d13bc]197              'b', 'B',
198              'cite', 'CITE',
199              'code', 'CODE',
[4e425a]200              'ctrl', '&do_ctrl',       # special case
201              'dfn', 'EM',              # DFN tag is illegal in the standard
[5d13bc]202              'dmn', '',                # useless
[4e425a]203              'email', '&do_email',     # insert a clickable email address
[5d13bc]204              'emph', 'EM',
205              'file', '"TT',            # will put quotes, cf. &apply_style
206              'i', 'I',
207              'kbd', 'KBD',
[4e425a]208              'key', 'KBD',
209              'math', '&do_math',
[5d13bc]210              'r', '',                  # unsupported
211              'samp', '"SAMP',          # will put quotes, cf. &apply_style
212              'sc', '&do_sc',           # special case
213              'strong', 'STRONG',
214              't', 'TT',
[4e425a]215              'titlefont', '',          # useless
216              'uref', '&do_uref',       # insert a clickable URL
217              'url', '&do_url',         # insert a clickable URL
[5d13bc]218              'var', 'VAR',
219              'w', '',                  # unsupported
220              );
221
222#
223# texinfo format (@foo/@end foo) to HTML ones
224#
225%format_map = (
226               'display', 'PRE',
227               'example', 'PRE',
[4e425a]228               'format', 'PRE',
[5d13bc]229               'lisp', 'PRE',
230               'quotation', 'BLOCKQUOTE',
231               'smallexample', 'PRE',
232               'smalllisp', 'PRE',
233               # lists
234               'itemize', 'UL',
235               'enumerate', 'OL',
236               # poorly supported
237               'flushleft', 'PRE',
238               'flushright', 'PRE',
239               );
240
241#
242# texinfo definition shortcuts to real ones
243#
244%def_map = (
245            # basic commands
246            'deffn', 0,
247            'defvr', 0,
248            'deftypefn', 0,
249            'deftypevr', 0,
250            'defcv', 0,
251            'defop', 0,
252            'deftp', 0,
253            # basic x commands
254            'deffnx', 0,
255            'defvrx', 0,
256            'deftypefnx', 0,
257            'deftypevrx', 0,
258            'defcvx', 0,
259            'defopx', 0,
260            'deftpx', 0,
261            # shortcuts
262            'defun', 'deffn Function',
263            'defmac', 'deffn Macro',
264            'defspec', 'deffn {Special Form}',
265            'defvar', 'defvr Variable',
266            'defopt', 'defvr {User Option}',
267            'deftypefun', 'deftypefn Function',
268            'deftypevar', 'deftypevr Variable',
269            'defivar', 'defcv {Instance Variable}',
270            'defmethod', 'defop Method',
271            # x shortcuts
272            'defunx', 'deffnx Function',
273            'defmacx', 'deffnx Macro',
274            'defspecx', 'deffnx {Special Form}',
275            'defvarx', 'defvrx Variable',
276            'defoptx', 'defvrx {User Option}',
277            'deftypefunx', 'deftypefnx Function',
278            'deftypevarx', 'deftypevrx Variable',
279            'defivarx', 'defcvx {Instance Variable}',
280            'defmethodx', 'defopx Method',
281            );
282
283#
284# things to skip
285#
286%to_skip = (
287            # comments
288            'c', 1,
289            'comment', 1,
[4e425a]290            'ifnotinfo', 1,
291            'ifnottex', 1,
292            'ifhtml', 1,
293            'end ifhtml', 1,
294            'end ifnotinfo', 1,
295            'end ifnottex', 1,
[5d13bc]296            # useless
[4e425a]297            'detailmenu', 1,
298            'direntry', 1,
[5d13bc]299            'contents', 1,
300            'shortcontents', 1,
301            'summarycontents', 1,
302            'footnotestyle', 1,
303            'end ifclear', 1,
304            'end ifset', 1,
305            'titlepage', 1,
306            'end titlepage', 1,
307            # unsupported commands (formatting)
308            'afourpaper', 1,
309            'cropmarks', 1,
310            'finalout', 1,
311            'headings', 1,
[4e425a]312            'sp', 1,
[5d13bc]313            'need', 1,
314            'page', 1,
315            'setchapternewpage', 1,
316            'everyheading', 1,
317            'everyfooting', 1,
318            'evenheading', 1,
319            'evenfooting', 1,
320            'oddheading', 1,
321            'oddfooting', 1,
322            'smallbook', 1,
323            'vskip', 1,
324            'filbreak', 1,
[4e425a]325            'paragraphindent', 1,
[5d13bc]326            # unsupported formats
327            'cartouche', 1,
328            'end cartouche', 1,
329            'group', 1,
330            'end group', 1,
331            );
332
333#+++############################################################################
334#                                                                              #
335# Argument parsing, initialisation                                             #
336#                                                                              #
337#---############################################################################
338
[4e425a]339#
340# flush stdout and stderr after every write
341#
342select(STDERR);
343$| = 1;
344select(STDOUT);
345$| = 1;
346
347%value = ();                            # hold texinfo variables, see also -D
348
[5d13bc]349$use_bibliography = 1;
350$use_acc = 0;
351$usage = <<EOT;
352This is $THISPROG
353To convert a Texinfo file to HMTL: $0 [options] file
[4e425a]354 where options can be:
355  -expandinfo         : use \@ifinfo sections, not \@iftex
356  -glossary           : handle a glossary
357  -invisible name     : use 'name' as an invisible anchor
358  -Dname              : define name like with \@set
359  -I dir              : search also for files in 'dir'
360  -index_file file    : use 'file' as index file
361  -menu               : handle menus
362  -number             : number sections
363  -split node|chapter : split on node or chapter
364  -short_ref          : cross references without section numbers
365  -l2h                : use latex2html for \@math, \@tex, and \@sc
366  -l2h_latex2html prog: use 'prog' as latex2html program
367                        (default: 'latex2html')
368  -l2h_tmp dir        : use 'dir' as temp dir for latex2html
369  -l2h_clean          : remove temporary files generated by l2h extension
370  -l2h_skip           : skip latex2html run (needs temporary files)
371  -init_file 'file'   : use 'file' for texi2html and latex2html initialization
372  -sidx               : index jump label to top of section
373  -usage              : print usage instructions
374  -verbose            : verbose output
[5d13bc]375To check converted files: $0 -check [-verbose] files
376EOT
377
[4e425a]378while (@ARGV && $ARGV[0] =~ /^-/) {
[5d13bc]379    $_ = shift(@ARGV);
380    if (/^-acc$/)            { $use_acc = 1; next; }
[4e425a]381    if (/^-D(.+)?$/)         { $value{$1 || shift(@ARGV)} = 1; next; }
382    if (/^-d(ebug)?(\d+)?$/) { $T2H_DEBUG = $2 || shift(@ARGV); next; }
383    if (/^-doctype$/)        { $T2H_DOCTYPE = shift(@ARGV); next; }
384    if (/^-c(heck)?$/)       { $T2H_CHECK = 1; next; }
385    if (/^-e(xpand)?$/)      { $T2H_EXPAND = shift(@ARGV); next; }
386    if (/^-g(lossary)?$/)    { $T2H_USE_GLOSSARY = 1; next; }
387    if (/^-i(nvisible)?$/)   { $T2H_INVISIBLE_MARK = shift(@ARGV); next; }
388    if (/^-I(.+)?$/)         { push(@T2H_INCLUDE_DIRS, $1 || shift(@ARGV)); next; }
389    if (/^-iso$/)            { $T2H_USE_ISO = 1; next; }
390    if (/^-init_file$/)     
391    { 
392      $init_file = shift(@ARGV); 
393      if (-f $init_file)
394      {
395        print "# reading initialization file from $init_file\n" 
396          if ($T2H_VERBOSE);
397        require($init_file);
398      }
399      else
400      {
401        print "$ERROR Error: can't read init file $int_file\n";
402        $init_file = '';
403      }
404      next; 
[5d13bc]405    }
[4e425a]406    if (/^-l2h$/)            { $T2H_L2H     = 1;            next; }
407    if (/^-l2h_l2h$/)        { $T2H_L2H_L2H = shift(@ARGV); next; }
408    if (/^-l2h_skip$/)       { $T2H_L2H_SKIP= 1;            next; }
409    if (/^-l2h_tmp$/)        { $T2H_L2H_TMP = shift(@ARGV); next; }
410    if (/^-l2h_clean$/)      { $T2H_L2H_CLEAN= 1;            next; }
411    if (/^-m(enu)?$/)        { $T2H_SHOW_MENU = 1; next; }
412    if (/^-nu(mber)?$/)      { $T2H_NUMBER_SECTIONS = 1; next; }
413    if (/^-o(ut_file)?$/)    { $T2H_OUT = shift (@ARGV); 
414                               undef $T2H_SPLIT; next;}   
415    if (/^-p(refix)?$/)      { $T2H_PREFIX = shift(@ARGV); next; }
416    if (/^-su(bdir)?$/)      { $T2H_SUBDIR = shift(@ARGV); next; }
417    if (/^-short_e(xtn)?$/)  { $T2H_SHORTEXTN = 1; next; }
418    if (/^-short_r(ef)?$/)   { $T2H_SHORT_REF = 1; next; }
419    if (/^-si(dx)?$/)        { $T2H_SECTION_IDX = 1; next; }
420    if (/^-s(plit)?$/)       { $T2H_SPLIT = shift(@ARGV); next;}
421    if (/^-t(op_file)?$/)    { $T2H_TOP_FILE = shift (@ARGV); next;}   
422    if (/^-v(erbose)?$/)     { $T2H_VERBOSE = 1; next; }
423    if (/^-no_v(erbose)?$/)  { $T2H_VERBOSE = 0; next; }
424    if (/^-vers(ion)?$/)     { print "$THISPROGRAM\n"; exit;}
425    die "Unknown option: $_\n$usage";
426}
427if ($T2H_CHECK) {
428    die "Need file to check\n$usage" unless @ARGV > 0;
[5d13bc]429    &check;
430    exit;
431}
432
[4e425a]433if ($T2H_EXPAND eq 'info') 
434{
435  $to_skip{'ifinfo'} = 1;
436  $to_skip{'end ifinfo'} = 1;
437} 
438elsif ($T2H_EXPAND eq 'tex')
439{
440  $to_skip{'iftex'} = 1;
441  $to_skip{'end iftex'} = 1;
442 
[5d13bc]443}
[4e425a]444
445$T2H_INVISIBLE_MARK = '<IMG SRC="invisible.xbm">' if $T2H_INVISIBLE_MARK eq 'xbm';
446
447#
448# file name buisness
449#
450die "Need exactly one file to translate\n$usage" unless @ARGV == 1;
[5d13bc]451$docu = shift(@ARGV);
452if ($docu =~ /.*\//) {
453    chop($docu_dir = $&);
454    $docu_name = $';
455} else {
456    $docu_dir = '.';
457    $docu_name = $docu;
458}
[4e425a]459unshift(@T2H_INCLUDE_DIRS, $docu_dir);
[5d13bc]460$docu_name =~ s/\.te?x(i|info)?$//;     # basename of the document
[4e425a]461$docu_name = $T2H_PREFIX if ($T2H_PREFIX);
462
463# subdir
464if ($T2H_SUBDIR && ! $T2H_OUT)
465{
466  $T2H_SUBDIR =~ s|/*$||;
467  unless (-d "$T2H_SUBDIR" && -w "$T2H_SUBDIR")
468  {
469    if ( mkdir($T2H_SUBDIR, oct(755)))
470    {
471      print "# created directory $T2H_SUBDIR\n" if ($T2H_VERBOSE);
472    }
473    else
474    {
475      warn "$ERROR can't create directory $T2H_SUBDIR. Put results into current directory\n";
476      $T2H_SUBDIR = '';
477    }
478  }
479}
480
481if ($T2H_SUBDIR && ! $T2H_OUT)
482{
483  $docu_rdir = "$T2H_SUBDIR/";
484  print "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
485}
486else
487{
488  if ($T2H_OUT && $T2H_OUT =~ m|(.*)/|)
489  {
490    $docu_rdir = "$1/";
491    print "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
492  }
493  else
494  {
495    print "# putting result files into current directory \n" if ($T2H_VERBOSE);
496    $docu_rdir = '';
497  }
498}
499
500# extension
501if ($T2H_SHORTEXTN)
502{
503  $docu_ext = "htm";
504}
505else
506{
507  $docu_ext = "html";
508}
509if ($T2H_TOP_FILE =~ /\..*$/)
510{
511  $T2H_TOP_FILE = $`.".$docu_ext";
512}
513else
514{
515  $T2H_TOP_FILE .= ".$docu_ext";
516}
517
518# result files
519if (! $T2H_OUT && ($T2H_SPLIT =~ /section/i || $T2H_SPLIT =~ /node/i))
520{
521  $T2H_SPLIT = 'section';
522}
523elsif (! $T2H_OUT && $T2H_SPLIT =~ /chapter/i)
524{
525  $T2H_SPLIT = 'chapter'
526}
527else
528{
529  undef $T2H_SPLIT;
530}
531
532$docu_doc = "$docu_name.$docu_ext";             # document's contents
533$docu_doc_file = "$docu_rdir$docu_doc";
534if ($T2H_SPLIT) 
535{
536  $docu_toc  = "${docu_name}_toc.$docu_ext"; # document's table of contents
537  $docu_stoc = "${docu_name}_ovr.$docu_ext"; # document's short toc
538  $docu_foot = "${docu_name}_fot.$docu_ext"; # document's footnotes
539  $docu_about = "${docu_name}_abt.$docu_ext"; # about this document
540  $docu_top  = $T2H_TOP_FILE;
541}
542else
543{
544  if ($T2H_OUT)
545  {
546    $docu_doc = $T2H_OUT;
547    $docu_doc =~ s|.*/||;
548  }
549  $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_top = $docu_doc;
550}
551
552$docu_toc_file  = "$docu_rdir$docu_toc";
553$docu_stoc_file = "$docu_rdir$docu_stoc";
554$docu_foot_file = "$docu_rdir$docu_foot";
555$docu_about_file = "$docu_rdir$docu_about";
556$docu_top_file  = "$docu_rdir$docu_top";
[5d13bc]557
558#
559# variables
560#
561$value{'html'} = 1;                     # predefine html (the output format)
[4e425a]562$value{'texi2html'} = $THISVERSION;     # predefine texi2html (the translator)
[5d13bc]563# _foo: internal to track @foo
564foreach ('_author', '_title', '_subtitle',
565         '_settitle', '_setfilename') {
566    $value{$_} = '';                    # prevent -w warnings
567}
568%node2sec = ();                         # node to section name
[4e425a]569%sec2node = ();                         # section to node name
[5d13bc]570%node2href = ();                        # node to HREF
[4e425a]571%node2next = ();                        # node to next
572%node2prev = ();                        # node to prev
573%node2up   = ();                        # node to up
[5d13bc]574%bib2href = ();                         # bibliography reference to HREF
575%gloss2href = ();                       # glossary term to HREF
576@sections = ();                         # list of sections
577%tag2pro = ();                          # protected sections
578
579#
580# initial indexes
581#
582$bib_num = 0;
583$foot_num = 0;
584$gloss_num = 0;
585$idx_num = 0;
586$sec_num = 0;
587$doc_num = 0;
588$html_num = 0;
589
590#
591# can I use ISO8879 characters? (HTML+)
592#
[4e425a]593if ($T2H_USE_ISO) {
[5d13bc]594    $things_map{'bullet'} = "&bull;";
595    $things_map{'copyright'} = "&copy;";
596    $things_map{'dots'} = "&hellip;";
597    $things_map{'equiv'} = "&equiv;";
598    $things_map{'expansion'} = "&rarr;";
599    $things_map{'point'} = "&lowast;";
600    $things_map{'result'} = "&rArr;";
601}
602
603#
604# read texi2html extensions (if any)
605#
606$extensions = 'texi2html.ext'; # extensions in working directory
607if (-f $extensions) {
[4e425a]608    print "# reading extensions from $extensions\n" if $T2H_VERBOSE;
[5d13bc]609    require($extensions);
610}
611($progdir = $0) =~ s/[^\/]+$//;
612if ($progdir && ($progdir ne './')) {
613    $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
614    if (-f $extensions) {
[4e425a]615        print "# reading extensions from $extensions\n" if $T2H_VERBOSE;
[5d13bc]616        require($extensions);
617    }
618}
619
[4e425a]620
621print "# reading from $docu\n" if $T2H_VERBOSE;
622
623#########################################################################
624#
625# latex2html stuff
626#
627# latex2html conversions consist of three stages:
628# 1) ToLatex: Put "latex" code into a latex file
629# 2) ToHtml: Use latex2html to generate corresponding html code and images
630# 3) FromHtml: Extract generated code and images from latex2html run
631#
632
633##########################
634# default settings
635#
636
637# defaults for files and names
638
639sub l2h_Init 
640{
641  local($root) = @_;
642 
643  return 0 unless ($root);
644 
645  $l2h_name =  "${root}_l2h";
646 
647  $l2h_latex_file = "$docu_rdir${l2h_name}.tex";
648  $l2h_cache_file = "${docu_rdir}l2h_cache.pm";
649  $T2H_L2H_L2H = "latex2html" unless ($T2H_L2H_L2H);
650 
651  # destination dir -- generated images are put there, should be the same
652  # as dir of enclosing html document --
653  $l2h_html_file = "$docu_rdir${l2h_name}.html";
654  $l2h_prefix = "${l2h_name}_";
655  return 1;
656}
657
658
659##########################
660#
661# First stage: Generation of Latex file
662# Initialize with: l2h_InitToLatex
663# Add content with: l2h_ToLatex($text) --> HTML placeholder comment
664# Finish with: l2h_FinishToLatex
665#
666
667$l2h_latex_preample = <<EOT;
668% This document was automatically generated by the l2h extenstion of texi2html
669% DO NOT EDIT !!!
670\\documentclass{article}
671\\usepackage{html}
672\\begin{document}
673EOT
674
675$l2h_latex_closing = <<EOT;
676\\end{document}
677EOT
678
679# return used latex 1, if l2h could be initalized properly, 0 otherwise
680sub l2h_InitToLatex
681{
682  %l2h_to_latex = ();
683  unless ($T2H_L2H_SKIP)
684  {
685    unless (open(L2H_LATEX, ">$l2h_latex_file"))
686    {
687      warn "$ERROR Error l2h: Can't open latex file '$latex_file' for writing\n";
688      return 0;
689    } 
690    print "# l2h: use ${l2h_latex_file} as latex file\n" if ($T2H_VERBOSE);
691    print L2H_LATEX $l2h_latex_preample;
692  }
693  # open database for caching
694  l2h_InitCache();
695  $l2h_latex_count = 0;
696  $l2h_to_latex_count = 0;
697  $l2h_cached_count = 0;
698  return  1;
699}
700
701# print text (1st arg) into latex file (if not already there), return
702# HTML commentary which can be later on replaced by the latex2html
703# generated text
704sub l2h_ToLatex
705{
706  my($text) = @_;
707  my($count);
708 
709  $l2h_to_latex_count++;
710  $text =~ s/(\s*)$//;
711 
712  # try whether we can cache it
713  my $cached_text = l2h_FromCache($text);
714  if ($cached_text)
715  {
716    $l2h_cached_count++;
717    return $cached_text;
718  }
719 
720  # try whether we have text already on things to do
721  unless ($count = $l2h_to_latex{$text})
722  {
723    $count = $l2h_latex_count;
724    $l2h_latex_count++;
725    $l2h_to_latex{$text} = $count;
726    $l2h_to_latex[$count] = $text;
727    unless ($T2H_L2H_SKIP)
728    {
729      print L2H_LATEX "\\begin{rawhtml}\n";
730      print L2H_LATEX "<!-- l2h_begin ${l2h_name} ${count} -->\n";
731      print L2H_LATEX "\\end{rawhtml}\n";
732     
733      print L2H_LATEX "$text\n";
734     
735      print L2H_LATEX "\\begin{rawhtml}\n";
736      print L2H_LATEX "<!-- l2h_end ${l2h_name} ${count} -->\n";
737      print L2H_LATEX "\\end{rawhtml}\n";
738    }
739  }
740  return "<!-- l2h_replace ${l2h_name} ${count} -->"; 
741}
742
743# print closing into latex file and close it
744sub l2h_FinishToLatex
745{
746  local ($reused);
747 
748  $reused = $l2h_to_latex_count - $l2h_latex_count - $l2h_cached_count;
749  unless ($T2H_L2H_SKIP)
750  {
751    print L2H_LATEX $l2h_latex_closing;
752    close(L2H_LATEX);
753  }
754  print "# l2h: finished to latex ($l2h_cached_count cached, $reused reused, $l2h_latex_count contents)\n" if ($T2H_VERBOSE);
755  unless ($l2h_latex_count)
756  {
757    l2h_Finish();
758    return 0;
759  }
760  return 1;
761}
762
763###################################
764# Second stage: Use latex2html to generate corresponding html code and images
765#
766# l2h_ToHtml([$l2h_latex_file, [$l2h_html_dir]]):
767#   Call latex2html on $l2h_latex_file
768#   Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir
769#   Return 1, on success
770#          0, otherwise
771#
772sub l2h_ToHtml
773{
774  local($call, $ext, $root, $dotbug);
775 
776  if ($T2H_L2H_SKIP)
777  {
778    print "# l2h: skipping latex2html run\n" if ($T2H_VERBOSE);
779    return 1;
780  }
781 
782  # Check for dot in directory where dvips will work
783  if ($T2H_L2H_TMP)
784  {
785    if ($T2H_L2H_TMP =~ /\./)
786    {
787      warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n";
788      $dotbug = 1;
789    }
790  }
791  else
792  {
793    if (&getcwd =~ /\./)
794    {
795     warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n";
796     $dotbug = 1;
797   }
798  }
799  # fix it, if necessary and hope that it works
800  $T2H_L2H_TMP = "/tmp" if ($dotbug);
801   
802  $call = $T2H_L2H_L2H;
803  # use init file, if specified
804  $call = $call . " -init_file " . $init_file if ($init_file && -f $init_file);
805  # set output dir
806  $call .=  ($docu_rdir ? " -dir $docu_rdir" : " -no_subdir");
807  # use l2h_tmp, if specified
808  $call = $call . " -tmp $T2H_L2H_TMP" if ($T2H_L2H_TMP);
809  # options we want to be sure of
810  $call = $call ." -address 0 -info 0 -split 0 -no_navigation -no_auto_link";
811  $call = $call ." -prefix ${l2h_prefix} $l2h_latex_file"; 
812
813  print "# l2h: executing '$call'\n" if ($T2H_VERBOSE);
814  if (system($call))
815  {
816    warn "l2h ***Error: '${call}' did not succeed\n";
817    return 0;
818  }
819  else
820  {
821    print "# l2h: latex2html finished successfully\n" if ($T2H_VERBOSE);
822    return 1;
823  }
824}
825
826# this is directly pasted over from latex2html
827sub getcwd {
828    local($_) = `pwd`;
829
830    die "'pwd' failed (out of memory?)\n"
831        unless length;
832    chop;
833    $_;
834}
835
836
837##########################
838# Third stage: Extract generated contents from latex2html run
839# Initialize with: l2h_InitFromHtml
840#   open $l2h_html_file for reading
841#   reads in contents into array indexed by numbers
842#   return 1,  on success -- 0, otherwise
843# Extract Html code with: l2h_FromHtml($text)
844#   replaces in $text all previosuly inserted comments by generated html code
845#   returns (possibly changed) $text
846# Finish with: l2h_FinishFromHtml
847#   closes $l2h_html_dir/$l2h_name.".$docu_ext"
848
849sub l2h_InitFromHtml
850{
851  local($h_line, $h_content, $count, %l2h_img);
852
853  if (! open(L2H_HTML, "<${l2h_html_file}"))
854  {
855    print "$ERROR Error l2h: Can't open ${l2h_html_file} for reading\n";
856    return 0;
857  }
858  print "# l2h: use ${l2h_html_file} as html file\n" if ($T2H_VERBOSE);
859
860  $l2h_html_count = 0;
861 
862  while ($h_line = <L2H_HTML>)
863  {
864    if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/)
865    {
866      $count = $1;
867      $h_content = "";
868      while ($h_line = <L2H_HTML>)
869      {
870        if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/)
871        {
872          chomp $h_content;
873          chomp $h_content;
874          $l2h_html_count++;
875          $h_content = l2h_ToCache($count, $h_content);
876          $l2h_from_html[$count] = $h_content;
877          $h_content = '';
878          last;
879        }
880        $h_content = $h_content.$h_line;
881      }
882      if ($hcontent)
883      {
884        print "$ERROR Warning l2h: l2h_end $l2h_name $count not found\n" 
885          if ($T2H_VERBOSE);
886        close(L2H_HTML);
887        return 0;
888      }
889    }
890  }
891  print "# l2h: Got $l2h_html_count of $l2h_latex_count html contents\n"
892    if ($T2H_VERBOSE);
893
894  close(L2H_HTML);
895  return 1;
896}
897
898sub l2h_FromHtml
899{
900  local($text) = @_;
901  local($done, $to_do, $count);
902 
903  $to_do = $text;
904 
905  while ($to_do =~ /([^\000]*)<!-- l2h_replace $l2h_name ([0-9]+) -->([^\000]*)/)
906  {
907    $to_do = $1;
908    $count = $2;
909    $done = $3.$done;
910   
911    $done = "<!-- l2h_end $l2h_name $count -->".$done
912      if ($T2H_DEBUG & $DEBUG_L2H);
913
914    $done = &l2h_ExtractFromHtml($count) . $done;
915
916    $done = "<!-- l2h_begin $l2h_name $count -->".$done
917      if ($T2H_DEBUG & $DEBUG_L2H);
918  }
919  return $to_do.$done;
920}
921
922
923sub l2h_ExtractFromHtml
924{
925  local($count) = @_;
926 
927  return $l2h_from_html[$count] if ($l2h_from_html[$count]);
928 
929  if ($count >= 0 && $count < $l2h_latex_count)
930  {
931    # now we are in trouble
932    local($l_l2h, $_);
933
934    $l2h_extract_error++;
935    print "$ERROR l2h: can't extract content $count from html\n" 
936      if ($T2H_VERBOSE);
937    # try simple (ordinary) substition (without l2h)
938    $l_l2h = $T2H_L2H;
939    $T2H_L2H = 0;
940    $_ = $l2h_to_latex{$count};
941    $_ = &substitute_style($_); 
942    &unprotect_texi;
943    $_ = "<!-- l2h: ". __LINE__ . " use texi2html -->" . $_
944      if ($T2H_DEBUG & $DEBUG_L2H);
945    $T2H_L2H = $l_l2h;
946    return $_;
947  }
948  else
949  {
950    # now we have been incorrectly called
951    $l2h_range_error++;
952    print "$ERROR l2h: Request of $count content which is out of valide range [0,$l2h_latex_count)\n";
953    return "<!-- l2h: ". __LINE__ . " out of range count $count -->"
954      if ($T2H_DEBUG & $DEBUG_L2H);
955    return "<!-- l2h: out of range count $count -->";
956  }
957}
958   
959sub l2h_FinishFromHtml
960{
961  if ($T2H_VERBOSE)
962  {
963    if ($l2h_extract_error + $l2h_range_error)
964    {
965      print "# l2h: finished from html ($l2h_extract_error extract and $l2h_range_error errors)\n";
966    }
967    else
968    {
969      print "# l2h: finished from html (no errors)\n";
970    }
971  }
972}
973
974sub l2h_Finish
975{
976  l2h_StoreCache();
977  if ($T2H_L2H_CLEAN)
978  {
979    print "# l2h: removing temporary files generated by l2h extension\n"
980      if $T2H_VERBOSE;
981    while (<"$docu_rdir$l2h_name"*>)
982    {
983      unlink $_;
984    }
985  }
986  print "# l2h: Finished\n" if $T2H_VERBOSE;
987  return 1;
988}
989
990##############################
991# stuff for l2h caching
992#
993
994# I tried doing this with a dbm data base, but it did not store all
995# keys/values. Hence, I did as latex2html does it
996sub l2h_InitCache
997{
998  if (-r "$l2h_cache_file")
999  {
1000    my $rdo = do "$l2h_cache_file";
1001    warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n")
1002      unless ($rdo);
1003  }
1004}
1005
1006sub l2h_StoreCache
1007{
1008  return unless $l2h_latex_count;
1009 
1010  my ($key, $value);
1011  open(FH, ">$l2h_cache_file") || return warn"$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n";
1012
1013 
1014  while (($key, $value) = each %l2h_cache)
1015  {
1016    # escape stuff
1017    $key =~ s|/|\\/|g;
1018    $key =~ s|\\\\/|\\/|g;
1019    # weird, a \ at the end of the key results in an error
1020    # maybe this also broke the dbm database stuff
1021    $key =~ s|\\$|\\\\|;
1022    $value =~ s/\|/\\\|/g; 
1023    $value =~ s/\\\\\|/\\\|/g; 
1024    $value =~ s|\\\\|\\\\\\\\|g;
1025    print FH "\n\$l2h_cache_key = q/$key/;\n";
1026    print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n";
1027  }
1028  print FH "1;";
1029  close(FH);
1030}
1031
1032# return cached html, if it exists for text, and if all pictures
1033# are there, as well
1034sub l2h_FromCache
1035{
1036  my $text = shift;
1037  my $cached = $l2h_cache{$text};
1038  if ($cached)
1039  {
1040    while ($cached =~ m/SRC="(.*?)"/g)
1041    {
1042      unless (-e "$docu_rdir$1")
1043      {
1044        return undef;
1045      }
1046    }
1047    return $cached;
1048  }
1049  return undef;
1050}
1051
1052# insert generated html into cache, move away images,
1053# return transformed html
1054$maximage = 1;
1055sub l2h_ToCache
1056{
1057  my $count = shift;
1058  my $content = shift;
1059  my @images = ($content =~ /SRC="(.*?)"/g);
1060  my ($src, $dest);
1061
1062  for $src (@images)
1063  {
1064    $dest = $l2h_img{$src};
1065    unless ($dest)
1066    {
1067      my $ext;
1068      if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext)
1069      {
1070        $ext = $1;
1071      }
1072      else
1073      {
1074        warn "$ERROR: L2h image $src has invalid extension\n";
1075        next;
1076      }
1077      while (-e "$docu_rdir${docu_name}_$maximage.$ext") { $maximage++;}
1078      $dest = "${docu_name}_$maximage.$ext";
1079      system("cp -f $docu_rdir$src $docu_rdir$dest");
1080      $l2h_img{$src} = $dest;
1081      unlink "$docu_rdir$src" unless ($DEBUG & DEBUG_L2H);
1082    }
1083    $content =~ s/$src/$dest/g;
1084  }
1085  $l2h_cache{$l2h_to_latex[$count]} = $content;
1086  return $content;
1087}
1088
[5d13bc]1089
1090#+++############################################################################
1091#                                                                              #
1092# Pass 1: read source, handle command, variable, simple substitution           #
1093#                                                                              #
1094#---############################################################################
1095
1096@lines = ();                            # whole document
1097@toc_lines = ();                        # table of contents
[4e425a]1098@stoc_lines = ();                       # table of contents
[5d13bc]1099$curlevel = 0;                          # current level in TOC
1100$node = '';                             # current node name
[4e425a]1101$node_next = '';                        # current node next name               
1102$node_prev = '';                        # current node prev name
1103$node_up = '';                          # current node up name
[5d13bc]1104$in_table = 0;                          # am I inside a table
[4e425a]1105$table_type = '';                       # type of table ('', 'f', 'v', 'multi')
[5d13bc]1106@tables = ();                           # nested table support
1107$in_bibliography = 0;                   # am I inside a bibliography
1108$in_glossary = 0;                       # am I inside a glossary
1109$in_top = 0;                            # am I inside the top node
[4e425a]1110$has_top = 0;                           # did I see a top node?
[5d13bc]1111$in_pre = 0;                            # am I inside a preformatted section
1112$in_list = 0;                           # am I inside a list
[4e425a]1113$in_html = 0;                           # am I inside an HTML section
[5d13bc]1114$first_line = 1;                        # is it the first line
1115$dont_html = 0;                         # don't protect HTML on this line
1116$deferred_ref = '';                     # deferred reference for indexes
1117@html_stack = ();                       # HTML elements stack
1118$html_element = '';                     # current HTML element
1119&html_reset;
[4e425a]1120
1121# init l2h
1122$T2H_L2H = &l2h_Init($docu_name) if ($T2H_L2H);
1123$T2H_L2H = &l2h_InitToLatex      if ($T2H_L2H);   
[5d13bc]1124
1125# build code for simple substitutions
1126# the maps used (%simple_map and %things_map) MUST be aware of this
1127# watch out for regexps, / and escaped characters!
1128$subst_code = '';
1129foreach (keys(%simple_map)) {
1130    ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
1131    $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
1132}
1133foreach (keys(%things_map)) {
1134    $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
1135}
1136if ($use_acc) {
1137    # accentuated characters
1138    foreach (keys(%accent_map)) {
1139        if ($_ eq "`") {
1140            $subst_code .= "s/$;3";
1141        } elsif ($_ eq "'") {
1142            $subst_code .= "s/$;4";
1143        } else {
1144            $subst_code .= "s/\\\@\\$_";
1145        }
1146        $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
1147    }
1148}
1149eval("sub simple_substitutions { $subst_code }");
1150
1151&init_input;
1152while ($_ = &next_line) {
1153    #
1154    # remove \input on the first lines only
1155    #
1156    if ($first_line) {
1157        next if /^\\input/;
1158        $first_line = 0;
1159    }
1160    #
1161    # parse texinfo tags
1162    #
1163    $tag = '';
1164    $end_tag = '';
[4e425a]1165    if (/^\s*\@end\s+(\w+)\b/) {
[5d13bc]1166        $end_tag = $1;
[4e425a]1167    } elsif (/^\s*\@(\w+)\b/) {
[5d13bc]1168        $tag = $1;
1169    }
1170    #
[4e425a]1171    # handle @html / @end html
[5d13bc]1172    #
1173    if ($in_html) {
[4e425a]1174        if ($end_tag eq 'html') {
[5d13bc]1175            $in_html = 0;
1176        } else {
1177            $tag2pro{$in_html} .= $_;
1178        }
1179        next;
[4e425a]1180    } elsif ($tag eq 'html') {
[5d13bc]1181        $in_html = $PROTECTTAG . ++$html_num;
[4e425a]1182        push(@lines, $in_html);
[5d13bc]1183        next;
1184    }
1185    #
1186    # try to skip the line
1187    #
1188    if ($end_tag) {
1189        next if $to_skip{"end $end_tag"};
1190    } elsif ($tag) {
1191        next if $to_skip{$tag};
1192        last if $tag eq 'bye';
1193    }
[4e425a]1194    if ($in_top) {
1195        # parsing the top node
1196        if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) {
1197            # no more in top
1198            $in_top = 0;
1199            push(@lines, $TOPEND);
[fb646a]1200        }
1201    }
[5d13bc]1202    #
1203    # try to remove inlined comments
1204    # syntax from tex-mode.el comment-start-skip
1205    #
[4e425a]1206    s/((^|[^\@])(\@\@)*)\@c(omment | |\{).*/$1/;
1207#     s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
1208#     s/(.*)\@c{.*?}(.*)/$1$2/;
1209#     s/(.*)\@comment{.*?}(.*)/$1$2/;
1210#     s/^(.*)\@c /$1/;
1211#     s/^(.*)\@comment /$1/;
[5d13bc]1212    # non-@ substitutions cf. texinfmt.el
[4e425a]1213    unless ($in_pre) {
1214        s/``/\"/g;
1215        s/''/\"/g;
1216        s/([\w ])---([\w ])/$1--$2/g;
1217    }
[5d13bc]1218    #
1219    # analyze the tag
1220    #
1221    if ($tag) {
1222        # skip lines
1223        &skip_until($tag), next if $tag eq 'ignore';
[4e425a]1224        &skip_until($tag), next if $tag eq 'ifnothtml';
1225        if ($tag eq 'ifinfo')
1226        {
1227          &skip_until($tag), next unless $T2H_EXPAND eq 'info';
1228        }
1229        if ($tag eq 'iftex')
1230        {
1231          &skip_until($tag), next unless $T2H_EXPAND eq 'tex';
1232        } 
1233        if ($tag eq 'tex')
1234        {
1235          # add to latex2html file
1236          if ($T2H_EXPAND eq 'tex' && $T2H_L2H && ! $in_pre)
1237          {
1238            # add space to the end -- tex(i2dvi) does this, as well
1239            push(@lines, &l2h_ToLatex(&string_until($tag) . " "));
1240          }
1241          else
1242          {
1243            &skip_until($tag);
1244          }
1245          next;
[5d13bc]1246        }
1247        # handle special tables
[4e425a]1248        if ($tag =~ /^(|f|v|multi)table$/) {
1249            $table_type = $1;
[5d13bc]1250            $tag = 'table';
1251        }
1252        # special cases
[4e425a]1253        if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*,/i)) {
[5d13bc]1254            $in_top = 1;
[4e425a]1255            $has_top = 1;
1256            @lines = (); # ignore all lines before top (title page garbage)
[5d13bc]1257            next;
1258        } elsif ($tag eq 'node') {
[4e425a]1259          if ($in_top)
1260          {
[5d13bc]1261            $in_top = 0;
[4e425a]1262            push(@lines, $TOPEND);
1263          }
1264          warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
1265          $_ = &protect_html($_); # if node contains '&' for instance
1266          s/^\@node\s+//;
1267          ($node, $node_next, $node_prev, $node_up) = split(/,/);
1268          &normalise_node($node);
1269          &normalise_node($node_next);
1270          &normalise_node($node_prev);
1271          &normalise_node($node_up);
1272          next;
[5d13bc]1273        } elsif ($tag eq 'include') {
1274            if (/^\@include\s+($FILERE)\s*$/o) {
1275                $file = $1;
1276                unless (-e $file) {
[4e425a]1277                    foreach $dir (@T2H_INCLUDE_DIRS) {
[5d13bc]1278                        $file = "$dir/$1";
1279                        last if -e $file;
1280                    }
1281                }
1282                if (-e $file) {
1283                    &open($file);
[4e425a]1284                    print "# including $file\n" if $T2H_VERBOSE;
[5d13bc]1285                } else {
1286                    warn "$ERROR Can't find $file, skipping";
1287                }
1288            } else {
1289                warn "$ERROR Bad include line: $_";
1290            }
1291            next;
1292        } elsif ($tag eq 'ifclear') {
1293            if (/^\@ifclear\s+($VARRE)\s*$/o) {
1294                next unless defined($value{$1});
1295                &skip_until($tag);
1296            } else {
1297                warn "$ERROR Bad ifclear line: $_";
1298            }
1299            next;
1300        } elsif ($tag eq 'ifset') {
1301            if (/^\@ifset\s+($VARRE)\s*$/o) {
1302                next if defined($value{$1});
1303                &skip_until($tag);
1304            } else {
1305                warn "$ERROR Bad ifset line: $_";
1306            }
1307            next;
1308        } elsif ($tag eq 'menu') {
[4e425a]1309            unless ($T2H_SHOW_MENU) {
[5d13bc]1310                &skip_until($tag);
1311                next;
1312            }
1313            &html_push_if($tag);
1314            push(@lines, &html_debug("\n", __LINE__));
1315        } elsif ($format_map{$tag}) {
1316            $in_pre = 1 if $format_map{$tag} eq 'PRE';
1317            &html_push_if($format_map{$tag});
1318            push(@lines, &html_debug("\n", __LINE__));
1319            $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
[4e425a]1320            push(@lines, &debug('<FONT size="-1">'."\n", __LINE__))
1321               if $tag =~ /smallexample/i;
1322            push(@lines, &debug("<BLOCKQUOTE>\n", __LINE__))
1323              if $tag =~ /example/i;
[5d13bc]1324            push(@lines, &debug("<$format_map{$tag}>\n", __LINE__));
1325            next;
1326        } elsif ($tag eq 'table') {
[4e425a]1327            if (/^\s*\@(|f|v|multi)table\s+\@(\w+)/) {
1328                $in_table = $2;
[5d13bc]1329                unshift(@tables, join($;, $table_type, $in_table));
[4e425a]1330                if ($table_type eq "multi") {
1331                    # don't use borders -- gets confused by empty cells
1332                    push(@lines, &debug("<TABLE>\n", __LINE__));
1333                    &html_push_if('TABLE');
1334                } else {
1335                    push(@lines, &debug("<DL COMPACT>\n", __LINE__));
1336                    &html_push_if('DL');
1337                }
[5d13bc]1338                push(@lines, &html_debug("\n", __LINE__));
1339            } else {
1340                warn "$ERROR Bad table line: $_";
1341            }
1342            next;
1343        } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
1344            if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
1345                eval("*${1}index = *${2}index");
1346            } else {
1347                warn "$ERROR Bad syn*index line: $_";
1348            }
1349            next;
1350        } elsif ($tag eq 'sp') {
1351            push(@lines, &debug("<P>\n", __LINE__));
1352            next;
[4e425a]1353        } elsif ($tag eq 'center') {
1354            push(@lines, &debug("<center>\n", __LINE__));
1355            s/\@center//;
[5d13bc]1356        } elsif ($tag eq 'setref') {
1357            &protect_html; # if setref contains '&' for instance
1358            if (/^\@$tag\s*{($NODERE)}\s*$/) {
1359                $setref = $1;
1360                $setref =~ s/\s+/ /g; # normalize
1361                $setref =~ s/ $//;
1362                $node2sec{$setref} = $name;
[4e425a]1363                $sec2node{$name} = $setref;
[5d13bc]1364                $node2href{$setref} = "$docu_doc#$docid";
1365            } else {
1366                warn "$ERROR Bad setref line: $_";
1367            }
1368            next;
1369        } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
1370            if (/^\@$tag\s+(\w\w)\s*$/) {
1371                $valid_index{$1} = 1;
1372            } else {
1373                warn "$ERROR Bad defindex line: $_";
1374            }
1375            next;
[4e425a]1376        } elsif ($tag eq 'lowersections') {
1377            local ($sec, $level);
1378            while (($sec, $level) = each %sec2level) {
1379                $sec2level{$sec} = $level + 1;
1380            }
1381            next;
1382        } elsif ($tag eq 'raisesections') {
1383            local ($sec, $level);
1384            while (($sec, $level) = each %sec2level) {
1385                $sec2level{$sec} = $level - 1;
1386            }
[5d13bc]1387            next;
1388        } elsif (defined($def_map{$tag})) {
1389            if ($def_map{$tag}) {
1390                s/^\@$tag\s+//;
1391                $tag = $def_map{$tag};
1392                $_ = "\@$tag $_";
1393                $tag =~ s/\s.*//;
1394            }
1395        } elsif (defined($user_sub{$tag})) {
1396            s/^\@$tag\s+//;
1397            $sub = $user_sub{$tag};
[4e425a]1398            print "# user $tag = $sub, arg: $_" if $T2H_DEBUG & $DEBUG_USER;
[5d13bc]1399            if (defined(&$sub)) {
1400                chop($_);
1401                &$sub($_);
1402            } else {
1403                warn "$ERROR Bad user sub for $tag: $sub\n";
1404            }
1405            next;
1406        }
1407        if (defined($def_map{$tag})) {
1408            s/^\@$tag\s+//;
1409            if ($tag =~ /x$/) {
1410                # extra definition line
1411                $tag = $`;
1412                $is_extra = 1;
1413            } else {
1414                $is_extra = 0;
1415            }
1416            while (/\{([^\{\}]*)\}/) {
1417                # this is a {} construct
1418                ($before, $contents, $after) = ($`, $1, $');
1419                # protect spaces
1420                $contents =~ s/\s+/$;9/g;
1421                # restore $_ protecting {}
1422                $_ = "$before$;7$contents$;8$after";
1423            }
1424            @args = split(/\s+/, &protect_html($_));
1425            foreach (@args) {
1426                s/$;9/ /g;      # unprotect spaces
1427                s/$;7/\{/g;     # ... {
1428                s/$;8/\}/g;     # ... }
1429            }
1430            $type = shift(@args);
1431            $type =~ s/^\{(.*)\}$/$1/;
1432            print "# def ($tag): {$type} ", join(', ', @args), "\n"
[4e425a]1433                if $T2H_DEBUG & $DEBUG_DEF;
[5d13bc]1434            $type .= ':'; # it's nicer like this
1435            $name = shift(@args);
1436            $name =~ s/^\{(.*)\}$/$1/;
1437            if ($is_extra) {
1438                $_ = &debug("<DT>", __LINE__);
1439            } else {
1440                $_ = &debug("<DL>\n<DT>", __LINE__);
1441            }
1442            if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') {
1443                $_ .= "<U>$type</U> <B>$name</B>";
1444                $_ .= " <I>@args</I>" if @args;
1445            } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
1446                     || $tag eq 'defcv' || $tag eq 'defop') {
1447                $ftype = $name;
1448                $name = shift(@args);
1449                $name =~ s/^\{(.*)\}$/$1/;
1450                $_ .= "<U>$type</U> $ftype <B>$name</B>";
1451                $_ .= " <I>@args</I>" if @args;
1452            } else {
1453                warn "$ERROR Unknown definition type: $tag\n";
1454                $_ .= "<U>$type</U> <B>$name</B>";
1455                $_ .= " <I>@args</I>" if @args;
1456            }
1457            $_ .= &debug("\n<DD>", __LINE__);
1458            $name = &unprotect_html($name);
1459            if ($tag eq 'deffn' || $tag eq 'deftypefn') {
1460                unshift(@input_spool, "\@findex $name\n");
1461            } elsif ($tag eq 'defop') {
1462                unshift(@input_spool, "\@findex $name on $ftype\n");
1463            } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') {
1464                unshift(@input_spool, "\@vindex $name\n");
1465            } else {
1466                unshift(@input_spool, "\@tindex $name\n");
1467            }
1468            $dont_html = 1;
1469        }
1470    } elsif ($end_tag) {
1471        if ($format_map{$end_tag}) {
1472            $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
1473            $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
1474            &html_pop_if('LI', 'P');
1475            &html_pop_if();
1476            push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
[4e425a]1477            push(@lines, &debug("</BLOCKQUOTE>\n", __LINE__))
1478              if $end_tag =~ /example/i;
1479            push(@lines, &debug("</FONT>\n", __LINE__))
1480               if $end_tag =~ /smallexample/i;
[5d13bc]1481            push(@lines, &html_debug("\n", __LINE__));
[4e425a]1482        } elsif ($end_tag =~ /^(|f|v|multi)table$/) {
1483            unless (@tables) {
1484                warn "$ERROR \@end $end_tag without \@*table\n";
1485                next;
1486            }
1487            ($table_type, $in_table) = split($;, shift(@tables));
1488            unless ($1 eq $table_type) {
1489                warn "$ERROR \@end $end_tag without matching \@$end_tag\n";
1490                next;
1491            }
1492            if ($table_type eq "multi") {
1493                push(@lines, "</TR></TABLE>\n");
1494                &html_pop_if('TR');
1495            } else {
1496                push(@lines, "</DL>\n");
1497                &html_pop_if('DD');
1498            }
1499            &html_pop_if();
[5d13bc]1500            if (@tables) {
1501                ($table_type, $in_table) = split($;, $tables[0]);
1502            } else {
1503                $in_table = 0;
1504            }
1505        } elsif (defined($def_map{$end_tag})) {
1506            push(@lines, &debug("</DL>\n", __LINE__));
1507        } elsif ($end_tag eq 'menu') {
1508            &html_pop_if();
1509            push(@lines, $_); # must keep it for pass 2
[4e425a]1510        } 
[5d13bc]1511        next;
1512    }
1513    #
1514    # misc things
1515    #
1516    # protect texi and HTML things
1517    &protect_texi;
1518    $_ = &protect_html($_) unless $dont_html;
1519    $dont_html = 0;
1520    # substitution (unsupported things)
1521    s/^\@exdent\s+//g;
1522    s/\@noindent\s+//g;
1523    s/\@refill\s+//g;
1524    # other substitutions
1525    &simple_substitutions;
1526    s/\@value{($VARRE)}/$value{$1}/eg;
1527    s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
1528    #
1529    # analyze the tag again
1530    #
1531    if ($tag) {
[4e425a]1532      if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
[5d13bc]1533            if (/^\@$tag\s+(.+)$/) {
1534                $name = $1;
1535                $name =~ s/\s+$//;
1536                $level = $sec2level{$tag};
1537                if ($tag =~ /heading$/) {
1538                    push(@lines, &html_debug("\n", __LINE__));
1539                    if ($html_element ne 'body') {
1540                        # We are in a nice pickle here. We are trying to get a H? heading
1541                        # even though we are not in the body level. So, we convert it to a
1542                        # nice, bold, line by itself.
[4e425a]1543                        $_ = &debug("\n\n<P><STRONG>$name</STRONG>\n\n", __LINE__);
[5d13bc]1544                    } else {
1545                        $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
1546                        &html_push_if('body');
1547                    }
1548                    print "# heading, section $name, level $level\n"
[4e425a]1549                        if $T2H_DEBUG & $DEBUG_TOC;
[5d13bc]1550                } else {
[4e425a]1551                $node = $name unless $node; 
1552                $name = &update_sec_num($tag, $level) . " $name"
1553                    if $T2H_NUMBER_SECTIONS && $tag !~ /^unnumbered/;
1554                  if (defined($toplevel))
1555                  {
1556                    push @lines, ($level==$toplevel ? $CHAPTEREND : $SECTIONEND);
1557                  }
1558                  else
1559                  {
1560                    # first time we see a "section"
1561                    unless ($level == 1) 
1562                    {
1563                      warn "$ERROR The first section found is not of level 1: $_";
[5d13bc]1564                    }
[4e425a]1565                    $toplevel = $level;
1566                  }
1567                  push(@sections, $name);
1568                  next_doc() if ($T2H_SPLIT eq 'section' || 
1569                                 ($T2H_SPLIT && $level == $toplevel));
1570                  $sec_num++;
1571                  $docid = "SEC$sec_num";
1572                  $tocid = "TOC$sec_num";
[5d13bc]1573                    # check biblio and glossary
[4e425a]1574                  $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
1575                  $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
[5d13bc]1576                    # check node
[4e425a]1577                    if ($node2sec{$node}) {
1578                      warn "$ERROR Duplicate node found: $node\n";
1579                    } else {
[5d13bc]1580                            $node2sec{$node} = $name;
[4e425a]1581                            warn "$ERROR Duplicate section found: $name\n"
1582                              if ($sec2node{$name});
1583                            $sec2node{$name} = $node;
[5d13bc]1584                            $node2href{$node} = "$docu_doc#$docid";
[4e425a]1585                            $node2next{$node} = $node_next;
1586                            $node2prev{$node} = $node_prev;
1587                            $node2up{$node} = $node_up;
[5d13bc]1588                            print "# node $node, section $name, level $level\n"
[4e425a]1589                                if $T2H_DEBUG & $DEBUG_TOC;
[5d13bc]1590                        }
1591                        $node = '';
[4e425a]1592                        $node_next = '';
1593                        $node_prev = '';
1594                        $node_next = '';
[5d13bc]1595                    # update TOC
1596                    while ($level > $curlevel) {
1597                        $curlevel++;
1598                        push(@toc_lines, "<UL>\n");
1599                    }
1600                    while ($level < $curlevel) {
1601                        $curlevel--;
1602                        push(@toc_lines, "</UL>\n");
1603                    }
[4e425a]1604                    $_ = &t2h_anchor($tocid, "$docu_doc#$docid", $name, 1);
1605                    $_ = &substitute_style($_);
1606                    push(@stoc_lines, "$_<BR>\n") if ($level == 1);
1607                    push(@toc_lines, "<LI>" . $_ ."</LI>");
[5d13bc]1608                    # update DOC
1609                    push(@lines, &html_debug("\n", __LINE__));
1610                    &html_reset;
[4e425a]1611#                   $_ =  "<H$level>".&t2h_anchor($docid, '', $name)."</H$level>\n";
1612                    $_ =  "<H$level> $name </H$level>\n";                   
[5d13bc]1613                    $_ = &debug($_, __LINE__);
1614                    push(@lines, &html_debug("\n", __LINE__));
1615                }
1616                # update DOC
1617                foreach $line (split(/\n+/, $_)) {
1618                    push(@lines, "$line\n");
1619                }
1620                next;
1621            } else {
1622                warn "$ERROR Bad section line: $_";
1623            }
1624        } else {
1625            # track variables
1626            $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o;
1627            delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
1628            # store things
1629            $value{'_setfilename'}   = $1, next if /^\@setfilename\s+(.*)$/;
1630            $value{'_settitle'}      = $1, next if /^\@settitle\s+(.*)$/;
1631            $value{'_author'}   .= "$1\n", next if /^\@author\s+(.*)$/;
1632            $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/;
1633            $value{'_title'}    .= "$1\n", next if /^\@title\s+(.*)$/;
1634            # index
1635            if (/^\@(..?)index\s+/) {
1636                unless ($valid_index{$1}) {
1637                    warn "$ERROR Undefined index command: $_";
1638                    next;
1639                }
[4e425a]1640                $id = ($T2H_SECTION_IDX ? $docid : 'IDX' . ++$idx_num);
[5d13bc]1641                $index = $1 . 'index';
1642                $what = &substitute_style($');
1643                $what =~ s/\s+$//;
1644                print "# found $index for '$what' id $id\n"
[4e425a]1645                    if $T2H_DEBUG & $DEBUG_INDEX;
[5d13bc]1646                eval(<<EOC);
1647                if (defined(\$$index\{\$what\})) {
1648                    \$$index\{\$what\} .= "$;$docu_doc#$id";
1649                } else {
1650                    \$$index\{\$what\} = "$docu_doc#$id";
1651                }
1652EOC
1653                #
1654                # dirty hack to see if I can put an invisible anchor...
1655                #
[4e425a]1656                unless ($T2H_SECTION_IDX) {
1657                if (
1658                    $html_element eq 'P' ||
[5d13bc]1659                    $html_element eq 'LI' ||
1660                    $html_element eq 'DT' ||
1661                    $html_element eq 'DD' ||
1662                    $html_element eq 'ADDRESS' ||
1663                    $html_element eq 'B' ||
1664                    $html_element eq 'BLOCKQUOTE' ||
1665                    $html_element eq 'PRE' ||
1666                    $html_element eq 'SAMP') {
[4e425a]1667                    push(@lines, &t2h_anchor($id, '', $T2H_INVISIBLE_MARK, !$in_pre));
[5d13bc]1668                } elsif ($html_element eq 'body') {
1669                    push(@lines, &debug("<P>\n", __LINE__));
[4e425a]1670                    push(@lines, &t2h_anchor($id, '', $T2H_INVISIBLE_MARK, !$in_pre));
[5d13bc]1671                    &html_push('P');
1672                } elsif ($html_element eq 'DL' ||
1673                         $html_element eq 'UL' ||
1674                         $html_element eq 'OL' ) {
[4e425a]1675                    $deferred_ref .= &t2h_anchor($id, '', $T2H_INVISIBLE_MARK, !$in_pre) . " ";
[5d13bc]1676                }
[4e425a]1677              }
[5d13bc]1678                next;
1679            }
1680            # list item
[4e425a]1681            if (/^\s*\@itemx?\s+/) {
[5d13bc]1682                $what = $';
1683                $what =~ s/\s+$//;
1684                if ($in_bibliography && $use_bibliography) {
1685                    if ($what =~ /^$BIBRE$/o) {
1686                        $id = 'BIB' . ++$bib_num;
1687                        $bib2href{$what} = "$docu_doc#$id";
1688                        print "# found bibliography for '$what' id $id\n"
[4e425a]1689                            if $T2H_DEBUG & $DEBUG_BIB;
1690                        $what = &t2h_anchor($id, '', $what);
[5d13bc]1691                    }
[4e425a]1692                } elsif ($in_glossary && $T2H_USE_GLOSSARY) {
[5d13bc]1693                    $id = 'GLOSS' . ++$gloss_num;
1694                    $entry = $what;
1695                    $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
1696                    $gloss2href{$entry} = "$docu_doc#$id";
1697                    print "# found glossary for '$entry' id $id\n"
[4e425a]1698                        if $T2H_DEBUG & $DEBUG_GLOSS;
1699                    $what = &t2h_anchor($id, '', $what);
[5d13bc]1700                }
1701                &html_pop_if('P');
1702                if ($html_element eq 'DL' || $html_element eq 'DD') {
1703                    if ($things_map{$in_table} && !$what) {
1704                        # special case to allow @table @bullet for instance
1705                        push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__));
1706                    } else {
1707                        push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
1708                    }
1709                    push(@lines, "<DD>");
1710                    &html_push('DD') unless $html_element eq 'DD';
1711                    if ($table_type) { # add also an index
1712                        unshift(@input_spool, "\@${table_type}index $what\n");
1713                    }
[4e425a]1714                } elsif ($html_element eq 'TABLE') {
1715                    push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
1716                    &html_push('TR');
1717                } elsif ($html_element eq 'TR') {
1718                    push(@lines, &debug("</TR>\n", __LINE__));
1719                    push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
[5d13bc]1720                } else {
1721                    push(@lines, &debug("<LI>$what\n", __LINE__));
1722                    &html_push('LI') unless $html_element eq 'LI';
1723                }
1724                push(@lines, &html_debug("\n", __LINE__));
1725                if ($deferred_ref) {
1726                    push(@lines, &debug("$deferred_ref\n", __LINE__));
1727                    $deferred_ref = '';
1728                }
1729                next;
[4e425a]1730            } elsif (/^\@tab\s+(.*)$/) {
1731                push(@lines, "<TD>$1</TD>\n");
1732                next;
[5d13bc]1733            }
1734        }
1735    }
1736    # paragraph separator
1737    if ($_ eq "\n") {
1738        next if $#lines >= 0 && $lines[$#lines] eq "\n";
1739        if ($html_element eq 'P') {
[4e425a]1740            push (@lines, &debug("</P><P>\n", __LINE__));
[5d13bc]1741        }
[4e425a]1742#       else
1743#       {
1744#         push(@lines, "<P></P>\n");
1745#         $_ = &debug("<P></P>\n", __LINE__);
1746#       }
1747        elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE' || $html_element eq 'DD') 
1748        {
1749          &html_push('P');
1750          push(@lines, &debug("<P>\n", __LINE__));
1751        }
1752      }
[5d13bc]1753    # otherwise
1754    push(@lines, $_);
[4e425a]1755
1756    push(@lines, &debug("</center>\n", __LINE__))  if ($tag eq 'center');
[5d13bc]1757}
1758
1759# finish TOC
1760$level = 0;
1761while ($level < $curlevel) {
1762    $curlevel--;
1763    push(@toc_lines, "</UL>\n");
1764}
1765
[4e425a]1766print "# end of pass 1\n" if $T2H_VERBOSE;
[5d13bc]1767
1768#+++############################################################################
1769#                                                                              #
1770# Pass 2/3: handle style, menu, index, cross-reference                         #
1771#                                                                              #
1772#---############################################################################
1773
1774@lines2 = ();                           # whole document (2nd pass)
1775@lines3 = ();                           # whole document (3rd pass)
1776$in_menu = 0;                           # am I inside a menu
1777
1778while (@lines) {
1779    $_ = shift(@lines);
1780    #
1781    # special case (protected sections)
1782    #
1783    if (/^$PROTECTTAG/o) {
1784        push(@lines2, $_);
1785        next;
1786    }
1787    #
1788    # menu
1789    #
[4e425a]1790    if (/^\@menu\b/)
1791    {
1792      $in_menu = 1;
1793      $T2H_NUMBER_SECTIONS ?
1794        push(@lines2, &debug("<BLOCKQUOTE><TABLE BORDER=0 CELLSPACING=0> \n", __LINE__)) :
1795          push(@lines2, &debug("<UL>\n", __LINE__));
1796      next;
1797    }
1798    if (/^\@end\s+menu\b/)
1799    {
1800      $in_menu = 0;
1801      $T2H_NUMBER_SECTIONS ?
1802        push(@lines2, &debug("</TABLE></BLOCKQUOTE>\n", __LINE__)) :
1803          push(@lines2, &debug("</UL>\n", __LINE__));
1804      next;
1805    }
[5d13bc]1806    if ($in_menu) {
1807        if (/^\*\s+($NODERE)::/o) {
1808            $descr = $';
1809            chop($descr);
1810            &menu_entry($1, $1, $descr);
1811        } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
1812            $descr = $';
1813            chop($descr);
1814            &menu_entry($1, $2, $descr);
1815        } elsif (/^\*/) {
1816            warn "$ERROR Bad menu line: $_";
1817        } else { # description continued?
1818            push(@lines2, $_);
1819        }
1820        next;
1821    }
1822    #
1823    # printindex
1824    #
[4e425a]1825    # obachman: replace ^\@printindex by \@printindex, otherwise
1826    # generation in debug mode fails
1827    if (/\@printindex\s+(\w\w)\b/) {
1828        local($index, *ary, @keys, $key, $letter, $last_letter, @refs, $fhidx);
[5d13bc]1829        if ($predefined_index{$1}) {
1830            $index = $predefined_index{$1} . 'index';
1831        } else {
1832            $index = $1 . 'index';
1833        }
[4e425a]1834        # check for index summary
1835        $letter = $1;
1836        if ($letter =~ /$T2H_IDX_SUMMARY/)
1837        {
1838          open(FHIDX, "> $docu_rdir$docu_name" . "_$letter.idx")
1839            || die "Can't open > $docu_rdir$docu_name" . "_$letter.idx for writing: $!\n";
1840          $fhidx = \*FHIDX;
1841          print "# writing index summary in $docu_rdir$docu_name" . "_$letter.idx..." if $T2H_VERBOSE;
1842        }
[5d13bc]1843        eval("*ary = *$index");
1844        @keys = keys(%ary);
1845        foreach $key (@keys) {
1846            $_ = $key;
1847            1 while s/<(\w+)>\`(.*)\'<\/\1>/$2/; # remove HTML tags with quotes
1848            1 while s/<(\w+)>(.*)<\/\1>/$2/;     # remove HTML tags
1849            $_ = &unprotect_html($_);
1850            &unprotect_texi;
1851            tr/A-Z/a-z/; # lowercase
1852            $key2alpha{$key} = $_;
1853            print "# index $key sorted as $_\n"
[4e425a]1854                if $key ne $_ && $T2H_DEBUG & $DEBUG_INDEX;
1855        }
1856        push(@lines2, "Jump to:\n");
1857        $last_letter = undef;
1858        foreach $key (sort byalpha @keys) {
1859            $letter = substr($key2alpha{$key}, 0, 1);
1860            $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
1861            if (!defined($last_letter) || $letter ne $last_letter) {
1862                push(@lines2, "-\n") if defined($last_letter);
1863                push(@lines2, "<A HREF=\"#$index\_$letter\">" . &protect_html($letter) . "</A>\n");
1864                $last_letter = $letter;
1865            }
[5d13bc]1866        }
[4e425a]1867        push(@lines2, "<P>\n");
[5d13bc]1868        $last_letter = undef;
1869        foreach $key (sort byalpha @keys) {
1870            $letter = substr($key2alpha{$key}, 0, 1);
1871            $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
1872            if (!defined($last_letter) || $letter ne $last_letter) {
1873                push(@lines2, "</DIR>\n") if defined($last_letter);
[4e425a]1874                push(@lines2, "<H2><A NAME=\"$index\_$letter\">" . &protect_html($letter) . "</A></H2>\n");
[5d13bc]1875                push(@lines2, "<DIR>\n");
1876                $last_letter = $letter;
1877            }
1878            @refs = ();
1879            foreach (split(/$;/, $ary{$key})) {
[4e425a]1880                push(@refs, &t2h_anchor('', $_, $key, 0));
[5d13bc]1881            }
1882            push(@lines2, "<LI>" . join(", ", @refs) . "\n");
[4e425a]1883            if ($fhidx)
1884            {
1885              ($letter) = split(/$;/, $ary{$key});
1886              $key = unprotect_html($key);
1887              print $fhidx "$key\t$letter\n";
1888            }
[5d13bc]1889        }
1890        push(@lines2, "</DIR>\n") if defined($last_letter);
[4e425a]1891        if ($fhidx)
1892        {
1893          print "\n" if $T2H_VERBOSE;
1894          close($fhidx);
1895        }
[5d13bc]1896        next;
1897    }
1898    #
1899    # simple style substitutions
1900    #
1901    $_ = &substitute_style($_);
1902    #
1903    # xref
1904    #
1905    while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) {
1906        # note: Texinfo may accept other characters
1907        ($type, $nodes, $full) = ($1, $2, $3);
1908        ($before, $after) = ($`, $');
1909        if (! $full && $after) {
1910            warn "$ERROR Bad xref (no ending } on line): $_";
1911            $_ = "$before$;0${type}ref\{$nodes$after";
1912            next; # while xref
1913        }
1914        if ($type eq 'x') {
1915            $type = 'See ';
1916        } elsif ($type eq 'px') {
1917            $type = 'see ';
1918        } elsif ($type eq 'info') {
1919            $type = 'See Info';
1920        } else {
1921            $type = '';
1922        }
1923        unless ($full) {
1924            $next = shift(@lines);
1925            $next = &substitute_style($next);
1926            chop($nodes); # remove final newline
1927            if ($next =~ /\}/) { # split on 2 lines
1928                $nodes .= " $`";
1929                $after = $';
1930            } else {
1931                $nodes .= " $next";
1932                $next = shift(@lines);
1933                $next = &substitute_style($next);
1934                chop($nodes);
1935                if ($next =~ /\}/) { # split on 3 lines
1936                    $nodes .= " $`";
1937                    $after = $';
1938                } else {
1939                    warn "$ERROR Bad xref (no ending }): $_";
1940                    $_ = "$before$;0xref\{$nodes$after";
1941                    unshift(@lines, $next);
1942                    next; # while xref
1943                }
1944            }
1945        }
1946        $nodes =~ s/\s+/ /g; # remove useless spaces
1947        @args = split(/\s*,\s*/, $nodes);
1948        $node = $args[0]; # the node is always the first arg
1949        &normalise_node($node);
1950        $sec = $node2sec{$node};
[4e425a]1951        $href = $node2href{$node};
[5d13bc]1952        if (@args == 5) { # reference to another manual
1953            $sec = $args[2] || $node;
1954            $man = $args[4] || $args[3];
[4e425a]1955            $_ = "${before}${type}section `$sec' in \@cite{$man}$after";
[5d13bc]1956        } elsif ($type =~ /Info/) { # inforef
1957            warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
1958            ($nn, $_, $in) = @args;
1959            $_ = "${before}${type} file `$in', node `$nn'$after";
[4e425a]1960        } elsif ($sec && $href && ! $T2H_SHORT_REF) {
1961            $_ = "${before}${type}section " . 
1962              &t2h_anchor('', $href, $sec) . $after;
1963        } 
1964        elsif ($href && $T2H_SHORT_REF)
1965        {
1966          $_ = "${before}${type} " . &t2h_anchor('', $href, $node) . $after;
1967        }
1968        else {
[5d13bc]1969            warn "$ERROR Undefined node ($node): $_";
1970            $_ = "$before$;0xref{$nodes}$after";
1971        }
1972    }
[4e425a]1973   
1974    if (/^\@image\s*{/) {
1975      s/\@image\s*{//;
1976      my (@args) = split (/,/);
1977      my $base = $args[0];
1978      my $image;
1979      if (-r "$base.jpg") {
1980        $image = "$base.jpg";
1981      } elsif (-r "$base.png") {
1982        $image = "$base.png";
1983      } elsif (-r "$base.gif") {
1984        $image = "$base.gif";
1985      } else {
1986        warn "$ERROR no image file for $base: $_";
1987      }
1988      $_ = "<IMG SRC=\"$image\" ALT=\"$base\">";
1989    }
1990
[5d13bc]1991    #
1992    # try to guess bibliography references or glossary terms
1993    #
1994    unless (/^<H\d><A NAME=\"SEC\d/) {
1995        if ($use_bibliography) {
1996            $done = '';
1997            while (/$BIBRE/o) {
1998                ($pre, $what, $post) = ($`, $&, $');
1999                $href = $bib2href{$what};
2000                if (defined($href) && $post !~ /^[^<]*<\/A>/) {
[4e425a]2001                    $done .= $pre . &t2h_anchor('', $href, $what);
[5d13bc]2002                } else {
2003                    $done .= "$pre$what";
2004                }
2005                $_ = $post;
2006            }
2007            $_ = $done . $_;
2008        }
[4e425a]2009        if ($T2H_USE_GLOSSARY) {
[5d13bc]2010            $done = '';
2011            while (/\b\w+\b/) {
2012                ($pre, $what, $post) = ($`, $&, $');
2013                $entry = $what;
2014                $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
2015                $href = $gloss2href{$entry};
2016                if (defined($href) && $post !~ /^[^<]*<\/A>/) {
[4e425a]2017                    $done .= $pre . &t2h_anchor('', $href, $what);
[5d13bc]2018                } else {
2019                    $done .= "$pre$what";
2020                }
2021                $_ = $post;
2022            }
2023            $_ = $done . $_;
2024        }
2025    }
2026    # otherwise
2027    push(@lines2, $_);
2028}
[4e425a]2029print "# end of pass 2\n" if $T2H_VERBOSE;
[5d13bc]2030
2031#
2032# split style substitutions
2033#
2034while (@lines2) {
2035    $_ = shift(@lines2);
2036    #
2037    # special case (protected sections)
2038    #
2039    if (/^$PROTECTTAG/o) {
2040        push(@lines3, $_);
2041        next;
2042    }
2043    #
2044    # split style substitutions
2045    #
2046    $old = '';
2047    while ($old ne $_) {
2048        $old = $_;
2049        if (/\@(\w+)\{/) {
2050            ($before, $style, $after) = ($`, $1, $');
2051            if (defined($style_map{$style})) {
2052                $_ = $after;
2053                $text = '';
2054                $after = '';
2055                $failed = 1;
2056                while (@lines2) {
2057                    if (/\}/) {
2058                        $text .= $`;
2059                        $after = $';
2060                        $failed = 0;
2061                        last;
2062                    } else {
2063                        $text .= $_;
2064                        $_ = shift(@lines2);
2065                    }
2066                }
2067                if ($failed) {
2068                    die "* Bad syntax (\@$style) after: $before\n";
2069                } else {
2070                    $text = &apply_style($style, $text);
2071                    $_ = "$before$text$after";
2072                }
2073            }
2074        }
2075    }
2076    # otherwise
2077    push(@lines3, $_);
2078}
[4e425a]2079print "# end of pass 3\n" if $T2H_VERBOSE;
2080       
[5d13bc]2081#+++############################################################################
2082#                                                                              #
2083# Pass 4: foot notes, final cleanup                                            #
2084#                                                                              #
2085#---############################################################################
2086
2087@foot_lines = ();                       # footnotes
2088@doc_lines = ();                        # final document
2089$end_of_para = 0;                       # true if last line is <P>
[4e425a]2090       
[5d13bc]2091while (@lines3) {
2092    $_ = shift(@lines3);
2093    #
2094    # special case (protected sections)
2095    #
2096    if (/^$PROTECTTAG/o) {
2097        push(@doc_lines, $_);
2098        $end_of_para = 0;
2099        next;
2100    }
2101    #
2102    # footnotes
2103    #
2104    while (/\@footnote([^\{\s]+)\{/) {
2105        ($before, $d, $after) = ($`, $1, $');
2106        $_ = $after;
2107        $text = '';
2108        $after = '';
2109        $failed = 1;
2110        while (@lines3) {
2111            if (/\}/) {
2112                $text .= $`;
2113                $after = $';
2114                $failed = 0;
2115                last;
2116            } else {
2117                $text .= $_;
2118                $_ = shift(@lines3);
2119            }
2120        }
2121        if ($failed) {
2122            die "* Bad syntax (\@footnote) after: $before\n";
2123        } else {
2124            $foot_num++;
2125            $docid  = "DOCF$foot_num";
2126            $footid = "FOOT$foot_num";
2127            $foot = "($foot_num)";
[4e425a]2128            push(@foot_lines, "<H3>" . &t2h_anchor($footid, "$d#$docid", $foot) . "</H3>\n");
[5d13bc]2129            $text = "<P>$text" unless $text =~ /^\s*<P>/;
2130            push(@foot_lines, "$text\n");
[4e425a]2131            $_ = $before . &t2h_anchor($docid, "$docu_foot#$footid", $foot) . $after;
[5d13bc]2132        }
2133    }
2134    #
2135    # remove unnecessary <P>
2136    #
2137    if (/^\s*<P>\s*$/) {
2138        next if $end_of_para++;
2139    } else {
2140        $end_of_para = 0;
2141    }
2142    # otherwise
2143    push(@doc_lines, $_);
2144}
[4e425a]2145       
2146print "# end of pass 4\n" if $T2H_VERBOSE;
[5d13bc]2147
2148#+++############################################################################
2149#                                                                              #
[4e425a]2150# Pass 5: print things                                                         #
[5d13bc]2151#                                                                              #
2152#---############################################################################
2153
[4e425a]2154$T2H_L2H = &l2h_FinishToLatex if ($T2H_L2H);
2155$T2H_L2H = &l2h_ToHtml        if ($T2H_L2H);
2156$T2H_L2H = &l2h_InitFromHtml  if ($T2H_L2H);
2157
2158# prepare %T2H_THISDOC
2159$T2H_THISDOC{fulltitle} = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
2160$T2H_THISDOC{title} = $value{'_settitle'} || $T2H_THISDOC{fulltitle};
2161$T2H_THISDOC{author} = $value{'_author'};
2162$T2H_THISDOC{subtitle} = $value{'_subtitle'};
2163for $key (keys %T2H_THISDOC)
2164{
2165  $_ = &substitute_style($T2H_THISDOC{$key});
2166  &unprotect_texi;
2167  s/\s*$//;
2168  $T2H_THISDOC{$key} = $_;
2169}
2170
2171# if no sections, then simply print docuemnt as is
2172unless (@sections)
2173{
2174  print "# Writing content into $docu_top_file \n" if $T2H_VERBOSE;
2175  open(FILE, "> $docu_doc_file") 
2176    || die "$ERROR: Can't open $docu_doc_file for writing: $!\n";
2177
2178  t2h_print_page_head(\*FILE);
2179  $T2H_THIS_SECTION = \@doc_lines;
2180  t2h_print_lines(\*FILE);
2181  t2h_print_page_foot(\*FILE);
2182  close(FILE);
2183  goto Finish;
2184}
2185
2186# initialize $T2H_HREF, $T2H_NAME
2187%T2H_HREF = 
2188  (
2189   'First' ,   sec_href($sections[0]),
2190   'Last',     sec_href($sections[$#sections]),
2191   'About',     $docu_about. '#SEC_About',
2192  );
2193
2194# prepare TOC, OVERVIEW, TOP
2195$T2H_TOC = \@toc_lines;
2196$T2H_OVERVIEW = \@stoc_lines;
2197if ($has_top)
2198{
2199  while (1)
2200  {
2201    $_ = shift @doc_lines;
2202    last if /$TOPEND/;
2203    push @$T2H_TOP, $_;
2204  }
2205  $T2H_HREF{'Top'} = $docu_top . '#SEC_Top';
2206}
2207else
2208{
2209  $T2H_HREF{'Top'} = $T2H_HREF{First};
2210}
2211
2212$node2href{Top} = $T2H_HREF{Top};
2213$T2H_HREF{Contents} = $docu_toc.'#SEC_Contents' if @toc_lines;
2214$T2H_HREF{Overview} = $docu_stoc.'#SEC_OVERVIEW' if @stoc_lines;
2215$T2H_HREF{Index} = $node2href{'Index'};
2216
2217%T2H_NAME =
2218  (
2219   'First',   clean_name($sec2node{$sections[0]}),
2220   'Last',    clean_name($sec2node{$sections[$#sections]}),
2221   'About',    'About this document',
2222   'Contents', 'Table of Contents',
2223   'Overview', 'Overview (Short Table of Contents)',
2224   'Index' ,   '',
2225   'Top',      '' 
2226  );
2227
2228#############################################################################
2229# print Top
[5d13bc]2230#
[4e425a]2231open(FILE, "> $docu_top_file") 
2232  || die "$ERROR: Can't open $docu_top_file for writing: $!\n";
2233if ($T2H_TOP)
2234{
2235  print "# Creating Top in $docu_top_file ...\n" if $T2H_VERBOSE;
2236  t2h_print_page_head(\*FILE) unless ($T2H_SPLIT);
2237  $T2H_THIS_SECTION = $T2H_TOP;
2238  $T2H_HREF{This} = $T2H_HREF{Top};
2239  $T2H_NAME{This} = $T2H_NAME{Top};
2240  t2h_print_Top(\*FILE);
2241 
2242}
2243close(FILE) if $T2H_SPLIT;
2244
2245#############################################################################
2246# Print sections
[5d13bc]2247#
[4e425a]2248$T2H_NODE{Forward} = $sec2node{$sections[0]};
2249$T2H_NAME{Forward} = &clean_name($sec2node{$sections[0]});
2250$T2H_HREF{Forward} = sec_href($sections[0]);
2251$T2H_NODE{This} = 'Top';
2252$T2H_NAME{This} = $T2H_NAME{Top};
2253$T2H_HREF{This} = $T2H_HREF{Top};
2254if ($T2H_SPLIT)
2255{
2256  print "# writing " . scalar(@sections) . 
2257    " sections in $docu_rdir$docu_name"."_[1.." . 
2258      ($T2H_SPLIT eq 'section' ? scalar(@sections) : scalar(@$T2H_OVERVIEW) ) . 
2259        "]" 
2260          if $T2H_VERBOSE;
2261  $previous = ($T2H_SPLIT eq 'chapter' ? $CHAPTEREND : $SECTIONEND);
2262  undef $FH;
2263  $doc_num = 0;
2264}
2265else
2266{
2267  print "# writing " . scalar(@sections) . " sections in $docu_top_file ..." 
2268    if $T2H_VERBOSE;
2269  $FH = \*FILE;
2270  $previous = '';
2271}
2272
2273$counter = 0;
2274# loop through sections
2275while ($section = shift(@sections)) 
2276{
2277  if ($T2H_SPLIT && ($T2H_SPLIT eq 'section' || $previous eq $CHAPTEREND))
2278  { # open new page
2279    if ($FH)
2280    { #close previous page
2281      t2h_print_page_foot($FH);
2282      close($FH);
[5d13bc]2283    }
[4e425a]2284    &next_doc;
2285    open(FILE, "> $docu_rdir$docu_doc") || 
2286      die "$ERROR: Can't open $docu_rdir$docu_doc for writing: $!\n";
2287    $FH = \*FILE;
2288    t2h_print_page_head($FH);
2289  }
2290  $T2H_NAME{Back} = $T2H_NAME{This};
2291  $T2H_HREF{Back} = $T2H_HREF{This};
2292  $T2H_NODE{Back} = $T2H_NODE{This};
2293  $T2H_NAME{This} = $T2H_NAME{Forward};
2294  $T2H_HREF{This} = $T2H_HREF{Forward};
2295  $T2H_NODE{This} = $T2H_NODE{Forward};
2296  if ($sections[0])
2297  {
2298    $T2H_NODE{Forward} = $sec2node{$sections[0]};
2299    $T2H_NAME{Forward} = &clean_name($T2H_NODE{Forward});
2300    $T2H_HREF{Forward} = sec_href($sections[0]);
2301  }
2302  else
2303  {
2304    undef $T2H_HREF{Forward}, $T2H_NODE{Forward}, $T2H_NAME{Forward};
2305  }
2306
2307  $node = $node2up{$T2H_NODE{This}};
2308  $T2H_HREF{Up} = $node2href{$node};
2309  if ($T2H_HREF{Up} eq $T2H_HREF{This} || ! $T2H_HREF{Up})
2310  {
2311    $T2H_NAME{Up} = $T2H_NAME{Top};
2312    $T2H_HREF{Up} = $T2H_HREF{Top};
2313    $T2H_NODE{Up} = 'Up';
2314  }
2315  else
2316  {
2317    $T2H_NAME{Up} = &clean_name($node);
2318    $T2H_NODE{Up} = $node;
2319  }
2320
2321  $node = $T2H_NODE{This};
2322  $node = $node2prev{$node};
2323  $T2H_NAME{Prev} = &clean_name($node);
2324  $T2H_HREF{Prev} = $node2href{$node};
2325  $T2H_NODE{Prev} = $node;
2326
2327  $node = $T2H_NODE{This};
2328  if ($node2up{$node} && $node2up{$node} ne 'Top'&&
2329      ($node2prev{$node} eq $T2H_NODE{Back} || ! $node2prev{$node}))
2330  {
2331    $node = $node2up{$node};
2332    while ($node && $node ne $node2up{$node} && ! $node2prev{$node})
2333    {
2334      $node = $node2up{$node};
[5d13bc]2335    }
[4e425a]2336    $node = $node2prev{$node} 
2337      unless $node2up{$node} eq 'Top' || ! $node2up{$node};
2338  }
2339  else
2340  {
2341    $node = $node2prev{$node};
2342  }
2343  $T2H_NAME{FastBack} = &clean_name($node);
2344  $T2H_HREF{FastBack} = $node2href{$node};
2345  $T2H_NODE{FastBack} = $node;
2346 
2347  $node = $T2H_NODE{This};
2348  $node = $node2next{$node};
2349  $T2H_NAME{Next} = &clean_name($node);
2350  $T2H_HREF{Next} = $node2href{$node};
2351  $T2H_NODE{Next} = $node;
2352
2353  $node = $T2H_NODE{This};
2354  if ($node2up{$node} && $node2up{$node} ne 'Top'&& 
2355      ($node2next{$node} eq $T2H_NODE{Forward} || ! $node2next{$node}))
2356  {
2357    $node = $node2up{$node};
2358    while ($node && $node ne $node2up{$node} && ! $node2next{$node})
2359    {
2360      $node = $node2up{$node};
[5d13bc]2361    }
[4e425a]2362  }
2363  $node = $node2next{$node};
2364  $T2H_NAME{FastForward} = &clean_name($node);
2365  $T2H_HREF{FastForward} = $node2href{$node};
2366  $T2H_NODE{FastForward} = $node;
2367
2368  $T2H_THIS_SECTION = [];
2369  while (@doc_lines) {
2370    $_ = shift(@doc_lines);
2371    last if ($_ eq $SECTIONEND || $_ eq $CHAPTEREND);
2372    push(@$T2H_THIS_SECTION, $_);
2373  }
2374  $previous = $_;
2375  t2h_print_label($FH);
2376  t2h_print_section($FH);
2377
2378  if ($T2H_VERBOSE)
2379  {
2380    $counter++;
2381    print "." if $counter =~ /00$/;
2382  }
2383}
2384if ($T2H_SPLIT)
2385{
2386  t2h_print_page_foot($FH);
2387  close($FH);
2388}
2389print "\n" if $T2H_VERBOSE;
2390
2391#############################################################################
2392# Print ToC, Overview, Footnotes
[5d13bc]2393#
[4e425a]2394undef $T2H_HREF{Prev};
2395undef $T2H_HREF{Next};
2396undef $T2H_HREF{Back};
2397undef $T2H_HREF{Forward};
2398undef $T2H_HREF{Up};
2399
2400if (@foot_lines)
2401{
2402  print "# writing Footnotes in $docu_foot_file...\n" if $T2H_VERBOSE;
2403  open (FILE, "> $docu_foot_file") || die "$ERROR: Can't open $docu_foot_file for writing: $!\n"
2404      if $T2H_SPLIT;
2405  $T2H_HREF{This} = $docu_foot;
2406  $T2H_NAME{This} = 'Footnotes';
2407  $T2H_THIS_SECTION = \@foot_lines;
2408  t2h_print_footnotes(\*FILE);
2409  close(FILE) if $T2H_SPLIT;
2410}
2411
2412if (@toc_lines)
2413{
2414  print "# writing Toc in $docu_toc_file...\n" if $T2H_VERBOSE;
2415  open (FILE, "> $docu_toc_file") || die "$ERROR: Can't open $docu_toc_file for writing: $!\n"
2416      if $T2H_SPLIT;
2417  $T2H_HREF{This} = $T2H_HREF{Contents};
2418  $T2H_NAME{This} = $T2H_NAME{Contents};
2419  $T2H_THIS_SECTION = \@toc_lines;
2420  t2h_print_Toc(\*FILE);
2421  close(FILE) if $T2H_SPLIT;
2422}
2423
2424if (@stoc_lines)
2425{
2426  print "# writing Overview in $docu_stoc_file...\n" if $T2H_VERBOSE;
2427  open (FILE, "> $docu_stoc_file") || die "$ERROR: Can't open $docu_stoc_file for writing: $!\n"
2428      if $T2H_SPLIT;
2429 
2430  $T2H_HREF{This} = $T2H_HREF{Overview};
2431  $T2H_NAME{This} = $T2H_NAME{Overview};
2432  $T2H_THIS_SECTION = \@stoc_lines;
2433  t2h_print_Overview(\*FILE);
2434  close(FILE) if $T2H_SPLIT;
2435}
2436
2437if ($about_body = t2h_about_body())
2438{
2439  print "# writing About in $docu_about_file...\n" if $T2H_VERBOSE;
2440  open (FILE, "> $docu_about_file") || die "$ERROR: Can't open $docu_about_file for writing: $!\n"
2441      if $T2H_SPLIT;
2442 
2443  $T2H_HREF{This} = $T2H_HREF{About};
2444  $T2H_NAME{This} = $T2H_NAME{About};
2445  $T2H_THIS_SECTION = [$about_body];
2446  t2h_print_About(\*FILE);
2447  close(FILE) if $T2H_SPLIT;
2448}
2449
2450unless ($T2H_SPLIT)
2451{
2452  t2h_print_page_foot(\*FILE);
2453  close (FILE);
2454}
2455 
2456Finish:
2457&l2h_FinishFromHtml if ($T2H_L2H);
2458&l2h_Finish if($T2H_L2H);
2459print "# that's all folks\n" if $T2H_VERBOSE;
2460
2461exit(0);
[5d13bc]2462
2463#+++############################################################################
2464#                                                                              #
2465# Low level functions                                                          #
2466#                                                                              #
2467#---############################################################################
2468
[4e425a]2469sub clean_name 
2470{
2471  local ($_);
2472  $_ = &remove_style($_[0]);
2473  &unprotect_texi;
2474  return $_;
2475}
2476
[5d13bc]2477sub update_sec_num {
2478    local($name, $level) = @_;
[4e425a]2479    my $ret;
[5d13bc]2480
2481    $level--; # here we start at 0
[4e425a]2482    if ($name =~ /^appendix/ || defined(@appendix_sec_num)) {
[5d13bc]2483        # appendix style
2484        if (defined(@appendix_sec_num)) {
2485            &incr_sec_num($level, @appendix_sec_num);
2486        } else {
2487            @appendix_sec_num = ('A', 0, 0, 0);
2488        }
[4e425a]2489        $ret = join('.', @appendix_sec_num[0..$level]);
[5d13bc]2490    } else {
2491        # normal style
[4e425a]2492        if (defined(@normal_sec_num)) 
2493        {
2494          &incr_sec_num($level, @normal_sec_num);
2495        } 
2496        else 
2497        {
2498          @normal_sec_num = (1, 0, 0, 0);
[5d13bc]2499        }
[4e425a]2500        $ret = join('.', @normal_sec_num[0..$level]);
[5d13bc]2501    }
[4e425a]2502   
2503    $ret .= "." if $level == 0;
2504    return $ret;
[5d13bc]2505}
2506
2507sub incr_sec_num {
2508    local($level, $l);
2509    $level = shift(@_);
2510    $_[$level]++;
2511    foreach $l ($level+1 .. 3) {
2512        $_[$l] = 0;
2513    }
2514}
2515
2516sub check {
2517    local($_, %seen, %context, $before, $match, $after);
2518
2519    while (<>) {
2520        if (/\@(\*|\.|\:|\@|\{|\})/) {
2521            $seen{$&}++;
[4e425a]2522            $context{$&} .= "> $_" if $T2H_VERBOSE;
[5d13bc]2523            $_ = "$`XX$'";
2524            redo;
2525        }
2526        if (/\@(\w+)/) {
2527            ($before, $match, $after) = ($`, $&, $');
2528            if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
2529                $seen{'e-mail address'}++;
[4e425a]2530                $context{'e-mail address'} .= "> $_" if $T2H_VERBOSE;
[5d13bc]2531            } else {
2532                $seen{$match}++;
[4e425a]2533                $context{$match} .= "> $_" if $T2H_VERBOSE;
[5d13bc]2534            }
2535            $match =~ s/^\@/X/;
2536            $_ = "$before$match$after";
2537            redo;
2538        }
2539    }
2540   
2541    foreach (sort(keys(%seen))) {
[4e425a]2542        if ($T2H_VERBOSE) {
[5d13bc]2543            print "$_\n";
2544            print $context{$_};
2545        } else {
2546            print "$_ ($seen{$_})\n";
2547        }
2548    }
2549}
2550
2551sub open {
2552    local($name) = @_;
2553
2554    ++$fh_name;
2555    if (open($fh_name, $name)) {
2556        unshift(@fhs, $fh_name);
2557    } else {
2558        warn "$ERROR Can't read file $name: $!\n";
2559    }
2560}
2561
2562sub init_input {
2563    @fhs = ();                  # hold the file handles to read
2564    @input_spool = ();          # spooled lines to read
2565    $fh_name = 'FH000';
2566    &open($docu);
2567}
2568
2569sub next_line {
2570    local($fh, $line);
2571
2572    if (@input_spool) {
2573        $line = shift(@input_spool);
2574        return($line);
2575    }
2576    while (@fhs) {
2577        $fh = $fhs[0];
2578        $line = <$fh>;
2579        return($line) if $line;
2580        close($fh);
2581        shift(@fhs);
2582    }
2583    return(undef);
2584}
2585
2586# used in pass 1, use &next_line
2587sub skip_until {
2588    local($tag) = @_;
2589    local($_);
2590
2591    while ($_ = &next_line) {
2592        return if /^\@end\s+$tag\s*$/;
2593    }
2594    die "* Failed to find '$tag' after: " . $lines[$#lines];
2595}
2596
[4e425a]2597# used in pass 1 for l2h use &next_line
2598sub string_until {
2599    local($tag) = @_;
2600    local($_, $string);
2601
2602    while ($_ = &next_line) {
2603        return $string if /^\@end\s+$tag\s*$/;
2604#       $_ =~ s/hbox/mbox/g;
2605        $string = $string.$_;
2606    }
2607    die "* Failed to find '$tag' after: " . $lines[$#lines];
2608}
2609
[5d13bc]2610#
2611# HTML stacking to have a better HTML output
2612#
2613
2614sub html_reset {
2615    @html_stack = ('html');
2616    $html_element = 'body';
2617}
2618
2619sub html_push {
2620    local($what) = @_;
2621    push(@html_stack, $html_element);
2622    $html_element = $what;
2623}
2624
2625sub html_push_if {
2626    local($what) = @_;
2627    push(@html_stack, $html_element)
2628        if ($html_element && $html_element ne 'P');
2629    $html_element = $what;
2630}
2631
2632sub html_pop {
2633    $html_element = pop(@html_stack);
2634}
2635
2636sub html_pop_if {
2637    local($elt);
2638
2639    if (@_) {
2640        foreach $elt (@_) {
2641            if ($elt eq $html_element) {
2642                $html_element = pop(@html_stack) if @html_stack;
2643                last;
2644            }
2645        }
2646    } else {
2647        $html_element = pop(@html_stack) if @html_stack;
2648    }
2649}
2650
2651sub html_debug {
2652    local($what, $line) = @_;
2653    return("<!-- $line @html_stack, $html_element -->$what")
[4e425a]2654        if $T2H_DEBUG & $DEBUG_HTML;
[5d13bc]2655    return($what);
2656}
2657
2658# to debug the output...
2659sub debug {
2660    local($what, $line) = @_;
2661    return("<!-- $line -->$what")
[4e425a]2662        if $T2H_DEBUG & $DEBUG_HTML;
[5d13bc]2663    return($what);
2664}
2665
2666sub normalise_node {
2667    $_[0] =~ s/\s+/ /g;
2668    $_[0] =~ s/ $//;
2669    $_[0] =~ s/^ //;
2670}
2671
2672sub menu_entry {
2673    local($entry, $node, $descr) = @_;
2674    local($href);
2675
2676    &normalise_node($node);
2677    $href = $node2href{$node};
2678    if ($href) {
2679        $descr =~ s/^\s+//;
[4e425a]2680        if ($T2H_NUMBER_SECTIONS)
2681        {
2682          $entry = $node2sec{$entry} if ! $descr && $node2sec{$entry};
2683          push(@lines2, 
2684               '<TR><TD ALIGN="left">' . 
2685               &t2h_anchor('', $href, $entry) . 
2686               '</TD><TD ALIGN="left">' . $descr . "</TD><TR>\n");
2687        }
2688        else
2689        {
2690          push(@lines2, "<LI>" . &t2h_anchor('', $href, $entry) . ": $descr\n");
2691        }
[5d13bc]2692    } else {
2693        warn "$ERROR Undefined node ($node): $_";
2694    }
2695}
2696
[4e425a]2697sub do_ctrl { "^$_[0]" }
2698
[5d13bc]2699sub do_email {
[4e425a]2700    local($addr, $text) = split(/,\s*/, $_[0]);
2701
2702    $text = $addr unless $text;
2703    &t2h_anchor('', "mailto:$addr", $text);
[5d13bc]2704}
2705
[4e425a]2706sub do_sc 
2707{ 
2708  # l2h does this much better
2709  return &l2h_ToLatex("{\\sc ".&unprotect_html($_[0])."}") if ($T2H_L2H);
2710  return "\U$_[0]\E";
[5d13bc]2711}
2712
[4e425a]2713sub do_math
2714{
2715  return &l2h_ToLatex("\$".&unprotect_html($_[0])."\$") if ($T2H_L2H);
2716  return "<EM>".$text."</EM>";
[5d13bc]2717}
2718
[4e425a]2719sub do_uref {
2720    local($url, $text, $only_text) = split(/,\s*/, $_[0]);
2721
2722    $text = $only_text if $only_text;
2723    $text = $url unless $text;
2724    &t2h_anchor('', $url, $text);
2725}
[5d13bc]2726
[4e425a]2727sub do_url { &t2h_anchor('', $_[0], $_[0]) }
[5d13bc]2728
2729sub apply_style {
2730    local($texi_style, $text) = @_;
2731    local($style);
2732
2733    $style = $style_map{$texi_style};
2734    if (defined($style)) { # known style
2735        if ($style =~ /^\"/) { # add quotes
2736            $style = $';
2737            $text = "\`$text\'";
2738        }
2739        if ($style =~ /^\&/) { # custom
2740            $style = $';
2741            $text = &$style($text);
2742        } elsif ($style) { # good style
2743            $text = "<$style>$text</$style>";
2744        } else { # no style
2745        }
2746    } else { # unknown style
2747        $text = undef;
2748    }
2749    return($text);
2750}
2751
2752# remove Texinfo styles
2753sub remove_style {
2754    local($_) = @_;
2755    s/\@\w+{([^\{\}]+)}/$1/g;
2756    return($_);
2757}
2758
2759sub substitute_style {
2760    local($_) = @_;
2761    local($changed, $done, $style, $text);
2762
2763    $changed = 1;
2764    while ($changed) {
2765        $changed = 0;
2766        $done = '';
2767        while (/\@(\w+){([^\{\}]+)}/) {
2768            $text = &apply_style($1, $2);
2769            if ($text) {
2770                $_ = "$`$text$'";
2771                $changed = 1;
2772            } else {
2773                $done .= "$`\@$1";
2774                $_ = "{$2}$'";
2775            }
2776        }
2777        $_ = $done . $_;
2778    }
2779    return($_);
2780}
2781
[4e425a]2782sub t2h_anchor {
2783    local($name, $href, $text, $newline) = @_;
[5d13bc]2784    local($result);
2785
2786    $result = "<A";
2787    $result .= " NAME=\"$name\"" if $name;
2788    $result .= " HREF=\"$href\"" if $href;
2789    $result .= ">$text</A>";
2790    $result .= "\n" if $newline;
2791    return($result);
2792}
2793
2794sub pretty_date {
2795    local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
2796
[4e425a]2797    @MoY = ('January', 'February', 'March', 'April', 'May', 'June',
[5d13bc]2798            'July', 'August', 'September', 'October', 'November', 'December');
2799    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
2800    $year += ($year < 70) ? 2000 : 1900;
[4e425a]2801    # obachman: Let's do it as the Americans do
2802    return("$MoY[$mon], $mday  $year");
[5d13bc]2803}
2804
[4e425a]2805sub doc_href {
[5d13bc]2806    local($num) = @_;
2807
[4e425a]2808    return("${docu_name}_$num.$docu_ext");
2809}
2810
2811sub sec_href
2812{
2813  return $node2href{$sec2node{$_[0]}};
[5d13bc]2814}
2815
2816sub next_doc {
[4e425a]2817    $docu_doc = &doc_href(++$doc_num);
[5d13bc]2818}
2819
[4e425a]2820sub t2h_print_lines {
2821    my ($fh, $lines) = @_;
[5d13bc]2822    local($_);
[4e425a]2823    $lines = $T2H_THIS_SECTION unless $lines;
2824    my $cnt = 0;
2825    for (@$lines) 
2826    {
2827        $_ = l2h_FromHtml($_) if ($T2H_L2H);
[5d13bc]2828        if (/^$PROTECTTAG/o) {
2829            $_ = $tag2pro{$_};
2830        } else {
2831            &unprotect_texi;
2832        }
2833        print $fh $_;
[4e425a]2834        $cnt += split(/\W*\s+\W*/);
[5d13bc]2835    }
[4e425a]2836    return $cnt;
[5d13bc]2837}
2838
2839sub protect_texi {
2840    # protect @ { } ` '
2841    s/\@\@/$;0/go;
2842    s/\@\{/$;1/go;
2843    s/\@\}/$;2/go;
2844    s/\@\`/$;3/go;
2845    s/\@\'/$;4/go;
2846}
2847
2848sub protect_html {
2849    local($what) = @_;
2850    # protect & < >
2851    $what =~ s/\&/\&\#38;/g;
2852    $what =~ s/\</\&\#60;/g;
2853    $what =~ s/\>/\&\#62;/g;
2854    # but recognize some HTML things
2855    $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g;             # </A>
2856    $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g;     # <A [^&]+>
2857    $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
2858    return($what);
2859}
2860
2861sub unprotect_texi {
2862    s/$;0/\@/go;
2863    s/$;1/\{/go;
2864    s/$;2/\}/go;
2865    s/$;3/\`/go;
2866    s/$;4/\'/go;
2867}
2868
2869sub unprotect_html {
2870    local($what) = @_;
2871    $what =~ s/\&\#38;/\&/g;
2872    $what =~ s/\&\#60;/\</g;
2873    $what =~ s/\&\#62;/\>/g;
2874    return($what);
2875}
2876
2877sub byalpha {
2878    $key2alpha{$a} cmp $key2alpha{$b};
2879}
2880
[4e425a]2881sub t2h_print_label
2882{
2883    my $fh = shift;
2884    my $href = shift || $T2H_HREF{This};
2885    $href =~ s/.*#(.*)$/$1/;
2886    print $fh qq{<A NAME="$href"></A>\n};
2887}
2888
[5d13bc]2889##############################################################################
2890
2891        # These next few lines are legal in both Perl and nroff.
2892
2893.00 ;                   # finish .ig
2894 
2895'di                     \" finish diversion--previous line must be blank
2896.nr nl 0-1              \" fake up transition to first page again
2897.nr % 0                 \" start at page 1
2898'; __END__ ############# From here on it's a standard manual page ############
[4e425a]2899.TH TEXI2HTML 1 "01/05/98"
[5d13bc]2900.AT 3
2901.SH NAME
2902texi2html \- a Texinfo to HTML converter
2903.SH SYNOPSIS
[4e425a]2904.B texi2html [options] file
[5d13bc]2905.PP
[4e425a]2906.B texi2html -check [-verbose] files
[5d13bc]2907.SH DESCRIPTION
2908.I Texi2html
2909converts the given Texinfo file to a set of HTML files. It tries to handle
2910most of the Texinfo commands. It creates hypertext links for cross-references,
2911footnotes...
2912.PP
2913It also tries to add links from a reference to its corresponding entry in the
2914bibliography (if any). It may also handle a glossary (see the
2915.B \-glossary
2916option).
2917.PP
2918.I Texi2html
[4e425a]2919may furthermore use latex2html to generate HTML (code and/or images) for @math
2920and @iftex tags (see the
2921.B \-l2h
2922option).
2923.PP
2924.I Texi2html
[5d13bc]2925creates several files depending on the contents of the Texinfo file and on
2926the chosen options (see FILES).
2927.PP
2928The HTML files created by
2929.I texi2html
2930are closer to TeX than to Info, that's why
2931.SH OPTIONS
2932.TP 12
2933.B \-check
2934Check the given file and give the list of all things that may be Texinfo commands.
2935This may be used to check the output of
2936.I texi2html
2937to find the Texinfo commands that have been left in the HTML file.
2938.TP
[4e425a]2939.B \-expand info|tex|none
2940Expand @ifinfo, or @iftex, or sections (default: info)
[5d13bc]2941.TP
2942.B \-glossary
2943Use the section named 'Glossary' to build a list of terms and put links in the HTML
2944document from each term toward its definition.
2945.TP
2946.B \-invisible \fIname\fP
[4e425a]2947Use \fIname\fP to create invisible destination anchors for index links
2948(you can for instance use the invisible.xbm file shipped with this program).
2949This is a workaround for a known bug of many WWW browsers, including netscape.
[5d13bc]2950.TP
2951.B \-I \fIdir\fP
2952Look also in \fIdir\fP to find included files.
2953.TP
2954.B \-menu
2955Show the Texinfo menus; by default they are ignored.
2956.TP
2957.B \-monolithic
2958Output only one file, including the table of contents and footnotes.
2959.TP
2960.B \-number
2961Number the sections.
2962.TP
2963.B \-split_chapter
2964Split the output into several HTML files (one per main section:
2965chapter, appendix...).
2966.TP
2967.B \-split_node
2968Split the output into several HTML files (one per node).
2969.TP
[4e425a]2970.B \-l2h
2971Use latex2html for content of @math and @tex tags. Content must be such that
2972both, latex and tex, can translate it correctly. I.e., no tex-only constructs
2973must be used.
2974.TP
2975.B \-l2h_latex2html \fIprog\fP 
2976Use \fIprog\fP as latex2html program (default \fIlatex2html\fP).
2977Program must be executable.
2978.TP
2979.B \-l2h_init \fIfile\fP 
2980Use \fIfile\fP as latex2html init file. \fIfile\fP should be used to specify in which way latex2html handles mathematical expressions and formulas.
2981
2982Note that latex2html locates 
2983(and uses) init-files in the following order (provided they exist):
2984(1) global init file (usually in latex2html source dir)
2985(2) $HOME/.latex2html_init
2986(3) ./.latex2html_init
2987(4) init file given on command line. 
2988.TP
2989.B \-l2h_dir \fIdir\fP
2990Use \fIdir\fP as tmp dir for latex2html. This directory (resp. its path)
2991must not contain a dot  (i.e., a ".").
2992.TP
2993.B \-l2h_clean
2994remove all intermediate files generated by latex2html (prevents caching!) 
2995.TP
2996.B \-l2h_skip
2997Do not really run latex2html. Use (kept) files of previous runs, instead.
2998.TP
[5d13bc]2999.B \-usage
3000Print usage instructions, listing the current available command-line options.
3001.TP
3002.B \-verbose
3003Give a verbose output. Can be used with the
3004.B \-check
3005option.
3006.PP
3007.SH FILES
3008By default
3009.I texi2html
3010creates the following files (foo being the name of the Texinfo file):
3011.TP 16
3012.B foo_toc.html
3013The table of contents.
3014.TP
3015.B foo.html
3016The document's contents.
3017.TP
3018.B foo_foot.html
3019The footnotes (if any).
[4e425a]3020.TP
3021.B foo_l2h_img*
3022Images generated by latex2html (if any).
[5d13bc]3023.PP
3024When used with the
3025.B \-split
3026option, it creates several files (one per chapter or node), named
3027.B foo_n.html
[4e425a]3028(n being the index of the chapter or node), instead of the single
[5d13bc]3029.B foo.html
3030file.
3031.PP
3032When used with the
3033.B \-monolithic
3034option, it creates only one file:
3035.B foo.html
3036.SH VARIABLES
3037.I texi2html
3038predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
3039.SH ADDITIONAL COMMANDS
3040.I texi2html
[4e425a]3041implements the following non-Texinfo commands (maybe they are in Texinfo now...):
[5d13bc]3042.TP 16
[4e425a]3043.B @html
[5d13bc]3044This indicates the start of an HTML section, this section will passed through
[4e425a]3045without any modification.
[5d13bc]3046.TP
[4e425a]3047.B @end html
3048This indicates the end of an HTML section.
[5d13bc]3049.SH VERSION
[4e425a]3050This is \fItexi2html\fP version 1.56k, 1999-02-20.
[5d13bc]3051.PP
[4e425a]3052The latest version of \fItexi2html\fP and \fIlatex22html\fPcan be found in WWW, cf. URLs
3053http://wwwinfo.cern.ch/dis/texi2html/
3054.br
3055http://texinfo.org/texi2html/
3056.br
3057http://www-dsed.llnl.gov/files/programs/unix/latex2html
3058.br
[5d13bc]3059.SH AUTHOR
[4e425a]3060The main author is Lionel Cons, CERN IT/DIS/OSE, Lionel.Cons@cern.ch.
[5d13bc]3061Many other people around the net contributed to this program.
3062.SH COPYRIGHT
3063This program is the intellectual property of the European
3064Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
3065provided by CERN. No liability whatsoever is accepted for any loss or damage
3066of any kind resulting from any defect or inaccuracy in this information or
3067code.
3068.PP
3069CERN, 1211 Geneva 23, Switzerland
3070.SH "SEE ALSO"
3071GNU Texinfo Documentation Format,
3072HyperText Markup Language (HTML),
3073World Wide Web (WWW).
3074.SH BUGS
[4e425a]3075This program does not understand all Texinfo commands (yet). A row of
3076a  mutlicolumn table has to be in one line.
[5d13bc]3077.PP
3078TeX specific commands (normally enclosed in @iftex) will be
[4e425a]3079passed over unmodified, unless latex2html is enabled.
3080.ex
Note: See TracBrowser for help on using the repository browser.