NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/gliderproc/trunk/MATLAB/opnml/mat2html

Revision 495 (checked in by cbc, 11 years ago)

Initial import of Stark code.

Line 
1 #!/usr/bin/perl
2
3 $URL = "http://www.nd.edu/Courses/kantor/matlab/mat2html";
4
5 # READ THE HELP SECTION BELOW FOR INFORMATION ON HOW TO USE THIS SCRIPT.
6 #
7 # To install, simply save this function at mat2html, and make it
8 # executible with
9 #
10 #     chmod +x mat2html
11 #
12 # This requires a perl interpreter and access to the standard perl
13 # library. Do not contact me about installing perl, I will ignore
14 # you. Instead, please check out the following standard sites:
15 #
16 #    ftp.uu.net                      gnu/perl*
17 #    jpl-decvax.jpl.nasa.gov         pub/perl*
18 #    archive.cis.ohio-state.edu      perl/
19 #
20 #
21 # Version 1.0  : 12 Jan 1995: Major workover to allow index of
22 #                             multiple matlab directories.
23 #                10 Jan 1995: Added cross-links to the help text
24 #                 9 Jan 1995: Looks for a Readme.m file to put
25 #                             to put in the directory index.
26 #                 9 Jan 1995: Fixed html cross-links
27 #
28 # First posted to comp.soft-sys.matlab on January 9, 1995
29
30 # Jeffrey C. Kantor
31 # kantor.1@nd.edu
32
33 # Copyright (c) Jeffrey C. Kantor 1995.
34 # All rights reserved
35 #
36 # Please feel free to use this script under the conditions of the
37 # standard GNU public license.
38
39 ######################################################################
40 #
41 #  Subroutines
42 #
43 ######################################################################
44
45 # From the standard Perl Library
46
47 require 'getopts.pl';
48 require 'ctime.pl';
49
50 # Translate special html characters
51
52 sub htmlchar {
53   s/&/&/g;
54   s/\</&lt;/g;
55   s/\>/&gt;/g;
56   s/\"/&quot;/g;
57 }
58
59 sub tagline {
60   print HFILE "Produced by <A HREF=\"$URL\">mat2html</A> on $date<BR>\n";
61   print HFILE "Cross-Directory links are: ";
62   if ($opt_g) {print HFILE "ON<BR>\n"} else {print HFILE "OFF<BR>\n"};
63 }
64
65 # Assume MFILE and HFILE are open, $headline contains a section
66 # title, and @zref contains cross-reference names
67
68 sub writehelpblock {
69   do {$_ = <MFILE>} until /^\s*%/ || eof;
70   if (!eof) {
71     print HFILE "<HR><H3>$headline</H3>\n";
72     print HFILE "<pre>\n";
73     while (/^\s*%/) {
74       s/^\s*%//;
75       &htmlchar;
76       foreach $z (@zref) {
77         next if /<A.*$z.*A>/;
78         $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
79         s/(\W+)($z)(\W+)/\1<A HREF = \"$html\">\2<\/A>\3/ig;
80       }
81       print HFILE $_;
82       $_ = <MFILE>;
83     }
84     print HFILE "</pre>\n";
85   }
86
87 }
88
89 ######################################################################
90 #
91 #  Command line processing
92 #
93 ######################################################################
94
95 # Get the current date string
96
97 $date = &ctime(time);
98
99 # Read the command line arguments
100
101 &Getopts('ghipqH:M:');
102
103 warn("WARNING: Options -M and -p are incompatable.\n") if ($opt_M && $opt_p);
104
105 if (($opt_h) || ($opt_M && $opt_p)) {
106   print <<EOF;
107
108 Usage:
109
110   mat2html [-i] [-q] [-g] [-M matlab_dir] [-H html_dir]
111   mat2html [-i] [-q] [-g] [-p] [-H html_dir]
112
113 mat2html reads a list of matlab .m files and/or directories from the
114 standard input to produce a hypertext documentation suitable for
115 browsing with a WWW browser such as Mosaic or Netscape.  An file
116 html_dir/index.html in written. Subdirectories are written for matlab
117 directory that is encountered containing
118 .html files corresponding to every .m file.
119
120 Help:
121
122   -h   Print this help message and exit.
123
124   -q   Quiet operation. Default is verbose.
125
126 Output Options:
127
128   -H  Specify a directory to place the html files and subdirectories.
129       The default is the current directory. If necessary, an attempt
130       is made to create the directory. The file index.html is placed
131       in this directory.
132
133   -i  Include matlab source code in the html documentation
134
135   -g  Do global hypertext links, that is, hypertext links among
136       separate matlab directories. Default is to do hypertext
137       links only among functions in the same directory.
138
139 Matlab Source Options:
140
141       The standard input is looked at first. If there is nothing there,
142       then we look in the current directory for .m files as if we did a
143       -M . option.
144
145   -M  Specify a root matlab directory to search. The standard input
146       is not read.
147
148   -p  Search the matlab path obtained by matlab -n. Options -M
149       and -p are incompatable.
150
151 Typical usages are:
152
153   mat2html
154       Produces a file index.html in the current directory, and a
155       .html file corresponding to each .m file in the current directory.
156       An index.html file is produced in the current directory.
157
158   mat2html -M matlab -H html
159       Same as above, except it looks in subdirectory matlab of
160       the current directory for the .m files, and puts the results
161       in subdirectory html. Useful for separating the .m files
162       from the documentation.
163
164   mat2html -p -H html
165       Creates documentation for everything on the default matlab
166       path, and puts it into a directory html.
167
168   ls *.m | mat2html -H html
169       Index the .m files in the current directory
170
171   find . -name "*.m" -print | mat2html -H html -i
172       The find command recursively builds a list of all .m files
173       to be found the directory and its subdirectories. These
174       are then processed and the html files put in the directory
175       html. The matlab source code is included in the html files.
176
177 EOF
178   exit;
179 }
180
181 # Read arguments and initialize
182
183 if ($opt_H) {$hroot = $opt_H} else {$hroot = "."};
184 if ($opt_q) {$verbose = 0} else {$verbose = 1};
185
186 ######################################################################
187 #
188 #  Reading the input
189 #
190 ######################################################################
191
192 # Get the list of files and directories to examine, put in @xfiles
193 # Start by checking the standard input.
194
195 undef(@xfiles);
196
197 if (!-t) {
198
199   # STDIN is connected to some input
200   print "Reading from the standard input\n" if $verbose;
201
202   warn("Reading from STDIN, ignoring redundant -M option.\n") if ($opt_M);
203
204   while (<>) {
205     chop;
206     @files = split;
207     @xfiles = (@xfiles,@files);
208   }
209
210 } elsif ($opt_p) {
211
212   # Get the matlab path
213   print "Running matlab -n to get the matlab path.\n" if $verbose;
214
215   open(MATLAB,"matlab -n|") || die("Can't run matlab -n to get the path");
216   do {$_ = <MATLAB>} until /MATLABPATH/ || eof;
217   while (<MATLAB>) {
218     last if /^----/;
219     chop;
220     s/\s*//g;
221     push(@xfiles,$_);
222   }
223   close(MATLAB);
224
225 } elsif ($opt_M) {
226
227   # We need to find the matlab directories to search
228   print "Setting matlab directory to $opt_M\n" if $verbose;
229
230   if (-d $opt_M) {
231     @xfiles = ($opt_M);
232   } else {
233     die("Specified -M $opt_M is not a directory\n");
234   }
235
236 } else {
237
238   print "Setting matlab directory to the current directory.\n" if $verbose;
239   @xfiles = (".");
240
241 }
242
243 # Now process the list of @xfiles to get a list of .m files @mfiles
244
245 print "Finding .m files in the search path.\n" if $verbose;
246
247 undef(@mfiles);
248 foreach (@xfiles) {
249
250   # chop off any trailing separators, sometimes added by ls
251
252   s/\/$//;
253
254   # Add to mfiles if it exits and text file with a .m suffix
255
256   if ((/\.m$/) && (-e) && (-T)) {
257     push(@mfiles,$_);
258     next;
259   }
260
261   # If it's a directory, then read it
262
263   if (-d) {
264     opendir(MDIR,$_) || die("Cannot open directory $_\n");
265     @files = grep(/\.m$/,readdir(MDIR));
266     foreach $file (@files) {
267       push(@mfiles,"$_/$file");
268     }
269   }
270 }
271
272 $n = $#mfiles + 1;
273 print "Found $n .m files.\n" if $verbose;
274
275 undef($n);
276 undef(@xfiles);
277 undef($mroot);
278
279 ######################################################################
280 #
281 #  Parse the matlab file names
282 #
283 ######################################################################
284
285 # Now we need to parse the mfile names to obtain for each file
286 #  $name{$file} - a matlab identifier used to search the texts
287 #  $mdir{$file} - the directory in which the file is found
288
289 print "Parsing the matlab file names.\n" if $verbose;
290
291 undef(%mdir);
292 foreach (@mfiles) {
293   local($x) = $_;
294   $x =~ s/\.m$//;
295   split("/",$x);
296   $name{$_} = pop(@_);
297   $mdir{$_} = join('/',@_);
298   $mdir{$_} = "." if $mdir{$_} eq "";
299 }
300
301 # Compute a unique list of matlab identifier names, put in @names.
302
303 grep($count{$_}++,values(%name));
304 @names = sort(keys(%count));
305 undef(%count);
306
307 $n = $#names + 1;
308 print "Found $n unique matlab identifiers.\n" if $verbose;
309 undef($n);
310
311 # Now we have a problem. Each matlab name may be associated with more
312 # than one .m file. The order of @mfiles is the order they would be
313 # encountered in a standard matlab search, so we preserve that order.
314 # We compute:
315 #
316 # $mfile{$name}  - look up the first mfile associated with a $name
317 #
318 # Confused yet?
319
320 print "Linking each matlab identifier to a unique .m file.\n" if $verbose;
321
322 foreach $n (@names) {
323   foreach (@mfiles) {
324     $file = $_;
325     last if ($n eq $name{$_});
326   }
327   $mfile{$n} = $file;
328 }
329
330 # Compute the set of unique matlab directory names, put in @mdirs
331
332 grep($count{$_}++,values(%mdir));
333 @mdirs = sort(keys(%count));
334 undef(%count);
335
336 $n = $#mdirs + 1;
337 print "Found $n unique matlab directories in the search path.\n" if $verbose;
338 undef($n);
339
340 ######################################################################
341 #
342 #  Read the m-files, and compute cross-reference information
343 #
344 ######################################################################
345
346 # Read each file and tabulate the distinct alphanumeric identifiers in
347 # an array of symbols. This is used to compute cross references within
348 # a matlab directory. Also scan for:
349 #
350 #   synposis  - The function declaration line
351 #   lookfor   - The first line of the help text
352 #   mtype     - File type, either "function" or "script"
353 #   ref      - Array of code cross references
354 #
355 # Dependency matrix value $ref{$x,$y} is 1 if $x refers to $y in the
356 # code section. $ref{$x,$y} is 2 if $x refers to $y in the comment
357 # lines.
358  
359 print "Read and compute cross-references among the matlab files.\n" if $verbose;
360
361 foreach $file (@mfiles) {
362
363   open(MFILE,"<$file") || die("Cannot open $file\n");
364
365   print "Reading $file\n" if $verbose;
366
367   while (<MFILE>) {
368     chop;
369
370     # If it's the function declaration line, then store it and skip
371     if (/^\s*function/) {
372       s/^\s*function\s*//;
373       $synopsis{$file} = $_;
374       $mtype{$file} = "function";
375       next;
376     }
377
378     # Compress multiple %'s to a single %
379     s/%+/%/g;
380
381     # Process comment lines and code lines separately
382
383     if (/^\s*%/) {
384
385       # cut out comment marker and surrounding white space
386       s/^\s*%\s*//;
387
388       # Store first comment line in lookfor
389       if (!$lookfor{$file}) {
390         $lookfor{$file} = $_;
391       }
392
393       # Split on nonalphanumerics, canonicalize to lower case
394
395       tr/A-Z/a-z/;
396       @words = grep(/[a-z]\w*/,split('\W',$_));
397       grep($hsymbols{$_}++,@words)
398
399     } else {
400
401       # Split off and ignore trailing comments
402       ($statement,$comment) = split('%',$_,2);
403
404       # Split on nonalphanumerics, preserve case
405       @words = grep(/[a-zA-Z]\w*/,split('\W',$statement));
406       grep($csymbols{$_}++,@words)
407     }
408
409   }
410   close MFILE;
411
412   # Now mark each name that appears in the list of symbols
413
414   $dir = $mdir{$file};
415
416   if ($opt_g) {
417     foreach (grep($csymbols{$_},@names)) {
418       $ref{$file,$mfile{$_}} = 1;
419     }
420     foreach (grep($hsymbols{$_},@names)) {
421       $ref{$file,$mfile{$_}} = 2;
422     }
423   } else {
424     foreach (grep($csymbols{$_},@names)) {
425       $f = $mfile{$_};
426       next if ($mdir{$f} ne $dir);
427       $ref{$file,$f} = 1;
428     }
429     foreach (grep($hsymbols{$_},@names)) {
430       $f = $mfile{$_};
431       next if ($mdir{$f} ne $dir);
432       $ref{$file,$f} = 2;
433     }
434   }
435
436   undef(%csymbols);
437   undef(%hsymbols);
438 }
439
440 ######################################################################
441 #
442 #  Setup the html directories
443 #
444 ######################################################################
445
446 # Create an html subdirectory name for every unique matlab directory in the
447 # list @mdirs. The name is constructed using the tail of the directory
448 # prefaced by a unique number.
449 #
450 #  $hdir{$mdir}   - html subdirectory for matlab directory $mdir
451
452 $x = 1;
453 foreach (@mdirs) {
454   @z = reverse(split("/",$_));
455   $hdir{$_} = "$x.".@z[0];
456   $x++;
457 }
458
459 # for each .m file, name a corresponding .html file
460
461 foreach (@mfiles) {
462   $hfile{$file} = $name{$_}.".html";
463 }
464
465 # Now test a build the corresponding html directories.
466
467 print "Checking HTML directories.\n" if $verbose;
468
469 if (!-e $hroot) {
470   mkdir($hroot,umask) || die("Cannot create directory $hroot\n");
471   chmod 0755, $hroot;
472 }
473 opendir(HDIR,$hroot) || die ("Cannot open directory $hroot\n");
474 closedir(HDIR);
475 die("HTML directory $hroot is not writable\n") if !-w $hroot;
476
477 print "HTML Directory $hroot is OK\n" if $verbose;
478
479 foreach (@mdirs) {
480   local($x) = $hroot."/".$hdir{$_};
481   if (!-e $x) {
482     mkdir($x,umask) || die("Cannot create directory $x\n");
483     chmod(0755,$x);
484   }
485   opendir(HDIR,$x) || die ("Cannot open directory $x\n");
486   closedir(HDIR);
487   die("HTML directory $x is not writable\n") if !-w $x;
488   print "HTML Directory $x is OK\n" if $verbose;
489 }
490
491 ######################################################################
492 #
493 #  Write the master index file
494 #
495 ######################################################################
496
497 $indexfile = "$hroot/index.html";
498
499 print "Writing master $indexfile\n" if $verbose;
500
501 open(HFILE,">$indexfile") || die("Cannot open index file $indexfile\n");
502 print HFILE "<TITLE>Matlab Index</TITLE>\n";
503 print HFILE "<BODY>\n";
504 print HFILE "<H1>Matlab Index</H1>\n";
505 &tagline;
506
507 # Print a short introduction
508
509 # Print directory listing
510
511 print HFILE "<HR><H2>Matlab Directory Indices</H2>\n<pre>\n";
512 print HFILE "<UL>\n";
513 foreach $dir (@mdirs) {
514   print HFILE "<LI><A HREF = \"$hdir{$dir}/index.html\">$dir</A></LI>\n";
515 }
516 print HFILE "</UL>\n";
517
518 # Include links to every file that was found
519
520 print HFILE "<HR><H2>Identifiers found in these directories</H2>\n";
521
522 # We'll do this five across in alphabetical order
523 $i = 1;
524 foreach (@names) {
525   $b = " " x (15 - length($_));
526   $html = "$hdir{$mdir{$mfile{$_}}}/$_.html";
527   print HFILE "<A HREF = \"$html\">$_</A>$b";
528   print HFILE "\n" if (0 == $i%5);
529   $i++;
530 }
531
532 print HFILE "<HR></BODY>\n";
533 close(HFILE);
534
535 ######################################################################
536 #
537 #  Write an index for each html subdirectory
538 #
539 ######################################################################
540
541 @readme = grep(/readme/i,@mfiles);
542
543 foreach $dir (@mdirs) {
544
545   $indexfile = "$hroot/$hdir{$dir}/index.html";
546
547   print "Writing an index file $indexfile\n" if $verbose;
548
549   open(HFILE,">$indexfile") || die("Cannot open index file $indexfile\n");
550   print HFILE "<TITLE>Index for Directory $dir</TITLE>\n";
551   print HFILE "<BODY>\n";
552   print HFILE "<A HREF = \"../index.html\">[Return to Master Index]</A>\n";
553   print HFILE "<H1>Index for $dir</H1>\n";
554   &tagline;
555
556   # Now look for a Readme.m file, seemingly a Matlab standard. If there
557   # is one, then the help portion is included in the index file.
558
559   foreach $file (@readme) {
560     next if !($mdir{$file} eq $dir);
561     open(MFILE,$file) || die("Cannot open the file $file");
562
563     # Help Cross Reference information
564
565     undef(@zref);
566     foreach $_ (@mfiles) {
567       push(@zref,$name{$_}) if $ref{$file,$_} == 2;
568     }
569
570     # Look for the matlab help text block
571
572     $headline = "Readme";
573     &writehelpblock;
574   }
575
576   # Now write the index catalog for the .m files in this directory
577
578   print HFILE "<HR><H2>Matlab files in this Directory</H2>\n<pre>\n";
579   foreach $file (@mfiles) {
580     next if $dir ne $mdir{$file};
581     $b = " " x (15 - length($name{$file}));
582     $html = $name{$file}.".html";
583     print HFILE "<A HREF = \"$html\">$name{$file}</A>$b$lookfor{$file}\n";
584   }
585   print HFILE "</pre>\n";
586   print HFILE "<HR></BODY>\n";
587
588   close(HFILE);
589 }
590
591 ######################################################################
592 #
593 #  Write an html file for every m-file
594 #
595 ######################################################################
596
597 # Now write the html file for each matlab file. Need to reread each matlab
598 # file to find the help text. Note that we can't do this in a single loop
599 # because we want the back reference information, and also some people
600 # put the help text before the function declarations. 
601
602 # Need a list of mfiles with unique identifiers
603
604 @umfiles = values(%mfile);
605
606 foreach $file (@mfiles) {
607
608   $h = "$hroot/$hdir{$mdir{$file}}/$name{$file}.html";
609  
610   print "Writing $h\n" if $verbose;
611   # Cross Reference information
612   # Find list of names.
613
614   undef(@xref);
615   undef(@yref);
616   undef(@zref);
617   foreach (@umfiles) {
618     next if ($name{$_} eq $name{$file});
619       push(@xref,$name{$_}) if $ref{$file,$_} == 1; # files we call
620       push(@yref,$name{$_}) if $ref{$_,$file} == 1; # files that call us
621       push(@zref,$name{$_}) if $ref{$file,$_} == 2; # files in the comment lines
622     }
623
624   open(MFILE,"<$file") || die("Cannot open $file");
625   open(HFILE,">$h") || die("Cannot open $h");
626
627   print HFILE "<TITLE>$hdir{$file}/$hfile{$file}</TITLE>\n";
628   print HFILE "<BODY>\n";
629   print HFILE "<A HREF = \"index.html\">[Index for $mdir{$file}]</A>\n";
630   print HFILE "<A HREF = \"../index.html\">[Return to Master Index]</A>\n";
631   print HFILE "<H1>$name{$file}</H1>\n";
632   print HFILE "<H2>($mdir{$file}/$name{$file}.m)</H2>\n";
633
634   # If this is a function, then write out the first line as a synposis
635
636   if ($mtype{$file}) {
637     print HFILE "<HR><H3>Function Synopsis</H3>\n";
638     print HFILE "<pre>$synopsis{$file}</pre>\n";
639   }
640
641   # Write the help block
642
643   $headline = "Help text";
644   &writehelpblock;
645
646   print HFILE "<HR><H3>Cross-Reference Information</H3>" if (@xref || @yref);
647   if (@xref) {
648     print HFILE "This $mtype{$file} calls\n";
649     print HFILE "<pre><UL>\n";
650     foreach $x (sort @xref) {
651       $html = "../$hdir{$mdir{$mfile{$x}}}/$x.html";
652       $b = " " x (15 - length("$x"));
653       print HFILE "<LI><A HREF = \"$html\">$x</A>".$b."$mfile{$x}</LI>\n";
654     }
655     print HFILE "</UL></pre>\n";
656   }
657   if (@yref) {
658     print HFILE "This $mtype{$file} is called by\n";
659     print HFILE "<pre><UL>\n";
660     foreach $y (sort @yref) {
661       $html = "../$hdir{$mdir{$mfile{$y}}}/$y.html";
662       $b = " " x (15 - length("$y"));
663       print HFILE "<LI><A HREF = \"$html\">$y</A>".$b."$mfile{$y}</LI>\n";
664     }
665     print HFILE "</UL></pre>\n";
666   }
667
668   # Include source text if requested
669
670   if ($opt_i) {
671     print HFILE "<HR><H3>Listing of $mtype{$file} $mfile{$file}</H3>\n";
672     seek(MFILE,0,0);
673     print HFILE "<pre>\n";
674     while (<MFILE>) {
675       &htmlchar;
676       if (/^\s*%/) {
677         foreach $z (@zref) {
678           next if /<A.*$z.*A>/;
679           $html = "../$hdir{$mdir{$mfile{$z}}}/$z.html";
680           s/(\W+)($z)(\W+)/$1<A HREF = $html>$2<\/A>$3/gi;
681         }
682       } else {
683         foreach $x (@xref) {
684           next if /<A.*$x.*A>/;
685           $html = "../$hdir{$mdir{$mfile{$x}}}/$x.html";
686           s/(\W+)($x)(\W+)/$1<A HREF = $html>$2<\/A>$3/g;
687           s/^(\s*)($x)(\W+)/$1<A HREF = $html>$2<\/A>$3/g;
688         }
689       }
690       print HFILE $_;
691     }
692     print HFILE "</pre>\n";
693   }
694  
695   # Print a date stamp
696
697   print HFILE "<HR>\n";
698   &tagline;
699   print HFILE "</BODY>";
700   close(MFILE);
701   close(HFILE);
702 }
703
Note: See TracBrowser for help on using the browser.