#!/usr/bin/perl # (change this to invoce your local perl5) ##### ABOUT for2html ##### # for2html: the FORTRAN77 to HTML translator # Home page http://for2html.sourceforge.net # Copyright Joachim Wuttke (jwuttke@ph.tum.de) 1999,2002 # Distributed under the Eiffel Forum License # Version 1 released on 29dec99 # Version 1.1 released on 4jan00 (bug fix: 1.0 ate trailing 0's) # Version 1.2 released on 26jan00 (line number in error report, TAB's) # Version 1.3 released on 22mar00 (INCLUDE .h; better handling of col's 2-6) # Version 1.3+ continuously amended $for2html = "\n for2html"; ##### SUBROUTINES ##### ### error messages ### : sub errc { # call error die "for2html aborted while parsing command line :\n@_[0]\n"; } sub errf { # file-access error die "for2html @_[0]\n"; } sub errs { # syntax error die "for2html failed in line $lino :\n@_[0]\n"; } ### analyse command-line parameters : sub com_lin_pars { $argvin = join ' ', @ARGV; @ARGLOOP = @ARGV; foreach (@ARGLOOP) { if ( s/^\-// ) { if ( m/^h/i ) { die "usage: for2html [-s[C][T]] [-d] [-t] [-u<URL>] <source_file[s]>;\n" ."call for2html -s or -d or ... to obtain information " ."on command-line options.\n"; } elsif ( s/^s// ) { if ( ! m/[CT]/ ) { errc "available style options are: -sC C-like comparisons"; } if ( m/C/ ) { $c_like_comps = 1; } if ( m/T/ ) { $allow_tabs = 1; } } elsif ( s/^t// ) { if ( $_ ) { $prjparam = $_; } else { errc "use -t<title> to enter a project title"; } } elsif ( s/^d// ) { if ( $_ ) { $prjparam = $_; } else { errc "use -d<directory> to specify the HTML output directory"; } } elsif ( s/^u// ) { if ( $_ ) { $urlparam = $_; } else { errc "use -u<URL> to provide a link to a project home page"; } } shift @ARGV; } # /-/ } # foreach @ARGLOOP if (@ARGV < 1) { errc "no input files given"; } } # sub com_lin_pars ### file handling : sub splitextension { # geht auch einfacher $File = @_[0]; $File =~ m/^(.*)\.(.*)/; return ($1, $2) } sub open_infile { ($inname,$inext) = splitextension $infile; if (length $inname<1) { errc "input file name \"$infile\" has no extension" } unless ($inext eq "f" || $inext eq "f77") { errc "input file is \"$infile\" but should have extension .f or .f77" } open (INFILE,$infile) || errf "could not open input file $infile"; $outfile = "$inname.html"; # put in open IN_file because needed BEFORE pass 3 $lastept = ""; # in case, ept is called from non-entry-region (include-file) $lino = 0; # line number, for error report } sub open_outfile { open (OUTFILE,">$dirname$outfile") || errf "could not open output module file $dirname$outfile"; } sub open_prjfile { if ($prjparam) { $prjname = $prjparam; } if ($dirparam) { $dirname = "$dirparam/"; } else { $dirname = "$prjname/" ; } if (opendir OUTDIR,$dirname) { chmod 0755, $dirname; } elsif (! mkdir $dirname, 0755) { errf "could not create HTML output directory $dirname"; } $prjfile = "PROJECT_OVERVIEW.html"; open (PRJFILE,">$dirname$prjfile") || errf "could not open output project file $dirname$prjfile"; } ### cross reference handling : sub new_ept { # learn new entry_point $ept=@_[0]; $fref{$ept} = $inname; } sub new_call { # learn new call $called=@_[0]; if ($lastept && $called ne $lastept && $lref{$called} ne $lastept) { $cref{$called} = "$cref{$called} <a href=\"#$lastept\">$LastEpt</a>"; $lref{$called} = $lastept; # do not learn two calls from the same ept } } ### convert fragments of FORTRAN code to HTML : sub printif { if ( $pass == 3 ) { print OUTFILE "@_[0]"; } } sub printeol { printif "<br>\n"; } sub printtriv { # print anything, just substitute blank_character by   $_=@_[0]; s/\ / /g; # preserve whitespace printif $_; } sub printchar { # print any character occuring in a normal Fortran statement $_=@_[0]; if ( m/(<|>)/ ) { print "\"$_\"\n"; errs "encountered $1 outside comment or string" } printtriv $_; } sub printnum { # print any character allowed in columns 2-5 $_=@_[0]; if ( m/!/ ) { errs "sorry: inline-comment starting in columns 2-5 cannot be handled by for2html" } if ( m/[^0-9\s]/ ) { print "\"$_\"\n"; errs "invalid character in columns 2-5" } printtriv $_; } sub printtext { # print quoted text (comment or string) $_=@_[0]; # substitute characters that have a special meaning in HTML s/&/&/g; # of course this substitution must be done first s/</</g; s/>/>/g; printchar $_; } sub parse_line { $lino = $lino + 1; # new_line already treated by splitting input into lines : s/\n//g; s/\r//g; # I do not like tab's in source code : if ( ! $allow_tabs && m/\t/ ) { errs "found TAB" } # full comment lines are handled once and for all : if ( m/^[Cc*!](.*)/ ) { printif "#<i>"; s/\t/ /g; printtext $1; printif "</i>"; printeol; return; } # TAB's in columns 1-6 always mean: next char is in column 7 : if ( $allow_tabs ) { if (! s/^\t/ / ) { if (! s/^(.{1})\t/$1 /) { if (! s/^(.{2})\t/$1 /) { if (! s/^(.{3})\t/$1 /) { if (! s/^(.{4})\t/$1 /) { if (! s/^(.{5})\t/$1 /) {}}}}}} s/\t/ /g; # in columns 7pp: TAB replaced by three blanks } # statement label in columns 1-5 $l = $_; $f = substr $l,0,5; printnum $f; # continuation indicator in column 6 $f = substr $l,5,1; printtriv $f; # corrected for bug reported by Liam.Healy@nrl.navy.mil # statement field (..72 or ..132: would need command-line switch) $_ = substr $l,6; while ( m/./ ) { if ( s/^\ // ) { # whitespace -> HTML escape printif " " } elsif ( m/^([A-Za-z]\w*)(.*)/ ) { # an identifier or a reserved word if ( m/^(PROGRAM|SUBROUTINE|FUNCTION|ENTRY|BLOCK\ *DATA)(\ *)(\w*)(.*)/i ) { # a block name -> save in hash table $Key = $1; $Key =~ tr /a-z/A-Z/; $LastEpt = $3; # original spelling $lastept = $3; $lastept =~ tr/A-Z/a-z/; # canonical minuscels if ( $pass == 1 ) { new_ept $lastept; if ( ! $prjparam && $Key eq "PROGRAM" ) { # take project name from PROGRAM statement if ( ! $prjname ) { $prjname = $3; } else { errs "There are several PROGRAM statements - " ."use the -t parameter to set the project title"; } } } elsif ( $pass == 3 ) { # write entry-point to project-overview : print PRJFILE "<li><b><a name=\"$lastept\" " ."href=\"$outfile#$lastept\">$1$2$3</a></b><br>\n"; # write back-references to project-overview : if ( $Key eq "PROGRAM" ) { print PRJFILE "<i>main entry</i>\n"; } else { if ( $ctxt = $cref{$lastept} ) { print PRJFILE "<i>called by </i>$ctxt\n"; } else { print PRJFILE "<i>never called</i>\n"; } } } # write out: underline and provide entry point printif "<a name=\"$lastept\" href=\"$prjfile#$lastept\">"; printchar "$1$2"; printif "$3</a>"; $_ = $4; } elsif ( m/^(INCLUDE)(\ *)'(.*)'(.*)/i ) { # including a definition file -> provide link printchar "$1$2"; ($fnam,$fext) = splitextension $3; unless ($fext eq "f" || $fext eq "f77" || $fext eq "h") { warn "unexpected file name extension in included file $3\n" } printif "\'<a href=\"$fnam.html\">$3</a>\'"; $_ = $4; } else { # a known identifier ? -> provide link to where it was defined $key = $1; $key =~ tr/A-Z/a-z/; if ($fnam=$fref{$key}) { # Zuweisung, kein Test auf Gleichheit ! printif "<a href=\"$fnam.html#$key\">$1</a>"; if ( $pass == 2 ) { new_call $key; } } else { printif $1; } $_ = $2; } } elsif ( s/^!// ) { # comment from here to end-of-line printif "!<i>"; printtext $_; printif "</i>"; $_ = ""; } elsif ( s/^\'// ) { # a string unless ( m/^(.*?)'(.*)/ ) { errs "unmatched apostrophe in \`$2\'" } printif "'<i>"; printtext $1; printif "</i>'"; $_ = $2; } elsif ( m/^\.(.*)/ && $c_like_comps ) { # nice symbols for comparison operators (C-like) if ( s/^\.eq\.//i ) { printif "==" } elsif ( s/^\.ne\.//i ) { printif "!=" } elsif ( s/^\.gt\.//i ) { printif ">" } elsif ( s/^\.lt\.//i ) { printif "<" } elsif ( s/^\.ge\.//i ) { printif ">=" } elsif ( s/^\.le\.//i ) { printif "<=" } elsif ( s/^\.or\.//i ) { printif "||" } elsif ( s/^\.and\.//i ) { printif "&&" } elsif ( s/^\.not\.//i ) { printif "! " } else { s/\.//; printif "." } } elsif ( m/^(<|>|&)/ ) { # at this place, special characters should never occur print "$_\n"; errs "found $1 outside string or comment"; } else { # any other character : print out literally m /^(.)(.*)/; printif $1; $_ = $2; } } printeol; "<br>\n"; } ### write HTML trivia : sub print_HTML_header { @fstat = stat INFILE; $mdate = nicetime ($fstat[9]); printif "<html><head><title>$infile
\n"; printif "

