source: git/doc/texi2html @ 7a9a32

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