#!/usr/bin/perl $URL = "http://www.nd.edu/Courses/kantor/matlab/mat2html"; # READ THE HELP SECTION BELOW FOR INFORMATION ON HOW TO USE THIS SCRIPT. # # To install, simply save this function at mat2html, and make it # executible with # # chmod +x mat2html # # 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'; # Translate special html characters sub htmlchar { s/&/&/g; s/\/>/g; s/\"/"/g; } sub tagline { print HFILE "Produced by mat2html on $date
\n"; print HFILE "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 sub writehelpblock { do {$_ = } until /^\s*%/ || eof; if (!eof) { print HFILE "

$headline

\n"; print HFILE "
\n";
    while (/^\s*%/) {
      s/^\s*%//;
      &htmlchar;
      foreach $z (@zref) {
        next if //;
        $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
        s/(\W+)($z)(\W+)/\1\2<\/A>\3/ig;
      }
      print HFILE $_;
      $_ = ;
    }
    print HFILE "
\n"; } } ###################################################################### # # 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 incompatable.\n") if ($opt_M && $opt_p); if (($opt_h) || ($opt_M && $opt_p)) { print <) { chop; @files = split; @xfiles = (@xfiles,@files); } } elsif ($opt_p) { # Get the matlab path print "Running matlab -n to get the matlab path.\n" if $verbose; open(MATLAB,"matlab -n|") || die("Can't run matlab -n to get the path"); do {$_ = } until /MATLABPATH/ || eof; while () { last if /^----/; chop; s/\s*//g; push(@xfiles,$_); } close(MATLAB); } elsif ($opt_M) { # We need to find the matlab directories to search print "Setting matlab 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 matlab 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 exits 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 matlab file names # ###################################################################### # Now we need to parse the mfile names to obtain for each file # $name{$file} - a matlab identifier used to search the texts # $mdir{$file} - the directory in which the file is found print "Parsing the matlab file names.\n" if $verbose; undef(%mdir); foreach (@mfiles) { local($x) = $_; $x =~ s/\.m$//; split("/",$x); $name{$_} = pop(@_); $mdir{$_} = join('/',@_); $mdir{$_} = "." if $mdir{$_} eq ""; } # Compute a unique list of matlab identifier names, put in @names. grep($count{$_}++,values(%name)); @names = sort(keys(%count)); undef(%count); $n = $#names + 1; print "Found $n unique matlab identifiers.\n" if $verbose; undef($n); # Now we have a problem. Each matlab name may be associated with more # than one .m file. The order of @mfiles is the order they would be # encountered in a standard matlab search, so we preserve that order. # We compute: # # $mfile{$name} - look up the first mfile associated with a $name # # Confused yet? print "Linking each matlab identifier to a unique .m file.\n" if $verbose; foreach $n (@names) { foreach (@mfiles) { $file = $_; last if ($n eq $name{$_}); } $mfile{$n} = $file; } # Compute the set of unique matlab directory names, put in @mdirs grep($count{$_}++,values(%mdir)); @mdirs = sort(keys(%count)); undef(%count); $n = $#mdirs + 1; print "Found $n unique matlab 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 matlab 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 matlab files.\n" if $verbose; foreach $file (@mfiles) { open(MFILE,"<$file") || die("Cannot open $file\n"); print "Reading $file\n" if $verbose; while () { chop; # If it's the function declaration line, then store it and skip if (/^\s*function/) { s/^\s*function\s*//; $synopsis{$file} = $_; $mtype{$file} = "function"; next; } # Compress multiple %'s to a single % s/%+/%/g; # Process comment lines and code lines separately if (/^\s*%/) { # cut out comment marker and surrounding white space s/^\s*%\s*//; # Store first comment line in lookfor if (!$lookfor{$file}) { $lookfor{$file} = $_; } # 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 ($statement,$comment) = split('%',$_,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 matlab 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 matlab 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 "Matlab Index\n"; print HFILE "\n"; print HFILE "

Matlab Index

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

Matlab Directory Indices

\n
\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 = 1; foreach (@names) { $b = " " x (15 - length($_)); $html = "$hdir{$mdir{$mfile{$_}}}/$_.html"; print HFILE "$_$b"; print HFILE "\n" if (0 == $i%5); $i++; } 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"; print HFILE "\n"; print HFILE "[Return to Master Index]\n"; print HFILE "

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 matlab help text block $headline = "Readme"; &writehelpblock; } # Now write the index catalog for the .m files in this directory print HFILE "

Matlab files in this Directory

\n
\n";
  foreach $file (@mfiles) {
    next if $dir ne $mdir{$file};
    $b = " " x (15 - length($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 matlab file. Need to reread each matlab # 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 $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"; print HFILE "\n"; print HFILE "[Index for $mdir{$file}]\n"; print HFILE "[Return to Master Index]\n"; print HFILE "

$name{$file}

\n"; print HFILE "

($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"; print HFILE "
$synopsis{$file}
\n"; } # Write the help block $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"; $b = " " x (15 - length("$x")); 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} $mfile{$file}

\n"; seek(MFILE,0,0); print HFILE "
\n";
    while () {
      &htmlchar;
      if (/^\s*%/) {
        foreach $z (@zref) {
          next if //;
          $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
          s/(\W+)($z)(\W+)/$1$2<\/A>$3/gi;
        }
      } else {
        foreach $x (@xref) {
          next if //;
          $html = "../$hdir{$mdir{$mfile{$x}}}/$x.html";
          s/(\W+)($x)(\W+)/$1$2<\/A>$3/g;
          s/^(\s*)($x)(\W+)/$1$2<\/A>$3/g;
        }
      }
      print HFILE $_;
    }
    print HFILE "
\n"; } # Print a date stamp print HFILE "
\n"; &tagline; print HFILE ""; close(MFILE); close(HFILE); }