#!/usr/local/bin/perl
#makemenu.pl -- Makes simple menu for HTML files, based on each file's <title>,
#            and can make simple table of contents based on <h1>-<h6> headings.
#
#Typical use:
#
#  perl makemenu.pl [options] infiles.html > menu.html
#
#    Where command-line options have the form "option=value".  The possible
# options are title="...", toc=1, and dirprefix="..." and should appear on the
# command line _before_ the names of files to be processed.
#
#    The menu contains a list of <A HREF="file.html">....</A> elements: the
# content of each of these menu items is taken from that of the
# <TITLE>...</TITLE> element of the corresponding file.
#
#    The title="..." option specifies the title of the menu itself:
#
#  perl makemenu.pl title="Menu for HTML files" *.html > menu.html
#
#    To make a menu of all the files in one's personal hierarchy under Unix:
#
#  cd $HOME/public_html
#  perl makemenu.pl title="My Files" `find . -name \*.html -print` > menu.html
#
#    The toc=1 command-line option attempts to construct a table of contents
# for each file as part of the menu, based on the <H1>-<H6> headings in the
# file.  If there are links inside headings, then makemenu.pl will attempt to
# preserve the validity of <A HREF="..."> references, and transform an
# <A NAME="..."> into an <A HREF="..."> link to the heading from the menu file;
# however, makemenu.pl is limited by the fact that it does not examine each
# <A> tag in a heading individually, but only does global search-and-replace
# operations on the whole <Hn>...</Hn> element (for this reason, the values
# of <A HREF=> and <A NAME=> are only operated on if they are quoted).
#
#    A dirprefix="..."  option can also be specified on the command line; this
# specifies a string which is prefixed to filenames, and which can be used to
# convert local filesystem references (relative URL's) to absolute URL's.
# An example:
#
#  perl makemenu.pl dirprefix=http://myhost.edu/~myself/ *.html > menu.html
#
#    This program is rather simple-minded; if an HTML file does not have a
# <TITLE>...</TITLE> element, it will not appear in the menu.  If the closing
# </TITLE> tag is not present, it will try to stuff the whole remaining text of
# the file into the menu.  The closing `>' character of the <TITLE>, </TITLE>,
# <H1>-<H6> and </H1>-</H6> tags should not be on a different line from the
# rest of the tag.  Also, multiple headings should not be contained on a single
# line.  This is not an error-checking program, and illegal HTML input may
# result in incorrect HTML output.
#
# Copyright 1995 by H. Churchyard, churchh@uts.cc.utexas.edu -- freely
# redistributable.  This program is a port to perl of the original makemenu.awk
# (the port was fairly mechanical, so programming style and efficency may not
# be high).
#
#  Version 1.0 12/94?? -- Was for my personal use only.
#  Version 1.1 1/8/95 -- Made more general, added documentation comments,
# ported from awk to perl.
#  Version 1.2 1/12/95 -- Added heading-to-Table-of-Contents stuff.  Included
# in htmlchek 4.0 release.
#
eval "exec /usr/local/bin/perl -S $0 $*"
    if $running_under_some_shell; # this emulates #! processing on NIH machines.