$prjname / $infile

\n"; printif "Fortran project $prjname, source module $infile.

\n"; printif "Source module last modified on $mdate;
\n"; $thistime = nicetime(time); printif "HTML image of Fortran source automatically generated by $for2html on $thistime.\n"; printif "


\n"; } sub print_HTML_epilogue { printif "


\n"; } sub print_HTML_head_prj { print PRJFILE "$prjname

\n"; print PRJFILE "

$prjname

\n"; if ($urlparam) { print PRJFILE "Up: project home page.

\n"; } $thistime = nicetime(time); print PRJFILE "Fortran project overview automatically generated" ." by $for2html on $thistime,
\n"; print PRJFILE "called as for2html $argvin.
\n"; print PRJFILE "


\n"; } sub print_HTML_epi_prj { print PRJFILE "


\n"; } ### PERL trivia : sub nicetime { ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime (@_[0]); $wdname = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$wday]; $moname = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$mon]; $year = 1900 + $year; return "$wdname, $mday $moname $year, ".(sprintf "%2u",$hour) .":".(sprintf "%02u",$min); } ##### MAIN PROGRAM ##### com_lin_pars; print "first pass\n"; # learn entry points $pass = 1; foreach $infile (@ARGV) { print "$infile\n"; open_infile; while () { parse_line } close INFILE; } if (! ( $prjname || $prjparam )) { die "for2html found no PROGRAM statement - " ."use -t to set the project title\n"; } print "second pass\n"; # learn calls to entry points $pass = 2; foreach $infile (@ARGV) { print "$infile\n"; open_infile; while () { parse_line } close INFILE; } print "third pass\n"; # write out $pass = 3; open_prjfile; print_HTML_head_prj; foreach $infile (@ARGV) { print "$infile\n"; open_infile; open_outfile; print PRJFILE "

  • Source Module $infile
      \n"; print_HTML_header; while () { parse_line } print_HTML_epilogue; close INFILE; close OUTFILE; print PRJFILE "
    \n"; } print_HTML_epi_prj; close PRJFILE; ##### EOF #####