#! /usr/local/bin/perl 

# Script to read a tag-enhanced book of plots
# Copyright 1996, 1998 by Alexander Forst
#                         alex@complang.tuwien.ac.at

# 
# This is my first Perl script. You are allowed to point out
# errors, make every change you like as long as you notify me
# and don't laugh.    :-)
#

# usage: plt2html.pl <book1> <book2> ...
# outputs a number of files: pl0.html, pl1.html,...

#
# these constants are useful for parsing in different modes
# the variable $parseMode must be set to one of these values

#open(IN,"plots1.tag") || die("not found");
#open(IN,"tag.txt") || die("not found");


$parsePreamble = "<(author|date|length|genre|type|setting|monster|plot)>";
$parseAuthor = "</?(author|email)>";
$parseEnd = "<title>";
$parseVillain = "<(stats|list|/villain)>";
$parsePlot = "<(stats|list|villain|/plot)>";

$htmlFooter = <<EOT;
<hr>
<ADDRESS class="plots">
[<A HREF="index.html">The Net Book of Plots Home Page</A>]
</ADDRESS>
EOT


&initParse;
$parseMode = "<title>";

$otherText = "";        # Placeholder for text before and after plots.
                        # This text is stored in the file contents.html

$count = 0;
&newPlot;

while( &nextToken ) {
    if( $token eq "<title>" ) {
	$otherText .= $text;         # save text before and between plots
	if( $plotTitle ) 
	{
	    &outPlot;
	    $count++;
	}
	&newPlot;
	&readTitle;
    }
    &readAuthor  if( $token eq "<author>" );
    &readDate    if( $token eq "<date>" );
    &readLength  if( $token eq "<length>" );
    &readGenre   if( $token eq "<genre>" );
    &readType    if( $token eq "<type>" );
    &readSetting if( $token eq "<setting>" );
    &readMonster if( $token eq "<monster>" );
    &readPlot    if( $token eq "<plot>" );
}

$text = $otherText . $text;
&parseText;
$otherText = $text;     # save text after all plots

&outPlot;


open( INDEX, ">contents.html" ) || die( "Cannot open contents.html" );
print INDEX "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
print INDEX "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
print INDEX "<html>\n<head>\n<title>Plot Book: Contents</title>\n";
print INDEX "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n";
print INDEX "<body>\n\n";

print INDEX <<EOT;
<P><strong>Note:</strong>
This page contains editor's notes and any additional text of the 
Net Books of Plots.
</P>

<h1>Contents</h1>
EOT

print INDEX $otherText;
print INDEX $htmlFooter;
print INDEX "</body></html>\n";
close( INDEX );

open( INDEX, ">length.html" ) || die( "Cannot open length.html" );
print INDEX "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
print INDEX "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
print INDEX "<html>\n<head>\n<title>Plots by length</title>\n";
print INDEX "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n";
print INDEX "<body>\n<h1>Plots by length</h1>\n";
foreach $key (sort(keys(%lengths))) {
    print INDEX "<h2>Plots of length \"<a name=\"$key\">$key</a>\"</h2>\n";
    print INDEX "<ul>\n";
    
    foreach $pl (unpack("s*",$lengths{$key})) {
	print INDEX "<li> <a href=\"pl$pl.html\">$titles{$pl}</a>\n";
    }
    print INDEX "</ul>\n\n";
}
print INDEX $htmlFooter;
print INDEX "</body></html>\n";
close( INDEX );

open( INDEX, ">genre.html" ) || die( "Cannot open genre.html" );
print INDEX "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
print INDEX "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
print INDEX "<html>\n<head>\n<title>Plots by genre</title>\n";
print INDEX "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n";
print INDEX "<body>\n<h1>Plots by genre</h1>\n";
foreach $key (sort(keys(%genres))) {
    print INDEX "<h2>Plots of genre \"<a name=\"$key\">$key</a>\"</h2>\n";
    print INDEX "<ul>\n";
    
    foreach $pl (unpack("s*",$genres{$key})) {
	print INDEX "<li> <a href=\"pl$pl.html\">$titles{$pl}</a>\n";
    }
    print INDEX "</ul>\n\n";
}
print INDEX $htmlFooter;
print INDEX "</body></html>\n";
close( INDEX );