$title = ''; $toc = 0; $dirprefix = '';
eval '$'.$1.'$2;' while $ARGV[0] =~ /^(title=|toc=|dirprefix=)(.*)/ && shift;
$[ = 1;                 # set array base to 1
$\ = "\n";              # set output record separator
foreach $X (@ARGV) {
    if ($X =~ /^[^=]+=/) {
        print STDERR "Apparent misspelled or badly-placed command-line option $&";
        print STDERR "Attempting to continue anyway...";}}
$accum = ''; $haccum = '';
$xRS = $/;
#
while (<>) {
    if ($_ =~ /$xRS$/o) {chop;} # strip record separator
    if (($.-$FNRbase) == 1) {
        if ($. == 1) {
            if (!$title) {
                $title = 'Menu for HTML files';}
            print "<html><head><title>$title</title></head>";
            print "<body><h1>$title</h1><hr><ul>";}
        else {
            if ($toc) {
                &liout();}}
        $hlevel = 0;}
    #
    if (/<[Tt][Ii][Tt][Ll][Ee][^<>]*>/ .. /<\/[Tt][Ii][Tt][Ll][Ee][^<>]*>/) {
        $line = $_;
        $line =~ s/^.*<[Tt][Ii][Tt][Ll][Ee][^<>]*>//;
        $X = ($line =~ s/<\/[Tt][Ii][Tt][Ll][Ee][^<>]*>.*$//);
        $accum = ($accum . ' ' . $line);
        if ($X) {
            if ($toc) {
                &liout();}
            $fn = $ARGV;
            $fn =~ s/^\.\///;
            $accum =~ s/^  *//; $accum =~ s/  *$//;
            print " <LI><A HREF=\042$dirprefix$fn\042>$accum</A> <tt>($fn)</tt>";
            $accum = '';}}
    #
    if ((/<[Hh][1-6][^<>]*>/ .. /<\/[Hh][1-6][^<>]*>/)&&($toc)) {
        if (((($_ =~ /<[Hh][1-6]/) eq 1) && ($RSTART = length($`)+1)) != 0) {
            $newhlevel = substr($_, ($RSTART + 2), 1);
            if ($newhlevel > $hlevel) {
                printf '%' . (($newhlevel * 2) + 1) . 's', '';
                for ($i = ($newhlevel - $hlevel); $i >= 1; --$i) {
                    printf '<UL>';}
                printf "\n";}
            else {
                if ($newhlevel < $hlevel) {
                    printf '%' . (($hlevel * 2) + 1) . 's', '';
                    for ($i = ($hlevel - $newhlevel); $i >= 1; --$i) {
                        printf '</UL>';}
                    printf "\n";}}
            $hlevel = $newhlevel;}
        $line = $_;
        $line =~ s/^.*<[Hh][1-6][^<>]*>//;
        $X = ($line =~ s/<\/[Hh][1-6][^<>]*>.*$//);
        $haccum = ($haccum . ' ' . $line);
        if ($X) {
            $fn = $ARGV;
            $fn =~ s/^\.\///;
            $haccum =~ s/^  *//;
            $haccum =~ s/  *$//;
            # The following code attempts to preserve the validity of HREF's,
            # and transform <A NAME>'s into HREF's where possible, but it's kind
            # of lame because it doesn't examine each <A> tag individually.
            if ($haccum =~ /<[Aa]/) {
            $haccum =~ s/[ \t]*=[ \t]*\042/=\042/g;
            $z = ($haccum =~ s/[Hh][Rr][Ee][Ff]=\042#/HREF=\042$dirprefix$fn#/g);
            if ((!$z) && ($haccum !~
              /[Hh][Rr][Ee][Ff]=\042[^\042]*[:\057][^\042]*\042/)) {
                $haccum =~ s/[Hh][Rr][Ee][Ff]=\042/HREF=\042$dirprefix/g;}
            if (($haccum !~ /[Hh][Rr][Ee][Ff]=\042/) || (($haccum !~
              /<[Aa][^<>]*[Hh][Rr][Ee][Ff][ \t]*=[^<>]*[Nn][Aa][Mm][Ee][ \t]*=[^<>]*>/) &&
              ($haccum !~
              /<[Aa][^<>]*[Nn][Aa][Mm][Ee][ \t]*=[^<>]*[Hh][Rr][Ee][Ff][ \t]*=[^<>]*>/))) {
                $haccum =~ s/[Nn][Aa][Mm][Ee]=\042/HREF=\042$dirprefix$fn#/g;}}
            # </lame>
            printf '%' . (($hlevel * 2) + 1) . "s<LI>%s\n", '', $haccum;
            $haccum = '';}}}
continue {
    $FNRbase = $. if eof;}
#
#END
#
if ($. > 0) {
    if ($toc) {
        &liout();}
    print '</ul>';
    print '<!-- Replace this comment with your signature stuff -->';
    print '</body></html>';}
#
sub liout {
    if ($hlevel > 0) {
        printf '%' . (($hlevel * 2) + 1) . 's', '';
        for ($i = $hlevel; $i >= 1; --$i) {
            printf '</UL>';}
        printf "\n";}
    $hlevel = 0;}
##EOF
