#!/usr/bin/perl $URL = "http://anonimo.isr.ist.utl.pt:8080/~etienne/octave"; ###################################################################### # # This file is a slight modification of Jeffrey C. Kantor's # "mat2html". Basically, the difference lies in recognizing '#' as a # comment character. # # I may have broken a few things, but I don't think so. There are a # few glitches. # # The original code was very well documented and easy to modify. Thank # you Jeffrey. # # 2000/03/10 # # Etienne Grossmann # ###################################################################### # READ THE HELP SECTION BELOW FOR INFORMATION ON HOW TO USE THIS SCRIPT. # # To install, simply save this function at oct2html, and make it # executible with # # chmod +x oct2html # # This requires a perl interpreter and access to the standard perl # library. Do not contact me about installing perl, I will ignore # you. Instead, please check out the following standard sites: # # ftp.uu.net gnu/perl* # jpl-decvax.jpl.nasa.gov pub/perl* # archive.cis.ohio-state.edu perl/ # # # Version 1.0 : 12 Jan 1995: Major workover to allow index of # multiple matlab directories. # 10 Jan 1995: Added cross-links to the help text # 9 Jan 1995: Looks for a Readme.m file to put # to put in the directory index. # 9 Jan 1995: Fixed html cross-links # # First posted to comp.soft-sys.matlab on January 9, 1995 # Jeffrey C. Kantor # kantor.1@nd.edu # Copyright (c) Jeffrey C. Kantor 1995. # All rights reserved # # Please feel free to use this script under the conditions of the # standard GNU public license. ###################################################################### # # Subroutines # ###################################################################### # From the standard Perl Library require 'getopts.pl'; require 'ctime.pl'; $CR = '[#%]' ; # Comment Regex # Translate special html characters sub htmlchar { s/&/&/g; s/\/>/g; s/\"/"/g; #" } sub tagline { print HFILE "Produced by oct2html on $date
\n", "Cross-Directory links are: "; if ($opt_g) {print HFILE "ON
\n"} else {print HFILE "OFF
\n"}; } # Assume MFILE and HFILE are open, $headline contains a section # title, and @zref contains cross-reference names # Don't print empty help. sub writehelpblock { do {$_ = } until /^\s*$CR/ || eof; my $help ; if (!eof) { while ((/^\s*$CR/ || /^\s*$/) && !eof) { s/^\s*$CR+//; &htmlchar; foreach $z (@zref) { next if m|\]*\b$z\b[^\>]*\|i; $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html"; s{\b($z)\b(?![\w\.\/]+html)}{$1}ig ; } $help .= $_ ; $_ = ; } # Remove copyright, author and licence info from help string $help = no_nothing($help) ; print HFILE "

$headline