open( INDEX, ">type.html" ) || die( "Cannot open type.html" );
print INDEX "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
print INDEX "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
print INDEX "<html>\n<head>\n<title>Plots by type</title>\n";
print INDEX "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n";
print INDEX "<body>\n<h1>Plots by type</h1>\n";
foreach $key (sort(keys(%types))) {
    print INDEX "<h2>Plots of type \"<a name=\"$key\">$key</a>\"</h2>\n";
    print INDEX "<ul>\n";
    
    foreach $pl (unpack("s*",$types{$key})) {
	print INDEX "<li> <a href=\"pl$pl.html\">$titles{$pl}</a>\n";
    }
    print INDEX "</ul>\n\n";
}
print INDEX $htmlFooter;
print INDEX "</body></html>\n";
close( INDEX );

open( INDEX, ">setting.html" ) || die( "Cannot open setting.html" );
print INDEX "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
print INDEX "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
print INDEX "<html>\n<head>\n<title>Plots by setting</title>\n";
print INDEX "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n";
print INDEX "<body>\n<h1>Plots by setting</h1>\n";
foreach $key (sort(keys(%settings))) {
    print INDEX "<h2>Plots of setting \"<a name=\"$key\">$key</a>\"</h2>\n";
    print INDEX "<ul>\n";
    
    foreach $pl (unpack("s*",$settings{$key})) {
	print INDEX "<li> <a href=\"pl$pl.html\">$titles{$pl}</a>\n";
    }
    print INDEX "</ul>\n\n";
}
print INDEX $htmlFooter;
print INDEX "</body></html>\n";
close( INDEX );

open( INDEX, ">monster.html" ) || die( "Cannot open monster.html" );
print INDEX "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
print INDEX "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
print INDEX "<html>\n<head>\n<title>Plots with special monster</title>\n";
print INDEX "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n";
print INDEX "<body>\n<h1>Plots with special monsters</h1>\n";
foreach $key (sort(keys(%monsters))) {
    print INDEX "<h2>Plots with monster \"<a name=\"$key\">$key</a>\"</h2>\n";
    print INDEX "<ul>\n";
    
    foreach $pl (unpack("s*",$monsters{$key})) {
	print INDEX "<li> <a href=\"pl$pl.html\">$titles{$pl}</a>\n";
    }
    print INDEX "</ul>\n\n";
}
print INDEX $htmlFooter;
print INDEX "</body></html>\n";
close( INDEX );


sub newPlot {
    $plotTitle = "";
    @plotAuthors = ();
    $plotDate = "";
    $plotLength = "";
    @plotGenres = ();
    @plotTypes = ();
    @plotSettings = ();
    @plotMonsters = ();
    $plotVillains = "";
    $plotPlot = "";
}

sub outPlot {
    $,  = ", ";
    
    open( OUT, ">pl$count.html" ) || die( "Cannot open pl$count.html" );

	print OUT "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n";
	print OUT "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
	
    print OUT "<html>\n<head>\n";
	print OUT "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n";
    print OUT "<title>Plot Book - $plotTitle</title>\n";
	print OUT "<LINK REL=\"Stylesheet\" TYPE=\"text/css\" HREF=\"plots.css\">\n"; 

    print OUT "</head>\n<body>\n";

    print OUT "<h1>$plotTitle</h1>\n";

	print OUT "<DIV class=\"author\">";
	
    print (OUT "<b>Author:</b> @plotAuthors <br>\n") if( @plotAuthors );

    print OUT "<b>Submission Date:</b> $plotDate<br>\n" if( $plotDate );
    print OUT "<b>Length:</b> $plotLength<br>\n";

    print OUT "<b>Genre:</b> ";
    print OUT @plotGenres;
    print OUT "<br>\n";

    print OUT "<b>Type:</b> ";
    print OUT @plotTypes;
    print OUT "<br>\n";

    print OUT "<b>Setting:</b> ";
    print OUT @plotSettings;
    print OUT "<br>\n";

    print (OUT "<b>Monster:</b> @plotMonsters <br>\n") if( @plotMonsters );

	print OUT "</DIV>\n";
	
    print OUT "\n<h2>The Plot</h2>\n<p>\n$plotPlot";

    print OUT "\n<h2>Villains</h2>\n<p>\n$plotVillains" if( $plotVillains );

    print OUT $htmlFooter;
    print OUT "\n</body>\n</html>\n";

    close( OUT );
}

