source: git/doc/texi2html @ 5b0536

spielwiese
Last change on this file since 5b0536 was 5b0536, checked in by Kai Krüger <krueger@…>, 26 years ago
changed icons git-svn-id: file:///usr/local/Singular/svn/trunk@2192 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 62.3 KB
RevLine 
[5d13bc]1#!/usr/bin/perl
2'di ';
3'ig 00 ';
[5b0536]4# $Id: texi2html,v 1.4 1998-06-18 09:21:40 krueger Exp $
[5d13bc]5# Description: Program to transform most Texinfo documents to HTML.
6# The plan is for the next version of makeinfo to support HTML output
7# directly, but until then ...
8
9$THISPROG = "texi2html 1.54";                   # program name and version
10# This version of texi2html is currently maintained at
11# ftp://ftp.cs.umb.edu/pub/tex/texi2html by kb@cs.umb.edu.
12
13# The man page for this program is included at the end of this file and can be
14# viewed using the command 'nroff -man texi2html'.
15# Please read the copyright at the end of the man page.
16
17# Fixme:
18# deal with @macro @unmacro @shorttitlepage @detailmenu @image
19# [plus more fixmes below]
20# Use <link>s for Up, Index, Glossary?
21# Inserting copyright links: Having texinfo markup for the online copyright
22#  would allow a link to that from wherever.
23
24#+++############################################################################
25#                                                                              #
26# Constants                                                                    #
27#                                                                              #
28#---############################################################################
29
30$DEBUG_TOC   =  1;
31$DEBUG_INDEX =  2;
32$DEBUG_BIB   =  4;
33$DEBUG_GLOSS =  8;
34$DEBUG_DEF   = 16;
35$DEBUG_HTML  = 32;
36$DEBUG_USER  = 64;
37
[5b0536]38#$IMG_FIRST_ACTIVE  = "<IMG SRC=\"first-b.gif\">";
39#$IMG_FIRST_PASSIVE = "<IMG SRC=\"first-t.gif\">";
40#$IMG_LAST_ACTIVE   = "<IMG SRC=\"last-b.gif\">";
41#$IMG_LAST_PASSIVE  = "<IMG SRC=\"last-t.gif\">";
42#$IMG_NEXT_ACTIVE   = "<IMG SRC=\"next-b.gif\">";
43#$IMG_NEXT_PASSIVE  = "<IMG SRC=\"next-t.gif\">";
44#$IMG_PREV_ACTIVE   = "<IMG SRC=\"previous-b.gif\">";
45#$IMG_PREV_PASSIVE  = "<IMG SRC=\"previous-t.gif\">";
46#$IMG_TOC           = "<IMG SRC=\"toc-b.gif\">";
47$IMG_FIRST_ACTIVE  = "";
48$IMG_FIRST_PASSIVE = "";
49$IMG_LAST_ACTIVE   = "";
50$IMG_LAST_PASSIVE  = "";
51$IMG_NEXT_ACTIVE   = "<IMG SRC=\"next_motif.gif\">";
52$IMG_NEXT_PASSIVE  = "<IMG SRC=\"next_motif_gr.gif\">";
53$IMG_PREV_ACTIVE   = "<IMG SRC=\"previous_motif.gif\">";
54$IMG_PREV_PASSIVE  = "<IMG SRC=\"previous_motif_gr.gif\">";
55$IMG_TOC           = "<IMG SRC=\"contents_motif.gif\">";
[fb646a]56
[5d13bc]57$BIBRE = '\[[\w\/]+\]';                 # RE for a bibliography reference
58$FILERE = '[\/\w.+-]+';                 # RE for a file name
59$VARRE = '[^\s\{\}]+';                  # RE for a variable name
60$NODERE = '[^@{}:\'`",]+';              # RE for a node name
61$NODESRE = '[^@{}:\'`"]+';              # RE for a list of node names
62$XREFRE = '[^@{}]+';                    # RE for a xref (should use NODERE)
63
64$ERROR = "***";                         # prefix for errors and warnings
65$HOMEPAGE = "http://wwwcn.cern.ch/dci/texi2html/"; # program home page
66$TODAY = &pretty_date;                  # like "20 September 1993"
67$SPLITTAG = "<!-- SPLIT HERE -->\n";    # tag to know where to split
68$PROTECTTAG = "_ThisIsProtected_";      # tag to recognize protected sections
69$TOPTAG = "<!--top-->";         # tag to mark first node (end of preamble)
70$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">';
71
72#
73# language dependent constants
74#
75#$LDC_SEE = 'see';
76#$LDC_SECTION = 'section';
77#$LDC_IN = 'in';
78#$LDC_TOC = 'Table of Contents';
79#$LDC_GOTO = 'Go to the';
80#$LDC_FOOT = 'Footnotes';
81# TODO: @def* shortcuts
82
83#
84# pre-defined indices
85#
86%predefined_index = (
87                    'cp', 'c',
88                    'fn', 'f',
89                    'vr', 'v',
90                    'ky', 'k',
91                    'pg', 'p',
92                    'tp', 't',
93                    );
94
95#
96# valid indices
97#
98%valid_index = (
99                    'c', 1,
100                    'f', 1,
101                    'v', 1,
102                    'k', 1,
103                    'p', 1,
104                    't', 1,
105                );
106
107#
108# texinfo section names to level
109#
110%sec2level = (
111              'top', 0,
112              'chapter', 1,
113              'unnumbered', 1,
114              'majorheading', 1,
115              'chapheading', 1,
116              'appendix', 1,
117              'section', 2,
118              'unnumberedsec', 2,
119              'heading', 2,
120              'appendixsec', 2,
121              'appendixsection', 2,
122              'subsection', 3,
123              'unnumberedsubsec', 3,
124              'subheading', 3,
125              'appendixsubsec', 3,
126              'subsubsection', 4,
127              'unnumberedsubsubsec', 4,
128              'subsubheading', 4,
129              'appendixsubsubsec', 4,
130              );
131
132#
133# accent map, TeX command to ISO name
134#
135%accent_map = (
136               '"',  'uml',
137               '~',  'tilde',
138               '^',  'circ',
139               '`',  'grave',
140               '\'', 'acute',
141               ',',  'cedil',
142               # fixme: (not Latin1) = H d dotaccent dotless ringaccent
143               # tieaccent u ubaraccent v
144               );
145
146#
147# texinfo "simple things" (@foo) to HTML ones
148#
149%simple_map = (
150               # cf. makeinfo.c
151               "*", "<BR>",             # HTML+
152               " ", "&#160;",   # nbsp
153               "\n", "\n",
154               "|", "",
155               # spacing commands
156               ":", "",
157               "!", "!",
158               "?", "?",
159               ".", ".",
160               "\t", " ",
161               "-", "&#173;",   # soft hyphen
162               'tab', '<TD>',
163               );
164
165#
166# texinfo "things" (@foo{}) to HTML ones
167#
168%things_map = (
169               'TeX', 'TeX',
170               'br', '<P>',             # paragraph break.  Gone from texinfo 3.9
171               'bullet', '*',
172               'copyright', '&#169;',
173               'dots', '...',
174               'enddots', '....',
175               'equiv', '==',
176               'error', 'error-->',
177               'expansion', '==>',
178               'minus', '-',
179               'point', '-!-',
180               'print', '-|',
181               'result', '=>',
182               'today', $TODAY,
183               # fixme: output these Latin1 characters as such rather
184               # than as entities?
185               'pounds', '&#163;',
186               'questiondown', '&#191;',
187               'ss', '&#223;',
188               'exclamdown', '&#161;',
189               'AA', '&#197;',
190               'AE', '&#198;',
191               'aa', '&#229;',
192               'ae', '&#230;',
193               'O', '&#216;',
194               'o', '&#248;',
195               # follow info rendering:
196               'L', 'L\/',
197               'l', 'l\/',
198               'OE', 'OE',
199               'oe', 'oe',
200               );
201
202#
203# texinfo styles (@foo{bar}) to HTML ones
204#
205%style_l_map = (
206              'center', 'CENTER',
207              );
208
209%style_map = (
210              'asis', '',               # ??
211              'b', 'B',
212              'cite', 'CITE',
213              'code', 'CODE',
214              'ctrl', '&do_ctrl',       # special case (obsolete)
215              'dfn', 'STRONG',          # DFN tag is illegal in the standard
216              'dmn', '',                # useless
217              'emph', 'EM',
218              'email', '&do_email',     # new special case
219              'file', '"TT',            # will put quotes, cf. &apply_style
220              'i', 'I',
221              'image', '&do_image',     # in-line images
222              'kbd', 'KBD',
223              'key', 'KBD',             # fixme: probably not <KBD>; possibly
224                                        # enclose in angles like makeinfo now does
225              'r', '',                  # unsupported
226              'samp', '"SAMP',          # will put quotes, cf. &apply_style
227              'sc', '&do_sc',           # special case
228              'strong', 'STRONG',
229              't', 'TT',
230              'titlefont', 'B',         # make it distinctive, at least
231              'uref', '&do_uref',       # new special case
232              'url', '&do_url',         # new special case
233              'var', 'VAR',
234              'w', '',                  # unsupported
235#             'math', 'I',              # not very useful, but at least italicize
236              'math', '',               # don't want italic numbers
237              );
238
239#
240# texinfo format (@foo/@end foo) to HTML ones
241#
242%format_map = (
243               'display', 'PRE',
244               'example', 'PRE',
245               'format', 'PRE', # fixme: shouldn't use tt, but can't avoid?
246               'lisp', 'PRE',
247               'quotation', 'BLOCKQUOTE',
248               'smallexample', 'PRE',
249               'smalllisp', 'PRE',
250               # lists
251               'itemize', 'UL',
252               'enumerate', 'OL',
253               # poorly supported
254               'flushleft', 'PRE',
255               'flushright', 'PRE',
256               );
257
258#
259# texinfo definition shortcuts to real ones
260#
261%def_map = (
262            # basic commands
263            'deffn', 0,
264            'defvr', 0,
265            'deftypefn', 0,
266            'deftypevr', 0,
267            'defcv', 0,
268            'defop', 0,
269            'deftp', 0,
270            # basic x commands
271            'deffnx', 0,
272            'defvrx', 0,
273            'deftypefnx', 0,
274            'deftypevrx', 0,
275            'defcvx', 0,
276            'defopx', 0,
277            'deftpx', 0,
278            # shortcuts
279            'defun', 'deffn Function',
280            'defmac', 'deffn Macro',
281            'defspec', 'deffn {Special Form}',
282            'defvar', 'defvr Variable',
283            'defopt', 'defvr {User Option}',
284            'deftypefun', 'deftypefn Function',
285            'deftypevar', 'deftypevr Variable',
286            'defivar', 'defcv {Instance Variable}',
287            'defmethod', 'defop Method',
288            # x shortcuts
289            'defunx', 'deffnx Function',
290            'defmacx', 'deffnx Macro',
291            'defspecx', 'deffnx {Special Form}',
292            'defvarx', 'defvrx Variable',
293            'defoptx', 'defvrx {User Option}',
294            'deftypefunx', 'deftypefnx Function',
295            'deftypevarx', 'deftypevrx Variable',
296            'defivarx', 'defcvx {Instance Variable}',
297            'defmethodx', 'defopx Method',
298            );
299
300#
301# things to skip
302#
[fb646a]303%to_ignore = (
304            'manual', 1,
305            'end manual', 1,
306            );
307
[5d13bc]308%to_skip = (
309            # comments
310            'c', 1,
311            'comment', 1,
312            # useless
313            'contents', 1,
314            'shortcontents', 1,
315            'summarycontents', 1,
316            'footnotestyle', 1,
317            'end ifclear', 1,
318            'end ifset', 1,
319            'titlepage', 1,
320            'end titlepage', 1,
321            'dircategory', 1,
322            # unsupported commands (formatting)
323            'afourpaper', 1,
324            'cropmarks', 1,
325            'finalout', 1,
326            'headings', 1,
327            'need', 1,
328            'page', 1,
329            'setchapternewpage', 1,
330            'everyheading', 1,
331            'everyfooting', 1,
332            'evenheading', 1,
333            'evenfooting', 1,
334            'oddheading', 1,
335            'oddfooting', 1,
336            'smallbook', 1,
337            'vskip', 1,
338            'filbreak', 1,
339            'centerchap', 1,
340            'setchapterstyle', 1,
341            'hyphenation', 1,
342            # unsupported formats
343            'cartouche', 1,
344            'end cartouche', 1,
345            'group', 1,
346            'end group', 1,
347            );
348
[fb646a]349%append2num = (
350               'A', 1,
351               'B', 2,
352               'C', 3,
353               'D', 4,
354               'E', 5,
355               'F', 6,
356               'G', 7,
357               'H', 8,
358               'I', 9,
359               'J', 10,
360               );
[5d13bc]361#+++############################################################################
362#                                                                              #
363# Argument parsing, initialisation                                             #
364#                                                                              #
365#---############################################################################
366
367$use_bibliography = 1;
368$use_acc = 0;
369$debug = 0;
370$doctype = '';
371$check = 0;
372$expandinfo = 0;
373$use_glossary = 0;
374$invisible_mark = '';
375$use_iso = 0;
376@include_dirs = ();
377$show_menu = 0;
378$number_sections = 0;
379$split_node = 0;
380$split_chapter = 0;
381$monolithic = 0;
382$verbose = 0;
383$make_entry_page = 1;
384$make_menu_page = 1;
385$section_type = 0;
[fb646a]386$ignore_part = 0;
[5d13bc]387$usage = <<EOT;
388This is $THISPROG
389To convert a Texinfo file to HMTL: $0 [options] file
390  where options can be:
391    -expandinfo    : use \@ifinfo sections, not \@iftex
392    -glossary      : handle a glossary
393    -invisible name: use 'name' as an invisible anchor
394    -I dir         : search also for files in 'dir'
395    -menu          : handle menus and don\'t do the ToC
396    -monolithic    : output only one file including ToC
397    -number        : number sections
398    -split_chapter : split on main sections
399    -split_node    : split on nodes
400    -check         : check given file for possible Texinfo commands
401    -usage         : print usage instructions
402    -verbose       : verbose output
403To check converted files: $0 -check [-verbose] files
404EOT
405
406while ($#ARGV >= 0 && $ARGV[0] =~ /^-/) {
407    $_ = shift(@ARGV);
408    if (/^-acc$/)            { $use_acc = 1; next; }
409    if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; }
410    if (/^-doctype$/)        { $doctype = shift(@ARGV); next; }
411    if (/^-c(heck)?$/)       { $check = 1; next; }
412    if (/^-e(xpandinfo)?$/)  { $expandinfo = 1; next; }
413    if (/^-g(lossary)?$/)    { $use_glossary = 1; next; }
414    if (/^-i(nvisible)?$/)   { $invisible_mark = shift(@ARGV); next; }
415    if (/^-iso$/)            { $use_iso = 1; next; }
416    if (/^-I(.+)?$/)         { push(@include_dirs, $1 || shift(@ARGV)); next; }
417    if (/^-m(enu)?$/)        { $show_menu = 1; next; }
418    if (/^-mono(lithic)?$/)  { $monolithic = 1; next; }
419    if (/^-n(umber)?$/)      { $number_sections = 1; next; }
420    if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) {
421        if ($2 =~ /^n/) {
422            $split_node = 1;
423        } else {
424            $split_chapter = 1;
425        }
426        next;
427    }
428    if (/^-v(erbose)?$/)     { $verbose = 1; next; }
429    die $usage;
430}
431if ($check) {
432    die $usage unless @ARGV > 0;
433    &check;
434    exit;
435}
436
437if (($split_node || $split_chapter) && $monolithic) {
438    warn "Can't use -monolithic with -split, -monolithic ignored.\n";
439    $monolithic = 0;
440}
441if ($expandinfo) {
442    $to_skip{'ifinfo'}++;
443    $to_skip{'end ifinfo'}++;
444} else {
445    $to_skip{'iftex'}++;
446    $to_skip{'end iftex'}++;
447}
448$invisible_mark = '<IMG SRC="invisible.xbm" ALT="">' if $invisible_mark eq 'xbm';
449die $usage unless @ARGV == 1;
450$docu = shift(@ARGV);
451if ($docu =~ /.*\//) {
452    chop($docu_dir = $&);
453    $docu_name = $';
454} else {
455    $docu_dir = '.';
456    $docu_name = $docu;
457}
458unshift(@include_dirs, $docu_dir);
459$docu_name =~ s/\.te?x(i|info)?$//;     # basename of the document
460
461$docu_doc = "$docu_name.html";          # document's contents
462if ($monolithic) {
463    $docu_toc = $docu_foot = $docu_doc;
464} else {
465    $docu_toc  = "${docu_name}_toc.html";  # document's table of contents
466    $docu_foot = "${docu_name}_foot.html"; # document's footnotes
467    $docu_left = "${docu_name}_left.html";
468    $docu_main = "index.html";
469}
470
471#
472# variables
473#
474%value = ();                            # hold texinfo variables
475$value{'html'} = 1;                     # predefine html (the output format)
476$value{'texi2html'} = '1.51a';          # predefine texi2html (the translator)
477# _foo: internal to track @foo
478foreach ('_author', '_title', '_subtitle',
479         '_settitle', '_setfilename') {
480    $value{$_} = '';                    # prevent -w warnings
481}
482%node2sec = ();                         # node to section name
483%node2href = ();                        # node to HREF
484%bib2href = ();                         # bibliography reference to HREF
485%gloss2href = ();                       # glossary term to HREF
486@sections = ();                         # list of sections
[94fcf4]487@left_index = ();
[5d13bc]488%tag2pro = ();                          # protected sections
489
490#
491# initial indexes
492#
493$bib_num = 0;
494$foot_num = 0;
495$gloss_num = 0;
496$idx_num = 0;
497$sec_num = 0;
498$doc_num = 0;
499$html_num = 0;
500
501#
502# can I use ISO8879 characters? (HTML+)
503#
504if ($use_iso) {
505    $things_map{'bullet'} = "&bull;";
506    $things_map{'copyright'} = "&copy;";
507    $things_map{'dots'} = "&hellip;";
508    $things_map{'equiv'} = "&equiv;";
509    $things_map{'expansion'} = "&rarr;";
510    $things_map{'point'} = "&lowast;";
511    $things_map{'result'} = "&rArr;";
512}
513
514#
515# read texi2html extensions (if any)
516#
517$extensions = 'texi2html.ext'; # extensions in working directory
518if (-f $extensions) {
519    print "# reading extensions from $extensions\n" if $verbose;
520    require($extensions);
521}
522($progdir = $0) =~ s/[^\/]+$//;
523if ($progdir && ($progdir ne './')) {
524    $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
525    if (-f $extensions) {
526        print "# reading extensions from $extensions\n" if $verbose;
527        require($extensions);
528    }
529}
530
531print "# reading from $docu\n" if $verbose;
532
533#+++############################################################################
534#                                                                              #
535# Pass 1: read source, handle command, variable, simple substitution           #
536#                                                                              #
537#---############################################################################
538
539@lines = ();                            # whole document
540@toc_lines = ();                        # table of contents
541@top_lines = ();                        # contents of top node
542@menu_lines = ();
543$toplevel = 0;                          # top level seen in hierarchy
544$curlevel = 0;                          # current level in TOC
545$node = '';                             # current node name
546$in_table = 0;                          # am I inside a table
547$table_type = '';                       # type of table ('', 'f', 'v')
548@tables = ();                           # nested table support
549$in_bibliography = 0;                   # am I inside a bibliography
550$in_glossary = 0;                       # am I inside a glossary
551$in_top = 0;                            # am I inside the top node
552$in_pre = 0;                            # am I inside a preformatted section
553$in_list = 0;                           # am I inside a list
554$in_html = 0;                           # am I inside an HTML section (@ifhtml)
555$in_raw_html = 0;                       # am I inside an HTML section (@html)
556$in_preamble = 1;                       # am I before the top node
557$first_line = 1;                        # is it the first line
558$dont_html = 0;                         # don't protect HTML on this line
559$split_num = 0;                         # split index
560$deferred_ref = '';                     # deferred reference for indexes
561@html_stack = ();                       # HTML elements stack
562$html_element = '';                     # current HTML element
563&html_reset;
[fb646a]564@raw_html = ();
[5d13bc]565
566# build code for simple substitutions
567# the maps used (%simple_map and %things_map) MUST be aware of this
568# watch out for regexps, / and escaped characters!
569$subst_code = '';
570foreach (keys(%simple_map)) {
571    ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
572    $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
573}
574foreach (keys(%things_map)) {
575    $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
576}
577if ($use_acc) {
578    # accentuated characters
579    foreach (keys(%accent_map)) {
580        if ($_ eq "`") {
581            $subst_code .= "s/$;3";
582        } elsif ($_ eq "'") {
583            $subst_code .= "s/$;4";
584        } else {
585            $subst_code .= "s/\\\@\\$_";
586        }
587        $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
588    }
589}
590eval("sub simple_substitutions { $subst_code }");
591
592&init_input;
593while ($_ = &next_line) {
594    #
595    # remove \input on the first lines only
596    #
597    if ($first_line) {
598        next if /^\\input/;
599        $first_line = 0;
600    }
601    #
602    # parse texinfo tags
603    #
604    $tag = '';
605    $end_tag = '';
606    if (/^\@end\s+(\w+)\b/) {
607        $end_tag = $1;
608    } elsif (/^\@(\w+)\b/) {
609        $tag = $1;
610    }
611    #
612    # handle @ifhtml / @end ifhtml
613    #
614    if ($in_html) {
615        if ($end_tag eq 'ifhtml') {
616            $in_html = 0;
617        } else {
618            $tag2pro{$in_html} .= $_;
619        }
620        next;
621    } elsif ($tag eq 'ifhtml') {
622        $in_html = $PROTECTTAG . ++$html_num;
[fb646a]623        push(@raw_html, $in_html);
[5d13bc]624        next;
625    }
626    #
627    # do raw HTML (no escapes)
628    #
629    if ($in_raw_html) {
630        if ($end_tag eq 'html') {
631            $in_raw_html = 0;
632        } else {
[fb646a]633            push (@raw_html, $_);
[5d13bc]634        }
635        next;
636    } elsif ($tag eq 'html') {
637        $in_raw_html = 1;
638    }
639    #
640    # try to skip the line
641    #
642    if ($end_tag) {
643        next if $to_skip{"end $end_tag"};
644    } elsif ($tag) {
645        next if $to_skip{$tag};
646        last if $tag eq 'bye';
647    }
[fb646a]648
649    if ($end_tag) {
650        if ($to_ignore{"end $end_tag"}) {
651            $ignore_part = 0;
652            next;
653        }
654    } elsif ($tag) {
655        if ($to_ignore{$tag}) {
656            $ignore_part = 1;
657        }
658    }
659    next if $ignore_part;
660
[5d13bc]661    #
662    # try to remove inlined comments
663    # syntax from tex-mode.el comment-start-skip
664    #
665    s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
666    # non-@ substitutions cf. texinfmt.el
667    s/``/\"/g;
668    s/''/\"/g;
669    s/([\w ])---([\w ])/$1--$2/g;
670    #
671    # analyze the tag
672    #
673    if ($tag) {
674        # skip lines
675        &skip_until($tag), next if $tag eq 'ignore';
676        if ($expandinfo) {
677            &skip_until($tag), next if $tag eq 'iftex';
678        } else {
679            &skip_until($tag), next if $tag eq 'ifinfo' &&
680                ! $in_preamble; # we want the contents of the top node
681        }
682        &skip_until($tag), next if $tag eq 'tex';
683        # handle special tables
684        if ($tag eq 'table') {
685            $table_type = '';
686        } elsif ($tag eq 'ftable') {
687            $tag = 'table';
688            $table_type = 'f';
689        } elsif ($tag eq 'vtable') {
690            $tag = 'table';
691            $table_type = 'v';
692        } elsif ($tag eq 'multitable') {
693            $tag = 'table';
694            $table_type = '';
695        }
696        # special cases
697        if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+Top\s*,/i)) {
698            # We want to stash the contents of the top node (including
699            # @ifinfo bits).
700            $in_top = 1;
701            $in_preamble = 0;
[fb646a]702            #@lines = (); # ignore all lines before top (title page garbage)
703            @lines = @raw_html;
[5d13bc]704            next;
705        } elsif ($tag eq 'node') {
706            push (@lines, "$TOPTAG") if ($in_top); # Mark end of top node
707            $in_top = 0;
708            $in_preamble = 0;
709            warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o;
710            $_ = &protect_html($_); # if node contains '&' for instance
711            s/^\@node\s+//;
712            ($node) = split(/,/);
713            &normalise_node($node);
714            if ($split_node) {
715                &next_doc;
716                push(@lines, $SPLITTAG) if $split_num++;
717                push(@sections, $node);
718            }
719            next;
720        } elsif ($tag eq 'include') {
721            if (/^\@include\s+($FILERE)\s*$/o) {
722                $file = $1;
723                unless (-e $file) {
724                    foreach $dir (@include_dirs) {
725                        $file = "$dir/$1";
726                        last if -e $file;
727                    }
728                }
729                if (-e $file) {
730                    &open($file);
731                    print "# including $file\n" if $verbose;
732                } else {
733                    warn "$ERROR Can't find $file, skipping";
734                }
735            } else {
736                warn "$ERROR Bad include line: $_";
737            }
738            next;
739        } elsif ($tag eq 'ifclear') {
740            if (/^\@ifclear\s+($VARRE)\s*$/o) {
741                next unless defined($value{$1});
742                &skip_until($tag);
743            } else {
744                warn "$ERROR Bad ifclear line: $_";
745            }
746            next;
747        } elsif ($tag eq 'ifset') {
748            if (/^\@ifset\s+($VARRE)\s*$/o) {
749                next if defined($value{$1});
750                &skip_until($tag);
751            } else {
752                warn "$ERROR Bad ifset line: $_";
753            }
754            next;
755        } elsif ($tag eq 'menu') {
756            unless ($show_menu) {
757                &skip_until($tag);
758                next;
759            }
760            &html_push_if($tag);
761            push(@lines, &html_debug("\n", __LINE__));
762        } elsif ($format_map{$tag}) {
763            $in_pre = 1 if $format_map{$tag} eq 'PRE';
764            &html_push_if($format_map{$tag});
765            push(@lines, &html_debug("\n", __LINE__));
766            $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
767            push(@lines, &debug("<$format_map{$tag}>\n", __LINE__));
768            next;
769        } elsif ($tag eq 'table') {
770            if (/^\@[fv]?table\s+\@(\w+)\s*$/) {
771                $in_table = $1;
772                unshift(@tables, join($;, $table_type, $in_table));
773                push(@lines, &debug("<DL COMPACT>\n", __LINE__));
774                &html_push_if('DL');
775                push(@lines, &html_debug("\n", __LINE__));
776            } elsif (/^\@multitable\s+/) {
777                # Note descent to HTML 3.2 necessary for multitable.
778                $in_table = ' ';
779                unshift(@tables, join($;, $table_type, $in_table));
780                push(@lines, &debug("<TABLE>\n", __LINE__));
781                &html_push_if('TABLE');
782                push(@lines, &html_debug("\n", __LINE__));
783            } else {
784                warn "$ERROR Bad table line: $_";
785            }
786            next;
787        } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
788            if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
789                eval("*${1}index = *${2}index");
790            } else {
791                warn "$ERROR Bad syn*index line: $_";
792            }
793            next;
794        } elsif ($tag eq 'sp') {
795            push(@lines, &debug("<P>\n", __LINE__));
796            next;
797        } elsif ($tag eq 'setref') {
798            &protect_html; # if setref contains '&' for instance
799            if (/^\@$tag\s*{($NODERE)}\s*$/) {
800                $setref = $1;
801                $setref =~ s/\s+/ /g; # normalize
802                $setref =~ s/ $//;
803                $node2sec{$setref} = $name;
804                $node2href{$setref} = "$docu_doc#$docid";
805            } else {
806                warn "$ERROR Bad setref line: $_";
807            }
808            next;
809        } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
810            if (/^\@$tag\s+(\w\w)\s*$/) {
811                $valid_index{$1} = 1;
812            } else {
813                warn "$ERROR Bad defindex line: $_";
814            }
815            next;
816        } elsif ($tag eq 'direntry') {
817            &skip_until ($tag);
818            next;
819        } elsif (defined($def_map{$tag})) {
820            if ($def_map{$tag}) {
821                s/^\@$tag\s+//;
822                $tag = $def_map{$tag};
823                $_ = "\@$tag $_";
824                $tag =~ s/\s.*//;
825            }
826        } elsif (defined($user_sub{$tag})) {
827            s/^\@$tag\s+//;
828            $sub = $user_sub{$tag};
829            print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER;
830            if (defined(&$sub)) {
831                chop($_);
832                &$sub($_);
833            } else {
834                warn "$ERROR Bad user sub for $tag: $sub\n";
835            }
836            next;
837        }
838        if (defined($def_map{$tag})) {
839            s/^\@$tag\s+//;
840            if ($tag =~ /x$/) {
841                # extra definition line
842                $tag = $`;
843                $is_extra = 1;
844            } else {
845                $is_extra = 0;
846            }
847            while (/\{([^\{\}]*)\}/) {
848                # this is a {} construct
849                ($before, $contents, $after) = ($`, $1, $');
850                # protect spaces
851                $contents =~ s/\s+/$;9/g;
852                # restore $_ protecting {}
853                $_ = "$before$;7$contents$;8$after";
854            }
855            @args = split(/\s+/, &protect_html($_));
856            foreach (@args) {
857                s/$;9/ /g;      # unprotect spaces
858                s/$;7/\{/g;     # ... {
859                s/$;8/\}/g;     # ... }
860            }
861            $type = shift(@args);
862            $type =~ s/^\{(.*)\}$/$1/;
863            print "# def ($tag): {$type} ", join(', ', @args), "\n"
864                if $debug & $DEBUG_DEF;
865            $type .= ':'; # it's nicer like this
866            $name = shift(@args);
867            $name =~ s/^\{(.*)\}$/$1/;
868            if ($is_extra) {
869                $_ = &debug("<DT>", __LINE__);
870            } else {
871                $_ = &debug("<DL>\n<DT>", __LINE__);
872            }
873            if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') {
874                $_ .= "<U>$type</U> <B>$name</B>";
875                $_ .= " <I>@args</I>" if @args;
876            } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
877                     || $tag eq 'defcv' || $tag eq 'defop') {
878                $ftype = $name;
879                $name = shift(@args);
880                $name =~ s/^\{(.*)\}$/$1/;
881                $_ .= "<U>$type</U> $ftype <B>$name</B>";
882                $_ .= " <I>@args</I>" if @args;
883            } else {
884                warn "$ERROR Unknown definition type: $tag\n";
885                $_ .= "<U>$type</U> <B>$name</B>";
886                $_ .= " <I>@args</I>" if @args;
887            }
888            $_ .= &debug("\n<DD>", __LINE__);
889            $name = &unprotect_html($name);
890            if ($tag eq 'deffn' || $tag eq 'deftypefn') {
891                unshift(@input_spool, "\@findex $name\n");
892            } elsif ($tag eq 'defop') {
893                unshift(@input_spool, "\@findex $name on $ftype\n");
894            } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') {
895                unshift(@input_spool, "\@vindex $name\n");
896            } else {
897                unshift(@input_spool, "\@tindex $name\n");
898            }
899            $dont_html = 1;
900        }
901    } elsif ($end_tag) {
902        if ($format_map{$end_tag}) {
903            $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
904            $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
905            &html_pop_if('LI', 'P');
906            &html_pop_if();
907            push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
908            push(@lines, &html_debug("\n", __LINE__));
909        } elsif ($end_tag eq 'table' ||
910                 $end_tag eq 'ftable' ||
911                 $end_tag eq 'vtable' ||
912                 $end_tag eq 'multitable') {
913            shift(@tables);
914            if (@tables) {
915                ($table_type, $in_table) = split($;, $tables[0]);
916            } else {
917                $in_table = 0;
918            }
919            if ($end_tag eq 'multitable') {
920                push(@lines, "</TABLE>\n");
921                &html_pop_if('TABLE');
922            } else {
923            push(@lines, "</DL>\n");
924            &html_pop_if('DD');
925            }
926            &html_pop_if();
927        } elsif (defined($def_map{$end_tag})) {
928            push(@lines, &debug("</DL>\n", __LINE__));
929        } elsif ($end_tag eq 'menu') {
930            &html_pop_if();
931            push(@lines, $_); # must keep it for pass 2
932        }
933        next;
934    }
935    #
936    # misc things
937    #
938    # protect texi and HTML things
939    &protect_texi;
940    $_ = &protect_html($_) unless $dont_html;
941    $dont_html = 0;
942    # substitution (unsupported things)
943    # s/^\@center\s+//g;                # fixme: use <center> or <div align=center>?
944    s/^\@exdent\s+//g;
945    s/\@noindent\s+//g;
946    s/\@refill\s+//g;
947    # other substitutions
948    &simple_substitutions;
949    s/\@value{($VARRE)}/$value{$1}/eg;
950    s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
951    #
952    # analyze the tag again
953    #
954    if ($tag) {
955        if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
956            if (/^\@$tag\s+(.+)$/) {
957                $name = $1;
958                $name =~ s/\s+$//;
959                $level = $sec2level{$tag};
960                $name = &update_sec_num($tag, $level) . "  $name"
961                    if $number_sections && $tag !~ /^unnumbered/;
[94fcf4]962                push(@left_index, $name);
[5d13bc]963                if ($tag =~ /heading$/) {
964                    push(@lines, &html_debug("\n", __LINE__));
965                    if ($html_element ne 'body') {
966                        # We are in a nice pickle here. We are trying to get a H? heading
967                        # even though we are not in the body level. So, we convert it to a
968                        # nice, bold, line by itself.
969                        $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__);
970                    } else {
971                        $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
972                        &html_push_if('body');
973                    }
974                    print "# heading, section $name, level $level\n"
975                        if $debug & $DEBUG_TOC;
976                } else {
977                    if ($split_chapter) {
978                        unless ($toplevel) {
979                            # first time we see a "section"
980                            unless ($level == 1) {
981                                warn "$ERROR The first section found is not of level 1: $_";
982                                warn "$ERROR I'll split on sections of level $level...\n";
983                            }
984                            $toplevel = $level;
985                        }
986                        if ($level == $toplevel) {
987                            &next_doc;
988                            push(@lines, $SPLITTAG) if $split_num++;
989                            push(@sections, $name);
990                        }
991                    }
992                    $sec_num++;
993                    $docid = "SEC$sec_num";
994                    $tocid = "TOC$sec_num";
995                    # check biblio and glossary
996                    $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
997                    $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
998                    # check node
999                    if ($node) {
1000                        if ($node2sec{$node}) {
1001                            warn "$ERROR Duplicate node found: $node\n";
1002                        } else {
1003                            $node2sec{$node} = $name;
1004                            $node2href{$node} = "$docu_doc#$docid";
1005                            print "# node $node, section $name, level $level\n"
1006                                if $debug & $DEBUG_TOC;
1007                        }
1008                        $node = '';
1009                    } else {
1010                        print "# no node, section $name, level $level\n"
1011                            if $debug & $DEBUG_TOC;
1012                    }
1013                    # update TOC
1014                    while ($level > $curlevel) {
1015                        $curlevel++;
1016                        push(@toc_lines, "<UL>\n");
1017                    }
1018                    while ($level < $curlevel) {
1019                        $curlevel--;
1020                        push(@toc_lines, "</UL>\n");
1021                    }
1022                    $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", '', $name, 1);
1023                    push(@toc_lines, &substitute_style($_));
1024                    # update DOC
1025                    push(@lines, &html_debug("\n", __LINE__));
1026                    &html_reset;
1027                    $_ =  "<H$level>".&anchor($docid, "$docu_toc#$tocid", '', $name)."</H$level>\n";
1028                    $_ = &debug($_, __LINE__);
1029                    push(@lines, &html_debug("\n", __LINE__));
1030                }
1031                # update DOC
1032                foreach $line (split(/\n+/, $_)) {
1033                    push(@lines, "$line\n");
1034                }
1035                next;
1036            } else {
1037                warn "$ERROR Bad section line: $_";
1038            }
1039        } else {
1040            # track variables
1041            $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o;
1042            delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o;
1043            # store things
1044            $value{'_setfilename'}   = $1, next if /^\@setfilename\s+(.*)$/;
1045            $value{'_settitle'}      = $1, next if /^\@settitle\s+(.*)$/;
1046            $value{'_author'}   .= "$1\n", next if /^\@author\s+(.*)$/;
1047            $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/;
1048            $value{'_title'}    .= "$1\n", next if /^\@title\s+(.*)$/;
1049            # index
1050            if (/^\@(..?)index\s+/) {
1051                unless ($valid_index{$1}) {
1052                    warn "$ERROR Undefined index command: $_";
1053                    next;
1054                }
1055                $id = 'IDX' . ++$idx_num;
1056                $index = $1 . 'index';
1057                $what = &substitute_style($');
1058                $what =~ s/\s+$//;
1059                print "# found $index for '$what' id $id\n"
1060                    if $debug & $DEBUG_INDEX;
1061                eval(<<EOC);
1062                if (defined(\$$index\{\$what\})) {
1063                    \$$index\{\$what\} .= "$;$docu_doc#$id";
1064                } else {
1065                    \$$index\{\$what\} = "$docu_doc#$id";
1066                }
1067EOC
1068                #
1069                # dirty hack to see if I can put an invisible anchor...
1070                #
1071                if ($html_element eq 'P' ||
1072                    $html_element eq 'LI' ||
1073                    $html_element eq 'DT' ||
1074                    $html_element eq 'DD' ||
1075                    $html_element eq 'ADDRESS' ||
1076                    $html_element eq 'B' ||
1077                    $html_element eq 'BLOCKQUOTE' ||
1078                    $html_element eq 'PRE' ||
1079                    $html_element eq 'SAMP') {
1080                    push(@lines, &anchor($id, '', '', $invisible_mark, !$in_pre));
1081                } elsif ($html_element eq 'body') {
1082                    push(@lines, &debug("<P>\n", __LINE__));
1083                    push(@lines, &anchor($id, '', '', $invisible_mark, !$in_pre));
1084                    &html_push('P');
1085                } elsif ($html_element eq 'DL' ||
1086                         $html_element eq 'UL' ||
1087                         $html_element eq 'OL' ) {
1088                    $deferred_ref .= &anchor($id, '', '', $invisible_mark, !$in_pre) . " ";
1089                }
1090                next;
1091            }
1092            # list item
1093            if (/^\@itemx?\s+/) {
1094                $what = $';
1095                $what =~ s/\s+$//;
1096                if ($in_bibliography && $use_bibliography) {
1097                    if ($what =~ /^$BIBRE$/o) {
1098                        $id = 'BIB' . ++$bib_num;
1099                        $bib2href{$what} = "$docu_doc#$id";
1100                        print "# found bibliography for '$what' id $id\n"
1101                            if $debug & $DEBUG_BIB;
1102                        $what = &anchor($id, '', '', $what);
1103                    }
1104                } elsif ($in_glossary && $use_glossary) {
1105                    $id = 'GLOSS' . ++$gloss_num;
1106                    $entry = $what;
1107                    $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
1108                    $gloss2href{$entry} = "$docu_doc#$id";
1109                    print "# found glossary for '$entry' id $id\n"
1110                        if $debug & $DEBUG_GLOSS;
1111                    $what = &anchor($id, '', '', $what);
1112                }
1113                &html_pop_if('P');
1114                if ($html_element eq 'DL' || $html_element eq 'DD') {
1115                    if ($things_map{$in_table} && !$what) {
1116                        # special case to allow @table @bullet for instance
1117                        push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__));
1118                    } else {
1119                        push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
1120                    }
1121                    push(@lines, "<DD>");
1122                    &html_push('DD') unless $html_element eq 'DD';
1123                    if ($table_type) { # add also an index
1124                        unshift(@input_spool, "\@${table_type}index $what\n");
1125                    }
1126                } elsif ($html_element eq 'TABLE' || $html_element eq 'TR') {
1127                    # Add <br> at ends of rows for non-tables browsers.
1128                    push(@lines, "<BR>\n") if $html_element eq 'TR';
1129                    push(@lines, "<TR>$what");
1130                    &html_push('TR') unless $html_element eq 'TR';
1131                } else {
1132                    push(@lines, &debug("<LI>$what\n", __LINE__));
1133                    &html_push('LI') unless $html_element eq 'LI';
1134                }
1135                push(@lines, &html_debug("\n", __LINE__));
1136                if ($deferred_ref) {
1137                    push(@lines, &debug("$deferred_ref\n", __LINE__));
1138                    $deferred_ref = '';
1139                }
1140                next;
1141            }
1142        }
1143    }
1144    # paragraph separator
1145    if ($_ eq "\n") {
1146        next if $#lines >= 0 && $lines[$#lines] eq "\n";
1147        if ($html_element eq 'P') {
1148            push(@lines, "\n");
1149            $_ = &debug("</P>\n", __LINE__);
1150            &html_pop;
1151        }
1152    } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') {
1153        push(@lines, "<P>\n");
1154        &html_push('P');
1155        $_ = &debug($_, __LINE__);
1156    }
1157    # otherwise
1158    push(@lines, $_);
1159}
1160
1161# finish TOC
1162$level = 0;
1163while ($level < $curlevel) {
1164    $curlevel--;
1165    push(@toc_lines, "</UL>\n");
1166}
1167
1168print "# end of pass 1\n" if $verbose;
1169
1170#+++############################################################################
1171#                                                                              #
1172# Pass 2/3: handle style, menu, index, cross-reference                         #
1173#                                                                              #
1174#---############################################################################
1175
1176@lines2 = ();                           # whole document (2nd pass)
1177@lines3 = ();                           # whole document (3rd pass)
1178$in_menu = 0;                           # am I inside a menu
1179$in_top = 1;
1180
1181while (@lines) {
1182    $_ = shift(@lines);
1183    #
1184    # special case (protected sections)
1185    #
1186    if (/^$PROTECTTAG/o) {
1187        push(@lines2, $_);
1188        next;
1189    }
1190    if ($in_top && $_ eq "$TOPTAG") {
1191        $in_top = 0;
1192        while(@lines2) {
1193            $_ = shift(@lines2);
1194            if (/\@(\w+)\ /) {
1195                ($before, $style, $after) = ($`, $1, $');
1196                if (defined($style_l_map{$style})) {
1197                    $_ = $after;
1198                    $text = '';
1199                    $after = '';
1200                    $failed = 1;
1201                    while (@lines2) {
1202                        if (/\n/) {
1203                            $text .= $`;
1204                            $after = $';
1205                            $failed = 0;
1206                            last;
1207                        } else {
1208                            $text .= $_;
1209                            $_ = shift(@lines2);
1210                        }
1211                    }
1212                    if ($failed) {
1213                        die "* Bad syntax (\@$style) after: $before\n";
1214                    } else {
1215                        $text = &apply_l_style($style, $text);
1216                        $_ = "$before$text$after\n";
1217                    }
1218                }
1219            }
1220            push(@top_lines, $_);
1221        }
1222        #@top_lines = @lines2;  # Contents of the top node.
1223        @lines2 = ();           # Don't use them in place.
1224        next;
1225    }
1226    #
1227    # menu
1228    #
1229    $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\@menu\b/;
1230    $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\@end\s+menu\b/;
1231    if ($in_menu) {
1232        if (/^\*\s+($NODERE)::/o) {
1233            $descr = $';
1234            chop($descr);
1235            &menu_entry($1, $1, $descr);
1236        } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
1237            $descr = $';
1238            chop($descr);
1239            &menu_entry($1, $2, $descr);
1240        } elsif (/^\*/) {
1241            warn "$ERROR Bad menu line: $_";
1242        } else { # description continued?
1243            push(@lines2, $_);
1244        }
1245        next;
1246    }
1247    #
1248    # printindex
1249    #
1250    if (/^\@printindex\s+(\w\w)\b/) {
1251        local($index, *ary, @keys, $key, $letter, $last_letter, @refs);
1252        if ($predefined_index{$1}) {
1253            $index = $predefined_index{$1} . 'index';
1254        } else {
1255            $index = $1 . 'index';
1256        }
1257        eval("*ary = *$index");
1258        @keys = keys(%ary);
1259        foreach $key (@keys) {
1260            $_ = $key;
1261            1 while s/<(\w+)>\`(.*)\'<\/\1>/$2/; # remove HTML tags with quotes
1262            1 while s/<(\w+)>(.*)<\/\1>/$2/;     # remove HTML tags
1263            $_ = &unprotect_html($_);
1264            &unprotect_texi;
1265            tr/A-Z/a-z/; # lowercase
1266            $key2alpha{$key} = $_;
1267            print "# index $key sorted as $_\n"
1268                if $key ne $_ && $debug & $DEBUG_INDEX;
1269        }
1270        $last_letter = undef;
1271        foreach $key (sort byalpha @keys) {
1272            $letter = substr($key2alpha{$key}, 0, 1);
1273            $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
1274            if (!defined($last_letter) || $letter ne $last_letter) {
1275                push(@lines2, "</DIR>\n") if defined($last_letter);
1276                push(@lines2, "<H2>" . &protect_html($letter) . "</H2>\n");
1277                push(@lines2, "<DIR>\n");
1278                $last_letter = $letter;
1279            }
1280            @refs = ();
1281            foreach (split(/$;/, $ary{$key})) {
1282                push(@refs, &anchor('', $_, '', $key, 0));
1283            }
1284            push(@lines2, "<LI>" . join(", ", @refs) . "\n");
1285        }
1286        push(@lines2, "</DIR>\n") if defined($last_letter);
1287        next;
1288    }
1289    #
1290    # simple style substitutions
1291    #
1292    $_ = &substitute_style($_);
1293    #
1294    # xref
1295    #
1296    while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) {
1297        # note: Texinfo may accept other characters
1298        ($type, $nodes, $full) = ($1, $2, $3);
1299        ($before, $after) = ($`, $');
1300        if (! $full && $after) {
1301            warn "$ERROR Bad xref (no ending } on line): $_";
1302            $_ = "$before$;0${type}ref\{$nodes$after";
1303            next; # while xref
1304        }
1305        if ($type eq 'x') {
1306            $type = 'See ';
1307        } elsif ($type eq 'px') {
1308            $type = 'see ';
1309        } elsif ($type eq 'info') {
1310            $type = 'See Info';
1311        } else {
1312            $type = '';
1313        }
1314        unless ($full) {
1315            $next = shift(@lines);
1316            $next = &substitute_style($next);
1317            chop($nodes); # remove final newline
1318            if ($next =~ /\}/) { # split on 2 lines
1319                $nodes .= " $`";
1320                $after = $';
1321            } else {
1322                $nodes .= " $next";
1323                $next = shift(@lines);
1324                $next = &substitute_style($next);
1325                chop($nodes);
1326                if ($next =~ /\}/) { # split on 3 lines
1327                    $nodes .= " $`";
1328                    $after = $';
1329                } else {
1330                    warn "$ERROR Bad xref (no ending }): $_";
1331                    $_ = "$before$;0xref\{$nodes$after";
1332                    unshift(@lines, $next);
1333                    next; # while xref
1334                }
1335            }
1336        }
1337        $nodes =~ s/\s+/ /g; # remove useless spaces
1338        @args = split(/\s*,\s*/, $nodes);
1339        $node = $args[0]; # the node is always the first arg
1340        &normalise_node($node);
1341        $sec = $node2sec{$node};
1342        if (@args == 5) { # reference to another manual
1343            $sec = $args[2] || $node;
1344            $man = $args[4] || $args[3];
1345            $_ = "${before}${type}section `$sec' in \@cite{$man}$after";
1346        } elsif ($type =~ /Info/) { # inforef
1347            warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
1348            ($nn, $_, $in) = @args;
1349            $_ = "${before}${type} file `$in', node `$nn'$after";
1350        } elsif ($sec) {
1351            $href = $node2href{$node};
1352            $_ = "${before}${type}section " . &anchor('', $href, '', $sec) . $after;
1353        } else {
1354            warn "$ERROR Undefined node ($node): $_";
1355            $_ = "$before$;0xref{$nodes}$after";
1356        }
1357    }
1358    #
1359    # try to guess bibliography references or glossary terms
1360    #
1361    unless (/^<H\d><A NAME=\"SEC\d/) {
1362        if ($use_bibliography) {
1363            $done = '';
1364            while (/$BIBRE/o) {
1365                ($pre, $what, $post) = ($`, $&, $');
1366                $href = $bib2href{$what};
1367                if (defined($href) && $post !~ /^[^<]*<\/A>/) {
1368                    $done .= $pre . &anchor('', $href, '', $what);
1369                } else {
1370                    $done .= "$pre$what";
1371                }
1372                $_ = $post;
1373            }
1374            $_ = $done . $_;
1375        }
1376        if ($use_glossary) {
1377            $done = '';
1378            while (/\b\w+\b/) {
1379                ($pre, $what, $post) = ($`, $&, $');
1380                $entry = $what;
1381                $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
1382                $href = $gloss2href{$entry};
1383                if (defined($href) && $post !~ /^[^<]*<\/A>/) {
1384                    $done .= $pre . &anchor('', $href, '', $what);
1385                } else {
1386                    $done .= "$pre$what";
1387                }
1388                $_ = $post;
1389            }
1390            $_ = $done . $_;
1391        }
1392    }
1393    # otherwise
1394    push(@lines2, $_);
1395}
1396print "# end of pass 2\n" if $verbose;
1397
1398#
1399# split style substitutions
1400#
1401while (@lines2) {
1402    $_ = shift(@lines2);
1403    #
1404    # special case (protected sections)
1405    #
1406    if (/^$PROTECTTAG/o) {
1407        push(@lines3, $_);
1408        next;
1409    }
1410    #
1411    # split style substitutions
1412    #
1413    $old = '';
1414    while ($old ne $_) {
1415        $old = $_;
1416        if (/\@(\w+)\{/) {
1417            ($before, $style, $after) = ($`, $1, $');
1418            if (defined($style_map{$style})) {
1419                $_ = $after;
1420                $text = '';
1421                $after = '';
1422                $failed = 1;
1423                while (@lines2) {
1424                    if (/\}/) {
1425                        $text .= $`;
1426                        $after = $';
1427                        $failed = 0;
1428                        last;
1429                    } else {
1430                        $text .= $_;
1431                        $_ = shift(@lines2);
1432                    }
1433                }
1434                if ($failed) {
1435                    die "* Bad syntax (\@$style) after: $before\n";
1436                } else {
1437                    $text = &apply_style($style, $text);
1438                    $_ = "$before$text$after";
1439                }
1440            }
1441        }
1442        if (/\@(\w+)\ /) {
1443            ($before, $style, $after) = ($`, $1, $');
1444            if (defined($style_l_map{$style})) {
1445                $_ = $after;
1446                $text = '';
1447                $after = '';
1448                $failed = 1;
1449                while (@lines2) {
1450                    if (/\n/) {
1451                        $text .= $`;
1452                        $after = $';
1453                        $failed = 0;
1454                        last;
1455                    } else {
1456                        $text .= $_;
1457                        $_ = shift(@lines2);
1458                    }
1459                }
1460                if ($failed) {
1461                    die "* Bad syntax (\@$style) after: $before\n";
1462                } else {
1463                    $text = &apply_l_style($style, $text);
1464                    $_ = "$before$text$after";
1465                }
1466            }
1467        }
1468    }
1469    # otherwise
1470    push(@lines3, $_);
1471}
1472print "# end of pass 3\n" if $verbose;
1473
1474#+++############################################################################
1475#                                                                              #
1476# Pass 4: foot notes, final cleanup                                            #
1477#                                                                              #
1478#---############################################################################
1479
1480@foot_lines = ();                       # footnotes
1481@doc_lines = ();                        # final document
1482$end_of_para = 0;                       # true if last line is <P>
1483
1484while (@lines3) {
1485    $_ = shift(@lines3);
1486    #
1487    # special case (protected sections)
1488    #
1489    if (/^$PROTECTTAG/o) {
1490        push(@doc_lines, $_);
1491        $end_of_para = 0;
1492        next;
1493    }
1494    #
1495    # footnotes
1496    #
1497    while (/\@footnote([^\{\s]+)\{/) {
1498        ($before, $d, $after) = ($`, $1, $');
1499        $_ = $after;
1500        $text = '';
1501        $after = '';
1502        $failed = 1;
1503        while (@lines3) {
1504            if (/\}/) {
1505                $text .= $`;
1506                $after = $';
1507                $failed = 0;
1508                last;
1509            } else {
1510                $text .= $_;
1511                $_ = shift(@lines3);
1512            }
1513        }
1514        if ($failed) {
1515            die "* Bad syntax (\@footnote) after: $before\n";
1516        } else {
1517            $foot_num++;
1518            $docid  = "DOCF$foot_num";
1519            $footid = "FOOT$foot_num";
1520            $foot = "($foot_num)";
1521            push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", '', $foot) . "</H3>\n");
1522            $text = "<P>$text" unless $text =~ /^\s*<P>/;
1523            push(@foot_lines, "$text\n");
1524            $_ = $before . &anchor($docid, "$docu_foot#$footid", '', $foot) . $after;
1525        }
1526    }
1527    #
1528    # remove unnecessary <P>
1529    #
1530    if (/^\s*<P>\s*$/) {
1531        next if $end_of_para++;
1532    } else {
1533        $end_of_para = 0;
1534    }
1535    # otherwise
1536    push(@doc_lines, $_);
1537}
1538print "# end of pass 4\n" if $verbose;
1539
1540push(@menu_lines, "<BODY BACKGROUND=\"/rock.gif\">\n");
[5b0536]1541push(@menu_lines, "<IMG SRC=\"singular-small.jpg\"><P>\n");
[5d13bc]1542#push(@menu_lines, "<BODY BACKGROUND=\"/rock.gif\" TEXT=\"yellow\"");
1543#push(@menu_lines, " LINK=#FFFFFF ALINK=#FF00FF VLINK=\"#00FF00\">\n");
1544#push(@menu_lines, "<NOBR>\n");
[fb646a]1545push(@menu_lines, "<OL>\n");
[94fcf4]1546foreach (@left_index) {
[fb646a]1547    $entry = $_;
1548    @part = split(/\ /);
1549    $name = join(' ', @part[1..$#part]);
[94fcf4]1550    if (!/^[A-Z0-9]\./) {
[fb646a]1551        &left_menu_entry($part[0], $name);
[94fcf4]1552    }
[5d13bc]1553}
[fb646a]1554push(@menu_lines, "</OL>\n");
[5d13bc]1555print "# end of pass 5\n" if $verbose;
1556
1557#+++############################################################################
1558#                                                                              #
1559# Pass 6: print things                                                         #
1560#                                                                              #
1561#---############################################################################
1562
1563$header = <<EOT;
1564<!-- This HTML file has been created by $THISPROG
1565     from $docu on $TODAY -->
1566EOT
1567
1568$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
1569$title = $value{'_settitle'} || $full_title;
1570$_ = &substitute_style($full_title);
1571&unprotect_texi;
1572s/\n$//; # rmv last \n (if any)
1573$full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
1574
1575#
1576# print ToC
1577#
1578# ... unless using menus instead.  Make the TOC lines empty rather than
1579# null so we get a ToC page with the top node (including menu).
1580@toc_lines = ("") if $show_menu;
1581
1582if (!$monolithic && @toc_lines) {
1583    if (open(FILE, "> $docu_toc")) {
1584        print "# creating $docu_toc...\n" if $verbose;
1585        &print_toplevel_header("$title - Table of Contents");
1586        &print_ruler;
1587        &print (*top_lines, FILE); # Contents of the top node before the TOC.
1588        &print(*toc_lines, FILE);
1589        &print_toplevel_footer;
1590        close(FILE);
1591    } else {
1592        warn "$ERROR Can't write to $docu_toc: $!\n";
1593    }
1594}
1595
1596#
1597# print footnotes
1598#
1599if (!$monolithic && @foot_lines) {
1600    if (open(FILE, "> $docu_foot")) {
1601        print "# creating $docu_foot...\n" if $verbose;
1602        &print_toplevel_header("$title - Footnotes");
1603        &print_ruler;
1604        &print(*foot_lines, FILE);
1605        &print_toplevel_footer;
1606        close(FILE);
1607    } else {
1608        warn "$ERROR Can't write to $docu_foot: $!\n";
1609    }
1610}
1611
1612#
1613#
1614#
1615if (!$monolithic && $make_entry_page) {
1616    if(open(FILE, "> $docu_main")) {
1617        &print_header("$title - $docu_name", "", 1);
1618        print "# creating $docu_main...\n" if $verbose;
[fb646a]1619        #&print_frame($docu_name . "_1.html");
1620        &print_frame($docu_toc);
[5d13bc]1621        &print_toplevel_footer;
1622        close(FILE);
1623    } else {
1624        warn "$ERROR Can't write to $docu_main: $!\n";
1625    }
1626}
1627
1628#
1629#
1630#
1631if (!$monolithic && $make_menu_page && @menu_lines) {
1632    if(open(FILE, "> $docu_left")) {
1633        &print_header("$title - $docu_left", "", 1);
1634        print "# creating $docu_left...\n" if $verbose;
1635        &print(*menu_lines, FILE);
1636        &print_footer;
1637        close(FILE);
1638    } else {
1639        warn "$ERROR Can't write to $docu_main: $!\n";
1640    }
1641}
1642
1643#
1644# print document
1645#
1646if ($split_chapter || $split_node) { # split
1647    $doc_num = 0;
1648    $last_num = scalar(@sections);
1649    $first_doc = &doc_name(1);
1650    $last_doc = &doc_name($last_num);
1651    while (@sections) {
1652        $section = shift(@sections);
1653        &next_doc;
1654        if (open(FILE, "> $docu_doc")) {
1655            print "# creating $docu_doc...\n" if $verbose;
1656            $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1));
1657            $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1));
1658            $links = ($next_doc ? "<link href=\"$next_doc\" rel=Next>\n" : "");
1659            $links .= ($prev_doc ? "<link href=\"$prev_doc\" rel=Previous>\n" : "");
1660            $links .= "<link href=\"$docu_toc\" rel=ToC>\n";
1661            # fixme: try rel=Index too?
1662            &print_header("$title - $section", $links, 0);
1663
[fb646a]1664            #$navigation = "<p>Go to the ";
1665            $navigation = "<p>";
[5b0536]1666            if ($IMG_FIRST_ACTIVE ne "") {
1667                $navigation .= ($prev_doc ? &anchor('', $first_doc, '', 
1668                             $IMG_FIRST_ACTIVE) : $IMG_FIRST_PASSIVE);
1669                $navigation .= " ";
1670            }
[fb646a]1671            $navigation .= ($prev_doc ? &anchor('', $prev_doc, '', $IMG_PREV_ACTIVE) : $IMG_PREV_PASSIVE);
1672            $navigation .= " ";
1673            $navigation .= ($next_doc ? &anchor('', $next_doc, '', $IMG_NEXT_ACTIVE) : $IMG_NEXT_PASSIVE);
[5b0536]1674            if ($IMG_LAST_ACTIVE ne "") {
1675                $navigation .= " ";
1676                $navigation .= ($next_doc ? &anchor('', $last_doc, '',
1677                             $IMG_LAST_ACTIVE) : $IMG_LAST_PASSIVE);
1678            }
[fb646a]1679            #$navigation .= " section, " . &anchor('', $docu_toc, '', "<IMG SRC=\"toc-b.gif\">") . ".\n";
1680            $navigation .= " " . &anchor('', $docu_toc, '', $IMG_TOC) . "\n";
[5d13bc]1681            print FILE $navigation;
1682            &print_ruler;
1683            # find corresponding lines
1684            @tmp_lines = ();
1685            while (@doc_lines) {
1686                $_ = shift(@doc_lines);
1687                last if ($_ eq $SPLITTAG);
1688                push(@tmp_lines, $_);
1689            }
1690            &print(*tmp_lines, FILE);
1691            &print_ruler;
1692            print FILE $navigation;
1693            &print_footer;
1694            close(FILE);
1695        } else {
1696            warn "$ERROR Can't write to $docu_doc: $!\n";
1697        }
1698    }
1699} else { # not split
1700    if (open(FILE, "> $docu_doc")) {
1701        print "# creating $docu_doc...\n" if $verbose;
1702        if ($monolithic || !@toc_lines) {
1703            &print_toplevel_header($title);
1704        } else {
1705            &print_header($title, "", 0);
1706            print FILE $full_title;
1707        }
1708        if ($monolithic && @toc_lines) {
1709            &print_ruler;
1710            print FILE "<H1>Table of Contents</H1>\n";
1711            &print(*toc_lines, FILE);
1712        }
1713        &print_ruler;
1714        &print(*doc_lines, FILE);
1715        if ($monolithic && @foot_lines) {
1716            &print_ruler;
1717            print FILE "<H1>Footnotes</H1>\n";
1718            &print(*foot_lines, FILE);
1719        }
1720        if ($monolithic || !@toc_lines) {
1721            &print_toplevel_footer;
1722        } else {
1723            &print_footer;
1724        }
1725        close(FILE);
1726    } else {
1727        warn "$ERROR Can't write to $docu_doc: $!\n";
1728    }
1729}
1730
1731print "# that's all folks\n" if $verbose;
1732
1733#+++############################################################################
1734#                                                                              #
1735# Low level functions                                                          #
1736#                                                                              #
1737#---############################################################################
1738
1739sub update_sec_num {
1740    local($name, $level) = @_;
1741
1742    $level--; # here we start at 0
1743    if (($name =~ /^appendix/) || ($section_type)) {
1744        # appendix style
1745        $section_type = 1;
1746        if (defined(@appendix_sec_num)) {
1747            &incr_sec_num($level, @appendix_sec_num);
1748        } else {
1749            @appendix_sec_num = ('A', 0, 0, 0);
1750        }
1751        return(join('.', @appendix_sec_num[0..$level]));
1752    } else {
1753        # normal style
1754        $section_type = 0;
1755        if (defined(@normal_sec_num)) {
1756            &incr_sec_num($level, @normal_sec_num);
1757        } else {
1758            @normal_sec_num = (1, 0, 0, 0);
1759        }
1760        return(join('.', @normal_sec_num[0..$level]));
1761    }
1762}
1763
1764sub incr_sec_num {
1765    local($level, $l);
1766    $level = shift(@_);
1767    $_[$level]++;
1768    foreach $l ($level+1 .. 3) {
1769        $_[$l] = 0;
1770    }
1771}
1772
1773sub check {
1774    local($_, %seen, %context, $before, $match, $after);
1775
1776    while (<>) {
1777        if (/\@(\*|\.|\:|\@|\{|\})/) {
1778            $seen{$&}++;
1779            $context{$&} .= "> $_" if $verbose;
1780            $_ = "$`XX$'";
1781            redo;
1782        }
1783        if (/\@(\w+)/) {
1784            ($before, $match, $after) = ($`, $&, $');
1785            if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
1786                $seen{'e-mail address'}++;
1787                $context{'e-mail address'} .= "> $_" if $verbose;
1788            } else {
1789                $seen{$match}++;
1790                $context{$match} .= "> $_" if $verbose;
1791            }
1792            $match =~ s/^\@/X/;
1793            $_ = "$before$match$after";
1794            redo;
1795        }
1796    }
1797   
1798    foreach (sort(keys(%seen))) {
1799        if ($verbose) {
1800            print "$_\n";
1801            print $context{$_};
1802        } else {
1803            print "$_ ($seen{$_})\n";
1804        }
1805    }
1806}
1807
1808sub open {
1809    local($name) = @_;
1810
1811    ++$fh_name;
1812    if (open($fh_name, $name)) {
1813        unshift(@fhs, $fh_name);
1814    } else {
1815        warn "$ERROR Can't read file $name: $!\n";
1816    }
1817}
1818
1819sub init_input {
1820    @fhs = ();                  # hold the file handles to read
1821    @input_spool = ();          # spooled lines to read
1822    $fh_name = 'FH000';
1823    &open($docu);
1824}
1825
1826sub next_line {
1827    local($fh, $line);
1828
1829    if (@input_spool) {
1830        $line = shift(@input_spool);
1831        return($line);
1832    }
1833    while (@fhs) {
1834        $fh = $fhs[0];
1835        $line = <$fh>;
1836        return($line) if $line;
1837        close($fh);
1838        shift(@fhs);
1839    }
1840    return(undef);
1841}
1842
1843# used in pass 1, use &next_line
1844sub skip_until {
1845    local($tag) = @_;
1846    local($_);
1847
1848    while ($_ = &next_line) {
1849        return if /^\@end\s+$tag\s*$/;
1850    }
1851    die "* Failed to find '$tag' after: " . $lines[$#lines];
1852}
1853
1854#
1855# HTML stacking to have a better HTML output
1856#
1857
1858sub html_reset {
1859    @html_stack = ('html');
1860    $html_element = 'body';
1861}
1862
1863sub html_push {
1864    local($what) = @_;
1865    push(@html_stack, $html_element);
1866    $html_element = $what;
1867}
1868
1869sub html_push_if {
1870    local($what) = @_;
1871    push(@html_stack, $html_element)
1872        if ($html_element && $html_element ne 'P');
1873    $html_element = $what;
1874}
1875
1876sub html_pop {
1877    $html_element = pop(@html_stack);
1878}
1879
1880sub html_pop_if {
1881    local($elt);
1882
1883    if (@_) {
1884        foreach $elt (@_) {
1885            if ($elt eq $html_element) {
1886                $html_element = pop(@html_stack) if @html_stack;
1887                last;
1888            }
1889        }
1890    } else {
1891        $html_element = pop(@html_stack) if @html_stack;
1892    }
1893}
1894
1895sub html_debug {
1896    local($what, $line) = @_;
1897    return("<!-- $line @html_stack, $html_element -->$what")
1898        if $debug & $DEBUG_HTML;
1899    return($what);
1900}
1901
1902# to debug the output...
1903sub debug {
1904    local($what, $line) = @_;
1905    return("<!-- $line -->$what")
1906        if $debug & $DEBUG_HTML;
1907    return($what);
1908}
1909
1910sub normalise_node {
1911    $_[0] =~ s/\s+/ /g;
1912    $_[0] =~ s/ $//;
1913    $_[0] =~ s/^ //;
1914}
1915
1916sub left_menu_entry {
[fb646a]1917    local($secnum, $entry) = @_;
[5d13bc]1918    local($_);
[fb646a]1919    local($href, $descr, $oltype,$value);
[5d13bc]1920
[fb646a]1921    $_ = $secnum;
1922    $value = $secnum;
1923    if (/[A-Z]/) { 
1924        $oltype = "<LI TYPE=A";
1925        $value = $append2num{$secnum};
1926    } else {
1927        $oltype = "<LI";
1928    }
1929    $_ = $entry;
1930    print "===>($secnum): $entry\n";
1931    #s/^[0-9A-Z.]+ //;
[5d13bc]1932    $_ = $entry;
1933    &normalise_node($_);
1934    $href = $node2href{$_};
1935    if ($href) {
1936        $descr =~ s/^\s+//;
1937        $descr = ": $descr" if $descr;
[fb646a]1938        push(@menu_lines, "$oltype VALUE=$value>" . &anchor('', $href, "Main", $entry) . "$descr\n");
[5d13bc]1939    } else {
1940        warn "$ERROR Undefined node ($node): $_";
1941    }
1942}
1943
1944sub menu_entry {
1945    local($entry, $node, $descr) = @_;
1946    local($href);
1947
1948    &normalise_node($node);
1949    $href = $node2href{$node};
1950    if ($href) {
1951        $descr =~ s/^\s+//;
1952        $descr = ": $descr" if $descr;
1953        push(@lines2, "<LI>" . &anchor('', $href, '', $entry) . "$descr\n");
1954    } else {
1955        warn "$ERROR Undefined node ($node): $_";
1956    }
1957}
1958
1959sub do_email {
1960    my($address,$text);
1961    ($address,$text) = split(/,/, "$_[0]");
1962    $text =~ s/(^\s+)|(\s+$)//; # trim leading and trailing white space
1963    $text = $address unless $text;
1964    &anchor('', "mailto:${address}", '', "<TT>${text}</TT>")
1965}
1966
1967sub do_image {
1968    my($base,$width,$height,$image);
1969    ($base,$width,$height) = split(/,/,"$_[0]");
1970    if ( -f "${base}.jpg" ) {
1971        $image = "${base}.jpg";
1972    } elsif ( -f "${base}.gif" ) {
1973        $image = "${base}.gif";
1974    } else {
1975        $image = $base;
1976        warn "$ERROR image not found for ($base): $_";
1977    }
1978    "<BR><IMG SRC=\"${image}\"><BR>";
1979}
1980
1981sub do_uref {
1982  my($href,$text);
1983  ($href,$text) = split(/,/,"$_[0]");
1984  $text =~ s/(^\s+)|(\s+$)//;   # trim leading and trailing white space
1985  $text = $href unless $text;
1986# args to anchor() are: ($name, $href, $text, $newline)
1987  &anchor('', "$href", '', "<TT>$text</TT>")
1988}
1989
1990sub do_url {
1991    my($address,$text);
1992    ($address,$text) = split(/,/, "$_[0]");
1993    $text =~ s/(^\s+)|(\s+$)//; # trim leading and trailing white space
1994    $text = $address unless $text;
1995    $address =~ s/&#173;//g;
1996    &anchor('', "${address}", '', "<TT>${text}</TT>")
1997}
1998
1999sub do_ctrl { "^$_[0]" }
2000
2001sub do_sc { "\U$_[0]\E" }
2002
2003sub apply_style {
2004    local($texi_style, $text) = @_;
2005    local($style);
2006
2007    $style = $style_map{$texi_style};
2008    if (defined($style)) { # known style
2009        if ($style =~ /^\"/) { # add quotes
2010            $style = $';
2011            $text = "\`$text\'";
2012        }
2013        if ($style =~ /^\&/) { # custom
2014            $style = $';
2015            $text = &$style($text);
2016        } elsif ($style) { # good style
2017            $text = "<$style>$text</$style>";
2018        } else { # no style
2019        }
2020    } else { # unknown style
2021        $text = undef;
2022    }
2023    return($text);
2024}
2025
2026sub apply_l_style {
2027    local($texi_style, $text) = @_;
2028    local($style);
2029
2030    $style = $style_l_map{$texi_style};
2031    if (defined($style)) { # known style
2032        if ($style =~ /^\"/) { # add quotes
2033            $style = $';
2034            $text = "\`$text\'";
2035        }
2036        if ($style =~ /^\&/) { # custom
2037            $style = $';
2038            $text = &$style($text);
2039        } elsif ($style) { # good style
2040            $text = "<$style>$text</$style>";
2041        } else { # no style
2042        }
2043    } else { # unknown style
2044        $text = undef;
2045    }
2046    return($text);
2047}
2048
2049# remove Texinfo styles
2050sub remove_style {
2051    local($_) = @_;
2052    s/\@\w+{([^\{\}]+)}/$1/g;
2053    return($_);
2054}
2055
2056sub substitute_style {
2057    local($_) = @_;
2058    local($changed, $done, $style, $text);
2059
2060    $changed = 1;
2061    while ($changed) {
2062        $changed = 0;
2063        $done = '';
2064        while (/\@(\w+){([^\{\}]+)}/) {
2065            $text = &apply_style($1, $2);
2066            if ($text) {
2067                $_ = "$`$text$'";
2068                $changed = 1;
2069            } else {
2070                $done .= "$`\@$1";
2071                $_ = "{$2}$'";
2072            }
2073        }
2074        $_ = $done . $_;
2075    }
2076    return($_);
2077}
2078
2079sub anchor {
2080    local($name, $href, $target, $text, $newline) = @_;
2081    local($result);
2082
2083    $result = "<A";
2084    $result .= " NAME=\"$name\"" if $name;
2085    $result .= " HREF=\"$href\"" if $href;
2086    $result .= " TARGET=\"$target\"" if $target;
2087    $result .= ">$text</A>";
2088    $result .= "\n" if $newline;
2089    return($result);
2090}
2091
2092sub pretty_date {
2093    local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
2094
2095    @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
2096            'July', 'August', 'September', 'October', 'November', 'December');
2097    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
2098    $year += ($year < 70) ? 2000 : 1900;
2099    return("$mday $MoY[$mon] $year");
2100}
2101
2102sub doc_name {
2103    local($num) = @_;
2104
2105    return("${docu_name}_$num.html");
2106}
2107
2108sub next_doc {
2109    $docu_doc = &doc_name(++$doc_num);
2110}
2111
2112sub print {
2113    local(*lines, $fh) = @_;
2114    local($_);
2115
2116    while (@lines) {
2117        $_ = shift(@lines);
2118        if (/^$PROTECTTAG/o) {
2119            $_ = $tag2pro{$_};
2120        } else {
2121            &unprotect_texi;
2122        }
2123        print $fh $_;
2124    }
2125}
2126
2127sub print_ruler {
2128    print FILE "<P><HR><P>\n";
2129}
2130
2131sub print_frame {
2132    print FILE <<EOT;
2133<FRAMESET COLS="20%,*" BORDER=0>
2134<FRAME SRC="$docu_left" NAME="Links">
[fb646a]2135<FRAME SRC="$_[0]" NAME="Main">
[5d13bc]2136</FRAMESET>
2137
2138EOT
2139}
2140
2141sub print_header {
2142    local($_);
2143
2144    $links = $_[1];
2145    $is_frame = $_[2];
2146    # clean the title
2147    $_ = &remove_style($_[0]);
2148    &unprotect_texi;
2149    # print the header
2150    if ($doctype eq 'html2') {
2151        print FILE $html2_doctype; # Wrong if any multitable used
2152    } elsif ($doctype) {
2153        print FILE $doctype;
2154    }
2155    print FILE <<EOT;
2156<HTML>
2157<HEAD>
2158$header
2159<TITLE>$_</TITLE>
2160$links
2161</HEAD>
2162EOT
2163    if(!$is_frame) { print FILE "<BODY background=\"/rock.gif\">\n"; }
2164}
2165
2166sub print_toplevel_header {
2167    local($_);
2168
2169    &print_header ($_[0], "", 0);
2170    print FILE $full_title;
2171    if ($value{'_subtitle'}) {
2172        $value{'_subtitle'} =~ s/\n+$//;
2173        foreach (split(/\n/, $value{'_subtitle'})) {
2174            $_ = &substitute_style($_);
2175            &unprotect_texi;
2176            print FILE "<H2>$_</H2>\n";
2177        }
2178    }
2179    if ($value{'_author'}) {
2180        $value{'_author'} =~ s/\n+$//;
2181        foreach (split(/\n/, $value{'_author'})) {
2182            $_ = &substitute_style($_);
2183            &unprotect_texi;
2184#           s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
2185            print FILE "<ADDRESS>$_</ADDRESS>\n";
2186        }
2187    }
2188    print FILE "<P>\n";
2189}
2190
2191sub print_footer {
2192    print FILE <<EOT;
2193</BODY>
2194</HTML>
2195EOT
2196}
2197
2198sub print_toplevel_footer {
2199    &print_ruler;
2200    print FILE <<EOT;
2201This document was generated on $TODAY using the
2202<A HREF=\"$HOMEPAGE\">texi2html</A>
2203translator version 1.51a.</P>
2204EOT
2205    &print_footer;
2206}
2207
2208sub protect_texi {
2209    # protect @ { } ` '
2210    s/\@\@/$;0/go;
2211    s/\@\{/$;1/go;
2212    s/\@\}/$;2/go;
2213    s/\@\`/$;3/go;
2214    s/\@\'/$;4/go;
2215}
2216
2217sub protect_html {
2218    local($what) = @_;
2219    # protect & < >
2220    $what =~ s/\&/\&\#38;/g;
2221    $what =~ s/\</\&\#60;/g;
2222    $what =~ s/\>/\&\#62;/g;
2223    # but recognize some HTML things
2224    $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g;             # </A>
2225    $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g;     # <A [^&]+>
2226    $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
2227    return($what);
2228}
2229
2230sub unprotect_texi {
2231    s/$;0/\@/go;
2232    s/$;1/\{/go;
2233    s/$;2/\}/go;
2234    s/$;3/\`/go;
2235    s/$;4/\'/go;
2236}
2237
2238sub unprotect_html {
2239    local($what) = @_;
2240    $what =~ s/\&\#38;/\&/g;
2241    $what =~ s/\&\#60;/\</g;
2242    $what =~ s/\&\#62;/\>/g;
2243    return($what);
2244}
2245
2246sub byalpha {
2247    $key2alpha{$a} cmp $key2alpha{$b};
2248}
2249
2250##############################################################################
2251
2252        # These next few lines are legal in both Perl and nroff.
2253
2254.00 ;                   # finish .ig
2255 
2256'di                     \" finish diversion--previous line must be blank
2257.nr nl 0-1              \" fake up transition to first page again
2258.nr % 0                 \" start at page 1
2259'; __END__ ############# From here on it's a standard manual page ############
2260.TH TEXI2HTML 1 "08/12/97"
2261.AT 3
2262.SH NAME
2263texi2html \- a Texinfo to HTML converter
2264.SH SYNOPSIS
2265.B texi2html [OPTION]... FILE
2266.PP
2267.B texi2html -check [-verbose] FILE...
2268.SH DESCRIPTION
2269.I Texi2html
2270converts the given Texinfo file to a set of HTML files. It tries to handle
2271most of the Texinfo commands. It creates hypertext links for cross-references,
2272footnotes...
2273.PP
2274It also tries to add links from a reference to its corresponding entry in the
2275bibliography (if any). It may also handle a glossary (see the
2276.B \-glossary
2277option).
2278.PP
2279.I Texi2html
2280creates several files depending on the contents of the Texinfo file and on
2281the chosen options (see FILES).
2282.PP
2283The HTML files created by
2284.I texi2html
2285are closer to TeX than to Info, that's why
2286.I texi2html
2287converts @iftex sections and not @ifinfo ones by default. You can reverse
2288this with the \-expandinfo option.
2289.SH OPTIONS
2290.TP 12
2291.B \-check
2292Check the given file and give the list of all things that may be Texinfo commands.
2293This may be used to check the output of
2294.I texi2html
2295to find the Texinfo commands that have been left in the HTML file.
2296.TP
2297.B \-expandinfo
2298Expand @ifinfo sections, not @iftex ones.
2299.TP
2300.B \-glossary
2301Use the section named 'Glossary' to build a list of terms and put links in the HTML
2302document from each term toward its definition.
2303.TP
2304.B \-invisible \fIname\fP
2305Use \fIname\fP to create invisible destination anchors for index links. This is a workaround
2306for a known bug of many WWW browsers, including xmosaic.
2307.TP
2308.B \-I \fIdir\fP
2309Look also in \fIdir\fP to find included files.
2310.TP
2311.B \-menu
2312Show the Texinfo menus; by default they are ignored.
2313.TP
2314.B \-monolithic
2315Output only one file, including the table of contents and footnotes.
2316.TP
2317.B \-number
2318Number the sections.
2319.TP
2320.B \-split_chapter
2321Split the output into several HTML files (one per main section:
2322chapter, appendix...).
2323.TP
2324.B \-split_node
2325Split the output into several HTML files (one per node).
2326.TP
2327.B \-usage
2328Print usage instructions, listing the current available command-line options.
2329.TP
2330.B \-verbose
2331Give a verbose output. Can be used with the
2332.B \-check
2333option.
2334.PP
2335.SH FILES
2336By default
2337.I texi2html
2338creates the following files (foo being the name of the Texinfo file):
2339.TP 16
2340.B foo_toc.html
2341The table of contents.
2342.TP
2343.B foo.html
2344The document's contents.
2345.TP
2346.B foo_foot.html
2347The footnotes (if any).
2348.PP
2349When used with the
2350.B \-split
2351option, it creates several files (one per chapter or node), named
2352.B foo_n.html
2353(n being the indice of the chapter or node), instead of the single
2354.B foo.html
2355file.
2356.PP
2357When used with the
2358.B \-monolithic
2359option, it creates only one file:
2360.B foo.html
2361.SH VARIABLES
2362.I texi2html
2363predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
2364.SH ADDITIONAL COMMANDS
2365.I texi2html
2366implements the following non-Texinfo commands:
2367.TP 16
2368.B @ifhtml
2369This indicates the start of an HTML section, this section will passed through
2370without any modofication.
2371.TP
2372.B @end ifhtml
2373This indcates the end of an HTML section.
2374.SH VERSION
2375This is \fItexi2html\fP version 1.54, 1998-01-17
2376.PP
2377The latest version of \fItexi2html\fP can be found at
2378ftp://ftp.cs.umb.edu/pub/tex/texi2html
2379.SH AUTHOR
2380The main author is Lionel Cons, CERN CN/DCI/UWS.
2381This version is maintained at ftp://ftp.cs.umb.edu/pub/tex/texi2html
2382by kb@cs.umb.edu.
2383Many other people around the net contributed to this program.
2384.SH COPYRIGHT
2385This program is the intellectual property of the European
2386Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
2387provided by CERN. No liability whatsoever is accepted for any loss or damage
2388of any kind resulting from any defect or inaccuracy in this information or
2389code.
2390.PP
2391CERN, 1211 Geneva 23, Switzerland
2392.SH "SEE ALSO"
2393GNU Texinfo Documentation Format,
2394HyperText Markup Language (HTML),
2395World Wide Web (WWW).
2396.SH BUGS
2397This program does not understand all Texinfo commands (yet).
2398.PP
2399TeX specific commands (normally enclosed in @iftex) will be
2400passed unmodified.
2401.ex
Note: See TracBrowser for help on using the repository browser.