\n
\n$help\n
\n" if $help =~ /\S/ ; } } # Padd $s with $p so that length of $s.$p is a multiple of 15. sub padding { my $s = shift ; my $j = int(length($s)/15)+1 ; my $p = " " x ($j*15 - length($s)) ; return ($j,$p) ; } # Remove copyright, author and licence info sub no_nothing { $_ = shift ; my @remove = ("copyright", "author", "This program is free software.", "This file is part", "This program is free software", "you can redistribute it", "under the terms of the ", "GNU General Public License", "Free Software", "License", "any later version", "This program is distributed", "in the hope that it will be useful", "WITHOUT ANY WARRANTY", "without even the implied warranty", "MERCHANTABILITY", "FITNESS FOR A PARTICULAR PURPOSE", "You should have received", "along with this program", "59 Temple Place", "Suite 330, Boston", "MA 02111-1307, USA"); foreach $r (@remove){ s/^.*$r.*$//img } s/(\n\s*)+\n/\n\n/sg ; return $_ ; } ###################################################################### # # Command line processing # ###################################################################### # Get the current date string $date = &ctime(time); # Read the command line arguments &Getopts('ghipqH:M:'); warn("WARNING: Options -M and -p are incompatible.\n") if ($opt_M && $opt_p); if (($opt_h) || ($opt_M && $opt_p)) { print <) { chomp; @files = split; @xfiles = (@xfiles,@files); } } elsif ($opt_p) { # Get the octave path print "Running octave to get the octave path.\n" if $verbose; $_ = `echo 'printf("LOADPATH=%s\\n",LOADPATH);' |octave|grep LOADPATH` or die "Can't run octave to get the path" ; s/LOADPATH=//; push @xfiles, grep {/\S/} split ":",$_ ; print "xfiles is :\n--",join("\n--",@xfiles),"\n" if $verbose ; } elsif ($opt_M) { # We need to find the octave directories to search print "Setting octave directory to $opt_M\n" if $verbose; if (-d $opt_M) { @xfiles = ($opt_M); } else { die("Specified -M $opt_M is not a directory\n"); } } else { print "Setting octave directory to the current directory.\n" if $verbose; @xfiles = ("."); } # Now process the list of @xfiles to get a list of .m files @mfiles print "Finding .m files in the search path.\n" if $verbose; undef(@mfiles); foreach (@xfiles) { # chop off any trailing separators, sometimes added by ls s/\/$//; # Add to mfiles if it exists and text file with a .m suffix if ((/\.m$/) && (-e) && (-T)) { push(@mfiles,$_); next; } # If it's a directory, then read it if (-d) { opendir(MDIR,$_) || die("Cannot open directory $_\n"); @files = grep(/\.m$/,readdir(MDIR)); foreach $file (@files) { push(@mfiles,"$_/$file"); } } } $n = $#mfiles + 1; print "Found $n .m files.\n" if $verbose; undef($n); undef(@xfiles); undef($mroot); ###################################################################### # # Parse the octave file names # ###################################################################### # Now we need to parse the mfile names to obtain for each file # $name{$file} - a octave identifier used to search the texts # $mdir{$file} - the directory in which the file is found # $mfile{$name} - look up the first mfile associated with a $name # @mdirs - sorted directory names # @names - sorted filenames print "Parsing the octave file names.\n" if $verbose; undef(%mdir); foreach (@mfiles) { # Regexp for dir and file ($mdir{$_},$name{$_}) = m|(.*?)/?([^/]*)$| ; $name{$_} =~ s/\.m$//; $mdir{$_} = "." unless exists $mdir{$_} ; $mfile{$name{$_}} = $_ unless exists $mfile{$name{$_}} ; $tmp1{$mdir{$_}} = 1 ; $tmp2{$name{$_}} = 1 ; # printf("222 : %-30s -> %-20s, %-10s\n",$_,$mdir{$_},$name{$_}) ; } @mdirs = sort keys %tmp1 ; @names = sort keys %tmp2 ; while (($n,$f)=each(%mfile)){ print "Func $n -> $f\n"; } $n = $#mdirs + 1; print "Found $n unique octave directories in the search path.\n" if $verbose; undef($n); ###################################################################### # # Read the m-files, and compute cross-reference information # ###################################################################### # Read each file and tabulate the distinct alphanumeric identifiers in # an array of symbols. This is used to compute cross references within # a octave directory. Also scan for: # # synposis - The function declaration line # lookfor - The first line of the help text # mtype - File type, either "function" or "script" # ref - Array of code cross references # # Dependency matrix value $ref{$x,$y} is 1 if $x refers to $y in the # code section. $ref{$x,$y} is 2 if $x refers to $y in the comment # lines. print "Read and compute cross-references among the octave files.\n" if $verbose; foreach $file (@mfiles) { open(MFILE,"<$file") || die("Cannot open $file\n"); print "Reading $file\n" if $verbose; while( ! eof(MFILE) ) { my ($statement,$comment,$all) = ("","",""); # Extract a full statement : read many # lines if needed. Statement and # comments are separated. while( ! eof(MFILE) && # A little leaning toothpick syndrome? ( $_ = ) =~ /(.*)(\.\.\.|\\)\s*($CR+(.*))?$/ ) { $all .= $_ ; $statement .= $1 ; $comment .= $4 if defined $4; } /(.*?)\s*($CR+(.*))$/ ; $statement .= $1 ; $comment .= $3 if defined $3; $comment =~ s/^\s*//; # $comment = no_nothing( $comment ) ; $_ = $all . $_ ; # If it's the function declaration line, then store it and skip if (/^\s*function/) { s/^\s*function\s*//; $synopsis{$file} = $_; $mtype{$file} = "function"; # print "synopsis of '$file' is $_\n" ; next; } # Compress multiple [%#]'s to a single [%#] s/$CR+/#/g; # Process comment lines and code lines separately if (/^\s*$CR/) { # cut out comment marker and surrounding white space s/^\s*$CR\s*//; # Store first comment line in lookfor if (!$lookfor{$file}) { # $lookfor{$file} = $_; $lookfor{$file} = $comment; } # Split on nonalphanumerics, canonicalize to lower case tr/A-Z/a-z/; @words = grep(/[a-z]\w*/,split('\W',$_)); grep($hsymbols{$_}++,@words) } else { # Split off and ignore trailing comments # That has been done previously # ($statement,$comment) = split(/$CR/,$_,2); # Split on nonalphanumerics, preserve case @words = grep(/[a-zA-Z]\w*/,split('\W',$statement)); grep($csymbols{$_}++,@words) } } close MFILE; # Now mark each name that appears in the list of symbols $dir = $mdir{$file}; if ($opt_g) { foreach (grep($csymbols{$_},@names)) { $ref{$file,$mfile{$_}} = 1; } foreach (grep($hsymbols{$_},@names)) { $ref{$file,$mfile{$_}} = 2; } } else { foreach (grep($csymbols{$_},@names)) { $f = $mfile{$_}; next if ($mdir{$f} ne $dir); $ref{$file,$f} = 1; } foreach (grep($hsymbols{$_},@names)) { $f = $mfile{$_}; next if ($mdir{$f} ne $dir); $ref{$file,$f} = 2; } } undef(%csymbols); undef(%hsymbols); } ###################################################################### # # Setup the html directories # ###################################################################### # Create an html subdirectory name for every unique octave directory in the # list @mdirs. The name is constructed using the tail of the directory # prefaced by a unique number. # # $hdir{$mdir} - html subdirectory for octave directory $mdir $x = 1; foreach (@mdirs) { @z = reverse(split("/",$_)); $hdir{$_} = "$x.".@z[0]; $x++; } # for each .m file, name a corresponding .html file foreach (@mfiles) { $hfile{$file} = $name{$_}.".html"; } # Now test a build the corresponding html directories. print "Checking HTML directories.\n" if $verbose; if (!-e $hroot) { mkdir($hroot,umask) || die("Cannot create directory $hroot\n"); chmod 0755, $hroot; } opendir(HDIR,$hroot) || die ("Cannot open directory $hroot\n"); closedir(HDIR); die("HTML directory $hroot is not writable\n") if !-w $hroot; print "HTML Directory $hroot is OK\n" if $verbose; foreach (@mdirs) { local($x) = $hroot."/".$hdir{$_}; if (!-e $x) { mkdir($x,umask) || die("Cannot create directory $x\n"); chmod(0755,$x); } opendir(HDIR,$x) || die ("Cannot open directory $x\n"); closedir(HDIR); die("HTML directory $x is not writable\n") if !-w $x; print "HTML Directory $x is OK\n" if $verbose; } ###################################################################### # # Write the master index file # ###################################################################### $indexfile = "$hroot/index.html"; print "Writing master $indexfile\n" if $verbose; open(HFILE,">$indexfile") || die("Cannot open index file $indexfile\n"); print HFILE "Octave Index\n", "\n", "

