Subversion Repositories shark

Rev

Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed

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