#!/usr/local/bin/perl $URL = "http://www.nd.edu/Courses/kantor/matlab/mat2html"; @keyWords = ('break', 'else', 'elseif', 'end', 'for', 'if', 'return', 'while', 'function', 'global', 'eval', 'feval', 'nargchk', 'pause', 'menu', 'keyboard', 'input', 'ans', 'computer', 'eps', 'flops', 'inf', 'NaN', 'nargin', 'nargout', 'pi', 'realmax', 'realmin'); # 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/ # # # 13 Jan 1995: Fixed a bug in tracking cross- # references, and other refinements. # 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; } # Write an html anchor, and keep track of how many have been # written using the global variable $anchor_count $anchor_count = 0; sub anchor_url{ local($url,$name) = @_; $anchor_count++; return("$name<\/A>"); } # A standard tagline is added to each page created. # The total page count is kept in $page_count $page_count = 0; sub tagline { $page_count++; print HFILE "Produced by ",&anchor_url($URL,'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.&anchor_url($html,$2).$3/eig;
      }
      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" # cref,href - Arrays o cross references # # Dependency matrix value $cref{$x,$y} is 1 if $x refers to $y in the # code section. $href{$x,$y} is 1 if $x refers to $y in the help # lines. print "Read and compute cross-references among the .m 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} = $_; } # Canonicalize to lower case, split on nonalphanumerics, # and count things that look like matlab identifiers. tr/A-Z/a-z/; grep($hsymbols{$_}++,grep(/[a-z]\w*/,split('\W',$_))) } else { # Split off and ignore trailing comments # Split on nonalphanumerics and count identifiers ($statement,$comment) = split('%',$_,2); grep($csymbols{$_}++,grep(/[a-zA-Z]\w*/,split('\W',$statement))); } } close MFILE; # Now mark each name that appears in the list of symbols # Compute the names appearing among the symbols in the code section # (@csym), in the help section (@hsym) # if ($opt_g) { We always want cross listed if (1) { # If global, search among all symbols @csym = grep($csymbols{$_},@names); @hsym = grep($hsymbols{$_},@names); } else { # If not global, search among files appearing in the same directory $dir = $mdir{$file}; @csym = grep(($csymbols{$_} && ($dir eq $mdir{$mfile{$_}})), @names); @hsym = grep(($hsymbols{$_} && ($dir eq $mdir{$mfile{$_}})), @names); } # Now record the cross references in $cref and $href grep($cref{$file,$mfile{$_}}=$csymbols{$_},@csym); grep($href{$file,$mfile{$_}}=$hsymbols{$_},@hsym); 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; } ###################################################################### # # If verbose mode, write a sparse matrix with the xref data # ###################################################################### # For kicks, let's write out name and cross reference info in a # sparse matrix format. These can be anaylzed using matlab. if ($verbose) { local($x,$y,$i,$j); open(TXT,">$hroot/names.txt"); foreach (@mfiles) { $b = " " x (20-length($name{$_})); print TXT $name{$_},$b,$_,"\n"; } close TXT; open(DAT,">$hroot/xref.dat"); $i = 0; foreach $x (@mfiles) { $j = 0; $i++; foreach $y (@mfiles) { $j++; print DAT "$i $j $cref{$x,$y}\n" if $cref{$x,$y}; } } close(DAT); } ###################################################################### # # 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 ''; 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"; foreach $dir (@mdirs) { print HFILE "
  • ",&anchor_url("$hdir{$dir}/index.html",$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 4 across in alphabetical order $i = 1; foreach (@names) { # changed a 15 to 20 to give me more space $b = " " x (20 - length($_)); $html = "$hdir{$mdir{$mfile{$_}}}/$_.html"; print HFILE &anchor_url($html,$_),$b; print HFILE "\n" if (0 == $i%4); # changed a 5 to 4 $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 ''; print HFILE "\n"; print HFILE &anchor_url("../index.html","[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 $href{$file,$_}; } # 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 (grep($dir eq $mdir{$_},@mfiles)) {
 # changed a 15 to a 20 to give me more space.
    $b = " " x (20 - length($name{$file}));
    $html = $name{$file}.".html";
    print HFILE &anchor_url($html,$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 $cref{$file,$_}; # files we call push(@yref,$name{$_}) if $cref{$_,$file}; # files that call us push(@zref,$name{$_}) if $href{$file,$_}; # 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 "$file\n"; print HFILE ''; print HFILE "\n"; print HFILE &anchor_url("../index.html","[Master Index]"),"\n"; print HFILE &anchor_url("index.html","[Index for $mdir{$file}]"),"\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 (sort @xref) { $html = "../$hdir{$mdir{$mfile{$_}}}/$_.html"; $b = " " x (15 - length($_)); print HFILE "
  • ",&anchor_url($html,$_),"$b$mfile{$_}
  • \n"; } print HFILE "
\n"; } if (@yref) { print HFILE "This $mtype{$file} is called by\n"; print HFILE "
    \n"; foreach (sort @yref) { $html = "../$hdir{$mdir{$mfile{$_}}}/$_.html"; $b = " " x (15 - length($_)); print HFILE "
  • ",&anchor_url($html,$_),"$b$mfile{$_}
  • \n"; } print HFILE "
\n"; } # Include source text if requested # Source text is always requested, replace 1 by $opt_i to revert if (1) { print HFILE "

Listing of $mtype{$file} $file

\n"; seek(MFILE,0,0); print HFILE "
\n";
    $spaces = " " x 4;
    $red = '';
    $green = '';
    $endFont = '';
    
    while () {
      &htmlchar;
      s/\t/$spaces/g;  # convert tabs to 4 whitespace characters.
      if (/^\s*%/) {  # checks to see if we're on a comment line
        foreach $z (@zref) {
          next if //;
          $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
          s/(\W+)($z)(\W+)/$1.&anchor_url($html,$2).$3/egi;
        }
      } else {
		  foreach $key (@keyWords){ # should select out each keyword
			 s/\b$key\b/$green$key$endFont/g;	# and then highlight it if found
        }
        foreach $x (@xref) {
          next if //;
          $html = "../$hdir{$mdir{$mfile{$x}}}/$x.html";
          s/(\W+)($x)(\W+)/$1.&anchor_url($html,$2).$3/eg;
          s/^(\s*)($x)(\W+)/$1.&anchor_url($html,$2).$3/eg;
        }
      }
      s/(%.*)/$red\1$endFont/; # should highlight the comments
      print HFILE $_;
    }
    print HFILE "
\n"; } # Print a date stamp print HFILE "
\n"; &tagline; print HFILE ""; close(MFILE); close(HFILE); } ###################################################################### # # Do some final statistics # ###################################################################### print $anchor_count," HTML anchors were written.\n" if $verbose; print $page_count," HTML files were written.\n" if $verbose;