Octave Index

\n"; &tagline; # Print a short introduction # Print directory listing print HFILE "

Octave Directory Indices

\n
\n",
  "
    \n"; foreach $dir (@mdirs) { print HFILE "
  • $dir
  • \n"; } print HFILE "
\n"; # Include links to every file that was found print HFILE "

Identifiers found in these directories

\n"; # We'll do this five across in alphabetical order $i = 0; foreach (@names) { my ($j,$b) = padding($_) ; $html = "$hdir{$mdir{$mfile{$_}}}/$_.html"; print HFILE "$_$b"; print HFILE "\n" if int($i/5) < int(($i+$j)/5) ; $i+=$j; } print HFILE "
\n"; close(HFILE); ###################################################################### # # Write an index for each html subdirectory # ###################################################################### @readme = grep(/readme/i,@mfiles); foreach $dir (@mdirs) { $indexfile = "$hroot/$hdir{$dir}/index.html"; print "Writing an index file $indexfile\n" if $verbose; open(HFILE,">$indexfile") || die("Cannot open index file $indexfile\n"); print HFILE "Index for Directory $dir\n", "\n", "[Return to Master Index]\n", "

Index for $dir

\n"; &tagline; # Now look for a Readme.m file, seemingly a "Matlab" standard. If # there is one, then the help portion is included in the index file. foreach $file (@readme) { next if !($mdir{$file} eq $dir); open(MFILE,$file) || die("Cannot open the file $file"); # Help Cross Reference information undef(@zref); foreach $_ (@mfiles) { push(@zref,$name{$_}) if $ref{$file,$_} == 2; } # Look for the octave help text block $headline = "Readme"; &writehelpblock; } # Now write the index catalog for the .m files in this directory print HFILE "

