163eb84d1Schristos#!/usr/local/bin/perl
263eb84d1Schristos'di ';
363eb84d1Schristos'ig 00 ';
463eb84d1Schristos#+##############################################################################
563eb84d1Schristos#                                                                              #
663eb84d1Schristos# File: texi2html                                                              #
763eb84d1Schristos#                                                                              #
863eb84d1Schristos# Description: Program to transform most Texinfo documents to HTML             #
963eb84d1Schristos#                                                                              #
1063eb84d1Schristos#-##############################################################################
1163eb84d1Schristos
1263eb84d1Schristos# @(#)texi2html	1.52b 01/05/98	Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch
1363eb84d1Schristos# 1.52a: Use acute accent instead of apostrophe. Add support for ISO-8859-1
1463eb84d1Schristos#        characters with cedilla, circumflex etc.
1563eb84d1Schristos# 1.52b: Add option -expandtex. Expand @ifhtml by default, not @ifinfo.
1663eb84d1Schristos#        Use Unicode quotation marks instead of grave and acute accents.
1763eb84d1Schristos#        Emit charset=UTF-8 declaration.
1863eb84d1Schristos
1963eb84d1Schristos# The man page for this program is included at the end of this file and can be
2063eb84d1Schristos# viewed using the command 'nroff -man texi2html'.
2163eb84d1Schristos# Please read the copyright at the end of the man page.
2263eb84d1Schristos
2363eb84d1Schristos#+++############################################################################
2463eb84d1Schristos#                                                                              #
2563eb84d1Schristos# Constants                                                                    #
2663eb84d1Schristos#                                                                              #
2763eb84d1Schristos#---############################################################################
2863eb84d1Schristos
2963eb84d1Schristos$DEBUG_TOC   =  1;
3063eb84d1Schristos$DEBUG_INDEX =  2;
3163eb84d1Schristos$DEBUG_BIB   =  4;
3263eb84d1Schristos$DEBUG_GLOSS =  8;
3363eb84d1Schristos$DEBUG_DEF   = 16;
3463eb84d1Schristos$DEBUG_HTML  = 32;
3563eb84d1Schristos$DEBUG_USER  = 64;
3663eb84d1Schristos
3763eb84d1Schristos$BIBRE = '\[[\w\/-]+\]';		# RE for a bibliography reference
3863eb84d1Schristos$FILERE = '[\/\w.+-]+';			# RE for a file name
3963eb84d1Schristos$VARRE = '[^\s\{\}]+';			# RE for a variable name
4063eb84d1Schristos$NODERE = '[^@{}:\'`",]+';		# RE for a node name
4163eb84d1Schristos$NODESRE = '[^@{}:\'`"]+';		# RE for a list of node names
4263eb84d1Schristos$XREFRE = '[^@{}]+';			# RE for a xref (should use NODERE)
4363eb84d1Schristos
4463eb84d1Schristos$ERROR = "***";			        # prefix for errors and warnings
4563eb84d1Schristos$THISPROG = "texi2html 1.52b";			# program name and version
4663eb84d1Schristos$HOMEPAGE = "http://wwwinfo.cern.ch/dis/texi2html/"; # program home page
4763eb84d1Schristos$TODAY = &pretty_date;			# like "20 September 1993"
4863eb84d1Schristos$SPLITTAG = "<!-- SPLIT HERE -->\n";	# tag to know where to split
4963eb84d1Schristos$PROTECTTAG = "_ThisIsProtected_";	# tag to recognize protected sections
5063eb84d1Schristos$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">';
5163eb84d1Schristos
5263eb84d1Schristos#
5363eb84d1Schristos# language dependent constants
5463eb84d1Schristos#
5563eb84d1Schristos#$LDC_SEE = 'see';
5663eb84d1Schristos#$LDC_SECTION = 'section';
5763eb84d1Schristos#$LDC_IN = 'in';
5863eb84d1Schristos#$LDC_TOC = 'Table of Contents';
5963eb84d1Schristos#$LDC_GOTO = 'Go to the';
6063eb84d1Schristos#$LDC_FOOT = 'Footnotes';
6163eb84d1Schristos# TODO: @def* shortcuts
6263eb84d1Schristos
6363eb84d1Schristos#
6463eb84d1Schristos# pre-defined indices
6563eb84d1Schristos#
6663eb84d1Schristos%predefined_index = (
6763eb84d1Schristos		    'cp', 'c',
6863eb84d1Schristos		    'fn', 'f',
6963eb84d1Schristos		    'vr', 'v',
7063eb84d1Schristos		    'ky', 'k',
7163eb84d1Schristos		    'pg', 'p',
7263eb84d1Schristos		    'tp', 't',
7363eb84d1Schristos	            );
7463eb84d1Schristos
7563eb84d1Schristos#
7663eb84d1Schristos# valid indices
7763eb84d1Schristos#
7863eb84d1Schristos%valid_index = (
7963eb84d1Schristos		    'c', 1,
8063eb84d1Schristos		    'f', 1,
8163eb84d1Schristos		    'v', 1,
8263eb84d1Schristos		    'k', 1,
8363eb84d1Schristos		    'p', 1,
8463eb84d1Schristos		    't', 1,
8563eb84d1Schristos		);
8663eb84d1Schristos
8763eb84d1Schristos#
8863eb84d1Schristos# texinfo section names to level
8963eb84d1Schristos#
9063eb84d1Schristos%sec2level = (
9163eb84d1Schristos	      'top', 0,
9263eb84d1Schristos	      'chapter', 1,
9363eb84d1Schristos	      'unnumbered', 1,
9463eb84d1Schristos	      'majorheading', 1,
9563eb84d1Schristos	      'chapheading', 1,
9663eb84d1Schristos	      'appendix', 1,
9763eb84d1Schristos	      'section', 2,
9863eb84d1Schristos	      'unnumberedsec', 2,
9963eb84d1Schristos	      'heading', 2,
10063eb84d1Schristos	      'appendixsec', 2,
10163eb84d1Schristos	      'appendixsection', 2,
10263eb84d1Schristos	      'subsection', 3,
10363eb84d1Schristos	      'unnumberedsubsec', 3,
10463eb84d1Schristos	      'subheading', 3,
10563eb84d1Schristos	      'appendixsubsec', 3,
10663eb84d1Schristos	      'subsubsection', 4,
10763eb84d1Schristos	      'unnumberedsubsubsec', 4,
10863eb84d1Schristos	      'subsubheading', 4,
10963eb84d1Schristos	      'appendixsubsubsec', 4,
11063eb84d1Schristos	      );
11163eb84d1Schristos
11263eb84d1Schristos#
11363eb84d1Schristos# accent map, TeX command to ISO name
11463eb84d1Schristos#
11563eb84d1Schristos%accent_map = (
11663eb84d1Schristos	       '"',  'uml',
11763eb84d1Schristos	       '~',  'tilde',
11863eb84d1Schristos	       '^',  'circ',
11963eb84d1Schristos	       '`',  'grave',
12063eb84d1Schristos	       '\'', 'acute',
12163eb84d1Schristos	       );
12263eb84d1Schristos
12363eb84d1Schristos#
12463eb84d1Schristos# texinfo "simple things" (@foo) to HTML ones
12563eb84d1Schristos#
12663eb84d1Schristos%simple_map = (
12763eb84d1Schristos	       # cf. makeinfo.c
12863eb84d1Schristos	       "*", "<BR>",		# HTML+
12963eb84d1Schristos	       " ", " ",
13063eb84d1Schristos	       "\n", "\n",
13163eb84d1Schristos	       "|", "",
13263eb84d1Schristos	       # spacing commands
13363eb84d1Schristos	       ":", "",
13463eb84d1Schristos	       "!", "!",
13563eb84d1Schristos	       "?", "?",
13663eb84d1Schristos	       ".", ".",
13763eb84d1Schristos	       "-", "",
13863eb84d1Schristos	       );
13963eb84d1Schristos
14063eb84d1Schristos#
14163eb84d1Schristos# texinfo "things" (@foo{}) to HTML ones
14263eb84d1Schristos#
14363eb84d1Schristos%things_map = (
14463eb84d1Schristos	       'TeX', 'TeX',
14563eb84d1Schristos	       'br', '<P>',		# paragraph break
14663eb84d1Schristos	       'bullet', '*',
14763eb84d1Schristos	       'copyright', '(C)',
14863eb84d1Schristos	       'dots', '...',
14963eb84d1Schristos	       'equiv', '==',
15063eb84d1Schristos	       'error', 'error-->',
15163eb84d1Schristos	       'expansion', '==>',
15263eb84d1Schristos	       'minus', '-',
15363eb84d1Schristos	       'point', '-!-',
15463eb84d1Schristos	       'print', '-|',
15563eb84d1Schristos	       'result', '=>',
15663eb84d1Schristos	       'today', $TODAY,
15763eb84d1Schristos	       'aa', '&aring;',
15863eb84d1Schristos	       'AA', '&Aring;',
15963eb84d1Schristos	       'ae', '&aelig;',
16063eb84d1Schristos	       'AE', '&AElig;',
16163eb84d1Schristos	       'o',  '&oslash;',
16263eb84d1Schristos	       'O',  '&Oslash;',
16363eb84d1Schristos	       'ss', '&szlig;',
16463eb84d1Schristos	       'exclamdown', '&iexcl;',
16563eb84d1Schristos	       'questiondown', '&iquest;',
16663eb84d1Schristos	       'pounds', '&pound;'
16763eb84d1Schristos	       );
16863eb84d1Schristos
16963eb84d1Schristos#
17063eb84d1Schristos# texinfo styles (@foo{bar}) to HTML ones
17163eb84d1Schristos#
17263eb84d1Schristos%style_map = (
17363eb84d1Schristos	      'asis', '',
17463eb84d1Schristos	      'b', 'B',
17563eb84d1Schristos	      'cite', 'CITE',
17663eb84d1Schristos	      'code', 'CODE',
17763eb84d1Schristos	      'ctrl', '&do_ctrl',	# special case
17863eb84d1Schristos	      'dfn', 'EM',		# DFN tag is illegal in the standard
17963eb84d1Schristos	      'dmn', '',		# useless
18063eb84d1Schristos	      'email', '&do_email',     # insert a clickable email address
18163eb84d1Schristos	      'emph', 'EM',
18263eb84d1Schristos	      'file', '"TT',		# will put quotes, cf. &apply_style
18363eb84d1Schristos	      'i', 'I',
18463eb84d1Schristos	      'kbd', 'KBD',
18563eb84d1Schristos	      'key', 'KBD',
18663eb84d1Schristos	      'math', 'EM',
18763eb84d1Schristos	      'r', '',			# unsupported
18863eb84d1Schristos	      'samp', '"SAMP',		# will put quotes, cf. &apply_style
18963eb84d1Schristos	      'sc', '&do_sc',		# special case
19063eb84d1Schristos	      'strong', 'STRONG',
19163eb84d1Schristos	      't', 'TT',
19263eb84d1Schristos	      'titlefont', '',		# useless
19363eb84d1Schristos	      'uref', '&do_uref',       # insert a clickable URL
19463eb84d1Schristos	      'url', '&do_url',         # insert a clickable URL
19563eb84d1Schristos	      'var', 'VAR',
19663eb84d1Schristos	      'w', '',			# unsupported
19763eb84d1Schristos	      '"', '&do_diaeresis',
19863eb84d1Schristos	      '\'', '&do_acuteaccent',	# doesn't work??
19963eb84d1Schristos	      '\`', '&do_graveaccent',	# doesn't work??
20063eb84d1Schristos	      '~', '&do_tildeaccent',
20163eb84d1Schristos	      ',', '&do_cedilla',
20263eb84d1Schristos	      '^', '&do_circumflex',
20363eb84d1Schristos	      );
20463eb84d1Schristos
20563eb84d1Schristos#
20663eb84d1Schristos# texinfo format (@foo/@end foo) to HTML ones
20763eb84d1Schristos#
20863eb84d1Schristos%format_map = (
20963eb84d1Schristos	       'display', 'PRE',
21063eb84d1Schristos	       'example', 'PRE',
21163eb84d1Schristos	       'format', 'PRE',
21263eb84d1Schristos	       'lisp', 'PRE',
21363eb84d1Schristos	       'quotation', 'BLOCKQUOTE',
21463eb84d1Schristos	       'smallexample', 'PRE',
21563eb84d1Schristos	       'smalllisp', 'PRE',
21663eb84d1Schristos	       # lists
21763eb84d1Schristos	       'itemize', 'UL',
21863eb84d1Schristos	       'enumerate', 'OL',
21963eb84d1Schristos	       # poorly supported
22063eb84d1Schristos	       'flushleft', 'PRE',
22163eb84d1Schristos	       'flushright', 'PRE',
22263eb84d1Schristos	       );
22363eb84d1Schristos
22463eb84d1Schristos#
22563eb84d1Schristos# texinfo definition shortcuts to real ones
22663eb84d1Schristos#
22763eb84d1Schristos%def_map = (
22863eb84d1Schristos	    # basic commands
22963eb84d1Schristos	    'deffn', 0,
23063eb84d1Schristos	    'defvr', 0,
23163eb84d1Schristos	    'deftypefn', 0,
23263eb84d1Schristos	    'deftypevr', 0,
23363eb84d1Schristos	    'defcv', 0,
23463eb84d1Schristos	    'defop', 0,
23563eb84d1Schristos	    'deftp', 0,
23663eb84d1Schristos	    # basic x commands
23763eb84d1Schristos	    'deffnx', 0,
23863eb84d1Schristos	    'defvrx', 0,
23963eb84d1Schristos	    'deftypefnx', 0,
24063eb84d1Schristos	    'deftypevrx', 0,
24163eb84d1Schristos	    'defcvx', 0,
24263eb84d1Schristos	    'defopx', 0,
24363eb84d1Schristos	    'deftpx', 0,
24463eb84d1Schristos	    # shortcuts
24563eb84d1Schristos	    'defun', 'deffn Function',
24663eb84d1Schristos	    'defmac', 'deffn Macro',
24763eb84d1Schristos	    'defspec', 'deffn {Special Form}',
24863eb84d1Schristos	    'defvar', 'defvr Variable',
24963eb84d1Schristos	    'defopt', 'defvr {User Option}',
25063eb84d1Schristos	    'deftypefun', 'deftypefn Function',
25163eb84d1Schristos	    'deftypevar', 'deftypevr Variable',
25263eb84d1Schristos	    'defivar', 'defcv {Instance Variable}',
25363eb84d1Schristos	    'defmethod', 'defop Method',
25463eb84d1Schristos	    # x shortcuts
25563eb84d1Schristos	    'defunx', 'deffnx Function',
25663eb84d1Schristos	    'defmacx', 'deffnx Macro',
25763eb84d1Schristos	    'defspecx', 'deffnx {Special Form}',
25863eb84d1Schristos	    'defvarx', 'defvrx Variable',
25963eb84d1Schristos	    'defoptx', 'defvrx {User Option}',
26063eb84d1Schristos	    'deftypefunx', 'deftypefnx Function',
26163eb84d1Schristos	    'deftypevarx', 'deftypevrx Variable',
26263eb84d1Schristos	    'defivarx', 'defcvx {Instance Variable}',
26363eb84d1Schristos	    'defmethodx', 'defopx Method',
26463eb84d1Schristos	    );
26563eb84d1Schristos
26663eb84d1Schristos#
26763eb84d1Schristos# things to skip
26863eb84d1Schristos#
26963eb84d1Schristos%to_skip = (
27063eb84d1Schristos	    # comments
27163eb84d1Schristos	    'c', 1,
27263eb84d1Schristos	    'comment', 1,
27363eb84d1Schristos	    # useless
27463eb84d1Schristos	    'contents', 1,
27563eb84d1Schristos	    'shortcontents', 1,
27663eb84d1Schristos	    'summarycontents', 1,
27763eb84d1Schristos	    'footnotestyle', 1,
27863eb84d1Schristos	    'end ifclear', 1,
27963eb84d1Schristos	    'end ifset', 1,
28063eb84d1Schristos	    'titlepage', 1,
28163eb84d1Schristos	    'end titlepage', 1,
28263eb84d1Schristos	    # unsupported commands (formatting)
28363eb84d1Schristos	    'afourpaper', 1,
28463eb84d1Schristos	    'cropmarks', 1,
28563eb84d1Schristos	    'finalout', 1,
28663eb84d1Schristos	    'headings', 1,
28763eb84d1Schristos	    'need', 1,
28863eb84d1Schristos	    'page', 1,
28963eb84d1Schristos	    'setchapternewpage', 1,
29063eb84d1Schristos	    'everyheading', 1,
29163eb84d1Schristos	    'everyfooting', 1,
29263eb84d1Schristos	    'evenheading', 1,
29363eb84d1Schristos	    'evenfooting', 1,
29463eb84d1Schristos	    'oddheading', 1,
29563eb84d1Schristos	    'oddfooting', 1,
29663eb84d1Schristos	    'smallbook', 1,
29763eb84d1Schristos	    'vskip', 1,
29863eb84d1Schristos	    'filbreak', 1,
29963eb84d1Schristos	    'paragraphindent', 1,
30063eb84d1Schristos	    # unsupported formats
30163eb84d1Schristos	    'cartouche', 1,
30263eb84d1Schristos	    'end cartouche', 1,
30363eb84d1Schristos	    'group', 1,
30463eb84d1Schristos	    'end group', 1,
30563eb84d1Schristos	    );
30663eb84d1Schristos
30763eb84d1Schristos#+++############################################################################
30863eb84d1Schristos#                                                                              #
30963eb84d1Schristos# Argument parsing, initialisation                                             #
31063eb84d1Schristos#                                                                              #
31163eb84d1Schristos#---############################################################################
31263eb84d1Schristos
31363eb84d1Schristos%value = ();				# hold texinfo variables, see also -D
31463eb84d1Schristos
31563eb84d1Schristos$use_bibliography = 1;
31663eb84d1Schristos$use_acc = 0;
31763eb84d1Schristos$debug = 0;
31863eb84d1Schristos$doctype = '';
31963eb84d1Schristos$check = 0;
32063eb84d1Schristos$expandinfo = 0;
32163eb84d1Schristos$expandtex = 0;
32263eb84d1Schristos$use_glossary = 0;
32363eb84d1Schristos$invisible_mark = '';
32463eb84d1Schristos$use_iso = 0;
32563eb84d1Schristos@include_dirs = ();
32663eb84d1Schristos$show_menu = 0;
32763eb84d1Schristos$number_sections = 0;
32863eb84d1Schristos$split_node = 0;
32963eb84d1Schristos$split_chapter = 0;
33063eb84d1Schristos$monolithic = 0;
33163eb84d1Schristos$verbose = 0;
33263eb84d1Schristos$usage = <<EOT;
33363eb84d1SchristosThis is $THISPROG
33463eb84d1SchristosTo convert a Texinfo file to HMTL: $0 [options] file
33563eb84d1Schristos  where options can be:
33663eb84d1Schristos    -expandinfo    : use \@ifinfo sections, not \@ifhtml
33763eb84d1Schristos    -expandtex     : use \@iftex sections, not \@ifhtml
33863eb84d1Schristos    -glossary      : handle a glossary
33963eb84d1Schristos    -invisible name: use 'name' as an invisible anchor
34063eb84d1Schristos    -Dname         : define name like with \@set
34163eb84d1Schristos    -I dir         : search also for files in 'dir'
34263eb84d1Schristos    -menu          : handle menus
34363eb84d1Schristos    -monolithic    : output only one file including ToC
34463eb84d1Schristos    -number        : number sections
34563eb84d1Schristos    -split_chapter : split on main sections
34663eb84d1Schristos    -split_node    : split on nodes
34763eb84d1Schristos    -usage         : print usage instructions
34863eb84d1Schristos    -verbose       : verbose output
34963eb84d1SchristosTo check converted files: $0 -check [-verbose] files
35063eb84d1SchristosEOT
35163eb84d1Schristos
35263eb84d1Schristoswhile (@ARGV && $ARGV[0] =~ /^-/) {
35363eb84d1Schristos    $_ = shift(@ARGV);
35463eb84d1Schristos    if (/^-acc$/)            { $use_acc = 1; next; }
35563eb84d1Schristos    if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; }
35663eb84d1Schristos    if (/^-doctype$/)        { $doctype = shift(@ARGV); next; }
35763eb84d1Schristos    if (/^-c(heck)?$/)       { $check = 1; next; }
35863eb84d1Schristos    if (/^-expandi(nfo)?$/)  { $expandinfo = 1; next; }
35963eb84d1Schristos    if (/^-expandt(ex)?$/)   { $expandtex = 1; next; }
36063eb84d1Schristos    if (/^-g(lossary)?$/)    { $use_glossary = 1; next; }
36163eb84d1Schristos    if (/^-i(nvisible)?$/)   { $invisible_mark = shift(@ARGV); next; }
36263eb84d1Schristos    if (/^-iso$/)            { $use_iso = 1; next; }
36363eb84d1Schristos    if (/^-D(.+)?$/)         { $value{$1 || shift(@ARGV)} = 1; next; }
36463eb84d1Schristos    if (/^-I(.+)?$/)         { push(@include_dirs, $1 || shift(@ARGV)); next; }
36563eb84d1Schristos    if (/^-m(enu)?$/)        { $show_menu = 1; next; }
36663eb84d1Schristos    if (/^-mono(lithic)?$/)  { $monolithic = 1; next; }
36763eb84d1Schristos    if (/^-n(umber)?$/)      { $number_sections = 1; next; }
36863eb84d1Schristos    if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) {
36963eb84d1Schristos	if ($2 =~ /^n/) {
37063eb84d1Schristos	    $split_node = 1;
37163eb84d1Schristos	} else {
37263eb84d1Schristos	    $split_chapter = 1;
37363eb84d1Schristos	}
37463eb84d1Schristos	next;
37563eb84d1Schristos    }
37663eb84d1Schristos    if (/^-v(erbose)?$/)     { $verbose = 1; next; }
37763eb84d1Schristos    die $usage;
37863eb84d1Schristos}
37963eb84d1Schristosif ($check) {
38063eb84d1Schristos    die $usage unless @ARGV > 0;
38163eb84d1Schristos    &check;
38263eb84d1Schristos    exit;
38363eb84d1Schristos}
38463eb84d1Schristos
38563eb84d1Schristosif (($split_node || $split_chapter) && $monolithic) {
38663eb84d1Schristos    warn "Can't use -monolithic with -split, -monolithic ignored.\n";
38763eb84d1Schristos    $monolithic = 0;
38863eb84d1Schristos}
38963eb84d1Schristosif ($expandinfo) {
39063eb84d1Schristos    $to_skip{'ifinfo'}++;
39163eb84d1Schristos    $to_skip{'end ifinfo'}++;
39263eb84d1Schristos    $to_skip{'ifnottex'}++;
39363eb84d1Schristos    $to_skip{'end ifnottex'}++;
39463eb84d1Schristos    $to_skip{'ifnothtml'}++;
39563eb84d1Schristos    $to_skip{'end ifnothtml'}++;
39663eb84d1Schristos} elsif ($expandtex) {
39763eb84d1Schristos    $to_skip{'ifnotinfo'}++;
39863eb84d1Schristos    $to_skip{'end ifnotinfo'}++;
39963eb84d1Schristos    $to_skip{'iftex'}++;
40063eb84d1Schristos    $to_skip{'end iftex'}++;
40163eb84d1Schristos    $to_skip{'ifnothtml'}++;
40263eb84d1Schristos    $to_skip{'end ifnothtml'}++;
40363eb84d1Schristos} else {
40463eb84d1Schristos    $to_skip{'ifnotinfo'}++;
40563eb84d1Schristos    $to_skip{'end ifnotinfo'}++;
40663eb84d1Schristos    $to_skip{'ifnottex'}++;
40763eb84d1Schristos    $to_skip{'end ifnottex'}++;
40863eb84d1Schristos    $to_skip{'ifhtml'}++;
40963eb84d1Schristos    $to_skip{'end ifhtml'}++;
41063eb84d1Schristos}
41163eb84d1Schristos$invisible_mark = '<IMG SRC="invisible.xbm">' if $invisible_mark eq 'xbm';
41263eb84d1Schristosdie $usage unless @ARGV == 1;
41363eb84d1Schristos$docu = shift(@ARGV);
41463eb84d1Schristosif ($docu =~ /.*\//) {
41563eb84d1Schristos    chop($docu_dir = $&);
41663eb84d1Schristos    $docu_name = $';
41763eb84d1Schristos} else {
41863eb84d1Schristos    $docu_dir = '.';
41963eb84d1Schristos    $docu_name = $docu;
42063eb84d1Schristos}
42163eb84d1Schristosunshift(@include_dirs, $docu_dir);
42263eb84d1Schristos$docu_name =~ s/\.te?x(i|info)?$//;	# basename of the document
42363eb84d1Schristos
42463eb84d1Schristos$docu_doc = "$docu_name.html";		# document's contents
42563eb84d1Schristosif ($monolithic) {
42663eb84d1Schristos    $docu_toc = $docu_foot = $docu_doc;
42763eb84d1Schristos} else {
42863eb84d1Schristos    $docu_toc  = "${docu_name}_toc.html";  # document's table of contents
42963eb84d1Schristos    $docu_foot = "${docu_name}_foot.html"; # document's footnotes
43063eb84d1Schristos}
43163eb84d1Schristos
43263eb84d1Schristos#
43363eb84d1Schristos# variables
43463eb84d1Schristos#
43563eb84d1Schristos$value{'html'} = 1;			# predefine html (the output format)
43663eb84d1Schristos$value{'texi2html'} = '1.52b';		# predefine texi2html (the translator)
43763eb84d1Schristos# _foo: internal to track @foo
43863eb84d1Schristosforeach ('_author', '_title', '_subtitle',
43963eb84d1Schristos	 '_settitle', '_setfilename') {
44063eb84d1Schristos    $value{$_} = '';		        # prevent -w warnings
44163eb84d1Schristos}
44263eb84d1Schristos%node2sec = ();				# node to section name
44363eb84d1Schristos%node2href = ();			# node to HREF
44463eb84d1Schristos%bib2href = ();				# bibliography reference to HREF
44563eb84d1Schristos%gloss2href = ();			# glossary term to HREF
44663eb84d1Schristos@sections = ();				# list of sections
44763eb84d1Schristos%tag2pro = ();				# protected sections
44863eb84d1Schristos
44963eb84d1Schristos#
45063eb84d1Schristos# initial indexes
45163eb84d1Schristos#
45263eb84d1Schristos$bib_num = 0;
45363eb84d1Schristos$foot_num = 0;
45463eb84d1Schristos$gloss_num = 0;
45563eb84d1Schristos$idx_num = 0;
45663eb84d1Schristos$sec_num = 0;
45763eb84d1Schristos$doc_num = 0;
45863eb84d1Schristos$html_num = 0;
45963eb84d1Schristos
46063eb84d1Schristos#
46163eb84d1Schristos# can I use ISO8879 characters? (HTML+)
46263eb84d1Schristos#
46363eb84d1Schristosif ($use_iso) {
46463eb84d1Schristos    $things_map{'bullet'} = "&bull;";
46563eb84d1Schristos    $things_map{'copyright'} = "&copy;";
46663eb84d1Schristos    $things_map{'dots'} = "&hellip;";
46763eb84d1Schristos    $things_map{'equiv'} = "&equiv;";
46863eb84d1Schristos    $things_map{'expansion'} = "&rarr;";
46963eb84d1Schristos    $things_map{'point'} = "&lowast;";
47063eb84d1Schristos    $things_map{'result'} = "&rArr;";
47163eb84d1Schristos}
47263eb84d1Schristos
47363eb84d1Schristos#
47463eb84d1Schristos# read texi2html extensions (if any)
47563eb84d1Schristos#
47663eb84d1Schristos$extensions = 'texi2html.ext'; # extensions in working directory
47763eb84d1Schristosif (-f $extensions) {
47863eb84d1Schristos    print "# reading extensions from $extensions\n" if $verbose;
47963eb84d1Schristos    require($extensions);
48063eb84d1Schristos}
48163eb84d1Schristos($progdir = $0) =~ s/[^\/]+$//;
48263eb84d1Schristosif ($progdir && ($progdir ne './')) {
48363eb84d1Schristos    $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
48463eb84d1Schristos    if (-f $extensions) {
48563eb84d1Schristos	print "# reading extensions from $extensions\n" if $verbose;
48663eb84d1Schristos	require($extensions);
48763eb84d1Schristos    }
48863eb84d1Schristos}
48963eb84d1Schristos
49063eb84d1Schristosprint "# reading from $docu\n" if $verbose;
49163eb84d1Schristos
49263eb84d1Schristos#+++############################################################################
49363eb84d1Schristos#                                                                              #
49463eb84d1Schristos# Pass 1: read source, handle command, variable, simple substitution           #
49563eb84d1Schristos#                                                                              #
49663eb84d1Schristos#---############################################################################
49763eb84d1Schristos
49863eb84d1Schristos@lines = ();				# whole document
49963eb84d1Schristos@toc_lines = ();			# table of contents
50063eb84d1Schristos$toplevel = 0;			        # top level seen in hierarchy
50163eb84d1Schristos$curlevel = 0;				# current level in TOC
50263eb84d1Schristos$node = '';				# current node name
50363eb84d1Schristos$in_table = 0;				# am I inside a table
50463eb84d1Schristos$table_type = '';			# type of table ('', 'f', 'v', 'multi')
50563eb84d1Schristos@tables = ();			        # nested table support
50663eb84d1Schristos$in_bibliography = 0;			# am I inside a bibliography
50763eb84d1Schristos$in_glossary = 0;			# am I inside a glossary
50863eb84d1Schristos$in_top = 0;				# am I inside the top node
50963eb84d1Schristos$in_pre = 0;				# am I inside a preformatted section
51063eb84d1Schristos$in_list = 0;				# am I inside a list
51163eb84d1Schristos$in_html = 0;				# am I inside an HTML section
51263eb84d1Schristos$first_line = 1;		        # is it the first line
51363eb84d1Schristos$dont_html = 0;				# don't protect HTML on this line
51463eb84d1Schristos$split_num = 0;				# split index
51563eb84d1Schristos$deferred_ref = '';			# deferred reference for indexes
51663eb84d1Schristos@html_stack = ();			# HTML elements stack
51763eb84d1Schristos$html_element = '';			# current HTML element
51863eb84d1Schristos&html_reset;
51963eb84d1Schristos
52063eb84d1Schristos# build code for simple substitutions
52163eb84d1Schristos# the maps used (%simple_map and %things_map) MUST be aware of this
52263eb84d1Schristos# watch out for regexps, / and escaped characters!
52363eb84d1Schristos$subst_code = '';
52463eb84d1Schristosforeach (keys(%simple_map)) {
52563eb84d1Schristos    ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
52663eb84d1Schristos    $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
52763eb84d1Schristos}
52863eb84d1Schristosforeach (keys(%things_map)) {
52963eb84d1Schristos    $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
53063eb84d1Schristos}
53163eb84d1Schristosif ($use_acc) {
53263eb84d1Schristos    # accentuated characters
53363eb84d1Schristos    foreach (keys(%accent_map)) {
53463eb84d1Schristos	if ($_ eq "`") {
53563eb84d1Schristos	    $subst_code .= "s/$;3";
53663eb84d1Schristos	} elsif ($_ eq "'") {
53763eb84d1Schristos	    $subst_code .= "s/$;4";
53863eb84d1Schristos	} else {
53963eb84d1Schristos	    $subst_code .= "s/\\\@\\$_";
54063eb84d1Schristos	}
54163eb84d1Schristos	$subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
54263eb84d1Schristos    }
54363eb84d1Schristos}
54463eb84d1Schristoseval("sub simple_substitutions { $subst_code }");
54563eb84d1Schristos
54663eb84d1Schristos&init_input;
54763eb84d1Schristoswhile ($_ = &next_line) {
54863eb84d1Schristos    #
54963eb84d1Schristos    # remove \input on the first lines only
55063eb84d1Schristos    #
55163eb84d1Schristos    if ($first_line) {
55263eb84d1Schristos	next if /^\\input/;
55363eb84d1Schristos	$first_line = 0;
55463eb84d1Schristos    }
55563eb84d1Schristos    #
55663eb84d1Schristos    # parse texinfo tags
55763eb84d1Schristos    #
55863eb84d1Schristos    $tag = '';
55963eb84d1Schristos    $end_tag = '';
56063eb84d1Schristos    if (/^\@end\s+(\w+)\b/) {
56163eb84d1Schristos	$end_tag = $1;
56263eb84d1Schristos    } elsif (/^\@(\w+)\b/) {
56363eb84d1Schristos	$tag = $1;
56463eb84d1Schristos    }
56563eb84d1Schristos    #
56663eb84d1Schristos    # handle @ifhtml / @end ifhtml
56763eb84d1Schristos    #
56863eb84d1Schristos    if ($in_html) {
56963eb84d1Schristos	if ($end_tag eq 'ifhtml') {
57063eb84d1Schristos	    $in_html = 0;
57163eb84d1Schristos	} else {
57263eb84d1Schristos	    $tag2pro{$in_html} .= $_;
57363eb84d1Schristos	}
57463eb84d1Schristos	next;
57563eb84d1Schristos    } elsif ($tag eq 'ifhtml') {
57663eb84d1Schristos	$in_html = $PROTECTTAG . ++$html_num;
57763eb84d1Schristos	push(@lines, $in_html);
57863eb84d1Schristos	next;
57963eb84d1Schristos    }
58063eb84d1Schristos    #
58163eb84d1Schristos    # try to skip the line
58263eb84d1Schristos    #
58363eb84d1Schristos    if ($end_tag) {
58463eb84d1Schristos	next if $to_skip{"end $end_tag"};
58563eb84d1Schristos    } elsif ($tag) {
58663eb84d1Schristos	next if $to_skip{$tag};
58763eb84d1Schristos	last if $tag eq 'bye';
58863eb84d1Schristos    }
58963eb84d1Schristos    if ($in_top) {
59063eb84d1Schristos	# parsing the top node
59163eb84d1Schristos	if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) {
59263eb84d1Schristos	    # no more in top
59363eb84d1Schristos	    $in_top = 0;
59463eb84d1Schristos	} else {
59563eb84d1Schristos	    # skip it
59663eb84d1Schristos	    next;
59763eb84d1Schristos	}
59863eb84d1Schristos    }
59963eb84d1Schristos    #
60063eb84d1Schristos    # try to remove inlined comments
60163eb84d1Schristos    # syntax from tex-mode.el comment-start-skip
60263eb84d1Schristos    #
60363eb84d1Schristos    s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
60463eb84d1Schristos    # non-@ substitutions cf. texinfmt.el
60563eb84d1Schristos    unless ($in_pre) {
60663eb84d1Schristos	s/``/“/g;
60763eb84d1Schristos	s/''/”/g;
60863eb84d1Schristos	s/([\w ])---([\w ])/$1--$2/g;
60963eb84d1Schristos    }
61063eb84d1Schristos    #
61163eb84d1Schristos    # analyze the tag
61263eb84d1Schristos    #
61363eb84d1Schristos    if ($tag) {
61463eb84d1Schristos	# skip lines
61563eb84d1Schristos	&skip_until($tag), next if $tag eq 'ignore';
61663eb84d1Schristos	if ($expandinfo) {
61763eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifnotinfo';
61863eb84d1Schristos	    &skip_until($tag), next if $tag eq 'iftex';
61963eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifhtml';
62063eb84d1Schristos	} elsif ($expandtex) {
62163eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifinfo';
62263eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifnottex';
62363eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifhtml';
62463eb84d1Schristos	} else {
62563eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifinfo';
62663eb84d1Schristos	    &skip_until($tag), next if $tag eq 'iftex';
62763eb84d1Schristos	    &skip_until($tag), next if $tag eq 'ifnothtml';
62863eb84d1Schristos	}
62963eb84d1Schristos	&skip_until($tag), next if $tag eq 'tex';
63063eb84d1Schristos	# handle special tables
63163eb84d1Schristos	if ($tag =~ /^(|f|v|multi)table$/) {
63263eb84d1Schristos	    $table_type = $1;
63363eb84d1Schristos	    $tag = 'table';
63463eb84d1Schristos	}
63563eb84d1Schristos	# special cases
63663eb84d1Schristos	if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*,/i)) {
63763eb84d1Schristos	    $in_top = 1;
63863eb84d1Schristos	    @lines = (); # ignore all lines before top (title page garbage)
63963eb84d1Schristos	    next;
64063eb84d1Schristos	} elsif ($tag eq 'node') {
64163eb84d1Schristos	    $in_top = 0;
64263eb84d1Schristos	    warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
64363eb84d1Schristos	    $_ = &protect_html($_); # if node contains '&' for instance
64463eb84d1Schristos	    s/^\@node\s+//;
64563eb84d1Schristos	    ($node) = split(/,/);
64663eb84d1Schristos	    &normalise_node($node);
64763eb84d1Schristos	    if ($split_node) {
64863eb84d1Schristos		&next_doc;
64963eb84d1Schristos		push(@lines, $SPLITTAG) if $split_num++;
65063eb84d1Schristos		push(@sections, $node);
65163eb84d1Schristos	    }
65263eb84d1Schristos	    next;
65363eb84d1Schristos	} elsif ($tag eq 'include') {
65463eb84d1Schristos	    if (/^\@include\s+($FILERE)\s*$/o) {
65563eb84d1Schristos		$file = $1;
65663eb84d1Schristos		unless (-e $file) {
65763eb84d1Schristos		    foreach $dir (@include_dirs) {
65863eb84d1Schristos			$file = "$dir/$1";
65963eb84d1Schristos			last if -e $file;
66063eb84d1Schristos		    }
66163eb84d1Schristos		}
66263eb84d1Schristos		if (-e $file) {
66363eb84d1Schristos		    &open($file);
66463eb84d1Schristos		    print "# including $file\n" if $verbose;
66563eb84d1Schristos		} else {
66663eb84d1Schristos		    warn "$ERROR Can't find $file, skipping";
66763eb84d1Schristos		}
66863eb84d1Schristos	    } else {
66963eb84d1Schristos		warn "$ERROR Bad include line: $_";
67063eb84d1Schristos	    }
67163eb84d1Schristos	    next;
67263eb84d1Schristos	} elsif ($tag eq 'ifclear') {
67363eb84d1Schristos	    if (/^\@ifclear\s+($VARRE)\s*$/o) {
67463eb84d1Schristos		next unless defined($value{$1});
67563eb84d1Schristos		&skip_until($tag);
67663eb84d1Schristos	    } else {
67763eb84d1Schristos		warn "$ERROR Bad ifclear line: $_";
67863eb84d1Schristos	    }
67963eb84d1Schristos	    next;
68063eb84d1Schristos	} elsif ($tag eq 'ifset') {
68163eb84d1Schristos	    if (/^\@ifset\s+($VARRE)\s*$/o) {
68263eb84d1Schristos		next if defined($value{$1});
68363eb84d1Schristos		&skip_until($tag);
68463eb84d1Schristos	    } else {
68563eb84d1Schristos		warn "$ERROR Bad ifset line: $_";
68663eb84d1Schristos	    }
68763eb84d1Schristos	    next;
68863eb84d1Schristos	} elsif ($tag eq 'menu') {
68963eb84d1Schristos	    unless ($show_menu) {
69063eb84d1Schristos		&skip_until($tag);
69163eb84d1Schristos		next;
69263eb84d1Schristos	    }
69363eb84d1Schristos	    &html_push_if($tag);
69463eb84d1Schristos	    push(@lines, &html_debug("\n", __LINE__));
69563eb84d1Schristos	} elsif ($format_map{$tag}) {
69663eb84d1Schristos	    $in_pre = 1 if $format_map{$tag} eq 'PRE';
69763eb84d1Schristos	    &html_push_if($format_map{$tag});
69863eb84d1Schristos	    push(@lines, &html_debug("\n", __LINE__));
69963eb84d1Schristos	    $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
70063eb84d1Schristos	    push(@lines, &debug("<$format_map{$tag}>\n", __LINE__));
70163eb84d1Schristos	    next;
70263eb84d1Schristos	} elsif ($tag eq 'table') {
70363eb84d1Schristos	    if (/^\@(|f|v|multi)table\s+\@(\w+)/) {
70463eb84d1Schristos		$in_table = $2;
70563eb84d1Schristos		unshift(@tables, join($;, $table_type, $in_table));
70663eb84d1Schristos		if ($table_type eq "multi") {
70763eb84d1Schristos		    push(@lines, &debug("<TABLE BORDER>\n", __LINE__));
70863eb84d1Schristos		    &html_push_if('TABLE');
70963eb84d1Schristos		} else {
71063eb84d1Schristos		    push(@lines, &debug("<DL COMPACT>\n", __LINE__));
71163eb84d1Schristos		    &html_push_if('DL');
71263eb84d1Schristos		}
71363eb84d1Schristos		push(@lines, &html_debug("\n", __LINE__));
71463eb84d1Schristos	    } else {
71563eb84d1Schristos		warn "$ERROR Bad table line: $_";
71663eb84d1Schristos	    }
71763eb84d1Schristos	    next;
71863eb84d1Schristos	} elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
71963eb84d1Schristos	    if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
72063eb84d1Schristos		eval("*${1}index = *${2}index");
72163eb84d1Schristos	    } else {
72263eb84d1Schristos		warn "$ERROR Bad syn*index line: $_";
72363eb84d1Schristos	    }
72463eb84d1Schristos	    next;
72563eb84d1Schristos	} elsif ($tag eq 'sp') {
72663eb84d1Schristos	    push(@lines, &debug("<P>\n", __LINE__));
72763eb84d1Schristos	    next;
72863eb84d1Schristos	} elsif ($tag eq 'setref') {
72963eb84d1Schristos	    &protect_html; # if setref contains '&' for instance
73063eb84d1Schristos	    if (/^\@$tag\s*{($NODERE)}\s*$/) {
73163eb84d1Schristos		$setref = $1;
73263eb84d1Schristos		$setref =~ s/\s+/ /g; # normalize
73363eb84d1Schristos		$setref =~ s/ $//;
73463eb84d1Schristos		$node2sec{$setref} = $name;
73563eb84d1Schristos		$node2href{$setref} = "$docu_doc#$docid";
73663eb84d1Schristos	    } else {
73763eb84d1Schristos		warn "$ERROR Bad setref line: $_";
73863eb84d1Schristos	    }
73963eb84d1Schristos	    next;
74063eb84d1Schristos	} elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
74163eb84d1Schristos	    if (/^\@$tag\s+(\w\w)\s*$/) {
74263eb84d1Schristos		$valid_index{$1} = 1;
74363eb84d1Schristos	    } else {
74463eb84d1Schristos		warn "$ERROR Bad defindex line: $_";
74563eb84d1Schristos	    }
74663eb84d1Schristos	    next;
74763eb84d1Schristos	} elsif (defined($def_map{$tag})) {
74863eb84d1Schristos	    if ($def_map{$tag}) {
74963eb84d1Schristos		s/^\@$tag\s+//;
75063eb84d1Schristos		$tag = $def_map{$tag};
75163eb84d1Schristos		$_ = "\@$tag $_";
75263eb84d1Schristos		$tag =~ s/\s.*//;
75363eb84d1Schristos	    }
75463eb84d1Schristos	} elsif (defined($user_sub{$tag})) {
75563eb84d1Schristos	    s/^\@$tag\s+//;
75663eb84d1Schristos	    $sub = $user_sub{$tag};
75763eb84d1Schristos	    print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER;
75863eb84d1Schristos	    if (defined(&$sub)) {
75963eb84d1Schristos		chop($_);
76063eb84d1Schristos		&$sub($_);
76163eb84d1Schristos	    } else {
76263eb84d1Schristos		warn "$ERROR Bad user sub for $tag: $sub\n";
76363eb84d1Schristos	    }
76463eb84d1Schristos	    next;
76563eb84d1Schristos	}
76663eb84d1Schristos	if (defined($def_map{$tag})) {
76763eb84d1Schristos	    s/^\@$tag\s+//;
76863eb84d1Schristos	    if ($tag =~ /x$/) {
76963eb84d1Schristos		# extra definition line
77063eb84d1Schristos		$tag = $`;
77163eb84d1Schristos		$is_extra = 1;
77263eb84d1Schristos	    } else {
77363eb84d1Schristos		$is_extra = 0;
77463eb84d1Schristos	    }
77563eb84d1Schristos	    while (/\{([^\{\}]*)\}/) {
77663eb84d1Schristos		# this is a {} construct
77763eb84d1Schristos		($before, $contents, $after) = ($`, $1, $');
77863eb84d1Schristos		# protect spaces
77963eb84d1Schristos		$contents =~ s/\s+/$;9/g;
78063eb84d1Schristos		# restore $_ protecting {}
78163eb84d1Schristos		$_ = "$before$;7$contents$;8$after";
78263eb84d1Schristos	    }
78363eb84d1Schristos	    @args = split(/\s+/, &protect_html($_));
78463eb84d1Schristos	    foreach (@args) {
78563eb84d1Schristos		s/$;9/ /g;	# unprotect spaces
78663eb84d1Schristos		s/$;7/\{/g;	# ... {
78763eb84d1Schristos		s/$;8/\}/g;	# ... }
78863eb84d1Schristos	    }
78963eb84d1Schristos	    $type = shift(@args);
79063eb84d1Schristos	    $type =~ s/^\{(.*)\}$/$1/;
79163eb84d1Schristos	    print "# def ($tag): {$type} ", join(', ', @args), "\n"
79263eb84d1Schristos		if $debug & $DEBUG_DEF;
79363eb84d1Schristos	    $type .= ':'; # it's nicer like this
79463eb84d1Schristos	    $name = shift(@args);
79563eb84d1Schristos	    $name =~ s/^\{(.*)\}$/$1/;
79663eb84d1Schristos	    if ($is_extra) {
79763eb84d1Schristos		$_ = &debug("<DT>", __LINE__);
79863eb84d1Schristos	    } else {
79963eb84d1Schristos		$_ = &debug("<DL>\n<DT>", __LINE__);
80063eb84d1Schristos	    }
80163eb84d1Schristos	    if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') {
80263eb84d1Schristos		$_ .= "<U>$type</U> <B>$name</B>";
80363eb84d1Schristos		$_ .= " <I>@args</I>" if @args;
80463eb84d1Schristos	    } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
80563eb84d1Schristos		     || $tag eq 'defcv' || $tag eq 'defop') {
80663eb84d1Schristos		$ftype = $name;
80763eb84d1Schristos		$name = shift(@args);
80863eb84d1Schristos		$name =~ s/^\{(.*)\}$/$1/;
80963eb84d1Schristos		$_ .= "<U>$type</U> $ftype <B>$name</B>";
81063eb84d1Schristos		$_ .= " <I>@args</I>" if @args;
81163eb84d1Schristos	    } else {
81263eb84d1Schristos		warn "$ERROR Unknown definition type: $tag\n";
81363eb84d1Schristos		$_ .= "<U>$type</U> <B>$name</B>";
81463eb84d1Schristos		$_ .= " <I>@args</I>" if @args;
81563eb84d1Schristos	    }
81663eb84d1Schristos 	    $_ .= &debug("\n<DD>", __LINE__);
81763eb84d1Schristos	    $name = &unprotect_html($name);
81863eb84d1Schristos	    if ($tag eq 'deffn' || $tag eq 'deftypefn') {
81963eb84d1Schristos		unshift(@input_spool, "\@findex $name\n");
82063eb84d1Schristos	    } elsif ($tag eq 'defop') {
82163eb84d1Schristos		unshift(@input_spool, "\@findex $name on $ftype\n");
82263eb84d1Schristos	    } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') {
82363eb84d1Schristos		unshift(@input_spool, "\@vindex $name\n");
82463eb84d1Schristos	    } else {
82563eb84d1Schristos		unshift(@input_spool, "\@tindex $name\n");
82663eb84d1Schristos	    }
82763eb84d1Schristos	    $dont_html = 1;
82863eb84d1Schristos	}
82963eb84d1Schristos    } elsif ($end_tag) {
83063eb84d1Schristos	if ($format_map{$end_tag}) {
83163eb84d1Schristos	    $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
83263eb84d1Schristos	    $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
83363eb84d1Schristos	    &html_pop_if('LI', 'P');
83463eb84d1Schristos	    &html_pop_if();
83563eb84d1Schristos	    push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
83663eb84d1Schristos	    push(@lines, &html_debug("\n", __LINE__));
83763eb84d1Schristos	} elsif ($end_tag =~ /^(|f|v|multi)table$/) {
83863eb84d1Schristos	    unless (@tables) {
83963eb84d1Schristos		warn "$ERROR \@end $end_tag without \@*table\n";
84063eb84d1Schristos		next;
84163eb84d1Schristos	    }
84263eb84d1Schristos	    ($table_type, $in_table) = split($;, shift(@tables));
84363eb84d1Schristos	    unless ($1 eq $table_type) {
84463eb84d1Schristos		warn "$ERROR \@end $end_tag without matching \@$end_tag\n";
84563eb84d1Schristos		next;
84663eb84d1Schristos	    }
84763eb84d1Schristos	    if ($table_type eq "multi") {
84863eb84d1Schristos		push(@lines, "</TR></TABLE>\n");
84963eb84d1Schristos		&html_pop_if('TR');
85063eb84d1Schristos	    } else {
85163eb84d1Schristos		push(@lines, "</DL>\n");
85263eb84d1Schristos		&html_pop_if('DD');
85363eb84d1Schristos	    }
85463eb84d1Schristos	    &html_pop_if();
85563eb84d1Schristos	    if (@tables) {
85663eb84d1Schristos		($table_type, $in_table) = split($;, $tables[0]);
85763eb84d1Schristos	    } else {
85863eb84d1Schristos		$in_table = 0;
85963eb84d1Schristos	    }
86063eb84d1Schristos	} elsif (defined($def_map{$end_tag})) {
86163eb84d1Schristos 	    push(@lines, &debug("</DL>\n", __LINE__));
86263eb84d1Schristos	} elsif ($end_tag eq 'menu') {
86363eb84d1Schristos	    &html_pop_if();
86463eb84d1Schristos	    push(@lines, $_); # must keep it for pass 2
86563eb84d1Schristos	}
86663eb84d1Schristos	next;
86763eb84d1Schristos    }
86863eb84d1Schristos    #
86963eb84d1Schristos    # misc things
87063eb84d1Schristos    #
87163eb84d1Schristos    # protect texi and HTML things
87263eb84d1Schristos    &protect_texi;
87363eb84d1Schristos    $_ = &protect_html($_) unless $dont_html;
87463eb84d1Schristos    $dont_html = 0;
87563eb84d1Schristos    # substitution (unsupported things)
87663eb84d1Schristos    s/^\@center\s+//g;
87763eb84d1Schristos    s/^\@exdent\s+//g;
87863eb84d1Schristos    s/\@noindent\s+//g;
87963eb84d1Schristos    s/\@refill\s+//g;
88063eb84d1Schristos    # other substitutions
88163eb84d1Schristos    &simple_substitutions;
88263eb84d1Schristos    s/\@value{($VARRE)}/$value{$1}/eg;
88363eb84d1Schristos    s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
88463eb84d1Schristos    #
88563eb84d1Schristos    # analyze the tag again
88663eb84d1Schristos    #
88763eb84d1Schristos    if ($tag) {
88863eb84d1Schristos	if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
88963eb84d1Schristos	    if (/^\@$tag\s+(.+)$/) {
89063eb84d1Schristos		$name = $1;
89163eb84d1Schristos		$name =~ s/\s+$//;
89263eb84d1Schristos		$level = $sec2level{$tag};
89363eb84d1Schristos		$name = &update_sec_num($tag, $level) . "  $name"
89463eb84d1Schristos		    if $number_sections && $tag !~ /^unnumbered/;
89563eb84d1Schristos		if ($tag =~ /heading$/) {
89663eb84d1Schristos		    push(@lines, &html_debug("\n", __LINE__));
89763eb84d1Schristos		    if ($html_element ne 'body') {
89863eb84d1Schristos			# We are in a nice pickle here. We are trying to get a H? heading
89963eb84d1Schristos			# even though we are not in the body level. So, we convert it to a
90063eb84d1Schristos			# nice, bold, line by itself.
90163eb84d1Schristos			$_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__);
90263eb84d1Schristos		    } else {
90363eb84d1Schristos			$_ = &debug("<H$level>$name</H$level>\n", __LINE__);
90463eb84d1Schristos			&html_push_if('body');
90563eb84d1Schristos		    }
90663eb84d1Schristos		    print "# heading, section $name, level $level\n"
90763eb84d1Schristos			if $debug & $DEBUG_TOC;
90863eb84d1Schristos		} else {
90963eb84d1Schristos		    if ($split_chapter) {
91063eb84d1Schristos			unless ($toplevel) {
91163eb84d1Schristos			    # first time we see a "section"
91263eb84d1Schristos			    unless ($level == 1) {
91363eb84d1Schristos				warn "$ERROR The first section found is not of level 1: $_";
91463eb84d1Schristos				warn "$ERROR I'll split on sections of level $level...\n";
91563eb84d1Schristos			    }
91663eb84d1Schristos			    $toplevel = $level;
91763eb84d1Schristos			}
91863eb84d1Schristos			if ($level == $toplevel) {
91963eb84d1Schristos			    &next_doc;
92063eb84d1Schristos			    push(@lines, $SPLITTAG) if $split_num++;
92163eb84d1Schristos			    push(@sections, $name);
92263eb84d1Schristos			}
92363eb84d1Schristos		    }
92463eb84d1Schristos		    $sec_num++;
92563eb84d1Schristos		    $docid = "SEC$sec_num";
92663eb84d1Schristos		    $tocid = "TOC$sec_num";
92763eb84d1Schristos		    # check biblio and glossary
92863eb84d1Schristos		    $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
92963eb84d1Schristos		    $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
93063eb84d1Schristos		    # check node
93163eb84d1Schristos		    if ($node) {
93263eb84d1Schristos			if ($node2sec{$node}) {
93363eb84d1Schristos			    warn "$ERROR Duplicate node found: $node\n";
93463eb84d1Schristos			} else {
93563eb84d1Schristos			    $node2sec{$node} = $name;
93663eb84d1Schristos			    $node2href{$node} = "$docu_doc#$docid";
93763eb84d1Schristos			    print "# node $node, section $name, level $level\n"
93863eb84d1Schristos				if $debug & $DEBUG_TOC;
93963eb84d1Schristos			}
94063eb84d1Schristos			$node = '';
94163eb84d1Schristos		    } else {
94263eb84d1Schristos			print "# no node, section $name, level $level\n"
94363eb84d1Schristos			    if $debug & $DEBUG_TOC;
94463eb84d1Schristos		    }
94563eb84d1Schristos		    # update TOC
94663eb84d1Schristos		    while ($level > $curlevel) {
94763eb84d1Schristos			$curlevel++;
94863eb84d1Schristos			push(@toc_lines, "<UL>\n");
94963eb84d1Schristos		    }
95063eb84d1Schristos		    while ($level < $curlevel) {
95163eb84d1Schristos			$curlevel--;
95263eb84d1Schristos			push(@toc_lines, "</UL>\n");
95363eb84d1Schristos		    }
95463eb84d1Schristos		    $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", $name, 1);
95563eb84d1Schristos		    push(@toc_lines, &substitute_style($_));
95663eb84d1Schristos		    # update DOC
95763eb84d1Schristos		    push(@lines, &html_debug("\n", __LINE__));
95863eb84d1Schristos		    &html_reset;
95963eb84d1Schristos		    $_ =  "<H$level>".&anchor($docid, "$docu_toc#$tocid", $name)."</H$level>\n";
96063eb84d1Schristos		    $_ = &debug($_, __LINE__);
96163eb84d1Schristos		    push(@lines, &html_debug("\n", __LINE__));
96263eb84d1Schristos		}
96363eb84d1Schristos		# update DOC
96463eb84d1Schristos		foreach $line (split(/\n+/, $_)) {
96563eb84d1Schristos		    push(@lines, "$line\n");
96663eb84d1Schristos		}
96763eb84d1Schristos		next;
96863eb84d1Schristos	    } else {
96963eb84d1Schristos		warn "$ERROR Bad section line: $_";
97063eb84d1Schristos	    }
97163eb84d1Schristos	} else {
97263eb84d1Schristos	    # track variables
97363eb84d1Schristos	    $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o;
97463eb84d1Schristos	    delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
97563eb84d1Schristos	    # store things
97663eb84d1Schristos	    $value{'_setfilename'}   = $1, next if /^\@setfilename\s+(.*)$/;
97763eb84d1Schristos	    $value{'_settitle'}      = $1, next if /^\@settitle\s+(.*)$/;
97863eb84d1Schristos	    $value{'_author'}   .= "$1\n", next if /^\@author\s+(.*)$/;
97963eb84d1Schristos	    $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/;
98063eb84d1Schristos	    $value{'_title'}    .= "$1\n", next if /^\@title\s+(.*)$/;
98163eb84d1Schristos	    # index
98263eb84d1Schristos	    if (/^\@(..?)index\s+/) {
98363eb84d1Schristos		unless ($valid_index{$1}) {
98463eb84d1Schristos		    warn "$ERROR Undefined index command: $_";
98563eb84d1Schristos		    next;
98663eb84d1Schristos		}
98763eb84d1Schristos		$id = 'IDX' . ++$idx_num;
98863eb84d1Schristos		$index = $1 . 'index';
98963eb84d1Schristos		$what = &substitute_style($');
99063eb84d1Schristos		$what =~ s/\s+$//;
99163eb84d1Schristos		print "# found $index for '$what' id $id\n"
99263eb84d1Schristos		    if $debug & $DEBUG_INDEX;
99363eb84d1Schristos		eval(<<EOC);
99463eb84d1Schristos		if (defined(\$$index\{\$what\})) {
99563eb84d1Schristos		    \$$index\{\$what\} .= "$;$docu_doc#$id";
99663eb84d1Schristos		} else {
99763eb84d1Schristos		    \$$index\{\$what\} = "$docu_doc#$id";
99863eb84d1Schristos		}
99963eb84d1SchristosEOC
100063eb84d1Schristos		#
100163eb84d1Schristos		# dirty hack to see if I can put an invisible anchor...
100263eb84d1Schristos		#
100363eb84d1Schristos		if ($html_element eq 'P' ||
100463eb84d1Schristos		    $html_element eq 'LI' ||
100563eb84d1Schristos		    $html_element eq 'DT' ||
100663eb84d1Schristos		    $html_element eq 'DD' ||
100763eb84d1Schristos		    $html_element eq 'ADDRESS' ||
100863eb84d1Schristos		    $html_element eq 'B' ||
100963eb84d1Schristos		    $html_element eq 'BLOCKQUOTE' ||
101063eb84d1Schristos		    $html_element eq 'PRE' ||
101163eb84d1Schristos		    $html_element eq 'SAMP') {
101263eb84d1Schristos                    push(@lines, &anchor($id, '', $invisible_mark, !$in_pre));
101363eb84d1Schristos                } elsif ($html_element eq 'body') {
101463eb84d1Schristos		    push(@lines, &debug("<P>\n", __LINE__));
101563eb84d1Schristos                    push(@lines, &anchor($id, '', $invisible_mark, !$in_pre));
101663eb84d1Schristos		    &html_push('P');
101763eb84d1Schristos		} elsif ($html_element eq 'DL' ||
101863eb84d1Schristos			 $html_element eq 'UL' ||
101963eb84d1Schristos			 $html_element eq 'OL' ) {
102063eb84d1Schristos		    $deferred_ref .= &anchor($id, '', $invisible_mark, !$in_pre) . " ";
102163eb84d1Schristos		}
102263eb84d1Schristos		next;
102363eb84d1Schristos	    }
102463eb84d1Schristos	    # list item
102563eb84d1Schristos	    if (/^\@itemx?\s+/) {
102663eb84d1Schristos		$what = $';
102763eb84d1Schristos		$what =~ s/\s+$//;
102863eb84d1Schristos		if ($in_bibliography && $use_bibliography) {
102963eb84d1Schristos		    if ($what =~ /^$BIBRE$/o) {
103063eb84d1Schristos			$id = 'BIB' . ++$bib_num;
103163eb84d1Schristos			$bib2href{$what} = "$docu_doc#$id";
103263eb84d1Schristos			print "# found bibliography for '$what' id $id\n"
103363eb84d1Schristos			    if $debug & $DEBUG_BIB;
103463eb84d1Schristos			$what = &anchor($id, '', $what);
103563eb84d1Schristos		    }
103663eb84d1Schristos		} elsif ($in_glossary && $use_glossary) {
103763eb84d1Schristos		    $id = 'GLOSS' . ++$gloss_num;
103863eb84d1Schristos		    $entry = $what;
103963eb84d1Schristos		    $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
104063eb84d1Schristos		    $gloss2href{$entry} = "$docu_doc#$id";
104163eb84d1Schristos		    print "# found glossary for '$entry' id $id\n"
104263eb84d1Schristos			if $debug & $DEBUG_GLOSS;
104363eb84d1Schristos		    $what = &anchor($id, '', $what);
104463eb84d1Schristos		}
104563eb84d1Schristos		&html_pop_if('P');
104663eb84d1Schristos		if ($html_element eq 'DL' || $html_element eq 'DD') {
104763eb84d1Schristos		    if ($things_map{$in_table} && !$what) {
104863eb84d1Schristos			# special case to allow @table @bullet for instance
104963eb84d1Schristos			push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__));
105063eb84d1Schristos		    } else {
105163eb84d1Schristos			push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
105263eb84d1Schristos		    }
105363eb84d1Schristos		    push(@lines, "<DD>");
105463eb84d1Schristos		    &html_push('DD') unless $html_element eq 'DD';
105563eb84d1Schristos		    if ($table_type) { # add also an index
105663eb84d1Schristos			unshift(@input_spool, "\@${table_type}index $what\n");
105763eb84d1Schristos		    }
105863eb84d1Schristos		} elsif ($html_element eq 'TABLE') {
105963eb84d1Schristos		    push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
106063eb84d1Schristos		    &html_push('TR');
106163eb84d1Schristos		} elsif ($html_element eq 'TR') {
106263eb84d1Schristos		    push(@lines, &debug("</TR>\n", __LINE__));
106363eb84d1Schristos		    push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__));
106463eb84d1Schristos		} else {
106563eb84d1Schristos		    push(@lines, &debug("<LI>$what\n", __LINE__));
106663eb84d1Schristos		    &html_push('LI') unless $html_element eq 'LI';
106763eb84d1Schristos		}
106863eb84d1Schristos		push(@lines, &html_debug("\n", __LINE__));
106963eb84d1Schristos		if ($deferred_ref) {
107063eb84d1Schristos		    push(@lines, &debug("$deferred_ref\n", __LINE__));
107163eb84d1Schristos		    $deferred_ref = '';
107263eb84d1Schristos		}
107363eb84d1Schristos		next;
107463eb84d1Schristos	    } elsif (/^\@tab\s+(.*)$/) {
107563eb84d1Schristos		push(@lines, "<TD>$1</TD>\n");
107663eb84d1Schristos		next;
107763eb84d1Schristos	    }
107863eb84d1Schristos	}
107963eb84d1Schristos    }
108063eb84d1Schristos    # paragraph separator
108163eb84d1Schristos    if ($_ eq "\n") {
108263eb84d1Schristos	next if $#lines >= 0 && $lines[$#lines] eq "\n";
108363eb84d1Schristos	if ($html_element eq 'P') {
108463eb84d1Schristos	    push(@lines, "\n");
108563eb84d1Schristos	    $_ = &debug("</P>\n", __LINE__);
108663eb84d1Schristos	    &html_pop;
108763eb84d1Schristos	}
108863eb84d1Schristos    } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') {
108963eb84d1Schristos	push(@lines, "<P>\n");
109063eb84d1Schristos	&html_push('P');
109163eb84d1Schristos	$_ = &debug($_, __LINE__);
109263eb84d1Schristos    }
109363eb84d1Schristos    # otherwise
109463eb84d1Schristos    push(@lines, $_);
109563eb84d1Schristos}
109663eb84d1Schristos
109763eb84d1Schristos# finish TOC
109863eb84d1Schristos$level = 0;
109963eb84d1Schristoswhile ($level < $curlevel) {
110063eb84d1Schristos    $curlevel--;
110163eb84d1Schristos    push(@toc_lines, "</UL>\n");
110263eb84d1Schristos}
110363eb84d1Schristos
110463eb84d1Schristosprint "# end of pass 1\n" if $verbose;
110563eb84d1Schristos
110663eb84d1Schristos#+++############################################################################
110763eb84d1Schristos#                                                                              #
110863eb84d1Schristos# Pass 2/3: handle style, menu, index, cross-reference                         #
110963eb84d1Schristos#                                                                              #
111063eb84d1Schristos#---############################################################################
111163eb84d1Schristos
111263eb84d1Schristos@lines2 = ();				# whole document (2nd pass)
111363eb84d1Schristos@lines3 = ();				# whole document (3rd pass)
111463eb84d1Schristos$in_menu = 0;				# am I inside a menu
111563eb84d1Schristos
111663eb84d1Schristoswhile (@lines) {
111763eb84d1Schristos    $_ = shift(@lines);
111863eb84d1Schristos    #
111963eb84d1Schristos    # special case (protected sections)
112063eb84d1Schristos    #
112163eb84d1Schristos    if (/^$PROTECTTAG/o) {
112263eb84d1Schristos	push(@lines2, $_);
112363eb84d1Schristos	next;
112463eb84d1Schristos    }
112563eb84d1Schristos    #
112663eb84d1Schristos    # menu
112763eb84d1Schristos    #
112863eb84d1Schristos    $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\@menu\b/;
112963eb84d1Schristos    $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\@end\s+menu\b/;
113063eb84d1Schristos    if ($in_menu) {
113163eb84d1Schristos	if (/^\*\s+($NODERE)::/o) {
113263eb84d1Schristos	    $descr = $';
113363eb84d1Schristos	    chop($descr);
113463eb84d1Schristos	    &menu_entry($1, $1, $descr);
113563eb84d1Schristos	} elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
113663eb84d1Schristos	    $descr = $';
113763eb84d1Schristos	    chop($descr);
113863eb84d1Schristos	    &menu_entry($1, $2, $descr);
113963eb84d1Schristos	} elsif (/^\*/) {
114063eb84d1Schristos	    warn "$ERROR Bad menu line: $_";
114163eb84d1Schristos	} else { # description continued?
114263eb84d1Schristos	    push(@lines2, $_);
114363eb84d1Schristos	}
114463eb84d1Schristos	next;
114563eb84d1Schristos    }
114663eb84d1Schristos    #
114763eb84d1Schristos    # printindex
114863eb84d1Schristos    #
114963eb84d1Schristos    if (/^\@printindex\s+(\w\w)\b/) {
115063eb84d1Schristos	local($index, *ary, @keys, $key, $letter, $last_letter, @refs);
115163eb84d1Schristos	if ($predefined_index{$1}) {
115263eb84d1Schristos	    $index = $predefined_index{$1} . 'index';
115363eb84d1Schristos	} else {
115463eb84d1Schristos	    $index = $1 . 'index';
115563eb84d1Schristos	}
115663eb84d1Schristos	eval("*ary = *$index");
115763eb84d1Schristos	@keys = keys(%ary);
115863eb84d1Schristos	foreach $key (@keys) {
115963eb84d1Schristos	    $_ = $key;
116063eb84d1Schristos	    1 while s/<(\w+)>\`(.*)\&acute;<\/\1>/$2/; # remove HTML tags with quotes
116163eb84d1Schristos	    1 while s/<(\w+)>(.*)<\/\1>/$2/;     # remove HTML tags
116263eb84d1Schristos	    $_ = &unprotect_html($_);
116363eb84d1Schristos	    &unprotect_texi;
116463eb84d1Schristos	    tr/A-Z/a-z/; # lowercase
116563eb84d1Schristos	    $key2alpha{$key} = $_;
116663eb84d1Schristos	    print "# index $key sorted as $_\n"
116763eb84d1Schristos		if $key ne $_ && $debug & $DEBUG_INDEX;
116863eb84d1Schristos	}
116963eb84d1Schristos	push(@lines2, "Jump to:\n");
117063eb84d1Schristos	$last_letter = undef;
117163eb84d1Schristos	foreach $key (sort byalpha @keys) {
117263eb84d1Schristos	    $letter = substr($key2alpha{$key}, 0, 1);
117363eb84d1Schristos	    $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
117463eb84d1Schristos	    if (!defined($last_letter) || $letter ne $last_letter) {
117563eb84d1Schristos		push(@lines2, "-\n") if defined($last_letter);
117663eb84d1Schristos		push(@lines2, "<A HREF=\"#$index\_$letter\">" . &protect_html($letter) . "</A>\n");
117763eb84d1Schristos		$last_letter = $letter;
117863eb84d1Schristos	    }
117963eb84d1Schristos	}
118063eb84d1Schristos	push(@lines2, "<P>\n");
118163eb84d1Schristos	$last_letter = undef;
118263eb84d1Schristos	foreach $key (sort byalpha @keys) {
118363eb84d1Schristos	    $letter = substr($key2alpha{$key}, 0, 1);
118463eb84d1Schristos	    $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
118563eb84d1Schristos	    if (!defined($last_letter) || $letter ne $last_letter) {
118663eb84d1Schristos		push(@lines2, "</DIR>\n") if defined($last_letter);
118763eb84d1Schristos		push(@lines2, "<H2><A NAME=\"$index\_$letter\">" . &protect_html($letter) . "</A></H2>\n");
118863eb84d1Schristos		push(@lines2, "<DIR>\n");
118963eb84d1Schristos		$last_letter = $letter;
119063eb84d1Schristos	    }
119163eb84d1Schristos	    @refs = ();
119263eb84d1Schristos	    foreach (split(/$;/, $ary{$key})) {
119363eb84d1Schristos		push(@refs, &anchor('', $_, $key, 0));
119463eb84d1Schristos	    }
119563eb84d1Schristos	    push(@lines2, "<LI>" . join(", ", @refs) . "\n");
119663eb84d1Schristos	}
119763eb84d1Schristos	push(@lines2, "</DIR>\n") if defined($last_letter);
119863eb84d1Schristos	next;
119963eb84d1Schristos    }
120063eb84d1Schristos    #
120163eb84d1Schristos    # simple style substitutions
120263eb84d1Schristos    #
120363eb84d1Schristos    $_ = &substitute_style($_);
120463eb84d1Schristos    #
120563eb84d1Schristos    # xref
120663eb84d1Schristos    #
120763eb84d1Schristos    while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) {
120863eb84d1Schristos	# note: Texinfo may accept other characters
120963eb84d1Schristos	($type, $nodes, $full) = ($1, $2, $3);
121063eb84d1Schristos	($before, $after) = ($`, $');
121163eb84d1Schristos	if (! $full && $after) {
121263eb84d1Schristos	    warn "$ERROR Bad xref (no ending } on line): $_";
121363eb84d1Schristos	    $_ = "$before$;0${type}ref\{$nodes$after";
121463eb84d1Schristos	    next; # while xref
121563eb84d1Schristos	}
121663eb84d1Schristos	if ($type eq 'x') {
121763eb84d1Schristos	    $type = 'See ';
121863eb84d1Schristos	} elsif ($type eq 'px') {
121963eb84d1Schristos	    $type = 'see ';
122063eb84d1Schristos	} elsif ($type eq 'info') {
122163eb84d1Schristos	    $type = 'See Info';
122263eb84d1Schristos	} else {
122363eb84d1Schristos	    $type = '';
122463eb84d1Schristos	}
122563eb84d1Schristos	unless ($full) {
122663eb84d1Schristos	    $next = shift(@lines);
122763eb84d1Schristos	    $next = &substitute_style($next);
122863eb84d1Schristos	    chop($nodes); # remove final newline
122963eb84d1Schristos	    if ($next =~ /\}/) { # split on 2 lines
123063eb84d1Schristos		$nodes .= " $`";
123163eb84d1Schristos		$after = $';
123263eb84d1Schristos	    } else {
123363eb84d1Schristos		$nodes .= " $next";
123463eb84d1Schristos		$next = shift(@lines);
123563eb84d1Schristos		$next = &substitute_style($next);
123663eb84d1Schristos		chop($nodes);
123763eb84d1Schristos		if ($next =~ /\}/) { # split on 3 lines
123863eb84d1Schristos		    $nodes .= " $`";
123963eb84d1Schristos		    $after = $';
124063eb84d1Schristos		} else {
124163eb84d1Schristos		    warn "$ERROR Bad xref (no ending }): $_";
124263eb84d1Schristos		    $_ = "$before$;0xref\{$nodes$after";
124363eb84d1Schristos		    unshift(@lines, $next);
124463eb84d1Schristos		    next; # while xref
124563eb84d1Schristos		}
124663eb84d1Schristos	    }
124763eb84d1Schristos	}
124863eb84d1Schristos	$nodes =~ s/\s+/ /g; # remove useless spaces
124963eb84d1Schristos	@args = split(/\s*,\s*/, $nodes);
125063eb84d1Schristos	$node = $args[0]; # the node is always the first arg
125163eb84d1Schristos	&normalise_node($node);
125263eb84d1Schristos	$sec = $node2sec{$node};
125363eb84d1Schristos	if (@args == 5) { # reference to another manual
125463eb84d1Schristos	    $sec = $args[2] || $node;
125563eb84d1Schristos	    $man = $args[4] || $args[3];
125663eb84d1Schristos	    $_ = "${before}${type}section ‘$sec’ in \@cite{$man}$after";
125763eb84d1Schristos	} elsif ($type =~ /Info/) { # inforef
125863eb84d1Schristos	    warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
125963eb84d1Schristos	    ($nn, $_, $in) = @args;
126063eb84d1Schristos	    $_ = "${before}${type} file ‘$in’, node ‘$nn’$after";
126163eb84d1Schristos	} elsif ($sec) {
126263eb84d1Schristos	    $href = $node2href{$node};
126363eb84d1Schristos	    $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after;
126463eb84d1Schristos	} else {
126563eb84d1Schristos	    warn "$ERROR Undefined node ($node): $_";
126663eb84d1Schristos	    $_ = "$before$;0xref{$nodes}$after";
126763eb84d1Schristos	}
126863eb84d1Schristos    }
126963eb84d1Schristos    #
127063eb84d1Schristos    # try to guess bibliography references or glossary terms
127163eb84d1Schristos    #
127263eb84d1Schristos    unless (/^<H\d><A NAME=\"SEC\d/) {
127363eb84d1Schristos	if ($use_bibliography) {
127463eb84d1Schristos	    $done = '';
127563eb84d1Schristos	    while (/$BIBRE/o) {
127663eb84d1Schristos		($pre, $what, $post) = ($`, $&, $');
127763eb84d1Schristos		$href = $bib2href{$what};
127863eb84d1Schristos		if (defined($href) && $post !~ /^[^<]*<\/A>/) {
127963eb84d1Schristos		    $done .= $pre . &anchor('', $href, $what);
128063eb84d1Schristos		} else {
128163eb84d1Schristos		    $done .= "$pre$what";
128263eb84d1Schristos		}
128363eb84d1Schristos		$_ = $post;
128463eb84d1Schristos	    }
128563eb84d1Schristos	    $_ = $done . $_;
128663eb84d1Schristos	}
128763eb84d1Schristos	if ($use_glossary) {
128863eb84d1Schristos	    $done = '';
128963eb84d1Schristos	    while (/\b\w+\b/) {
129063eb84d1Schristos		($pre, $what, $post) = ($`, $&, $');
129163eb84d1Schristos		$entry = $what;
129263eb84d1Schristos		$entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
129363eb84d1Schristos		$href = $gloss2href{$entry};
129463eb84d1Schristos		if (defined($href) && $post !~ /^[^<]*<\/A>/) {
129563eb84d1Schristos		    $done .= $pre . &anchor('', $href, $what);
129663eb84d1Schristos		} else {
129763eb84d1Schristos		    $done .= "$pre$what";
129863eb84d1Schristos		}
129963eb84d1Schristos		$_ = $post;
130063eb84d1Schristos	    }
130163eb84d1Schristos	    $_ = $done . $_;
130263eb84d1Schristos	}
130363eb84d1Schristos    }
130463eb84d1Schristos    # otherwise
130563eb84d1Schristos    push(@lines2, $_);
130663eb84d1Schristos}
130763eb84d1Schristosprint "# end of pass 2\n" if $verbose;
130863eb84d1Schristos
130963eb84d1Schristos#
131063eb84d1Schristos# split style substitutions
131163eb84d1Schristos#
131263eb84d1Schristoswhile (@lines2) {
131363eb84d1Schristos    $_ = shift(@lines2);
131463eb84d1Schristos    #
131563eb84d1Schristos    # special case (protected sections)
131663eb84d1Schristos    #
131763eb84d1Schristos    if (/^$PROTECTTAG/o) {
131863eb84d1Schristos	push(@lines3, $_);
131963eb84d1Schristos	next;
132063eb84d1Schristos    }
132163eb84d1Schristos    #
132263eb84d1Schristos    # split style substitutions
132363eb84d1Schristos    #
132463eb84d1Schristos    $old = '';
132563eb84d1Schristos    while ($old ne $_) {
132663eb84d1Schristos        $old = $_;
132763eb84d1Schristos	if (/\@(\w+|"|\~|,|\^)\{/) {
132863eb84d1Schristos	    ($before, $style, $after) = ($`, $1, $');
132963eb84d1Schristos	    if (defined($style_map{$style})) {
133063eb84d1Schristos		$_ = $after;
133163eb84d1Schristos		$text = '';
133263eb84d1Schristos		$after = '';
133363eb84d1Schristos		$failed = 1;
133463eb84d1Schristos		while (@lines2) {
133563eb84d1Schristos		    if (/\}/) {
133663eb84d1Schristos			$text .= $`;
133763eb84d1Schristos			$after = $';
133863eb84d1Schristos			$failed = 0;
133963eb84d1Schristos			last;
134063eb84d1Schristos		    } else {
134163eb84d1Schristos			$text .= $_;
134263eb84d1Schristos			$_ = shift(@lines2);
134363eb84d1Schristos		    }
134463eb84d1Schristos		}
134563eb84d1Schristos		if ($failed) {
134663eb84d1Schristos		    die "* Bad syntax (\@$style) after: $before\n";
134763eb84d1Schristos		} else {
134863eb84d1Schristos		    $text = &apply_style($style, $text);
134963eb84d1Schristos		    $_ = "$before$text$after";
135063eb84d1Schristos		}
135163eb84d1Schristos	    }
135263eb84d1Schristos	}
135363eb84d1Schristos    }
135463eb84d1Schristos    # otherwise
135563eb84d1Schristos    push(@lines3, $_);
135663eb84d1Schristos}
135763eb84d1Schristosprint "# end of pass 3\n" if $verbose;
135863eb84d1Schristos
135963eb84d1Schristos#+++############################################################################
136063eb84d1Schristos#                                                                              #
136163eb84d1Schristos# Pass 4: foot notes, final cleanup                                            #
136263eb84d1Schristos#                                                                              #
136363eb84d1Schristos#---############################################################################
136463eb84d1Schristos
136563eb84d1Schristos@foot_lines = ();			# footnotes
136663eb84d1Schristos@doc_lines = ();			# final document
136763eb84d1Schristos$end_of_para = 0;			# true if last line is <P>
136863eb84d1Schristos
136963eb84d1Schristoswhile (@lines3) {
137063eb84d1Schristos    $_ = shift(@lines3);
137163eb84d1Schristos    #
137263eb84d1Schristos    # special case (protected sections)
137363eb84d1Schristos    #
137463eb84d1Schristos    if (/^$PROTECTTAG/o) {
137563eb84d1Schristos	push(@doc_lines, $_);
137663eb84d1Schristos	$end_of_para = 0;
137763eb84d1Schristos	next;
137863eb84d1Schristos    }
137963eb84d1Schristos    #
138063eb84d1Schristos    # footnotes
138163eb84d1Schristos    #
138263eb84d1Schristos    while (/\@footnote([^\{\s]+)\{/) {
138363eb84d1Schristos	($before, $d, $after) = ($`, $1, $');
138463eb84d1Schristos	$_ = $after;
138563eb84d1Schristos	$text = '';
138663eb84d1Schristos	$after = '';
138763eb84d1Schristos	$failed = 1;
138863eb84d1Schristos	while (@lines3) {
138963eb84d1Schristos	    if (/\}/) {
139063eb84d1Schristos		$text .= $`;
139163eb84d1Schristos		$after = $';
139263eb84d1Schristos		$failed = 0;
139363eb84d1Schristos		last;
139463eb84d1Schristos	    } else {
139563eb84d1Schristos		$text .= $_;
139663eb84d1Schristos		$_ = shift(@lines3);
139763eb84d1Schristos	    }
139863eb84d1Schristos	}
139963eb84d1Schristos	if ($failed) {
140063eb84d1Schristos	    die "* Bad syntax (\@footnote) after: $before\n";
140163eb84d1Schristos	} else {
140263eb84d1Schristos	    $foot_num++;
140363eb84d1Schristos	    $docid  = "DOCF$foot_num";
140463eb84d1Schristos	    $footid = "FOOT$foot_num";
140563eb84d1Schristos	    $foot = "($foot_num)";
140663eb84d1Schristos	    push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", $foot) . "</H3>\n");
140763eb84d1Schristos	    $text = "<P>$text" unless $text =~ /^\s*<P>/;
140863eb84d1Schristos	    push(@foot_lines, "$text\n");
140963eb84d1Schristos	    $_ = $before . &anchor($docid, "$docu_foot#$footid", $foot) . $after;
141063eb84d1Schristos	}
141163eb84d1Schristos    }
141263eb84d1Schristos    #
141363eb84d1Schristos    # remove unnecessary <P>
141463eb84d1Schristos    #
141563eb84d1Schristos    if (/^\s*<P>\s*$/) {
141663eb84d1Schristos	next if $end_of_para++;
141763eb84d1Schristos    } else {
141863eb84d1Schristos	$end_of_para = 0;
141963eb84d1Schristos    }
142063eb84d1Schristos    # otherwise
142163eb84d1Schristos    push(@doc_lines, $_);
142263eb84d1Schristos}
142363eb84d1Schristosprint "# end of pass 4\n" if $verbose;
142463eb84d1Schristos
142563eb84d1Schristos#+++############################################################################
142663eb84d1Schristos#                                                                              #
142763eb84d1Schristos# Pass 5: print things                                                         #
142863eb84d1Schristos#                                                                              #
142963eb84d1Schristos#---############################################################################
143063eb84d1Schristos
143163eb84d1Schristos$header = <<EOT;
143263eb84d1Schristos<!-- This HTML file has been created by $THISPROG
143363eb84d1Schristos     from $docu on $TODAY -->
143463eb84d1SchristosEOT
143563eb84d1Schristos
143663eb84d1Schristos$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
143763eb84d1Schristos$title = $value{'_settitle'} || $full_title;
143863eb84d1Schristos$_ = &substitute_style($full_title);
143963eb84d1Schristos&unprotect_texi;
144063eb84d1Schristoss/\n$//; # rmv last \n (if any)
144163eb84d1Schristos$full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
144263eb84d1Schristos
144363eb84d1Schristos#
144463eb84d1Schristos# print ToC
144563eb84d1Schristos#
144663eb84d1Schristosif (!$monolithic && @toc_lines) {
144763eb84d1Schristos    if (open(FILE, "> $docu_toc")) {
144863eb84d1Schristos	print "# creating $docu_toc...\n" if $verbose;
144963eb84d1Schristos	&print_toplevel_header("$title - Table of Contents");
145063eb84d1Schristos	&print_ruler;
145163eb84d1Schristos	&print(*toc_lines, FILE);
145263eb84d1Schristos	&print_toplevel_footer;
145363eb84d1Schristos	close(FILE);
145463eb84d1Schristos    } else {
145563eb84d1Schristos	warn "$ERROR Can't write to $docu_toc: $!\n";
145663eb84d1Schristos    }
145763eb84d1Schristos}
145863eb84d1Schristos
145963eb84d1Schristos#
146063eb84d1Schristos# print footnotes
146163eb84d1Schristos#
146263eb84d1Schristosif (!$monolithic && @foot_lines) {
146363eb84d1Schristos    if (open(FILE, "> $docu_foot")) {
146463eb84d1Schristos	print "# creating $docu_foot...\n" if $verbose;
146563eb84d1Schristos	&print_toplevel_header("$title - Footnotes");
146663eb84d1Schristos	&print_ruler;
146763eb84d1Schristos        &print(*foot_lines, FILE);
146863eb84d1Schristos	&print_toplevel_footer;
146963eb84d1Schristos	close(FILE);
147063eb84d1Schristos    } else {
147163eb84d1Schristos	warn "$ERROR Can't write to $docu_foot: $!\n";
147263eb84d1Schristos    }
147363eb84d1Schristos}
147463eb84d1Schristos
147563eb84d1Schristos#
147663eb84d1Schristos# print document
147763eb84d1Schristos#
147863eb84d1Schristosif ($split_chapter || $split_node) { # split
147963eb84d1Schristos    $doc_num = 0;
148063eb84d1Schristos    $last_num = scalar(@sections);
148163eb84d1Schristos    $first_doc = &doc_name(1);
148263eb84d1Schristos    $last_doc = &doc_name($last_num);
148363eb84d1Schristos    while (@sections) {
148463eb84d1Schristos	$section = shift(@sections);
148563eb84d1Schristos	&next_doc;
148663eb84d1Schristos	if (open(FILE, "> $docu_doc")) {
148763eb84d1Schristos	    print "# creating $docu_doc...\n" if $verbose;
148863eb84d1Schristos	    &print_header("$title - $section");
148963eb84d1Schristos	    $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1));
149063eb84d1Schristos	    $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1));
149163eb84d1Schristos	    $navigation = "Go to the ";
149263eb84d1Schristos	    $navigation .= ($prev_doc ? &anchor('', $first_doc, "first") : "first");
149363eb84d1Schristos	    $navigation .= ", ";
149463eb84d1Schristos	    $navigation .= ($prev_doc ? &anchor('', $prev_doc, "previous") : "previous");
149563eb84d1Schristos	    $navigation .= ", ";
149663eb84d1Schristos	    $navigation .= ($next_doc ? &anchor('', $next_doc, "next") : "next");
149763eb84d1Schristos	    $navigation .= ", ";
149863eb84d1Schristos	    $navigation .= ($next_doc ? &anchor('', $last_doc, "last") : "last");
149963eb84d1Schristos	    $navigation .= " section, " . &anchor('', $docu_toc, "table of contents") . ".\n";
150063eb84d1Schristos	    print FILE $navigation;
150163eb84d1Schristos	    &print_ruler;
150263eb84d1Schristos	    # find corresponding lines
150363eb84d1Schristos            @tmp_lines = ();
150463eb84d1Schristos            while (@doc_lines) {
150563eb84d1Schristos		$_ = shift(@doc_lines);
150663eb84d1Schristos		last if ($_ eq $SPLITTAG);
150763eb84d1Schristos		push(@tmp_lines, $_);
150863eb84d1Schristos	    }
150963eb84d1Schristos            &print(*tmp_lines, FILE);
151063eb84d1Schristos	    &print_ruler;
151163eb84d1Schristos	    print FILE $navigation;
151263eb84d1Schristos	    &print_footer;
151363eb84d1Schristos	    close(FILE);
151463eb84d1Schristos	} else {
151563eb84d1Schristos	    warn "$ERROR Can't write to $docu_doc: $!\n";
151663eb84d1Schristos	}
151763eb84d1Schristos    }
151863eb84d1Schristos} else { # not split
151963eb84d1Schristos    if (open(FILE, "> $docu_doc")) {
152063eb84d1Schristos	print "# creating $docu_doc...\n" if $verbose;
152163eb84d1Schristos	if ($monolithic || !@toc_lines) {
152263eb84d1Schristos	    &print_toplevel_header($title);
152363eb84d1Schristos	} else {
152463eb84d1Schristos	    &print_header($title);
152563eb84d1Schristos	    print FILE $full_title;
152663eb84d1Schristos	}
152763eb84d1Schristos	if ($monolithic && @toc_lines) {
152863eb84d1Schristos	    &print_ruler;
152963eb84d1Schristos 	    print FILE "<H1>Table of Contents</H1>\n";
153063eb84d1Schristos 	    &print(*toc_lines, FILE);
153163eb84d1Schristos	}
153263eb84d1Schristos	&print_ruler;
153363eb84d1Schristos        &print(*doc_lines, FILE);
153463eb84d1Schristos	if ($monolithic && @foot_lines) {
153563eb84d1Schristos	    &print_ruler;
153663eb84d1Schristos 	    print FILE "<H1>Footnotes</H1>\n";
153763eb84d1Schristos 	    &print(*foot_lines, FILE);
153863eb84d1Schristos	}
153963eb84d1Schristos	if ($monolithic || !@toc_lines) {
154063eb84d1Schristos	    &print_toplevel_footer;
154163eb84d1Schristos	} else {
154263eb84d1Schristos	    &print_footer;
154363eb84d1Schristos	}
154463eb84d1Schristos	close(FILE);
154563eb84d1Schristos    } else {
154663eb84d1Schristos	warn "$ERROR Can't write to $docu_doc: $!\n";
154763eb84d1Schristos    }
154863eb84d1Schristos}
154963eb84d1Schristos
155063eb84d1Schristosprint "# that's all folks\n" if $verbose;
155163eb84d1Schristos
155263eb84d1Schristos#+++############################################################################
155363eb84d1Schristos#                                                                              #
155463eb84d1Schristos# Low level functions                                                          #
155563eb84d1Schristos#                                                                              #
155663eb84d1Schristos#---############################################################################
155763eb84d1Schristos
155863eb84d1Schristossub update_sec_num {
155963eb84d1Schristos    local($name, $level) = @_;
156063eb84d1Schristos
156163eb84d1Schristos    $level--; # here we start at 0
156263eb84d1Schristos    if ($name =~ /^appendix/) {
156363eb84d1Schristos	# appendix style
1564*99c2fe91Schristos	if (@appendix_sec_num) {
156563eb84d1Schristos	    &incr_sec_num($level, @appendix_sec_num);
156663eb84d1Schristos	} else {
156763eb84d1Schristos	    @appendix_sec_num = ('A', 0, 0, 0);
156863eb84d1Schristos	}
156963eb84d1Schristos	return(join('.', @appendix_sec_num[0..$level]));
157063eb84d1Schristos    } else {
157163eb84d1Schristos	# normal style
1572*99c2fe91Schristos	if (@normal_sec_num) {
157363eb84d1Schristos	    &incr_sec_num($level, @normal_sec_num);
157463eb84d1Schristos	} else {
157563eb84d1Schristos	    @normal_sec_num = (1, 0, 0, 0);
157663eb84d1Schristos	}
157763eb84d1Schristos	return(join('.', @normal_sec_num[0..$level]));
157863eb84d1Schristos    }
157963eb84d1Schristos}
158063eb84d1Schristos
158163eb84d1Schristossub incr_sec_num {
158263eb84d1Schristos    local($level, $l);
158363eb84d1Schristos    $level = shift(@_);
158463eb84d1Schristos    $_[$level]++;
158563eb84d1Schristos    foreach $l ($level+1 .. 3) {
158663eb84d1Schristos	$_[$l] = 0;
158763eb84d1Schristos    }
158863eb84d1Schristos}
158963eb84d1Schristos
159063eb84d1Schristossub check {
159163eb84d1Schristos    local($_, %seen, %context, $before, $match, $after);
159263eb84d1Schristos
159363eb84d1Schristos    while (<>) {
159463eb84d1Schristos	if (/\@(\*|\.|\:|\@|\{|\})/) {
159563eb84d1Schristos	    $seen{$&}++;
159663eb84d1Schristos	    $context{$&} .= "> $_" if $verbose;
159763eb84d1Schristos	    $_ = "$`XX$'";
159863eb84d1Schristos	    redo;
159963eb84d1Schristos	}
160063eb84d1Schristos	if (/\@(\w+)/) {
160163eb84d1Schristos	    ($before, $match, $after) = ($`, $&, $');
160263eb84d1Schristos	    if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
160363eb84d1Schristos		$seen{'e-mail address'}++;
160463eb84d1Schristos		$context{'e-mail address'} .= "> $_" if $verbose;
160563eb84d1Schristos	    } else {
160663eb84d1Schristos		$seen{$match}++;
160763eb84d1Schristos		$context{$match} .= "> $_" if $verbose;
160863eb84d1Schristos	    }
160963eb84d1Schristos	    $match =~ s/^\@/X/;
161063eb84d1Schristos	    $_ = "$before$match$after";
161163eb84d1Schristos	    redo;
161263eb84d1Schristos	}
161363eb84d1Schristos    }
161463eb84d1Schristos
161563eb84d1Schristos    foreach (sort(keys(%seen))) {
161663eb84d1Schristos	if ($verbose) {
161763eb84d1Schristos	    print "$_\n";
161863eb84d1Schristos	    print $context{$_};
161963eb84d1Schristos	} else {
162063eb84d1Schristos	    print "$_ ($seen{$_})\n";
162163eb84d1Schristos	}
162263eb84d1Schristos    }
162363eb84d1Schristos}
162463eb84d1Schristos
162563eb84d1Schristossub open {
162663eb84d1Schristos    local($name) = @_;
162763eb84d1Schristos
162863eb84d1Schristos    ++$fh_name;
162963eb84d1Schristos    if (open($fh_name, $name)) {
163063eb84d1Schristos	unshift(@fhs, $fh_name);
163163eb84d1Schristos    } else {
163263eb84d1Schristos	warn "$ERROR Can't read file $name: $!\n";
163363eb84d1Schristos    }
163463eb84d1Schristos}
163563eb84d1Schristos
163663eb84d1Schristossub init_input {
163763eb84d1Schristos    @fhs = ();			# hold the file handles to read
163863eb84d1Schristos    @input_spool = ();		# spooled lines to read
163963eb84d1Schristos    $fh_name = 'FH000';
164063eb84d1Schristos    &open($docu);
164163eb84d1Schristos}
164263eb84d1Schristos
164363eb84d1Schristossub next_line {
164463eb84d1Schristos    local($fh, $line);
164563eb84d1Schristos
164663eb84d1Schristos    if (@input_spool) {
164763eb84d1Schristos	$line = shift(@input_spool);
164863eb84d1Schristos	return($line);
164963eb84d1Schristos    }
165063eb84d1Schristos    while (@fhs) {
165163eb84d1Schristos	$fh = $fhs[0];
165263eb84d1Schristos	$line = <$fh>;
165363eb84d1Schristos	return($line) if $line;
165463eb84d1Schristos	close($fh);
165563eb84d1Schristos	shift(@fhs);
165663eb84d1Schristos    }
165763eb84d1Schristos    return(undef);
165863eb84d1Schristos}
165963eb84d1Schristos
166063eb84d1Schristos# used in pass 1, use &next_line
166163eb84d1Schristossub skip_until {
166263eb84d1Schristos    local($tag) = @_;
166363eb84d1Schristos    local($_);
166463eb84d1Schristos
166563eb84d1Schristos    while ($_ = &next_line) {
166663eb84d1Schristos	return if /^\@end\s+$tag\s*$/;
166763eb84d1Schristos    }
166863eb84d1Schristos    die "* Failed to find '$tag' after: " . $lines[$#lines];
166963eb84d1Schristos}
167063eb84d1Schristos
167163eb84d1Schristos#
167263eb84d1Schristos# HTML stacking to have a better HTML output
167363eb84d1Schristos#
167463eb84d1Schristos
167563eb84d1Schristossub html_reset {
167663eb84d1Schristos    @html_stack = ('html');
167763eb84d1Schristos    $html_element = 'body';
167863eb84d1Schristos}
167963eb84d1Schristos
168063eb84d1Schristossub html_push {
168163eb84d1Schristos    local($what) = @_;
168263eb84d1Schristos    push(@html_stack, $html_element);
168363eb84d1Schristos    $html_element = $what;
168463eb84d1Schristos}
168563eb84d1Schristos
168663eb84d1Schristossub html_push_if {
168763eb84d1Schristos    local($what) = @_;
168863eb84d1Schristos    push(@html_stack, $html_element)
168963eb84d1Schristos	if ($html_element && $html_element ne 'P');
169063eb84d1Schristos    $html_element = $what;
169163eb84d1Schristos}
169263eb84d1Schristos
169363eb84d1Schristossub html_pop {
169463eb84d1Schristos    $html_element = pop(@html_stack);
169563eb84d1Schristos}
169663eb84d1Schristos
169763eb84d1Schristossub html_pop_if {
169863eb84d1Schristos    local($elt);
169963eb84d1Schristos
170063eb84d1Schristos    if (@_) {
170163eb84d1Schristos	foreach $elt (@_) {
170263eb84d1Schristos	    if ($elt eq $html_element) {
170363eb84d1Schristos		$html_element = pop(@html_stack) if @html_stack;
170463eb84d1Schristos		last;
170563eb84d1Schristos	    }
170663eb84d1Schristos	}
170763eb84d1Schristos    } else {
170863eb84d1Schristos	$html_element = pop(@html_stack) if @html_stack;
170963eb84d1Schristos    }
171063eb84d1Schristos}
171163eb84d1Schristos
171263eb84d1Schristossub html_debug {
171363eb84d1Schristos    local($what, $line) = @_;
171463eb84d1Schristos    return("<!-- $line @html_stack, $html_element -->$what")
171563eb84d1Schristos	if $debug & $DEBUG_HTML;
171663eb84d1Schristos    return($what);
171763eb84d1Schristos}
171863eb84d1Schristos
171963eb84d1Schristos# to debug the output...
172063eb84d1Schristossub debug {
172163eb84d1Schristos    local($what, $line) = @_;
172263eb84d1Schristos    return("<!-- $line -->$what")
172363eb84d1Schristos	if $debug & $DEBUG_HTML;
172463eb84d1Schristos    return($what);
172563eb84d1Schristos}
172663eb84d1Schristos
172763eb84d1Schristossub normalise_node {
172863eb84d1Schristos    $_[0] =~ s/\s+/ /g;
172963eb84d1Schristos    $_[0] =~ s/ $//;
173063eb84d1Schristos    $_[0] =~ s/^ //;
173163eb84d1Schristos}
173263eb84d1Schristos
173363eb84d1Schristossub menu_entry {
173463eb84d1Schristos    local($entry, $node, $descr) = @_;
173563eb84d1Schristos    local($href);
173663eb84d1Schristos
173763eb84d1Schristos    &normalise_node($node);
173863eb84d1Schristos    $href = $node2href{$node};
173963eb84d1Schristos    if ($href) {
174063eb84d1Schristos	$descr =~ s/^\s+//;
174163eb84d1Schristos	$descr = ": $descr" if $descr;
174263eb84d1Schristos	push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n");
174363eb84d1Schristos    } else {
174463eb84d1Schristos	warn "$ERROR Undefined node ($node): $_";
174563eb84d1Schristos    }
174663eb84d1Schristos}
174763eb84d1Schristos
174863eb84d1Schristossub do_ctrl { "^$_[0]" }
174963eb84d1Schristos
175063eb84d1Schristossub do_email {
175163eb84d1Schristos    local($addr, $text) = split(/,\s*/, $_[0]);
175263eb84d1Schristos
175363eb84d1Schristos    $text = $addr unless $text;
175463eb84d1Schristos    &anchor('', "mailto:$addr", $text);
175563eb84d1Schristos}
175663eb84d1Schristos
175763eb84d1Schristossub do_sc { "\U$_[0]\E" }
175863eb84d1Schristos
175963eb84d1Schristossub do_uref {
176063eb84d1Schristos    local($url, $text) = split(/,\s*/, $_[0]);
176163eb84d1Schristos
176263eb84d1Schristos    $text = $url unless $text;
176363eb84d1Schristos    &anchor('', $url, $text);
176463eb84d1Schristos}
176563eb84d1Schristos
176663eb84d1Schristossub do_url { &anchor('', $_[0], $_[0]) }
176763eb84d1Schristos
176863eb84d1Schristossub do_diaeresis { return "&$_[0]uml;"; }
176963eb84d1Schristossub do_acuteaccent { return "&$_[0]acute;"; }
177063eb84d1Schristossub do_graveaccent { return "&$_[0]grave;"; }
177163eb84d1Schristossub do_tildeaccent { return "&$_[0]tilde;"; }
177263eb84d1Schristossub do_cedilla { return "&$_[0]cedil;"; }
177363eb84d1Schristossub do_circumflex { return "&$_[0]circ;"; }
177463eb84d1Schristos
177563eb84d1Schristossub apply_style {
177663eb84d1Schristos    local($texi_style, $text) = @_;
177763eb84d1Schristos    local($style);
177863eb84d1Schristos
177963eb84d1Schristos    $style = $style_map{$texi_style};
178063eb84d1Schristos    if (defined($style)) { # known style
178163eb84d1Schristos	if ($style =~ /^\"/) { # add quotes
178263eb84d1Schristos	    $style = $';
178363eb84d1Schristos	    $text = "\&lsquo;$text\&rsquo;";
178463eb84d1Schristos	}
178563eb84d1Schristos	if ($style =~ /^\&/) { # custom
178663eb84d1Schristos	    $style = $';
178763eb84d1Schristos	    $text = &$style($text);
178863eb84d1Schristos	} elsif ($style) { # good style
178963eb84d1Schristos	    $text = "<$style>$text</$style>";
179063eb84d1Schristos	} else { # no style
179163eb84d1Schristos	}
179263eb84d1Schristos    } else { # unknown style
179363eb84d1Schristos	$text = undef;
179463eb84d1Schristos    }
179563eb84d1Schristos    return($text);
179663eb84d1Schristos}
179763eb84d1Schristos
179863eb84d1Schristos# remove Texinfo styles
179963eb84d1Schristossub remove_style {
180063eb84d1Schristos    local($_) = @_;
180163eb84d1Schristos    s/\@\w+{([^\{\}]+)}/$1/g;
180263eb84d1Schristos    return($_);
180363eb84d1Schristos}
180463eb84d1Schristos
180563eb84d1Schristossub substitute_style {
180663eb84d1Schristos    local($_) = @_;
180763eb84d1Schristos    local($changed, $done, $style, $text);
180863eb84d1Schristos
180963eb84d1Schristos    $changed = 1;
181063eb84d1Schristos    while ($changed) {
181163eb84d1Schristos	$changed = 0;
181263eb84d1Schristos	$done = '';
181363eb84d1Schristos	while (/\@(\w+|"|\~|,|\^){([^\{\}]+)}/) {
181463eb84d1Schristos	    $text = &apply_style($1, $2);
181563eb84d1Schristos	    if ($text) {
181663eb84d1Schristos		$_ = "$`$text$'";
181763eb84d1Schristos		$changed = 1;
181863eb84d1Schristos	    } else {
181963eb84d1Schristos		$done .= "$`\@$1";
182063eb84d1Schristos		$_ = "{$2}$'";
182163eb84d1Schristos	    }
182263eb84d1Schristos	}
182363eb84d1Schristos        $_ = $done . $_;
182463eb84d1Schristos    }
182563eb84d1Schristos    return($_);
182663eb84d1Schristos}
182763eb84d1Schristos
182863eb84d1Schristossub anchor {
182963eb84d1Schristos    local($name, $href, $text, $newline) = @_;
183063eb84d1Schristos    local($result);
183163eb84d1Schristos
183263eb84d1Schristos    $result = "<A";
183363eb84d1Schristos    $result .= " NAME=\"$name\"" if $name;
183463eb84d1Schristos    $result .= " HREF=\"$href\"" if $href;
183563eb84d1Schristos    $result .= ">$text</A>";
183663eb84d1Schristos    $result .= "\n" if $newline;
183763eb84d1Schristos    return($result);
183863eb84d1Schristos}
183963eb84d1Schristos
184063eb84d1Schristossub pretty_date {
184163eb84d1Schristos    local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
184263eb84d1Schristos
184363eb84d1Schristos    @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
184463eb84d1Schristos	    'July', 'August', 'September', 'October', 'November', 'December');
184563eb84d1Schristos    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
184663eb84d1Schristos    $year += ($year < 70) ? 2000 : 1900;
184763eb84d1Schristos    return("$mday $MoY[$mon] $year");
184863eb84d1Schristos}
184963eb84d1Schristos
185063eb84d1Schristossub doc_name {
185163eb84d1Schristos    local($num) = @_;
185263eb84d1Schristos
185363eb84d1Schristos    return("${docu_name}_$num.html");
185463eb84d1Schristos}
185563eb84d1Schristos
185663eb84d1Schristossub next_doc {
185763eb84d1Schristos    $docu_doc = &doc_name(++$doc_num);
185863eb84d1Schristos}
185963eb84d1Schristos
186063eb84d1Schristossub print {
186163eb84d1Schristos    local(*lines, $fh) = @_;
186263eb84d1Schristos    local($_);
186363eb84d1Schristos
186463eb84d1Schristos    while (@lines) {
186563eb84d1Schristos	$_ = shift(@lines);
186663eb84d1Schristos	if (/^$PROTECTTAG/o) {
186763eb84d1Schristos	    $_ = $tag2pro{$_};
186863eb84d1Schristos	} else {
186963eb84d1Schristos	    &unprotect_texi;
187063eb84d1Schristos	}
187163eb84d1Schristos	print $fh $_;
187263eb84d1Schristos    }
187363eb84d1Schristos}
187463eb84d1Schristos
187563eb84d1Schristossub print_ruler {
187663eb84d1Schristos    print FILE "<P><HR><P>\n";
187763eb84d1Schristos}
187863eb84d1Schristos
187963eb84d1Schristossub print_header {
188063eb84d1Schristos    local($_);
188163eb84d1Schristos
188263eb84d1Schristos    # clean the title
188363eb84d1Schristos    $_ = &remove_style($_[0]);
188463eb84d1Schristos    &unprotect_texi;
188563eb84d1Schristos    # print the header
188663eb84d1Schristos    if ($doctype eq 'html2') {
188763eb84d1Schristos	print FILE $html2_doctype;
188863eb84d1Schristos    } elsif ($doctype) {
188963eb84d1Schristos	print FILE $doctype;
189063eb84d1Schristos    }
189163eb84d1Schristos    print FILE <<EOT;
189263eb84d1Schristos<HTML>
189363eb84d1Schristos<HEAD>
189463eb84d1Schristos$header
189563eb84d1Schristos<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8">
189663eb84d1Schristos<TITLE>$_</TITLE>
189763eb84d1Schristos</HEAD>
189863eb84d1Schristos<BODY>
189963eb84d1SchristosEOT
190063eb84d1Schristos}
190163eb84d1Schristos
190263eb84d1Schristossub print_toplevel_header {
190363eb84d1Schristos    local($_);
190463eb84d1Schristos
190563eb84d1Schristos    &print_header; # pass given arg...
190663eb84d1Schristos    print FILE $full_title;
190763eb84d1Schristos    if ($value{'_subtitle'}) {
190863eb84d1Schristos	$value{'_subtitle'} =~ s/\n+$//;
190963eb84d1Schristos	foreach (split(/\n/, $value{'_subtitle'})) {
191063eb84d1Schristos	    $_ = &substitute_style($_);
191163eb84d1Schristos	    &unprotect_texi;
191263eb84d1Schristos	    print FILE "<H2>$_</H2>\n";
191363eb84d1Schristos	}
191463eb84d1Schristos    }
191563eb84d1Schristos    if ($value{'_author'}) {
191663eb84d1Schristos	$value{'_author'} =~ s/\n+$//;
191763eb84d1Schristos	foreach (split(/\n/, $value{'_author'})) {
191863eb84d1Schristos	    $_ = &substitute_style($_);
191963eb84d1Schristos	    &unprotect_texi;
192063eb84d1Schristos	    s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
192163eb84d1Schristos	    print FILE "<ADDRESS>$_</ADDRESS>\n";
192263eb84d1Schristos	}
192363eb84d1Schristos    }
192463eb84d1Schristos    print FILE "<P>\n";
192563eb84d1Schristos}
192663eb84d1Schristos
192763eb84d1Schristossub print_footer {
192863eb84d1Schristos    print FILE <<EOT;
192963eb84d1Schristos</BODY>
193063eb84d1Schristos</HTML>
193163eb84d1SchristosEOT
193263eb84d1Schristos}
193363eb84d1Schristos
193463eb84d1Schristossub print_toplevel_footer {
193563eb84d1Schristos    &print_ruler;
193663eb84d1Schristos    print FILE <<EOT;
193763eb84d1SchristosThis document was generated on $TODAY using the
193863eb84d1Schristos<A HREF=\"$HOMEPAGE\">texi2html</A>
193963eb84d1Schristostranslator version 1.52b.</P>
194063eb84d1SchristosEOT
194163eb84d1Schristos    &print_footer;
194263eb84d1Schristos}
194363eb84d1Schristos
194463eb84d1Schristossub protect_texi {
194563eb84d1Schristos    # protect @ { } ` '
194663eb84d1Schristos    s/\@\@/$;0/go;
194763eb84d1Schristos    s/\@\{/$;1/go;
194863eb84d1Schristos    s/\@\}/$;2/go;
194963eb84d1Schristos    s/\@\`/$;3/go;
195063eb84d1Schristos    s/\@\'/$;4/go;
195163eb84d1Schristos}
195263eb84d1Schristos
195363eb84d1Schristossub protect_html {
195463eb84d1Schristos    local($what) = @_;
195563eb84d1Schristos    # protect & < >
195663eb84d1Schristos    $what =~ s/\&/\&\#38;/g;
195763eb84d1Schristos    $what =~ s/\</\&\#60;/g;
195863eb84d1Schristos    $what =~ s/\>/\&\#62;/g;
195963eb84d1Schristos    # but recognize some HTML things
196063eb84d1Schristos    $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g;	      # </A>
196163eb84d1Schristos    $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g;     # <A [^&]+>
196263eb84d1Schristos    $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
196363eb84d1Schristos    return($what);
196463eb84d1Schristos}
196563eb84d1Schristos
196663eb84d1Schristossub unprotect_texi {
196763eb84d1Schristos    s/$;0/\@/go;
196863eb84d1Schristos    s/$;1/\{/go;
196963eb84d1Schristos    s/$;2/\}/go;
197063eb84d1Schristos    s/$;3/\`/go;
197163eb84d1Schristos    s/$;4/\'/go;
197263eb84d1Schristos}
197363eb84d1Schristos
197463eb84d1Schristossub unprotect_html {
197563eb84d1Schristos    local($what) = @_;
197663eb84d1Schristos    $what =~ s/\&\#38;/\&/g;
197763eb84d1Schristos    $what =~ s/\&\#60;/\</g;
197863eb84d1Schristos    $what =~ s/\&\#62;/\>/g;
197963eb84d1Schristos    return($what);
198063eb84d1Schristos}
198163eb84d1Schristos
198263eb84d1Schristossub byalpha {
198363eb84d1Schristos    $key2alpha{$a} cmp $key2alpha{$b};
198463eb84d1Schristos}
198563eb84d1Schristos
198663eb84d1Schristos##############################################################################
198763eb84d1Schristos
198863eb84d1Schristos	# These next few lines are legal in both Perl and nroff.
198963eb84d1Schristos
199063eb84d1Schristos.00 ;			# finish .ig
199163eb84d1Schristos
199263eb84d1Schristos'di			\" finish diversion--previous line must be blank
199363eb84d1Schristos.nr nl 0-1		\" fake up transition to first page again
199463eb84d1Schristos.nr % 0			\" start at page 1
199563eb84d1Schristos'; __END__ ############# From here on it's a standard manual page ############
199663eb84d1Schristos.TH TEXI2HTML 1 "01/05/98"
199763eb84d1Schristos.AT 3
199863eb84d1Schristos.SH NAME
199963eb84d1Schristostexi2html \- a Texinfo to HTML converter
200063eb84d1Schristos.SH SYNOPSIS
200163eb84d1Schristos.B texi2html [options] file
200263eb84d1Schristos.PP
200363eb84d1Schristos.B texi2html -check [-verbose] files
200463eb84d1Schristos.SH DESCRIPTION
200563eb84d1Schristos.I Texi2html
200663eb84d1Schristosconverts the given Texinfo file to a set of HTML files. It tries to handle
200763eb84d1Schristosmost of the Texinfo commands. It creates hypertext links for cross-references,
200863eb84d1Schristosfootnotes...
200963eb84d1Schristos.PP
201063eb84d1SchristosIt also tries to add links from a reference to its corresponding entry in the
201163eb84d1Schristosbibliography (if any). It may also handle a glossary (see the
201263eb84d1Schristos.B \-glossary
201363eb84d1Schristosoption).
201463eb84d1Schristos.PP
201563eb84d1Schristos.I Texi2html
201663eb84d1Schristoscreates several files depending on the contents of the Texinfo file and on
201763eb84d1Schristosthe chosen options (see FILES).
201863eb84d1Schristos.PP
201963eb84d1SchristosThe HTML files created by
202063eb84d1Schristos.I texi2html
202163eb84d1Schristosare closer to TeX than to Info, that's why
202263eb84d1Schristos.I texi2html
202363eb84d1Schristosconverts @ifhtml sections and not @ifinfo or @iftex ones by default. You can
202463eb84d1Schristoschange this with the \-expandinfo or \-expandtex options.
202563eb84d1Schristos.SH OPTIONS
202663eb84d1Schristos.TP 12
202763eb84d1Schristos.B \-check
202863eb84d1SchristosCheck the given file and give the list of all things that may be Texinfo commands.
202963eb84d1SchristosThis may be used to check the output of
203063eb84d1Schristos.I texi2html
203163eb84d1Schristosto find the Texinfo commands that have been left in the HTML file.
203263eb84d1Schristos.TP
203363eb84d1Schristos.B \-expandinfo
203463eb84d1SchristosExpand @ifinfo sections, not @ifhtml ones.
203563eb84d1Schristos.TP
203663eb84d1Schristos.B \-expandtex
203763eb84d1SchristosExpand @iftex sections, not @ifhtml ones.
203863eb84d1Schristos.TP
203963eb84d1Schristos.B \-glossary
204063eb84d1SchristosUse the section named 'Glossary' to build a list of terms and put links in the HTML
204163eb84d1Schristosdocument from each term toward its definition.
204263eb84d1Schristos.TP
204363eb84d1Schristos.B \-invisible \fIname\fP
204463eb84d1SchristosUse \fIname\fP to create invisible destination anchors for index links
204563eb84d1Schristos(you can for instance use the invisible.xbm file shipped with this program).
204663eb84d1SchristosThis is a workaround for a known bug of many WWW browsers, including netscape.
204763eb84d1Schristos.TP
204863eb84d1Schristos.B \-I \fIdir\fP
204963eb84d1SchristosLook also in \fIdir\fP to find included files.
205063eb84d1Schristos.TP
205163eb84d1Schristos.B \-menu
205263eb84d1SchristosShow the Texinfo menus; by default they are ignored.
205363eb84d1Schristos.TP
205463eb84d1Schristos.B \-monolithic
205563eb84d1SchristosOutput only one file, including the table of contents and footnotes.
205663eb84d1Schristos.TP
205763eb84d1Schristos.B \-number
205863eb84d1SchristosNumber the sections.
205963eb84d1Schristos.TP
206063eb84d1Schristos.B \-split_chapter
206163eb84d1SchristosSplit the output into several HTML files (one per main section:
206263eb84d1Schristoschapter, appendix...).
206363eb84d1Schristos.TP
206463eb84d1Schristos.B \-split_node
206563eb84d1SchristosSplit the output into several HTML files (one per node).
206663eb84d1Schristos.TP
206763eb84d1Schristos.B \-usage
206863eb84d1SchristosPrint usage instructions, listing the current available command-line options.
206963eb84d1Schristos.TP
207063eb84d1Schristos.B \-verbose
207163eb84d1SchristosGive a verbose output. Can be used with the
207263eb84d1Schristos.B \-check
207363eb84d1Schristosoption.
207463eb84d1Schristos.PP
207563eb84d1Schristos.SH FILES
207663eb84d1SchristosBy default
207763eb84d1Schristos.I texi2html
207863eb84d1Schristoscreates the following files (foo being the name of the Texinfo file):
207963eb84d1Schristos.TP 16
208063eb84d1Schristos.B foo_toc.html
208163eb84d1SchristosThe table of contents.
208263eb84d1Schristos.TP
208363eb84d1Schristos.B foo.html
208463eb84d1SchristosThe document's contents.
208563eb84d1Schristos.TP
208663eb84d1Schristos.B foo_foot.html
208763eb84d1SchristosThe footnotes (if any).
208863eb84d1Schristos.PP
208963eb84d1SchristosWhen used with the
209063eb84d1Schristos.B \-split
209163eb84d1Schristosoption, it creates several files (one per chapter or node), named
209263eb84d1Schristos.B foo_n.html
209363eb84d1Schristos(n being the indice of the chapter or node), instead of the single
209463eb84d1Schristos.B foo.html
209563eb84d1Schristosfile.
209663eb84d1Schristos.PP
209763eb84d1SchristosWhen used with the
209863eb84d1Schristos.B \-monolithic
209963eb84d1Schristosoption, it creates only one file:
210063eb84d1Schristos.B foo.html
210163eb84d1Schristos.SH VARIABLES
210263eb84d1Schristos.I texi2html
210363eb84d1Schristospredefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
210463eb84d1Schristos.SH ADDITIONAL COMMANDS
210563eb84d1Schristos.I texi2html
210663eb84d1Schristosimplements the following non-Texinfo commands (maybe they are in Texinfo now...):
210763eb84d1Schristos.TP 16
210863eb84d1Schristos.B @ifhtml
210963eb84d1SchristosThis indicates the start of an HTML section, this section will passed through
211063eb84d1Schristoswithout any modification.
211163eb84d1Schristos.TP
211263eb84d1Schristos.B @end ifhtml
211363eb84d1SchristosThis indicates the end of an HTML section.
211463eb84d1Schristos.SH VERSION
211563eb84d1SchristosThis is \fItexi2html\fP version 1.52b, 01/05/98.
211663eb84d1Schristos.PP
211763eb84d1SchristosThe latest version of \fItexi2html\fP can be found in WWW, cf. URL
211863eb84d1Schristoshttp://wwwinfo.cern.ch/dis/texi2html/
211963eb84d1Schristos.SH AUTHOR
212063eb84d1SchristosThe main author is Lionel Cons, CERN IT/DIS/OSE, Lionel.Cons@cern.ch.
212163eb84d1SchristosMany other people around the net contributed to this program.
212263eb84d1Schristos.SH COPYRIGHT
212363eb84d1SchristosThis program is the intellectual property of the European
212463eb84d1SchristosLaboratory for Particle Physics (known as CERN). No guarantee whatsoever is
212563eb84d1Schristosprovided by CERN. No liability whatsoever is accepted for any loss or damage
212663eb84d1Schristosof any kind resulting from any defect or inaccuracy in this information or
212763eb84d1Schristoscode.
212863eb84d1Schristos.PP
212963eb84d1SchristosCERN, 1211 Geneva 23, Switzerland
213063eb84d1Schristos.SH "SEE ALSO"
213163eb84d1SchristosGNU Texinfo Documentation Format,
213263eb84d1SchristosHyperText Markup Language (HTML),
213363eb84d1SchristosWorld Wide Web (WWW).
213463eb84d1Schristos.SH BUGS
213563eb84d1SchristosThis program does not understand all Texinfo commands (yet).
213663eb84d1Schristos.ex
2137