sub readTitle {
    $parseMode = "</title>";
    &nextToken;
    $plotTitle = $text;
    $parseMode = $parsePreamble;
    
    $titles{ $count } = $plotTitle;
}

sub readAuthor {
    local($author);
    local($item,@list);

    $parseMode = $parseAuthor;
    do {
	&nextToken;
	$author .= " &lt;<code><a href=\"mailto:$text\">$text</a></code>&gt;" if( $token eq "</email>" );
	$author = $text if( $token eq "<email>" );
    } until( $token eq "</author>" );
    $author = $text unless( $author );
    push( @plotAuthors, $author );
    $parseMode = $parsePreamble;

    $item = $authors{ $author };
    @list = unpack( "s*", $item );
    push( @list, $count );
    $authors{ $author } = pack( "s*", @list );
}

sub readDate {
    $parseMode = "</date>";
    &nextToken;
    $plotDate = $text;
    $parseMode = $parsePreamble;
}

sub readLength {
    local($item,@list);

    $parseMode = "</length>";
    &nextToken;
    $plotLength = "<a href=\"length.html#$text\">$text</a>";
    $parseMode = $parsePreamble;

    $item = $lengths{ $text };
    @list = unpack( "s*", $item );
    push( @list, $count );
    $lengths{ $text } = pack( "s*", @list );
}

sub readGenre {
    local($item,@list);

    $parseMode = "</genre>";
    &nextToken;
    push( @plotGenres, "<a href=\"genre.html#$text\">$text</a>" );
    $parseMode = $parsePreamble;

    $item = $genres{ $text };
    @list = unpack( "s*", $item );
    push( @list, $count );
    $genres{ $text } = pack( "s*", @list );
}

sub readType {
    local($item,@list);

    $parseMode = "</type>";
    &nextToken;
    push( @plotTypes, "<a href=\"type.html#$text\">$text</a>" );
    $parseMode = $parsePreamble;

    $item = $types{ $text };
    @list = unpack( "s*", $item );
    push( @list, $count );
    $types{ $text } = pack( "s*", @list );
}

sub readSetting {
    local($item,@list);

    $parseMode = "</setting>";
    &nextToken;
    push( @plotSettings, "<a href=\"setting.html#$text\">$text</a>" );
    $parseMode = $parsePreamble;

    $item = $settings{ $text };
    @list = unpack( "s*", $item );
    push( @list, $count );
    $settings{ $text } = pack( "s*", @list );
}

sub readMonster {
    local($item,@list);

    $parseMode = "</monster>";
    &nextToken;
    push( @plotMonsters, "<a href=\"monster.html#$text\">$text</a>" );
    $parseMode = $parsePreamble;

    $item = $monsters{ $text };
    @list = unpack( "s*", $item );
    push( @list, $count );
    $monsters{ $text } = pack( "s*", @list );
}

sub readVillain {
    $parseMode = $parseVillain;
    do {
	&nextToken;
	if( $token eq "<stats>" ) {
	    &parseText;
	    $plotVillains .= $text . "\n<pre>";
	    $parseMode = "</stats>";
	    &nextToken;
	    $plotVillains .= $text . "</pre>\n";
	    $parseMode = $parseVillain;
	} elsif( $token eq "<list>" ) {
	    &parseText;
	    $plotVillains .= $text;
	    $plotVillains .= &parseList;
	    $parseMode = $parseVillain;
        }
    } until( $token eq "</villain>" );
    &parseText;
    $plotVillains .= $text;
}