Octave files in this Directory

\n
\n";
  foreach $file (@mfiles) {
    next if $dir ne $mdir{$file};
    my $b = padding($name{$file}) ;
    $html = $name{$file}.".html";
    print HFILE "$name{$file}$b$lookfor{$file}\n";
  }
  print HFILE "
\n"; print HFILE "
\n"; close(HFILE); } ###################################################################### # # Write an html file for every m-file # ###################################################################### # Now write the html file for each octave file. Need to reread each octave # file to find the help text. Note that we can't do this in a single loop # because we want the back reference information, and also some people # put the help text before the function declarations. # Need a list of mfiles with unique identifiers @umfiles = values(%mfile); foreach $file (@mfiles) { $h = "$hroot/$hdir{$mdir{$file}}/$name{$file}.html"; print "Writing for mfile $h\n" if $verbose; # Cross Reference information # Find list of names. undef(@xref); undef(@yref); undef(@zref); foreach (@umfiles) { next if ($name{$_} eq $name{$file}); push(@xref,$name{$_}) if $ref{$file,$_} == 1; # files we call push(@yref,$name{$_}) if $ref{$_,$file} == 1; # files that call us push(@zref,$name{$_}) if $ref{$file,$_} == 2; # files in the comment lines } open(MFILE,"<$file") || die("Cannot open $file"); open(HFILE,">$h") || die("Cannot open $h"); print HFILE "$hdir{$file}/$hfile{$file}\n", "\n", "[Index for $mdir{$file}]\n", "[Return to Master Index]\n", "

$name{$file}

\n", "

($mdir{$file}/$name{$file}.m)

\n"; # If this is a function, then write out the first line as a synposis if ($mtype{$file}) { print HFILE "

Function Synopsis

\n", "
$synopsis{$file}
\n"; } # Write the help block print "Writing the help block\n" if $verbose ; $headline = "Help text"; &writehelpblock; print HFILE "

Cross-Reference Information

" if (@xref || @yref); if (@xref) { print HFILE "This $mtype{$file} calls\n"; print HFILE "
    \n"; foreach $x (sort @xref) { $html = "../$hdir{$mdir{$mfile{$x}}}/$x.html"; my $b = padding($name{$file}) ; print HFILE "
  • $x".$b."$mfile{$x}
  • \n"; } print HFILE "
\n"; } if (@yref) { print HFILE "This $mtype{$file} is called by\n"; print HFILE "
    \n"; foreach $y (sort @yref) { $html = "../$hdir{$mdir{$mfile{$y}}}/$y.html"; $b = " " x (15 - length("$y")); print HFILE "
  • $y".$b."$mfile{$y}
  • \n"; } print HFILE "
\n"; } # Include source text if requested if ($opt_i) { print HFILE "

Listing of $mtype{$file} file $file

\n"; seek(MFILE,0,0); print HFILE "
\n";
    while () {
      &htmlchar;
      if (/^\s*$CR/) {
        foreach $z (@zref) {
	  next if m|\]*\b$z\b[^\>]*\|i;
	  $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
	  s{\b($z)\b(?![\w\.\/]+html)}{$1}ig ;
        }
      } else {
        foreach $x (@xref) {
	  next if m|\]*\b$z\b[^\>]*\|i;
	  $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
	  s{\b($z)\b(?![\w\.\/]+html)}{$1}ig ;
        }
      }
      print HFILE $_;
    }
    print HFILE "
\n"; } # Print a date stamp print HFILE "
\n"; &tagline; print HFILE ""; close(MFILE); close(HFILE); }