'di ';
'ig 00 ';
#+##############################################################################
# #
# File: texi2html #
# #
# Description: Program to transform most Texinfo documents to HTML #
# #
#-##############################################################################
# From @(#)texi2html 1.52 01/05/98 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch
# $Id: texi2html,v 1.5 1999/02/20 20:27:00 karl Exp $
# This version of texi2html is currently maintained at
# ftp://ftp.cs.umb.edu/pub/tex/texi2html by kb@cs.umb.edu.
# The man page for this program is included at the end of this file and can be
# viewed using the command 'nroff -man texi2html'.
# Please read the copyright at the end of the man page.
#+++############################################################################
# #
# Constants #
# #
#---############################################################################
$DEBUG_TOC = 1;
$DEBUG_INDEX = 2;
$DEBUG_BIB = 4;
$DEBUG_GLOSS = 8;
$DEBUG_DEF = 16;
$DEBUG_HTML = 32;
$DEBUG_USER = 64;
$THISVERSION = "1.56k";
$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">';
#
# language dependent constants
#
#$LDC_SEE = 'see';
#$LDC_SECTION = 'section';
#$LDC_IN = 'in';
#$LDC_TOC = 'Table of Contents';
#$LDC_GOTO = 'Go to the';
#$LDC_FOOT = 'Footnotes';
# TODO: @def* shortcuts
#
# pre-defined indices
#
%predefined_index = (
'cp', 'c',
'fn', 'f',
'vr', 'v',
'ky', 'k',
'pg', 'p',
'tp', 't',
);
#
# valid indices
#
%valid_index = (
'c', 1,
'f', 1,
'v', 1,
'k', 1,
'p', 1,
't', 1,
);
#
# texinfo section names to level
#
%sec2level = (
'top', 0,
'chapter', 1,
'unnumbered', 1,
'majorheading', 1,
'chapheading', 1,
'appendix', 1,
'section', 2,
'unnumberedsec', 2,
'heading', 2,
'appendixsec', 2,
'appendixsection', 2,
'subsection', 3,
'unnumberedsubsec', 3,
'subheading', 3,
'appendixsubsec', 3,
'subsubsection', 4,
'unnumberedsubsubsec', 4,
'subsubheading', 4,
'appendixsubsubsec', 4,
);
#
# accent map, TeX command to ISO name
#
%accent_map = (
'"', 'uml',
'~', 'tilde',
'^', 'circ',
'`', 'grave',
'\'', 'acute',
);
#
# texinfo "simple things" (@foo) to HTML ones
#
%simple_map = (
# cf. makeinfo.c
"*", "<BR>", # HTML+
" ", " ",
"\t", " ",
"-", "­", # soft hyphen
"\n", "\n",
"|", "",
'tab', '<\/TD><TD>',
# spacing commands
":", "",
"!", "!",
"?", "?",
".", ".",
"-", "",
);
#
# texinfo "things" (@foo{}) to HTML ones
#
%things_map = (
'TeX', 'TeX',
'br', '<P>', # paragraph break
'bullet', '*',
'copyright', '(C)',
'dots', '...',
'equiv', '==',
'error', 'error-->',
'expansion', '==>',
'minus', '-',
'point', '-!-',
'print', '-|',
'result', '=>',
'today', $TODAY,
);
#
# texinfo styles (@foo{bar}) to HTML ones
#
%style_map = (
'asis', '',
'b', 'B',
'cite', 'CITE',
'code', 'CODE',
'ctrl', '&do_ctrl', # special case
'dfn', 'EM', # DFN tag is illegal in the standard
'dmn', '', # useless
'email', '&do_email', # insert a clickable email address
'emph', 'EM',
'file', '"TT', # will put quotes, cf. &apply_style
'i', 'I',
'kbd', 'KBD',
'key', 'KBD',
'math', 'EM',
'r', '', # unsupported
'samp', '"SAMP', # will put quotes, cf. &apply_style
'sc', '&do_sc', # special case
'strong', 'STRONG',
't', 'TT',
'titlefont', '', # useless
'uref', '&do_uref', # insert a clickable URL
'url', '&do_url', # insert a clickable URL
'var', 'VAR',
'w', '', # unsupported
);
#
# texinfo format (@foo/@end foo) to HTML ones
#
%format_map = (
'display', 'PRE',
'example', 'PRE',
'format', 'PRE',
'lisp', 'PRE',
'quotation', 'BLOCKQUOTE',
'smallexample', 'PRE',
'smalllisp', 'PRE',
# lists
'itemize', 'UL',
'enumerate', 'OL',
# poorly supported
'flushleft', 'PRE',
'flushright', 'PRE',
);
#
# texinfo definition shortcuts to real ones
#
%def_map = (
# basic commands
'deffn', 0,
'defvr', 0,
'deftypefn', 0,
'deftypevr', 0,
'defcv', 0,
'defop', 0,
'deftp', 0,
# basic x commands
'deffnx', 0,
'defvrx', 0,
'deftypefnx', 0,
'deftypevrx', 0,
'defcvx', 0,
'defopx', 0,
'deftpx', 0,
# shortcuts
'defun', 'deffn Function',
'defmac', 'deffn Macro',
'defspec', 'deffn {Special Form}',
'defvar', 'defvr Variable',
'defopt', 'defvr {User Option}',
'deftypefun', 'deftypefn Function',
'deftypevar', 'deftypevr Variable',
'defivar', 'defcv {Instance Variable}',
'defmethod', 'defop Method',
# x shortcuts
'defunx', 'deffnx Function',
'defmacx', 'deffnx Macro',
'defspecx', 'deffnx {Special Form}',
'defvarx', 'defvrx Variable',
'defoptx', 'defvrx {User Option}',
'deftypefunx', 'deftypefnx Function',
'deftypevarx', 'deftypevrx Variable',
'defivarx', 'defcvx {Instance Variable}',
'defmethodx', 'defopx Method',
);
#
# things to skip
#
%to_skip = (
# comments
'c', 1,
'comment', 1,
'ifnothtml', 1,
# useless
'detailmenu', 1,
'direntry', 1,
'contents', 1,
'shortcontents', 1,
'summarycontents', 1,
'footnotestyle', 1,
'end ifclear', 1,
'end ifset', 1,
'titlepage', 1,
'end titlepage', 1,
# unsupported commands (formatting)
'afourpaper', 1,
'cropmarks', 1,
'finalout', 1,
'headings', 1,
'sp', 1,
'need', 1,
'page', 1,
'setchapternewpage', 1,
'everyheading', 1,
'everyfooting', 1,
'evenheading', 1,
'evenfooting', 1,
'oddheading', 1,
'oddfooting', 1,
'smallbook', 1,
'vskip', 1,
'filbreak', 1,
'paragraphindent', 1,
# unsupported formats
'cartouche', 1,
'end cartouche', 1,
'group', 1,
'end group', 1,
);
#+++############################################################################
# #
# Argument parsing, initialisation #
# #
#---############################################################################
%value = (); # hold texinfo variables, see also -D
$use_bibliography = 1;
$use_acc = 0;
$debug = 0;
$doctype = '';
$check = 0;
$expandinfo = 0;
$use_glossary = 0;
$invisible_mark = '';
$use_iso = 0;
@include_dirs = ();
$show_menu = 0;
$number_sections = 0;
$split_node = 0;
$split_chapter = 0;
$monolithic = 0;
$verbose = 0;
$_ = shift(@ARGV);
if ($2 =~ /^n/) {
$split_node = 1;
} else {
$split_chapter = 1;
}
next;
}
die $usage;
}
if ($check) {
✓
exit;
}
warn "Can't use -monolithic with -split, -monolithic ignored.\n";
$monolithic = 0;
}
if ($expandinfo) {
$to_skip{'ifinfo'}++;
$to_skip{'end ifinfo'}++;
$to_skip{'ifnottex'}++;
$to_skip{'end ifnottex'}++;
} else {
$to_skip{'iftex'}++;
$to_skip{'end iftex'}++;
}
if ($docu =~ /.*\//) {
chop($docu_dir = $&);
$docu_name = $';
} else {
$docu_dir = '.';
}
unshift(@include_dirs, $docu_dir);
if ($monolithic) {
} else {
}
#
# variables
#
# _foo: internal to track @foo
foreach ('_author', '_title', '_subtitle',
'_settitle', '_setfilename') {
}
%node2sec = (); # node to section name
%node2href = (); # node to HREF
%bib2href = (); # bibliography reference to HREF
%gloss2href = (); # glossary term to HREF
@sections = (); # list of sections
%tag2pro = (); # protected sections
#
# initial indexes
#
$bib_num = 0;
$foot_num = 0;
$gloss_num = 0;
$idx_num = 0;
$sec_num = 0;
$doc_num = 0;
$html_num = 0;
#
# can I use ISO8879 characters? (HTML+)
#
if ($use_iso) {
}
#
# read texi2html extensions (if any)
#
if (-f $extensions) {
print "# reading extensions from $extensions\n" if $verbose;
require($extensions);
}
($progdir = $0) =~ s/[^\/]+$//;
if (-f $extensions) {
print "# reading extensions from $extensions\n" if $verbose;
require($extensions);
}
}
print "# reading from $docu\n" if $verbose;
#+++############################################################################
# #
# Pass 1: read source, handle command, variable, simple substitution #
# #
#---############################################################################
@lines = (); # whole document
@toc_lines = (); # table of contents
@tables = (); # nested table support
@html_stack = (); # HTML elements stack
# build code for simple substitutions
# the maps used (%simple_map and %things_map) MUST be aware of this
# watch out for regexps, / and escaped characters!
$subst_code = '';
foreach (keys(%simple_map)) {
$subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
}
foreach (keys(%things_map)) {
$subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
}
if ($use_acc) {
# accentuated characters
foreach (keys(%accent_map)) {
if ($_ eq "`") {
$subst_code .= "s/$;3";
} elsif ($_ eq "'") {
$subst_code .= "s/$;4";
} else {
$subst_code .= "s/\\\@\\$_";
}
$subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
}
}
eval("sub simple_substitutions { $subst_code }");
while ($_ = &next_line) {
#
# remove \input on the first lines only
#
if ($first_line) {
next if /^\\input/;
$first_line = 0;
}
#
# parse texinfo tags
#
$tag = '';
$end_tag = '';
if (/^\s*\@end\s+(\w+)\b/) {
$end_tag = $1;
} elsif (/^\s*\@(\w+)\b/) {
$tag = $1;
}
#
# handle @ifhtml / @end ifhtml
#
if ($in_html) {
if ($end_tag eq 'ifhtml') {
$in_html = 0;
} else {
}
next;
} elsif ($tag eq 'ifhtml') {
next;
}
#
# try to skip the line
#
if ($end_tag) {
next if $to_skip{"end $end_tag"};
} elsif ($tag) {
last if $tag eq 'bye';
}
if ($in_top) {
# parsing the top node
# no more in top
$in_top = 0;
} else {
# skip it
next;
}
}
#
# try to remove inlined comments
# syntax from tex-mode.el comment-start-skip
#
s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/;
# non-@ substitutions cf. texinfmt.el
unless ($in_pre) {
s/``/\"/g;
s/''/\"/g;
s/([\w ])---([\w ])/$1--$2/g;
}
#
# analyze the tag
#
if ($tag) {
# skip lines
if ($expandinfo) {
} else {
}
# handle special tables
$table_type = $1;
$tag = 'table';
}
# special cases
$in_top = 1;
@lines = (); # ignore all lines before top (title page garbage)
next;
} elsif ($tag eq 'node') {
$in_top = 0;
$_ = &protect_html($_); # if node contains '&' for instance
s/^\@node\s+//;
($node) = split(/,/);
&normalise_node($node);
if ($split_node) {
&next_doc;
}
next;
} elsif ($tag eq 'include') {
$file = $1;
unless (-e $file) {
foreach $dir (@include_dirs) {
$file = "$dir/$1";
last if -e $file;
}
}
if (-e $file) {
print "# including $file\n" if $verbose;
} else {
warn "$ERROR Can't find $file, skipping";
}
} else {
warn "$ERROR Bad include line: $_";
}
next;
} elsif ($tag eq 'ifclear') {
next unless defined($value{$1});
&skip_until($tag);
} else {
warn "$ERROR Bad ifclear line: $_";
}
next;
} elsif ($tag eq 'ifset') {
next if defined($value{$1});
&skip_until($tag);
} else {
warn "$ERROR Bad ifset line: $_";
}
next;
} elsif ($tag eq 'menu') {
unless ($show_menu) {
&skip_until($tag);
next;
}
&html_push_if($tag);
} elsif ($format_map{$tag}) {
next;
} elsif ($tag eq 'table') {
$in_table = $2;
if ($table_type eq "multi") {
&html_push_if('TABLE');
} else {
&html_push_if('DL');
}
} else {
warn "$ERROR Bad table line: $_";
}
next;
if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
eval("*${1}index = *${2}index");
} else {
warn "$ERROR Bad syn*index line: $_";
}
next;
} elsif ($tag eq 'sp') {
next;
} elsif ($tag eq 'setref') {
&protect_html; # if setref contains '&' for instance
$setref = $1;
$setref =~ s/\s+/ /g; # normalize
$setref =~ s/ $//;
} else {
warn "$ERROR Bad setref line: $_";
}
next;
if (/^\@$tag\s+(\w\w)\s*$/) {
} else {
warn "$ERROR Bad defindex line: $_";
}
next;
} elsif ($tag eq 'lowersections') {
}
next;
} elsif ($tag eq 'raisesections') {
}
next;
s/^\@$tag\s+//;
$_ = "\@$tag $_";
$tag =~ s/\s.*//;
}
s/^\@$tag\s+//;
if (defined(&$sub)) {
chop($_);
&$sub($_);
} else {
warn "$ERROR Bad user sub for $tag: $sub\n";
}
next;
}
s/^\@$tag\s+//;
if ($tag =~ /x$/) {
# extra definition line
$tag = $`;
$is_extra = 1;
} else {
$is_extra = 0;
}
while (/\{([^\{\}]*)\}/) {
# this is a {} construct
# protect spaces
$contents =~ s/\s+/$;9/g;
# restore $_ protecting {}
$_ = "$before$;7$contents$;8$after";
}
@args = split(/\s+/, &protect_html($_));
foreach (@args) {
s/$;9/ /g; # unprotect spaces
s/$;7/\{/g; # ... {
s/$;8/\}/g; # ... }
}
$type =~ s/^\{(.*)\}$/$1/;
$name =~ s/^\{(.*)\}$/$1/;
if ($is_extra) {
} else {
}
$_ .= "<U>$type</U> <B>$name</B>";
$_ .= " <I>@args</I>" if @args;
$name =~ s/^\{(.*)\}$/$1/;
$_ .= "<U>$type</U> $ftype <B>$name</B>";
$_ .= " <I>@args</I>" if @args;
} else {
warn "$ERROR Unknown definition type: $tag\n";
$_ .= "<U>$type</U> <B>$name</B>";
$_ .= " <I>@args</I>" if @args;
}
unshift(@input_spool, "\@findex $name\n");
} elsif ($tag eq 'defop') {
unshift(@input_spool, "\@findex $name on $ftype\n");
unshift(@input_spool, "\@vindex $name\n");
} else {
unshift(@input_spool, "\@tindex $name\n");
}
$dont_html = 1;
}
} elsif ($end_tag) {
if ($format_map{$end_tag}) {
&html_pop_if();
unless (@tables) {
warn "$ERROR \@end $end_tag without \@*table\n";
next;
}
unless ($1 eq $table_type) {
warn "$ERROR \@end $end_tag without matching \@$end_tag\n";
next;
}
if ($table_type eq "multi") {
push(@lines, "</TR></TABLE>\n");
&html_pop_if('TR');
} else {
push(@lines, "</DL>\n");
&html_pop_if('DD');
}
&html_pop_if();
if (@tables) {
} else {
$in_table = 0;
}
} elsif ($end_tag eq 'menu') {
&html_pop_if();
push(@lines, $_); # must keep it for pass 2
}
next;
}
#
# misc things
#
# protect texi and HTML things
$_ = &protect_html($_) unless $dont_html;
$dont_html = 0;
# substitution (unsupported things)
s/^\@center\s+//g;
s/^\@exdent\s+//g;
s/\@noindent\s+//g;
s/\@refill\s+//g;
# other substitutions
#
# analyze the tag again
#
if ($tag) {
if (/^\@$tag\s+(.+)$/) {
$name = $1;
$name =~ s/\s+$//;
if ($html_element ne 'body') {
# We are in a nice pickle here. We are trying to get a H? heading
# even though we are not in the body level. So, we convert it to a
# nice, bold, line by itself.
} else {
&html_push_if('body');
}
print "# heading, section $name, level $level\n"
} else {
if ($split_chapter) {
unless ($toplevel) {
# first time we see a "section"
unless ($level == 1) {
warn "$ERROR The first section found is not of level 1: $_";
warn "$ERROR I'll split on sections of level $level...\n";
}
}
&next_doc;
}
}
$sec_num++;
$docid = "SEC$sec_num";
$tocid = "TOC$sec_num";
# check biblio and glossary
# check node
if ($node) {
warn "$ERROR Duplicate node found: $node\n";
} else {
print "# node $node, section $name, level $level\n"
}
$node = '';
} else {
print "# no node, section $name, level $level\n"
}
# update TOC
$curlevel++;
push(@toc_lines, "<UL>\n");
}
$curlevel--;
push(@toc_lines, "</UL>\n");
}
push(@toc_lines, &substitute_style($_));
# update DOC
}
# update DOC
foreach $line (split(/\n+/, $_)) {
push(@lines, "$line\n");
}
next;
} else {
warn "$ERROR Bad section line: $_";
}
} else {
# track variables
# store things
# index
if (/^\@(..?)index\s+/) {
unless ($valid_index{$1}) {
warn "$ERROR Undefined index command: $_";
next;
}
$what =~ s/\s+$//;
print "# found $index for '$what' id $id\n"
if $debug & $DEBUG_INDEX;
eval(<<EOC);
} else {
}
#
# dirty hack to see if I can put an invisible anchor...
#
if ($html_element eq 'P' ||
$html_element eq 'LI' ||
$html_element eq 'DT' ||
$html_element eq 'DD' ||
$html_element eq 'ADDRESS' ||
$html_element eq 'B' ||
$html_element eq 'BLOCKQUOTE' ||
$html_element eq 'PRE' ||
$html_element eq 'SAMP') {
} elsif ($html_element eq 'body') {
&html_push('P');
} elsif ($html_element eq 'DL' ||
$html_element eq 'UL' ||
$html_element eq 'OL' ) {
}
next;
}
# list item
if (/^\s*\@itemx?\s+/) {
$what = $';
$what =~ s/\s+$//;
if ($in_bibliography && $use_bibliography) {
print "# found bibliography for '$what' id $id\n"
}
} elsif ($in_glossary && $use_glossary) {
print "# found glossary for '$entry' id $id\n"
if $debug & $DEBUG_GLOSS;
}
&html_pop_if('P');
# special case to allow @table @bullet for instance
} else {
}
push(@lines, "<DD>");
if ($table_type) { # add also an index
unshift(@input_spool, "\@${table_type}index $what\n");
}
} elsif ($html_element eq 'TABLE') {
&html_push('TR');
} elsif ($html_element eq 'TR') {
} else {
}
if ($deferred_ref) {
$deferred_ref = '';
}
next;
} elsif (/^\@tab\s+(.*)$/) {
push(@lines, "<TD>$1</TD>\n");
next;
}
}
}
# paragraph separator
if ($_ eq "\n") {
next if $#lines >= 0 && $lines[$#lines] eq "\n";
if ($html_element eq 'P') {
push(@lines, "\n");
&html_pop;
}
push(@lines, "<P>\n");
&html_push('P');
}
# otherwise
push(@lines, $_);
}
# finish TOC
$level = 0;
$curlevel--;
push(@toc_lines, "</UL>\n");
}
print "# end of pass 1\n" if $verbose;
#+++############################################################################
# #
# Pass 2/3: handle style, menu, index, cross-reference #
# #
#---############################################################################
@lines2 = (); # whole document (2nd pass)
@lines3 = (); # whole document (3rd pass)
while (@lines) {
$_ = shift(@lines);
#
# special case (protected sections)
#
if (/^$PROTECTTAG/o) {
push(@lines2, $_);
next;
}
#
# menu
#
if ($in_menu) {
if (/^\*\s+($NODERE)::/o) {
$descr = $';
chop($descr);
} elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
$descr = $';
chop($descr);
} elsif (/^\*/) {
warn "$ERROR Bad menu line: $_";
} else { # description continued?
push(@lines2, $_);
}
next;
}
#
# printindex
#
if (/^\@printindex\s+(\w\w)\b/) {
if ($predefined_index{$1}) {
} else {
}
eval("*ary = *$index");
$_ = $key;
1 while s/<(\w+)>\`(.*)\'<\/\1>/$2/; # remove HTML tags with quotes
1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags
$_ = &unprotect_html($_);
tr/A-Z/a-z/; # lowercase
print "# index $key sorted as $_\n"
}
push(@lines2, "Jump to:\n");
$last_letter = undef;
$last_letter = $letter;
}
}
push(@lines2, "<P>\n");
$last_letter = undef;
push(@lines2, "<DIR>\n");
$last_letter = $letter;
}
@refs = ();
}
}
next;
}
#
# simple style substitutions
#
$_ = &substitute_style($_);
#
# xref
#
# note: Texinfo may accept other characters
warn "$ERROR Bad xref (no ending } on line): $_";
$_ = "$before$;0${type}ref\{$nodes$after";
next; # while xref
}
if ($type eq 'x') {
$type = 'See ';
} elsif ($type eq 'px') {
$type = 'see ';
} elsif ($type eq 'info') {
$type = 'See Info';
} else {
$type = '';
}
unless ($full) {
chop($nodes); # remove final newline
if ($next =~ /\}/) { # split on 2 lines
$nodes .= " $`";
$after = $';
} else {
$nodes .= " $next";
chop($nodes);
if ($next =~ /\}/) { # split on 3 lines
$nodes .= " $`";
$after = $';
} else {
warn "$ERROR Bad xref (no ending }): $_";
$_ = "$before$;0xref\{$nodes$after";
next; # while xref
}
}
}
$nodes =~ s/\s+/ /g; # remove useless spaces
&normalise_node($node);
$_ = "${before}${type}section `$sec' in \@cite{$man}$after";
$_ = "${before}${type} file `$in', node `$nn'$after";
} elsif ($sec) {
} else {
warn "$ERROR Undefined node ($node): $_";
$_ = "$before$;0xref{$nodes}$after";
}
}
if (/^\@image\s*{/) {
s/\@image\s*{//;
my (@args) = split (/,/);
my $image;
if (-r "$base.jpg") {
$image = "$base.jpg";
} elsif (-r "$base.png") {
$image = "$base.png";
} elsif (-r "$base.gif") {
$image = "$base.gif";
} else {
warn "$ERROR no image file for $base: $_";
}
$_ = "<IMG SRC=\"$image\" ALT=\"$base\">";
}
#
# try to guess bibliography references or glossary terms
#
unless (/^<H\d><A NAME=\"SEC\d/) {
if ($use_bibliography) {
$done = '';
while (/$BIBRE/o) {
} else {
$done .= "$pre$what";
}
$_ = $post;
}
$_ = $done . $_;
}
if ($use_glossary) {
$done = '';
while (/\b\w+\b/) {
} else {
$done .= "$pre$what";
}
$_ = $post;
}
$_ = $done . $_;
}
}
# otherwise
push(@lines2, $_);
}
print "# end of pass 2\n" if $verbose;
#
# split style substitutions
#
while (@lines2) {
$_ = shift(@lines2);
#
# special case (protected sections)
#
if (/^$PROTECTTAG/o) {
push(@lines3, $_);
next;
}
#
# split style substitutions
#
$old = '';
while ($old ne $_) {
$old = $_;
if (/\@(\w+)\{/) {
$_ = $after;
$text = '';
$after = '';
$failed = 1;
while (@lines2) {
if (/\}/) {
$text .= $`;
$after = $';
$failed = 0;
last;
} else {
$text .= $_;
$_ = shift(@lines2);
}
}
if ($failed) {
die "* Bad syntax (\@$style) after: $before\n";
} else {
$_ = "$before$text$after";
}
}
}
}
# otherwise
push(@lines3, $_);
}
print "# end of pass 3\n" if $verbose;
#+++############################################################################
# #
# Pass 4: foot notes, final cleanup #
# #
#---############################################################################
@foot_lines = (); # footnotes
@doc_lines = (); # final document
while (@lines3) {
$_ = shift(@lines3);
#
# special case (protected sections)
#
if (/^$PROTECTTAG/o) {
push(@doc_lines, $_);
$end_of_para = 0;
next;
}
#
# footnotes
#
while (/\@footnote([^\{\s]+)\{/) {
$_ = $after;
$text = '';
$after = '';
$failed = 1;
while (@lines3) {
if (/\}/) {
$text .= $`;
$after = $';
$failed = 0;
last;
} else {
$text .= $_;
$_ = shift(@lines3);
}
}
if ($failed) {
die "* Bad syntax (\@footnote) after: $before\n";
} else {
$foot_num++;
$docid = "DOCF$foot_num";
$footid = "FOOT$foot_num";
$foot = "($foot_num)";
push(@foot_lines, "$text\n");
}
}
#
# remove unnecessary <P>
#
if (/^\s*<P>\s*$/) {
next if $end_of_para++;
} else {
$end_of_para = 0;
}
# otherwise
push(@doc_lines, $_);
}
print "# end of pass 4\n" if $verbose;
#+++############################################################################
# #
# Pass 5: print things #
# #
#---############################################################################
$_ = &substitute_style($full_title);
s/\n$//; # rmv last \n (if any)
#
# print ToC
#
if (!$monolithic && @toc_lines) {
if (open(FILE, "> $docu_toc")) {
print "# creating $docu_toc...\n" if $verbose;
&print_toplevel_header("$title - Table of Contents");
close(FILE);
} else {
warn "$ERROR Can't write to $docu_toc: $!\n";
}
}
#
# print footnotes
#
if (!$monolithic && @foot_lines) {
if (open(FILE, "> $docu_foot")) {
print "# creating $docu_foot...\n" if $verbose;
&print_toplevel_header("$title - Footnotes");
close(FILE);
} else {
warn "$ERROR Can't write to $docu_foot: $!\n";
}
}
#
# print document
#
$doc_num = 0;
while (@sections) {
&next_doc;
if (open(FILE, "> $docu_doc")) {
print "# creating $docu_doc...\n" if $verbose;
&print_header("$title - $section");
$navigation = "Go to the ";
$navigation .= ", ";
$navigation .= ", ";
$navigation .= ", ";
print FILE $navigation;
# find corresponding lines
@tmp_lines = ();
while (@doc_lines) {
$_ = shift(@doc_lines);
last if ($_ eq $SPLITTAG);
push(@tmp_lines, $_);
}
print FILE $navigation;
close(FILE);
} else {
warn "$ERROR Can't write to $docu_doc: $!\n";
}
}
} else { # not split
if (open(FILE, "> $docu_doc")) {
print "# creating $docu_doc...\n" if $verbose;
if ($monolithic || !@toc_lines) {
} else {
&print_header($title);
print FILE $full_title;
}
if ($monolithic && @toc_lines) {
print FILE "<H1>Table of Contents</H1>\n";
}
if ($monolithic && @foot_lines) {
print FILE "<H1>Footnotes</H1>\n";
}
if ($monolithic || !@toc_lines) {
} else {
}
close(FILE);
} else {
warn "$ERROR Can't write to $docu_doc: $!\n";
}
}
print "# that's all folks\n" if $verbose;
#+++############################################################################
# #
# Low level functions #
# #
#---############################################################################
sub update_sec_num {
my $ret;
$level--; # here we start at 0
# appendix style
if (defined(@appendix_sec_num)) {
} else {
}
} else {
# normal style
if (defined(@normal_sec_num)) {
} else {
}
}
return $ret;
}
sub incr_sec_num {
local($level, $l);
$level = shift(@_);
$_[$level]++;
$_[$l] = 0;
}
}
sub check {
while (<>) {
if (/\@(\*|\.|\:|\@|\{|\})/) {
$seen{$&}++;
$_ = "$`XX$'";
redo;
}
if (/\@(\w+)/) {
$seen{'e-mail address'}++;
} else {
}
$match =~ s/^\@/X/;
$_ = "$before$match$after";
redo;
}
}
foreach (sort(keys(%seen))) {
if ($verbose) {
print "$_\n";
print $context{$_};
} else {
print "$_ ($seen{$_})\n";
}
}
}
sub open {
local($name) = @_;
++$fh_name;
} else {
warn "$ERROR Can't read file $name: $!\n";
}
}
sub init_input {
@fhs = (); # hold the file handles to read
@input_spool = (); # spooled lines to read
$fh_name = 'FH000';
}
sub next_line {
if (@input_spool) {
$line = shift(@input_spool);
return($line);
}
while (@fhs) {
close($fh);
shift(@fhs);
}
return(undef);
}
# used in pass 1, use &next_line
sub skip_until {
local($tag) = @_;
local($_);
while ($_ = &next_line) {
}
}
#
# HTML stacking to have a better HTML output
#
sub html_reset {
@html_stack = ('html');
$html_element = 'body';
}
sub html_push {
local($what) = @_;
push(@html_stack, $html_element);
$html_element = $what;
}
sub html_push_if {
local($what) = @_;
push(@html_stack, $html_element)
$html_element = $what;
}
sub html_pop {
$html_element = pop(@html_stack);
}
sub html_pop_if {
local($elt);
if (@_) {
foreach $elt (@_) {
if ($elt eq $html_element) {
last;
}
}
} else {
}
}
sub html_debug {
return("<!-- $line @html_stack, $html_element -->$what")
if $debug & $DEBUG_HTML;
return($what);
}
# to debug the output...
sub debug {
return("<!-- $line -->$what")
if $debug & $DEBUG_HTML;
return($what);
}
sub normalise_node {
$_[0] =~ s/\s+/ /g;
$_[0] =~ s/ $//;
$_[0] =~ s/^ //;
}
sub menu_entry {
local($href);
&normalise_node($node);
if ($href) {
$descr =~ s/^\s+//;
} else {
warn "$ERROR Undefined node ($node): $_";
}
}
sub do_email {
}
sub do_uref {
}
sub apply_style {
local($texi_style, $text) = @_;
local($style);
if (defined($style)) { # known style
if ($style =~ /^\"/) { # add quotes
$style = $';
$text = "\`$text\'";
}
if ($style =~ /^\&/) { # custom
$style = $';
} elsif ($style) { # good style
$text = "<$style>$text</$style>";
} else { # no style
}
} else { # unknown style
$text = undef;
}
return($text);
}
# remove Texinfo styles
sub remove_style {
local($_) = @_;
s/\@\w+{([^\{\}]+)}/$1/g;
return($_);
}
sub substitute_style {
local($_) = @_;
$changed = 1;
while ($changed) {
$changed = 0;
$done = '';
while (/\@(\w+){([^\{\}]+)}/) {
if ($text) {
$_ = "$`$text$'";
$changed = 1;
} else {
$done .= "$`\@$1";
$_ = "{$2}$'";
}
}
$_ = $done . $_;
}
return($_);
}
sub anchor {
local($result);
$result = "<A";
$result .= ">$text</A>";
return($result);
}
sub pretty_date {
'July', 'August', 'September', 'October', 'November', 'December');
return("$mday $MoY[$mon] $year");
}
sub doc_name {
local($num) = @_;
return("${docu_name}_$num.html");
}
sub next_doc {
}
sub print {
local($_);
while (@lines) {
$_ = shift(@lines);
if (/^$PROTECTTAG/o) {
$_ = $tag2pro{$_};
} else {
}
print $fh $_;
}
}
sub print_ruler {
print FILE "<P><HR><P>\n";
}
sub print_header {
local($_);
# clean the title
$_ = &remove_style($_[0]);
# print the header
if ($doctype eq 'html2') {
print FILE $html2_doctype;
} elsif ($doctype) {
}
<HTML>
<HEAD>
</HEAD>
<BODY>
}
sub print_toplevel_header {
local($_);
&print_header; # pass given arg...
print FILE $full_title;
if ($value{'_subtitle'}) {
$value{'_subtitle'} =~ s/\n+$//;
foreach (split(/\n/, $value{'_subtitle'})) {
$_ = &substitute_style($_);
print FILE "<H2>$_</H2>\n";
}
}
if ($value{'_author'}) {
$value{'_author'} =~ s/\n+$//;
foreach (split(/\n/, $value{'_author'})) {
$_ = &substitute_style($_);
s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
print FILE "<ADDRESS>$_</ADDRESS>\n";
}
}
print FILE "<P>\n";
}
sub print_footer {
</BODY>
</HTML>
}
sub print_toplevel_footer {
<A HREF=\"$HOMEPAGE\">texi2html</A> $value{texi2html}.
}
sub protect_texi {
# protect @ { } ` '
s/\@\@/$;0/go;
s/\@\{/$;1/go;
s/\@\}/$;2/go;
s/\@\`/$;3/go;
s/\@\'/$;4/go;
}
sub protect_html {
local($what) = @_;
# protect & < >
$what =~ s/\&/\&\#38;/g;
$what =~ s/\</\&\#60;/g;
$what =~ s/\>/\&\#62;/g;
# but recognize some HTML things
$what =~ s/\&\#60;\/A\&\#62;/<\/A>/g; # </A>
$what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g; # <A [^&]+>
$what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
return($what);
}
sub unprotect_texi {
s/$;0/\@/go;
s/$;1/\{/go;
s/$;2/\}/go;
s/$;3/\`/go;
s/$;4/\'/go;
}
sub unprotect_html {
local($what) = @_;
$what =~ s/\&\#38;/\&/g;
$what =~ s/\&\#60;/\</g;
$what =~ s/\&\#62;/\>/g;
return($what);
}
sub byalpha {
}
##############################################################################
# These next few lines are legal in both Perl and nroff.
.00 ; # finish .ig
'di \" finish diversion--previous line must be blank
.AT 3
.PP
.I Texi2html
footnotes...
.PP
.B \-glossary
option).
.PP
.I Texi2html
.PP
.I texi2html
.I texi2html
.TP 12
.B \-check
.I texi2html
.TP
.B \-expandinfo
.TP
.B \-glossary
.TP
.TP
.TP
.B \-menu
.TP
.B \-monolithic
.TP
.B \-number
.TP
.B \-split_chapter
.TP
.B \-split_node
.TP
.B \-usage
.TP
.B \-verbose
.B \-check
.PP
.I texi2html
.TP 16
.TP
.TP
.PP
.B \-split
file.
.PP
.B \-monolithic
.I texi2html
.I texi2html
.TP 16
.B @ifhtml
.TP
.PP
.br
code.
.PP
.SH "SEE ALSO"
.PP
.ex