sub readPlot 
{
    local($listIndent);

    $parseMode = $parsePlot;
    
    do 
    {
	&nextToken;
	if( $token eq "<stats>" ) 
	{
	    &parseText;
	    $plotPlot .= $text . "\n<pre>";
	    $parseMode = "</stats>";
	    &nextToken;
	    $plotPlot .= $text . "</pre>\n";
	    $parseMode = $parsePlot;
	} 
	elsif( $token eq "<list>" ) 
	{
	    &parseText;
	    $plotPlot .= $text;
	    $plotPlot .= &parseList;
	    $parseMode = $parsePlot;
        }
        elsif( $token eq "<villain>" )
	{
            &parseText;
            $plotPlot .= "$text<p>";
	    &readVillain;
	    $parseMode = $parsePlot;
	}
    } until( $token eq "</plot>" );
    &parseText;
    $plotPlot .= $text;
    $parseMode = $parseEnd;
}

sub parseList {                    # the token <list> has been already parsed
    local($listText,$listType,$end);

    $parseMode = "</?list>";
    $listText = "";
    $listType = "";
    $end = 0;
    do {
    	&nextToken;                    # searching for the next token
    	if( $token eq "<list>" ) 
    	{                              # there is another list
    	    if( $text =~ s/\n\s*[-+\*][):]?/\n<li>/g ) 
    		{
    		    &parseText;
    		    $listText .= $text;
    		    $listType = "ul";
    		} 
    	    else 
    		{
    		    $text =~ s/\n\s*([0-9]+[.):]?)/\n<li>/g;
    		    $text =~ s/\n\s*([a-zA-Z][.)])/\n<li>/g;
    		    &parseText;
    		    $listText .= $text;
    		    $listType = "ol";
    		}
    	    $listText .= &parseList;
    	}
    	else         # end of list reached
    	{
    	    if( $text =~ s/\n\s*[-+\*][):]?/\n<li>/g ) 
    		{
    		    &parseText;
    		    $listText .= $text;
    		    $listType = "ul";
    		} 
    	    else 
    		{
    		    $text =~ s/\n\s*([0-9]+[.):]?)/\n<li>/g;
    		    $text =~ s/\n\s*([a-zA-Z][.)])/\n<li>/g;
    		    &parseText;
    		    $listText .= $text;
    		    $listType = "ol";
    		}
         $end = 1;
    	 }
    } until( $end );

     "<$listType>$listText</$listType>";
}

sub parseText {
    $text =~ s/\n([:=\-]+\n+)+/\n<hr>\n/g;       # dividers
    $text =~ s/\n\s*\n/\n<p>\n/g;               # paragraphs
    $text =~ s/([_*+])(\w+)\1/<em>$2<\/em>/g;   # emphasis
}


# read the next token  --> $token
# the text before the token is stored
# in $text

sub nextToken {
    $text ="";                                # clear the text
    do {
	if( $parse ) {                        # we have a parse line
	    if( $parse =~ m/$parseMode/i ) {  # we found a token
		$text .= $`;                  # save the text before the token
		$token = $&;                  # this is the token
		$token =~ tr/A-Z/a-z/;        # change to lowercase
		$parse = $';                  # parse the rest of the line
		return 1;                     # success!
	    } else {
		$text .= $parse;              # save all text
		$parse = "";                  # nothing left to parse
	    } 
	}
    } while( $parse = <> );                   # read next line
    return 0;                                 # it was the last line
}


sub initParse {
    $parse = "";
    %titles = ();
    %authors = ();
    %lengths = ();
    %genres = ();
    %types = ();
    %settings = ();
    %monsters = ();
}    
