#!/usr/bin/perl
#
# Translate Emacs info files into HTML pages, one page per node.
# Menus, Notes, and Up/Next/Prev pointers are translated into links.
# Other text is left as-is in <PRE></PRE> tags.
#
# Option: -d <directory> specifies where to put the output files.
#
# This code is in the public domain.  No warranties, express or implied.
#
# Author: Kian-Tat Lim (ktl@wag.caltech.edu),  Dec 1993.
# Bugfixes by: Wolfram Schneider <wosch@FreeBSD.org>, Oct 1997.
#
# $Id: info2html,v 1.3 1997/10/09 11:47:38 wosch Exp wosch $


# parent directory
$up = '..';

# Canonicalize a node name by translating any characters that may give problems
# in an HREF into acceptable alternatives.
sub canon {
	local($_) = $_[0];
	s/\&/_and_/g;
	s|[<>/#? ]|_|g;
	s/"/'/g;
	return $_;
}

# Translate HTML special characters into escape sequences
sub html {
	local($_) = $_[0];
	s/\&/&amp;/g;
	s/\</&lt;/g;
	s/\>/&gt;/g;
	return $_;
}

# Translate escape sequences back to characters
sub dehtml {
	local($_) = $_[0];
	s/\&lt;/</g;
	s/\&gt;/>/g;
	s/\&amp;/\&/g;
	return $_;
}

#
# Main program
#

# Handle -d switch
require 'getopts.pl';
do Getopts('d:');

# Any header stuff in the info file goes to the bit bucket
open(OUT, ">/dev/null");

# Process lines
while (<>) {

# Do this after first <> access so input file can be in original directory
	chdir($opt_d), $done_d = 1 if !$done_d && defined($opt_d);

# If we had a *Note that wrapped, tack it onto the beginning of this line
	$_ = $leftover . $_;
	$leftover = '';

# Start a new node
	if (/^\037/) {

	# Finish off what we were last doing
		if ($menumode) {
			print OUT "</DL></BODY></HTML>\n";
			$menumode = 0;
		}
		else {
			print OUT "</PRE></BODY></HTML>\n";
		}

	# ^_^L signals the end of the useful stuff
		exit if /^\037\014/;

	# Get the node header line, done if none left
		$_ = <>;
		exit if eof;

	# ignore tag table
		exit if /^Tag Table:$/;


		($file, $node) = /^File:\s+(\S+)\s+Node:\s+([^,]+),/;
		chop($file) if $file =~ /,$/;
		$cnode = &canon($node);
		$hnode = &html($node);

	# Start a new file
		close OUT;
		open(OUT, ">$file.$cnode.html");
		print OUT "<HTML><HEAD><TITLE>$hnode</TITLE>\n";
		$body = "</HEAD><BODY>\n";

	# Split out Up, Next, Prev pointers so we can make them into links
		@items = split(/,/);
		shift(@items);
		for (@items) {
			if (/^\s*Up:\s+(.*)/) {
			    if ($1 eq "(dir)" || $1 eq "(DIR)") {
				$node = $up;
			    } else {
				$node = $file . "." . &canon($1) . ".html";
			    }
				print OUT
				"<LINK REV=\"Subdocument\" HREF=\"$node\">\n";
				$body .= "<B>Go up to " .
				"<A HREF=\"$node\">$1</A>.</B><BR>\n";
			}
			if (/^\s*Next:\s+(.*)/) {
				$node = $file . "." . &canon($1) . ".html";
				print OUT
				"<LINK REL=\"Precedes\" HREF=\"$node\">\n";
				$body .= "<B>Go forward to " .
				"<A HREF=\"$node\">$1</A>.</B><BR>\n";
			}
			if (/^\s*Prev:\s+(.*)/) {
			    if ($1 eq "(dir)" || $1 eq "(DIR)") {
				$node = $up;
			    } else {
				$node = $file . "." . &canon($1) . ".html";
			    }
				print OUT
				"<LINK REV=\"Precedes\" HREF=\"$node\">\n";
				$body .= "<B>Go backward to " .
				"<A HREF=\"$node\">$1</A>.</B><BR>\n";
			}
		} # for (@items)

	# Start the body of the node
		print OUT $body;

	# Leave the rest of the text as-is
		print OUT "<PRE>\n";
	} # elsif (/^\037/)

# Start a menu
	elsif (/^\* Menu:/) {
		print OUT "</PRE><H2>Menu</H2><DL COMPACT>\n";
		$menumode = 1;
	}

# Process a menu item by turning it into a link
	elsif ($menumode && /^\*\s+([^:]*)::\s*(.*)/) {
		$node = &canon($1);
		$hnode = &html($1);
		$text = &html($2);
		print OUT "<DT><A HREF=\"$file.$node.html\">$hnode</A>\n";
		print OUT "<DD>$text\n";
	}
# Alternate menu style ("tag: node text").  Tab, comma, period inside brackets.
	elsif ($menumode && /^\*\s+([^:]*):\s*([^	,.]+)(.*)/) {
		$node = &canon($2);
		$hnode = &html($2);
		$text = &html($3);
		$tag = &html($1);
		print OUT "<DT>";
		print OUT "<A HREF=\"$file.$node.html\">$tag: $hnode</A>\n";
	# Trim off termination character and space, if any
		$text =~ s/^[	,.]\s*//;
		print OUT "<DD>$text\n";
	}

# Process heading text inside menus -- continuation lines are just dumped below
	elsif ($menumode && /^\S/) {
		print OUT "<P>", &html($_);
	}

# Anything else.  Look for notes; otherwise, just dump after handling specials.
	else {

# If a *Note wrapped, save it to be prepended to the next line
		if (/(\*[Nn]ote)\s+$/) {
			$_ = $` . "\n";
			$leftover = $1 . " ";
		}

# Protect HTML special characters
		$_ = &html($_);

# Convert a note into a link
		while (/\*([Nn])ote\s+([^:]*)::/) {

		    # continue line
		    if ($' eq '') {
			$backup = <>; 
			$backup =~ s/^\s*//;
			chop($_); $_ .= " $backup";
			next;
		    }

			$node = &canon(&dehtml($2));
			$see = ($1 eq "N") ? "See" : "see";

		        # ignore links to other info files (emacs)info
			if (substr($2, 0, 1) eq '(') {
			    $_ = $` . $';
			    next;
			}
			$_ = $` . "$see <A HREF=\"$file.$node.html\">$2</A>" .
				$';
		}

# Alternate note style
		while (/\*([Nn])ote\s+([^:]*):\s*([^	,.]+)/) {

		    # continue line
		    if ($' eq '') {
			$backup = <>; 
			$backup =~ s/^\s*//;
			chop($_); $_ .= " $backup";
			next;
		    }
		    # ignore links to other info files (emacs)info
		    if (substr($3, 0, 1) eq '(') {
			$_ = $`;
			next;
		    }

		    $node = &canon(&dehtml($3));
			$see = ($1 eq "N") ? "See" : "see";
			$_ = $` .
			"$see <A HREF=\"$file.$node.html\">$2: $3</A>" .  $';

		}

		print OUT;
	}

} # while (<>)
