To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / extra / soundsoftware / matlab-docs.pl @ 382:baff1c482d98

History | View | Annotate | Download (63.7 KB)

1 381:2dc8163e9150 Chris
@rem = '--*-Perl-*--';
2
@rem = '
3
@echo off
4
perl -w -S %0.bat %1 %2 %3 %4 %5 %6 %7 %8 %9
5
goto endofperl
6
@rem ';
7
# perl -w -S %0.bat "$@"
8 382:baff1c482d98 Chris
#!/usr/bin/perl
9 381:2dc8163e9150 Chris
#
10
# mtree2html_2000 - produce html files from Matlab m-files.
11
#                   use configuration file for flexibility
12
#                   can process tree of directories
13
#
14
# Copyright (C) 1996-2000 Hartmut Pohlheim.  All rights reserved.
15
# includes small parts of m2html from Jeffrey C. Kantor 1995
16
#
17
# Author:  Hartmut Pohlheim
18
# History: 06.03.1996  file created
19
#          07.03.1996  first working version
20
#          08.03.1996  modularized, help text only once included
21
#          11.03.1996  clean up, some functions rwritten
22
#          18.04.1996  silent output with writing in one line only
23
#                      version 0.20 fixed
24
#          14.05.1996  start of adding tree structure, could create tree
25
#          15.05.1996  creating of index files for every directory
26
#          17.05.1996  first working version except compact A-Z index
27
#          20.05.1996  cleanup of actual version, more variables and
28
#                      configurable settings
29
#          21.05.1996  reading, update and creation of contents.m added
30
#          22.05.1996  creation of short index started
31
#          28.05.1996  jump letters for short index,
32
#                      3 different directory indexes (short/long/contents)
33
#          29.05.1996  major cleanup, short and long index created from one function
34
#                      links for HTML and Indexes from 1 function,
35
#                      version 0.9
36
#          30.05.1996  contents.m changed to Contents.m (because unix likes it)
37
#                      function definition can be in first line of m file before comments
38
#                      version 0.91 fixed
39
#          03.06.1996  contents file can be written as wanted, the links will be correct
40
#                      cross references in help block of m-file will be found and
41
#                      converted, even if the name of the function is written upper case
42
#                      version 0.92 fixed
43
#          05.06.1996  construction of dependency matrix changed, is able now to process
44
#                      even the whole matlab tree (previous version needed to much memory)
45
#                      removed warning for contents files in different directories
46
#                      version 0.94 fixed
47
#          06.06.1996  new link name matrices for ConstructHTMLFile created,
48
#                      everything is done in ConstructDependencyMatrix,
49
#                      both dependencies (calls and called) and matrix
50
#                      with all mentioned names in this m-file, thus, much
51
#                      less scanning in html construction
52
#                      script is now (nearly) linear scalable, thus, matlab-toolbox
53
#                      tree takes less than 1 hour on a Pentium120, with source
54
#                      version 0.96 fixed
55
#          10.06.1996  order of creation changed, first all indexes (includes
56
#                      update/creation of contents.m) and then ConstructDepency
57
#                      thus, AutoAdd section will be linked as well
58
#                      excludenames extended, some more common word function names added
59
#                      version 0.97 fixed
60
#          17.02.1998  writecontentsm as command line parameter added
61
#                      error of file not found will even appear when silent
62
#                      version 1.02
63
#          21.05.2000  mark comments in source code specially (no fully correct,
64
#                      can't handle % in strings)
65
#                      version 1.11
66
#          05.11.2000  link also to upper and mixed case m-files
67
#                      searching for .m files now really works (doesn't find grep.com any longer)
68
#                      file renamed to mtree2html2001
69
#                      generated html code now all lower case
70
#                      inclusion of meta-description and meta-keywords in html files
71
#                      HTML4 compliance done (should be strict HTML4.0, quite near XHTML)
72
#                      version 1.23
73
#
74 382:baff1c482d98 Chris
#	   29.03.2011  (Chris Cannam) add frames option
75 381:2dc8163e9150 Chris
#
76
77
$VERSION  = '1.23';
78
($PROGRAM = $0) =~ s@.*/@@; $PROGRAM = "\U$PROGRAM\E";
79
$debug = 0;
80
81
#------------------------------------------------------------------------
82
# Define platform specific things
83
#------------------------------------------------------------------------
84
# suffix for files to search is defined twice
85
# the first ($suffix) is for string creation and contains the . as well
86
# the second ($suffixforsearch) is for regular expression, handling of . is quite special
87
$suffix = ".m";
88
$suffixforsearch = "m";
89
# the directory separator
90
$dirsep = "/";
91
# what is the current directory
92
$diract = ".";
93
94
#------------------------------------------------------------------------
95 382:baff1c482d98 Chris
#  Define all variables and their standard settings
96 381:2dc8163e9150 Chris
#  documentation of variables is contained in accompanying rc file
97
#------------------------------------------------------------------------
98
%var =
99
(
100
   'authorfile',                '',
101
   'codebodyfiles',             '',
102
   'codebodyindex',             '',
103
   'codeheadmeta',              '<meta name="author of conversion perl script" content="Hartmut Pohlheim" />',
104
   'codehr',                    '<hr size="3" noshade="noshade" />',
105
   'codeheader',                '',
106
   'configfile',                'mtree2html2001_rc.txt',
107
   'csslink',                   '',
108
   'dirmfiles',                 $diract,
109
   'dirhtml',                   $diract,
110
   'exthtml',                   '.html',
111 382:baff1c482d98 Chris
   'frames',                    'yes',
112 381:2dc8163e9150 Chris
   'filenametopframe',          'index',
113
   'filenameindexlongglobal',   'indexlg',
114
   'filenameindexlonglocal',    'indexll',
115
   'filenameindexshortglobal',  'indexsg',
116
   'filenameindexshortlocal',   'indexsl',
117
   'filenameextensionframe',    'f',
118
   'filenameextensionindex',    'i',
119
   'filenameextensionjump',     'j',
120
   'filenamedirshort',          'dirtops',
121
   'filenamedirlong',           'dirtopl',
122
   'filenamedircontents',       'dirtopc',
123
   'includesource',             'yes',
124
   'links2filescase',           'all',
125
   'processtree',               'yes',
126
   'producetree',               'yes',
127
   'textjumpindexlocal',        'Local Index',
128
   'textjumpindexglobal',       'Global Index',
129
   'texttitleframelayout',      'Documentation of Matlab Files',
130
   'texttitleindexalldirs',     'Index of Directories',
131
   'textheaderindexalldirs',    'Index of Directories',
132
   'texttitleindex',            '',
133
   'textheaderindex',           '',
134
   'texttitlefiles',            'Documentation of ',
135
   'textheaderfiles',           'Documentation of ',
136
   'usecontentsm',              'yes',
137
   'writecontentsm',            'no'
138
);
139
140
141
# define all m-file names, that should be excluded from linking
142
# however, files will still be converted
143
@excludenames = ( 'all','ans','any','are',
144
                  'cs',
145
                  'demo','dos',
146
                  'echo','edit','else','elseif','end','exist',
147
                  'flag','for','function',
148
                  'global',
149
                  'help',
150
                  'i','if','inf','info',
151
                  'j',
152
                  'more',
153
                  'null',
154
                  'return',
155
                  'script','strings',
156
                  'what','which','while','who','whos','why',
157
                );
158
159
# Text for inclusion in created HTML/Frame files: Doctype and Charset
160
$TextDocTypeHTML  = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">';
161
$TextDocTypeFrame = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">';
162
$TextMetaCharset = '<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />';
163
164
#------------------------------------------------------------------------
165
# Read the command line arguments
166
#------------------------------------------------------------------------
167
if (@ARGV == 0) {
168
   &DisplayHelp()  if &CheckFileName($var{'configfile'}, 'configuration file');
169
}
170
171
# Print provided command line arguments on screen
172
foreach (@ARGV) { print "   $_\n      "; }
173
174
# Get the options
175
use Getopt::Long;
176
@options = ('help|h', 'todo|t', 'version|v',
177
            'authorfile|a=s', 'configfile|c=s', 'dirhtml|html|d=s',
178
            'dirmfiles|mfiles|m=s', 'includesource|i=s',
179
            'processtree|r=s', 'producetree|p=s',
180
            'silent|quiet|q', 'writecontentsm|w=s');
181
&GetOptions(@options) || die "use -h switch to display help statement\n";
182
183
184
# Display help or todo list, when requested
185
&DisplayHelp()                         if $opt_help;
186
&DisplayTodo()                         if $opt_todo;
187
die "$PROGRAM v$VERSION\n"             if $opt_version;
188
189
$exit_status = 0;
190
191
#------------------------------------------------------------------------
192
# Read the config file
193
#------------------------------------------------------------------------
194
$var{'configfile'} = $opt_configfile         if $opt_configfile;
195
&GetConfigFile($var{'configfile'});
196
197
198
#------------------------------------------------------------------------
199
# Process/Check the command line otions
200
#------------------------------------------------------------------------
201
$var{'dirhtml'}   = $opt_dirhtml              if $opt_dirhtml;
202
if (!(substr($var{'dirhtml'}, -1, 1) eq $dirsep)) { $var{'dirhtml'} = $var{'dirhtml'}.$dirsep; }
203
$var{'dirmfiles'} = $opt_dirmfiles            if $opt_dirmfiles;
204
if (!(substr($var{'dirmfiles'}, -1, 1) eq $dirsep)) { $var{'dirmfiles'} = $var{'dirmfiles'}.$dirsep; }
205
206
$var{'authorfile'} = $opt_author              if $opt_author;
207
$var{'includesource'} = $opt_includesource    if $opt_includesource;
208
if ($var{'includesource'} ne 'no') { $var{'includesource'} = 'yes'; }
209
$var{'processtree'} = $opt_processtree        if $opt_processtree;
210
if ($var{'processtree'} ne 'no') { $var{'processtree'} = 'yes'; }
211
$var{'producetree'} = $opt_producetree        if $opt_producetree;
212
if ($var{'producetree'} ne 'no') { $var{'producetree'} = 'yes'; }
213
if ($var{'processtree'} eq 'no') { $var{'producetree'} = 'no'; }
214 382:baff1c482d98 Chris
if ($var{'frames'} ne 'no') { $var{'frames'} = 'yes'; }
215 381:2dc8163e9150 Chris
# if (($var{'processtree'} eq 'yes') && ($var{'producetree'} eq 'no')) { $var{'usecontentsm'} = 'no'; }
216
217
$var{'writecontentsm'} = $opt_writecontentsm  if $opt_writecontentsm;
218
219
#------------------------------------------------------------------------
220
# Do the real stuff
221
#------------------------------------------------------------------------
222
223
# Print variables on screen, when not silent
224
&ListVariables                          if !$opt_silent;
225
226
# Check the author file
227
if ($var{'authorfile'} ne '') {
228
   if (&CheckFileName($var{'authorfile'}, 'author file')) {
229
      $var{'authorfile'} = '';
230
      if (!$opt_silent) { print "   Proceeding without author information!\n"; }
231
   }
232
}
233
234
# Call the function doing all the real work
235
&ConstructNameMatrix;
236
237
&ConstructDependencyMatrix;
238
239
&ConstructAllIndexFiles;
240
241
&ConstructHTMLFiles;
242
243
exit $exit_status;
244
245
#------------------------------------------------------------------------
246
# Construct list of all mfile names and initialize various data arrays.
247
#------------------------------------------------------------------------
248
sub ConstructNameMatrix
249
{
250
   local(*MFILE);
251
   local($file, $dirname);
252
   local(@newdirectories);
253
   local(%localnames);
254
255
   $RecDeep = 0;
256
   &ParseTreeReadFiles($var{'dirmfiles'}, $RecDeep);
257
258
   foreach $dirname (@directories) {
259
      if ($dirnumbermfiles{$dirname} > 0) {
260
         push(@newdirectories, $dirname);
261
         if (! defined($contentsname{$dirname})) {
262
            $contentsname{$dirname} = 'Contents';
263
            if (($var{'writecontentsm'} eq 'no') && ($var{'usecontentsm'} eq 'yes')) {
264
               print "\r ParseTree - for directory  $dirname  no contents file found!\n";
265
               print   "             create one or enable writing of contents file (writecontentsm = yes)!\n";
266
            }
267
         }
268
      }
269
   }
270
   @alldirectories = @directories;
271
   @directories = @newdirectories;
272
273
   foreach $dirname (@directories) {
274
      if ($debug > 0) { print "Dir: $dirname \t\t $dirnumbermfiles{$dirname} \t$contentsname{$dirname}\n"; }
275
   }
276
277
   @names = sort(keys %mfile);
278
279
   # check, if name of directory is identical to name of file
280
   @dirsinglenames = values(%dirnamesingle);
281
   grep($localnames{$_}++, @dirsinglenames);
282
   @dirandfilename = grep($localnames{$_}, @names);
283
   if (@dirandfilename) {
284
      print "\r   Name clash between directory and file name: @dirandfilename\n";
285
      print   "      These files will be excluded from linking!\n";
286
      push(@excludenames, @dirandfilename);
287
   }
288
289
   # construct names matrix for help text linking
290
   #    exclude some common words (and at the same time m-functions) from linking in help text
291
   grep($localnames{$_}++, @excludenames);
292
   @linknames = grep(!$localnames{$_}, @names);
293
294
   if ($debug > 2) { print "linknames (names of found m-files):\n    @linknames\n"; }
295
296
}
297
298
#------------------------------------------------------------------------
299
# Parse tree and collect all Files
300
#------------------------------------------------------------------------
301
sub ParseTreeReadFiles
302
{
303
   local($dirname, $localRecDeep) = @_;
304
   local($file, $name, $filewosuffix);
305
   local($dirhtmlname, $dirmode);
306
   local($relpath, $relpathtoindex, $replacevardir);
307
   local(*CHECKDIR, *AKTDIR);
308
   local(@ALLEFILES);
309
310
   opendir(AKTDIR, $dirname) || die "ParseTree - Can't open directory $dirname: $!";
311
   if ($debug > 1) { print "\nDirectory: $dirname\n"; }
312
313
   # create relative path
314
   $_ = $dirname; $replacevardir = $var{'dirmfiles'};
315
   s/$replacevardir//; $relpath = $_;
316
   s/[^\/]+/../g; $relpathtoindex = $_;
317
318
   # producetree no
319
   if ($var{'producetree'} eq 'no') { $relpath = ''; $relpathtoindex = ''; }
320
321
   # names of directories (top-level and below top-level m-file-directory)
322
   push(@directories, $dirname);
323
   $dirnumbermfiles{$dirname} = 0;    # set number of m-files for this dir to zero
324
   # relative path from top-level directory, depends on directory name
325
   $dirnamerelpath{$dirname} = $relpath;
326
   # relative path from actual directory to top-level directory, depends on directory name
327
   $dirnamerelpathtoindex{$dirname} = $relpathtoindex;
328
   # recursion level for directory, depends on directory name
329
   $dirnamerecdeep{$dirname} = $localRecDeep;
330
331
   # only the name of the directory, without path
332
   $rindexprint = rindex($dirname, $dirsep, length($dirname)-2);
333
   $rindsub = substr($dirname, $rindexprint+1, length($dirname)-$rindexprint-2);
334
   $dirnamesingle{$dirname} = $rindsub;
335
336
   # create name of html-directories
337
   $_ = $dirname;
338
   s/$var{'dirmfiles'}/$var{'dirhtml'}/;
339
   $dirhtmlname = $_;
340
   if ($var{'producetree'} eq 'no') { $dirhtmlname = $var{'dirhtml'}; }
341
   # try to open html directory, if error, then create directory,
342
   # use same mode as for corresponding m-file directory
343
   opendir(CHECKDIR,"$dirhtmlname") || do {
344
      $dirmode = (stat($dirname))[2]; # print "$dirmode\n";
345
      mkdir("$dirhtmlname", $dirmode) || die ("Cannot create directory $dirhtmlname: $! !");
346
   };
347
   closedir(CHECKDIR);
348
349
350
   # read everything from this directory and process them
351
   @ALLEFILES = readdir(AKTDIR);
352
353
   foreach $file (@ALLEFILES) {
354
      # exclude . and .. directories
355
      next if $file eq '.';  next if $file eq '..';
356
357
      # test for existense of entry (redundant, used for debugging)
358
      if (-e $dirname.$file) {
359
         # if it's a directory, call this function recursively
360
         if (-d $dirname.$file) {
361
            if ($var{'processtree'} eq 'yes') {
362
               &ParseTreeReadFiles($dirname.$file.$dirsep, $localRecDeep+1);
363
            }
364
         }
365
         # if it's a file - test for m-file, save name and create some arrays
366
         elsif (-f $dirname.$file) {
367
            if ($file =~ /\.$suffixforsearch$/i) {
368
               # Remove the file suffix to establish the matlab identifiers
369
               $filewosuffix = $file;
370
               $filewosuffix =~ s/\.$suffixforsearch$//i;
371
               # $filename = $name;
372
373
               # Contents file in unix must start with a capital letter (Contents.m)
374
               # ensure, that m-file name is lower case, except the contents file
375
               if (! ($filewosuffix =~ /^contents$/i)) {
376
                  # if ($var{'links2filescase'}  eq 'low') { $filewosuffix = "\L$filewosuffix\E"; }
377
                  $filewosuffixlow = "\L$filewosuffix\E";
378
               }
379
               else { $contentsname{$dirname} = $filewosuffix; }
380
381
               # internal handle name is always lower case
382
               $name     = $filewosuffixlow;
383
               # file name is not lower case
384
               $filename = $filewosuffix;
385
386
               # if don't use C|contents.m, then forget all C|contents.m
387
               if ($var{'usecontentsm'} eq 'no') { if ($name =~ /contents/i) { next; } }
388
389
               # if m-file with this name already exists, use directory and name for name
390
               # only the first occurence of name will be used for links
391
               if (defined $mfile{$name}) {
392
                  if (! ($name =~ /^contents$/i) ) {
393
                     print "\r ParseTree - Name conflict:  $name in $dirname already exists: $mfile{$name} !\n";
394
                     print   "             $mfile{$name}  will be used for links!\n";
395
                  }
396
                  $name = $dirname.$name;
397
               }
398
               # mfile name with path
399
               $mfile{$name} = $dirname.$file;
400
               # mfile name (without path)
401
               $mfilename{$name} = $filename;
402
               # mfile directory
403
               $mfiledir{$name} = $dirname;
404
405
               # html file name and full path, special extension of Contents files
406
               if ($name =~ /contents/i) { $extrahtmlfilename = $dirnamesingle{$dirname}; }
407
               else { $extrahtmlfilename = ''; }
408
               $hfile{$name} = $dirhtmlname.$mfilename{$name}.$extrahtmlfilename.$var{'exthtml'};
409
410
               # save relative html path
411
               # if ($var{'producetree'} eq 'yes') {
412
               $hfilerelpath{$name} = $relpath;
413
               # } else { # if no tree to produce, relative path is empty
414
               #    $hfilerelpath{$name} = '';
415
               # }
416
417
               # create relative path from html file to directory with global index file
418
               $hfileindexpath{$name} = $relpathtoindex;
419
420
               # Function declaration, if one exists, set default to script
421
               $synopsis{$name} = "";
422
               $mtype{$name} = "script";
423
424
               # First comment line
425
               $apropos{$name} = "";
426
427
               # count number of m-files in directories
428
               $dirnumbermfiles{$dirname}++;
429
430
               if ($debug > 1) {
431
                  if ($opt_silent) { print "\r"; }
432
                  print "   ParseTree: $name \t\t $mfile{$name} \t\t $hfile{$name}\t\t";
433
                  if (!$opt_silent) { print "\n"; }
434
               }
435
            }
436
         }
437
         else {
438
            print "Unknown type of file in $dirname: $file\n";
439
         }
440
      }
441
      else { print "Error: Not existing file in $dirname: $file\n"; }
442
   }
443
444
   closedir(AKTDIR)
445
446
}
447
448
#------------------------------------------------------------------------
449
# Construct Dependency matrix
450
#    $dep{$x,$y} > 0 if $x includes a reference to $y.
451
#------------------------------------------------------------------------
452
sub ConstructDependencyMatrix
453
{
454
   &ConstructDependencyMatrixReadFiles('all');
455
   &ConstructDependencyMatrixReally;
456
}
457
458
459
#------------------------------------------------------------------------
460
# Construct Dependency matrix
461
#    $dep{$x,$y} > 0 if $x includes a reference to $y.
462
#------------------------------------------------------------------------
463
sub ConstructDependencyMatrixReadFiles
464
{
465
   local($whatstring) = @_;
466
   local(*MFILE);
467
   local($name, $inames);
468
   local(%symbolsdep, %symbolsall);
469
470
   # Initialize as all zeros.
471
   # foreach $name (@names) { grep($dep{$name,$_}=0,@names); if ($debug > 0) { print "\r   DepMatrix anlegen: $name\t$#names\t"; } }
472
473
   # Compute the dependency matrix
474
   $inames = -1;
475
   foreach $name (@names) {
476
      # Read each file and tabulate the distinct alphanumeric identifiers in
477
      # an array of symbols. Also scan for:
478
      #   synopsis: The function declaration line
479
      #   apropos:  The first line of the help text
480
481
      # look for whatstring, if all: process every file, if contents: process only contents files
482
      if ($whatstring eq 'contents') { if (! ($name =~ /contents$/i) ) { next; } }
483
      elsif ($whatstring eq 'all') { }    # do nothing
484
      else { print "\r   ConstructDependency: Unknown parameter whatstring: $whatstring \n"; }
485
486
      undef %symbolsall; undef %symbolsdep;
487
      open(MFILE,"<$mfile{$name}") || die("Can't open $mfile{$name}: $!\n");
488
      while (<MFILE>) {
489
         chop;
490
491
         # Split on nonalphanumerics, then look for all words, used for links later
492
         # this one for all references
493
         @wordsall = grep(/[a-zA-Z]\w*/, split('\W',$_));
494
         # set all words to lower case for link checking
495
         undef @wordsall2;
496
         # do case conversion not, case checking is done later
497
         foreach (@wordsall) { push(@wordsall2, "\L$_\E"); }
498
         # @wordsall2 = @wordsall;
499
         grep($symbolsall{$_}++, @wordsall2);
500
501
         # Store first comment line, skip all others.
502
         if (/^\s*%/) {
503
            if (!$apropos{$name}) {
504
               s/^\s*%\s*//;   # remove % and leading white spaces on line
505
               $_ = &SubstituteHTMLEntities($_);
506
               $apropos{$name} = $_;
507
            }
508
            next;
509
         }
510
511
         # If it's the function declaration line, then store it and skip
512
         # but only, when first function definition (multiple function lines when private subfunctions in file
513
         if ($synopsis{$name} eq '') {
514
            if (/^\s*function/) {
515
               s/^\s*function\s*//;
516
               $synopsis{$name} = $_;
517
               $mtype{$name} = "function";
518
               next;
519
            }
520
         }
521
522
         # Split off any trailing comments
523
         if ($_ ne '') {
524
            # this one for references in program code only
525
            # when syntax parsing, here is a working place
526
            ($statement) = split('%',$_,1);
527
            @wordsdep = grep(/[a-zA-Z]\w*/,split('\W',$statement));
528
            # do case conversion not, case checking is done later
529
            undef @wordsdep2;
530
            foreach (@wordsdep) { push(@wordsdep2, "\L$_\E"); }
531
            grep($symbolsdep{$_}++, @wordsdep2);
532
         }
533
      }
534
      close MFILE;
535
536
      # compute intersection between %symbolsall and @linknames
537
      delete($symbolsall{$name});
538
      # foreach $localsumall ($symbolsall) {
539
      #    $localsumall = "\L$localsumall\E";
540
      # }
541
      @{'all'.$name} = grep($symbolsall{$_}, @linknames);
542
543
      # compute intersection between %symbolsdep and @linknames
544
      delete($symbolsdep{$name});
545
      @{'depcalls'.$name} = grep($symbolsdep{$_}, @linknames);
546
547
      $inames++; print "\r   DepCallsMatrix: $inames/$#names\t $name\t";
548
      if ($debug > 2) { print "\n      depnames: @{'depcalls'.$name}\n      all: @{'all'.$name}\n"; }
549
   }
550
}
551
552
553
#------------------------------------------------------------------------
554
# Construct Dependency matrix
555
#    $dep{$x,$y} > 0 if $x includes a reference to $y.
556
#------------------------------------------------------------------------
557
sub ConstructDependencyMatrixReally
558
{
559
   local($inames, $name);
560
561
   $inames = -1;
562
   foreach $name (@names) { undef %{'depint'.$name}; }
563
   foreach $name (@names) {
564
      grep(${'depint'.$_}{$name}++, @{'depcalls'.$name});
565
      $inames++; print "\r   DepCalledMatrix1: $inames/$#names\t $name\t";
566
   }
567
   $inames = -1;
568
   foreach $name (@names) {
569
      # compute intersection between %depint.name{$_} and @linknames
570
      if (defined (%{'depint'.$name})) { @{'depcalled'.$name} = grep(${'depint'.$name}{$_}, @linknames); }
571
      $inames++; print "\r   DepCalledMatrix2: $inames/$#names\t $name\t";
572
      if ($debug > 2) { print "\n      depcalled: @{'depcalled'.$name}\n"; }
573
   }
574
575
}
576
577
578
#========================================================================
579
# Construct all index files
580
#========================================================================
581
sub ConstructAllIndexFiles
582
{
583
   local(@localnames);
584
   local($ActDir);
585
   local($name);
586
587
   # define variables and names for frame target
588
   $GlobalNameFrameMainLeft = 'Cont_Main';
589
   $GlobalNameFrameMainRight = 'Cont_Lower';
590
   $GlobalNameFrameAZIndexsmall = 'IndexAZindex';
591
   $GlobalNameFrameAZIndexjump = 'IndexAZjump';
592
593
   $indexcreated = 0;
594
595
   &ConstructHighestIndexFile;
596
   $indexcreated++;
597
598
   # if ($var{'producetree'} eq 'yes') {
599
      # moved next 2 lines out of if for producetree no
600
      # &ConstructHighestIndexFile;
601
      # $indexcreated++;
602
603
      foreach $ActDir (@directories) {
604
         undef @localnames;
605
         foreach $name (@names) {
606
            local($pathsubstr) = substr($mfile{$name}, 0, rindex($mfile{$name}, "/")+1);
607
            if ($ActDir eq $pathsubstr) {
608
               if ($debug > 1) { print "IndexFile: $pathsubstr    ActDir: $ActDir   Hfilerelpath: $hfilerelpath{$name}\n"; }
609
               push(@localnames, $name);
610
            }
611
         }
612
         if ($debug > 2) { print "localnames: @localnames\n"; }
613
         # create contents file and short|long index of files in local directory
614
         &ConstructContentsmFile($ActDir, @localnames);
615
         &ConstructAZIndexFile($ActDir, 'short', 'local', @localnames);
616
         &ConstructAZIndexFile($ActDir, 'long', 'local', @localnames);
617
         $indexcreated+=2;
618
      }
619
   # } else {
620
   #    &ConstructContentsmFile($var{'dirmfiles'}, @names);
621
   # }
622
623
   # create short|long index of files in all directory
624
   &ConstructAZIndexFile($var{'dirmfiles'}, 'short', 'global', @names);
625
   &ConstructAZIndexFile($var{'dirmfiles'}, 'long', 'global', @names);
626
   $indexcreated+=2;
627
628
   # if contents.m were created or updated, the dependency matrices should
629
   # be updated as well
630
   if ($var{'writecontentsm'} eq 'yes') { &ConstructDependencyMatrixReadFiles('contents');; }
631
}
632
633
634
#========================================================================
635
# Construct the highest level index file
636
#========================================================================
637
sub ConstructHighestIndexFile
638
{
639
   local(*IFILE);
640
   local($indexfile, $filename);
641
642
   # Build the frame layout file, this files includes the layout of the frames
643
   # Build the frame layout file name (highest one)
644
   $indexfile = $var{'dirhtml'}.$var{'filenametopframe'}.$var{'exthtml'};
645
646 382:baff1c482d98 Chris
   if ($var{'frames'} eq 'yes') {
647 381:2dc8163e9150 Chris
648 382:baff1c482d98 Chris
       open(IFILE,">$indexfile") || die("Cannot open frame layout file $indexfile\n");
649 381:2dc8163e9150 Chris
650 382:baff1c482d98 Chris
       # Write the header of frame file
651
       print IFILE "$TextDocTypeFrame\n<html>\n<head>\n$var{'codeheadmeta'}\n$TextMetaCharset\n";
652
       print IFILE "   <title>$var{'texttitleframelayout'}</title>\n";
653
       print IFILE "</head>\n";
654 381:2dc8163e9150 Chris
655 382:baff1c482d98 Chris
       # definition of 2 frames, left the tree of directories,
656
       # right the index of that directory or the docu of a file
657
       print IFILE "<frameset  cols=\"25%,75%\">\n";
658
       print IFILE "   <frame src=\"$var{'filenamedirshort'}$var{'exthtml'}\" name=\"$GlobalNameFrameMainLeft\" />\n";
659
       print IFILE "   <frame src=\"$var{'filenameindexshortglobal'}$var{'filenameextensionframe'}$var{'exthtml'}\" name=\"$GlobalNameFrameMainRight\" />\n";   print IFILE "</frameset>\n";
660 381:2dc8163e9150 Chris
661 382:baff1c482d98 Chris
       print IFILE "</html>\n";
662
663
       close(IFILE);
664
665
       if ($opt_silent) { print "\r"; }
666
       print "   Frame layout file created: $indexfile\t";
667
       if (!$opt_silent) { print "\n"; }
668
   }
669 381:2dc8163e9150 Chris
670
   for($irun=0; $irun <= 2; $irun++) {
671
      # Build the top directory index file, these files include the directory tree
672
      # Build the directory tree index file name
673
674
      # Create no directory file for contents, when no contents to use
675
      if (($irun == 2) && ($var{'usecontentsm'} eq 'no')) { next; }
676
677
      # Assign the correct index file name
678
      if ($irun == 0) { $filename = $var{'filenamedirshort'}; }
679
      elsif ($irun == 1) { $filename = $var{'filenamedirlong'}; }
680
      elsif ($irun == 2) { $filename = $var{'filenamedircontents'}; }
681
682
      $indexfile = $var{'dirhtml'}.$filename.$var{'exthtml'};
683
684
      open(IFILE,">$indexfile") || die("Cannot open directory tree index file $indexfile\n");
685
      # Write header of HTML file
686
      print IFILE "$TextDocTypeHTML\n<html>\n<head>\n$var{'codeheadmeta'}\n$TextMetaCharset\n$var{'csslink'}\n";
687
688
      if ($var{'texttitleindexalldirs'} eq '') {
689
         print IFILE "<title>Index of Directories of $var{'dirmfiles'}</title>\n";
690
      } else {
691
         print IFILE "<title>$var{'texttitleindexalldirs'}</title>\n";
692
      }
693 382:baff1c482d98 Chris
694
      if ($var{'frames'} eq 'yes') {
695
	  print IFILE "<base target=\"$GlobalNameFrameMainRight\" />\n";
696
      }
697
698 381:2dc8163e9150 Chris
      print IFILE "</head>\n";
699
      print IFILE "<body $var{'codebodyindex'}>\n";
700
      if ($var{'textheaderindexalldirs'} eq '') {
701
         print IFILE "<h1 $var{'codeheader'}>Index of Directories of <em>$var{'dirmfiles'}</em></h1>\n";
702
      } else {
703
         print IFILE "<h1 $var{'codeheader'}>$var{'textheaderindexalldirs'}</h1>\n";
704
      }
705
      print IFILE "<p align=\"center\">\n";
706 382:baff1c482d98 Chris
707
      if ($var{'frames'} eq 'yes') {
708
	  if ($irun == 0) { print IFILE "<strong>short</strong>\n"; }
709
	  else { print IFILE "<a href=\"$var{'filenamedirshort'}$var{'exthtml'}\" target=\"$GlobalNameFrameMainLeft\">short</a>\n"; }
710
	  if ($irun == 1) { print IFILE " | <strong>long</strong>\n"; }
711
	  else { print IFILE " | <a href=\"$var{'filenamedirlong'}$var{'exthtml'}\" target=\"$GlobalNameFrameMainLeft\">long</a>\n"; }
712
	  if ($var{'usecontentsm'} eq 'yes') {
713
	      if ($irun == 2) { print IFILE " | <strong>contents</strong>\n"; }
714
	      else { print IFILE " | <a href=\"$var{'filenamedircontents'}$var{'exthtml'}\" target=\"$GlobalNameFrameMainLeft\">contents</a>\n"; }
715
	  }
716
      } else {
717
	  if ($irun == 0) { print IFILE "<strong>short</strong>\n"; }
718
	  else { print IFILE "<a href=\"$var{'filenamedirshort'}$var{'exthtml'}\">short</a>\n"; }
719
	  if ($irun == 1) { print IFILE " | <strong>long</strong>\n"; }
720
	  else { print IFILE " | <a href=\"$var{'filenamedirlong'}$var{'exthtml'}\">long</a>\n"; }
721
	  if ($var{'usecontentsm'} eq 'yes') {
722
	      if ($irun == 2) { print IFILE " | <strong>contents</strong>\n"; }
723
	      else { print IFILE " | <a href=\"$var{'filenamedircontents'}$var{'exthtml'}\">contents</a>\n"; }
724
	  }
725 381:2dc8163e9150 Chris
      }
726
727
      print IFILE "</p><br />\n\n";
728
      print IFILE "<ul>\n";
729
730
      # go through all directories and create a list entry for each one,
731
      # depending on recursion level create sublists
732
      $prevrecdeeplevel = 0;
733
      foreach $name (@alldirectories) {
734
         $actrecdeeplevel = $dirnamerecdeep{$name};
735
         for( ; $prevrecdeeplevel < $actrecdeeplevel; $prevrecdeeplevel++ ) { print IFILE "<ul>\n"; }
736
         for( ; $prevrecdeeplevel > $actrecdeeplevel; $prevrecdeeplevel-- ) { print IFILE "</ul>\n"; }
737
         if ($irun == 0) { $indexfilenameused = $var{'filenameindexshortlocal'}.$var{'filenameextensionframe'}; }
738
         elsif ($irun == 1) { $indexfilenameused = $var{'filenameindexlonglocal'}.$var{'filenameextensionframe'}; }
739
         elsif ($irun == 2) { $indexfilenameused = $contentsname{$name}; }
740
         else { die "ConstructHighestIndexFile: Unknown value of irun"; }
741
         if ($dirnumbermfiles{$name} > 0) {
742
            # producetree no
743
            # if ($var{'producetree'} eq 'no') { $dirnamehere = ''; }
744
            # else { $dirnamehere = '$dirnamerelpath{$name}'; }
745
            # print IFILE "<LI><A HREF=\"$dirnamehere$indexfilenameused_$dirnamesingle{$name}$var{'exthtml'}\">$dirnamesingle{$name}</A>\n";
746
            print IFILE "<li><a href=\"$dirnamerelpath{$name}$indexfilenameused$dirnamesingle{$name}$var{'exthtml'}\">$dirnamesingle{$name}</a></li>\n";
747
         } else {
748
            # print directories with no m-files inside not
749
            # print IFILE "<li>$dirnamesingle{$name}</li>\n";
750
         }
751
      }
752
      $actrecdeeplevel = 0;
753
      for( ; $prevrecdeeplevel > $actrecdeeplevel; $prevrecdeeplevel-- ) { print IFILE "</ul>\n"; }
754
      print IFILE "</ul>\n<br />$var{'codehr'}\n";
755
756
      # Include info about author from authorfile
757
      &WriteFile2Handle($var{'authorfile'}, IFILE);
758
759
      print IFILE "<!--navigate-->\n";
760
      print IFILE "<!--copyright-->\n";
761
      print IFILE "</body>\n</html>\n";
762
763
      close(IFILE);
764
765
      if ($opt_silent) { print "\r"; }
766
      print "   Directory - Indexfile created: $indexfile\t";
767
      if (!$opt_silent) { print "\n"; }
768
   }
769
}
770
771
772
#========================================================================
773
# Construct the A-Z index file (global/local and/or short/long)
774
#========================================================================
775
sub ConstructAZIndexFile
776
{
777
   local($LocalActDir, $LocalShortLong, $LocalGlobalLocal, @localnames) = @_;
778
   local(*IFILE);
779
   local($name, $indexfilename, $dirpath);
780
   local($firstletter, $firstone);
781
782
   if ($debug > 2) { print "localnames in AZ small: @localnames\n"; print "     ActDir in A-Z: $LocalActDir\n"; }
783
784
   # extract filename of index file from parameters of function
785
   if ($LocalShortLong eq 'short') {
786
      if ($LocalGlobalLocal eq 'global') { $indexfilename = $var{'filenameindexshortglobal'}; }
787
      elsif ($LocalGlobalLocal eq 'local') { $indexfilename = $var{'filenameindexshortlocal'}; }
788
      else { die "wrong parameter for LocalGlobalLocal in ConstructAZIndexFile: $LocalGlobalLocal."; }
789
   } elsif ($LocalShortLong eq 'long') {
790
      if ($LocalGlobalLocal eq 'global') { $indexfilename = $var{'filenameindexlongglobal'}; }
791
      elsif ($LocalGlobalLocal eq 'local') { $indexfilename = $var{'filenameindexlonglocal'}; }
792
      else { die "wrong parameter for LocalGlobalLocal in ConstructAZIndexFile: $LocalGlobalLocal."; }
793
   } else { die "wrong parameter for LocalShortLong in ConstructAZIndexFile: $LocalShortLong."; }
794
795
   # producetree no
796
   # if ($var{'producetree'} eq 'no') { $dirnamehere = ''; }
797
   # else { $dirnamehere = '$dirnamerelpath{$LocalActDir}'; }
798
   # Build the index file name
799
   # handle the global index file case separately (no extra directory name in file)
800
   #    the local index file name must be extended by the name of the directory
801
   if ($LocalGlobalLocal eq 'global') { $extradirfilename = ''; }
802
   else { $extradirfilename = $dirnamesingle{$LocalActDir}; }
803
   $indexfile = $var{'dirhtml'}.$dirnamerelpath{$LocalActDir}.$indexfilename.$var{'filenameextensionindex'}.$extradirfilename.$var{'exthtml'};
804 382:baff1c482d98 Chris
805
   if ($LocalShortLong eq 'short' and $var{'frames'} ne 'yes') {
806
       # With no frames, this must go in the top-level index file instead
807
       $indexfile = $var{'dirhtml'}.$var{'filenametopframe'}.$var{'exthtml'};
808
   }
809
810 381:2dc8163e9150 Chris
   if ($debug > 2) { print "   indexfilename (a-z small): $indexfile\n"; }
811
812
   open(IFILE,">$indexfile") || die("Cannot open index file $indexfile: $!\n");
813
814
   # Write the header of HTML file
815
   print IFILE "$TextDocTypeHTML\n<html>\n<head>\n$var{'codeheadmeta'}\n$TextMetaCharset\n$var{'csslink'}\n";
816
817
   if ($var{'texttitleindex'} eq '') {
818
      print IFILE "<title>Index of Matlab Files in Directory $LocalActDir</title>\n";
819
   } else {
820
      if ($LocalGlobalLocal eq 'global') { print IFILE "<title>$var{'texttitleindex'}</title>\n"; }
821
      else { print IFILE "<title>$var{'texttitleindex'} in Directory $LocalActDir</title>\n"; }
822
   }
823 382:baff1c482d98 Chris
824
   if ($var{'frames'} eq 'yes') {
825
       print IFILE "<base target=\"$GlobalNameFrameMainRight\" />\n";
826
   }
827 381:2dc8163e9150 Chris
   print IFILE "</head>\n";
828 382:baff1c482d98 Chris
829 381:2dc8163e9150 Chris
   print IFILE "<body $var{'codebodyindex'}>\n";
830
   if ($var{'textheaderindex'} eq '') {
831
      print IFILE "<h1 $var{'codeheader'}>Index of Matlab Files in Directory $LocalActDir</h1>\n";
832
   } else {
833
      if ($LocalGlobalLocal eq 'global') { print IFILE "<h1 $var{'codeheader'}>$var{'textheaderindex'}</h1>\n"; }
834
      else { print IFILE "<h1 $var{'codeheader'}>$var{'textheaderindex'} in Directory $LocalActDir</h1>\n"; }
835
   }
836
837
   # include links to indexes
838
   &ConstructLinks2Index(IFILE, $dirnamerelpathtoindex{$LocalActDir}, $LocalActDir, $LocalGlobalLocal);
839
840
   # Collect the starting letters of m files in this directory or all m-files
841
   for('a'..'z') { undef @{$_}; }
842
   foreach $name (@localnames) {
843
      if (! ($mfilename{$name} =~ /contents/i)) {
844
         $firstletter = substr($mfilename{$name}, 0, 1);
845
         # convert first letter always to lower case
846
         # needed for reference to lower and upper case m-files
847
         $firstletter = "\L$firstletter\E";
848
         push(@{$firstletter}, $name);
849
      }
850
   }
851
852
   if ($LocalShortLong eq 'short') {
853
      # begin create short index
854
      print IFILE "<table width=\"100%\">\n";
855
856
      for('a'..'z') {
857
         # print "   $_: @{$_}\n";
858
         $numberofletter = $#{$_}+1;
859
         if ($numberofletter > 0) {
860
            print IFILE "\n<tr><td colspan=\"2\"><br /><strong><a name=\"\U$_\E$_\" class=\"an\">\U$_\E</a></strong></td></tr>\n";
861
            $numberhalf = ($numberofletter + 1 - (($numberofletter+1) % 2))/2;
862
            if ($debug > 2) { print "   $_: @{$_} \t $numberhalf \t $numberofletter\n"; }
863
            for($count = 0; $count < $numberhalf; $count++) {
864
               $name = @{$_}[$count];
865
               if ($LocalGlobalLocal eq 'global') { $dirpath = $hfilerelpath{$name}; } else { $dirpath = ""; }
866
               print IFILE "<tr><td width=\"50%\"><a href=\"$dirpath$mfilename{$name}$var{'exthtml'}\">$mfilename{$name}</a></td>";
867
               if (($count + $numberhalf) < $numberofletter) {
868
                  $name = @{$_}[$count + $numberhalf];
869
                  if ($LocalGlobalLocal eq 'global') { $dirpath = $hfilerelpath{$name}; } else { $dirpath = ""; }
870
                  print IFILE "<td width=\"50%\"><a href=\"$dirpath$mfilename{$name}$var{'exthtml'}\">$mfilename{$name}</a></td></tr>\n";
871
               } else {
872
                  print IFILE "<td width=\"50%\"></td></tr>\n";
873
               }
874
            }
875
         }
876
      }
877
      print IFILE "</table>\n<br />$var{'codehr'}\n";
878
879
   } elsif ($LocalShortLong eq 'long') {
880
      # begin create long index
881
      print IFILE "<table border=\"5\" width=\"100%\" cellpadding=\"5\">\n";
882
      print IFILE "<tr align=\"center\"><th>Name</th><th>Description</th></tr>\n";
883
884
      for('a'..'z') {
885
         # print "   $_: @{$_}\n";
886
         $numberofletter = $#{$_}+1;
887
         if ($numberofletter > 0) {
888
            $firstone = 1;
889
            foreach $name (@{$_}) {
890
               if ($debug > 1) { print "   AZinforeach1: $name \t\t $hfilerelpath{$name} \t\t $dirnamerelpath{$LocalActDir}\n"; }
891
               if ($LocalGlobalLocal eq 'global') { $dirpath = $hfilerelpath{$name}; } else { $dirpath = ""; }
892
               if (! ($mfilename{$name} =~ /contents/i)) {
893
                  if ($firstone == 1) { print IFILE "\n<tr><td colspan=\"2\"><br /><strong><a name=\"\U$_\E$_\" class=\"an\">\U$_\E</a></strong></td></tr>\n"; $firstone = 0; }
894
                  print IFILE "<tr><td valign=\"top\"><a href=\"$dirpath$mfilename{$name}$var{'exthtml'}\">$mfilename{$name}</a></td><td>$apropos{$name}</td></tr>\n";
895
               }
896
            }
897
         }
898
      }
899
      print IFILE "</table>\n<br />$var{'codehr'}\n";
900
   } else { die "wrong parameter for LocalShortLong in ConstructAZIndexFile: $LocalShortLong."; }
901
902
   # Include info about author from authorfile
903
   &WriteFile2Handle($var{'authorfile'}, IFILE);
904
905
   print IFILE "<!--navigate-->\n";
906
   print IFILE "<!--copyright-->\n";
907
   print IFILE "</body>\n</html>\n";
908
909
   close(IFILE);
910
911
   if ($opt_silent) { print "\r"; }
912
   print "   Indexfile small (A-Z) created: $indexfile\t";
913
   if (!$opt_silent) { print "\n"; }
914
915
916
   # Build the A-Z jump index file name
917
   # handle the global index file case separately (no extra directory name in file)
918
   if ($LocalGlobalLocal eq 'global') { $extradirfilename = ''; }
919
   else { $extradirfilename = $dirnamesingle{$LocalActDir}; }
920
921 382:baff1c482d98 Chris
   if ($var{'frames'} eq 'yes') {
922
923
       $indexfile = $var{'dirhtml'}.$dirnamerelpath{$LocalActDir}.$indexfilename.$var{'filenameextensionjump'}.$extradirfilename.$var{'exthtml'};
924
       if ($debug > 2) { print "   indexfilename (a-z jump): $indexfile\n"; }
925
       open(IFILE,">$indexfile") || die("Cannot open jump index file $indexfile: $!\n");
926
927
       # Write the header of HTML file
928
       print IFILE "$TextDocTypeHTML\n<html>\n<head>\n$var{'codeheadmeta'}\n$TextMetaCharset\n$var{'csslink'}\n";
929
930
       if ($var{'texttitleindex'} eq '') {
931
	   print IFILE "<title>A-Z jump index in directory $LocalActDir</title>\n";
932
       } else {
933
	   if ($LocalGlobalLocal eq 'global') { print IFILE "<title>$var{'texttitleindex'}</title>\n"; }
934
	   else { print IFILE "<title>$var{'texttitleindex'} in Directory $LocalActDir</title>\n"; }
935
       }
936
937
       if ($var{'frames'} eq 'yes') {
938
	   print IFILE "<base target=\"$GlobalNameFrameAZIndexsmall\" />\n";
939
       }
940
       print IFILE "</head>\n";
941
       print IFILE "<body $var{'codebodyindex'}>\n";
942
943
       # Write the A-Z jump line, generate link for letters with files starting with this letter
944
       # and only letters for no files starting with this letter
945
       # use previously generated arrays with names of files sorted by starting letter
946
       for('a'..'z') {
947
	   $numberofletter = $#{$_}+1;
948
	   if ($numberofletter > 0) {
949
	       print IFILE "<strong><a href=\"$indexfilename$var{'filenameextensionindex'}$extradirfilename$var{'exthtml'}#\U$_\E$_\">\U$_\E</a> </strong>\n";
950
	   } else {
951
	       print IFILE "\U$_\E \n";
952
	   }
953
       }
954
955
       print IFILE "</body>\n</html>\n";
956
957
       close(IFILE);
958
959
       if ($opt_silent) { print "\r"; }
960
       print "   Indexfile small (A-Z jump) created: $indexfile\t";
961
       if (!$opt_silent) { print "\n"; }
962 381:2dc8163e9150 Chris
   }
963
964
965
   # Build the frame layout file, this file includes the layout of the frames
966
   # Build the frame layout file name (for small/compact A-Z index)
967
   # handle the global index file case separately (no extra directory name in file)
968
   if ($LocalGlobalLocal eq 'global') { $extradirfilename = ''; }
969
   else { $extradirfilename = $dirnamesingle{$LocalActDir}; }
970
971 382:baff1c482d98 Chris
   if ($var{'frames'} eq 'yes') {
972 381:2dc8163e9150 Chris
973 382:baff1c482d98 Chris
       $indexfile = $var{'dirhtml'}.$dirnamerelpath{$LocalActDir}.$indexfilename.$var{'filenameextensionframe'}.$extradirfilename.$var{'exthtml'};
974
       if ($debug > 2) { print "   indexfilename (a-z frame): $indexfile\n"; }
975 381:2dc8163e9150 Chris
976 382:baff1c482d98 Chris
       open(IFILE,">$indexfile") || die("Cannot open jump index frame file $indexfile: $!\n");
977
978
       # Write the header of Frame file
979
       print IFILE "$TextDocTypeHTML\n<html>\n<head>\n$var{'codeheadmeta'}\n$TextMetaCharset\n$var{'csslink'}\n";
980
981
       if ($var{'texttitleindex'} eq '') {
982
	   print IFILE "<title>Index of Matlab Files in Directory $LocalActDir</title>\n";
983
       } else {
984
	   if ($LocalGlobalLocal eq 'global') { print IFILE "<title>$var{'texttitleindex'}</title>\n"; }
985
	   else { print IFILE "<title>$var{'texttitleindex'} in Directory $LocalActDir</title>\n"; }
986
       }
987
       print IFILE "</head>\n";
988
989
       # definition of 2 frames, top the A-Z index, below the jump letter line
990
       print IFILE "<frameset  rows=\"90%,10%\">\n";
991
       print IFILE "   <frame src=\"$indexfilename$var{'filenameextensionindex'}$extradirfilename$var{'exthtml'}\" name=\"$GlobalNameFrameAZIndexsmall\" />\n";
992
       print IFILE "   <frame src=\"$indexfilename$var{'filenameextensionjump'}$extradirfilename$var{'exthtml'}\" name=\"$GlobalNameFrameAZIndexjump\" />\n";
993
       print IFILE "</frameset>\n";
994
995
       print IFILE "</html>\n";
996
997
       close(IFILE);
998
999
       if ($opt_silent) { print "\r"; }
1000
       print "   Frame layout file created: $indexfile\t";
1001
       if (!$opt_silent) { print "\n"; }
1002 381:2dc8163e9150 Chris
   }
1003
}
1004 382:baff1c482d98 Chris
1005 381:2dc8163e9150 Chris
1006
#========================================================================
1007
# Construct the links to all indexes
1008
#========================================================================
1009
sub ConstructLinks2Index
1010
{
1011
   local(*WRITEFILE, $LocalPath2Index, $PathContents, $LocalGlobalLocal) = @_;
1012
1013
   # include links to short/long - local/global index and C|contents.m
1014
   print WRITEFILE "\n<p align=\"center\">";
1015
   print WRITEFILE "$var{'textjumpindexglobal'} (";
1016 382:baff1c482d98 Chris
1017
   if ($var{'frames'} eq 'yes') {
1018
       print WRITEFILE "<a href=\"$LocalPath2Index$var{'filenameindexshortglobal'}$var{'filenameextensionframe'}$var{'exthtml'}\">short</a> | ";
1019
   } else {
1020
       print WRITEFILE "<a href=\"$LocalPath2Index$var{'filenametopframe'}.$var{'exthtml'}\">short</a> | ";
1021
   }
1022
1023
   print WRITEFILE "<a href=\"$LocalPath2Index$var{'filenameindexlongglobal'}$var{'filenameextensionframe'}$var{'exthtml'}\">long</a>)\n";
1024 381:2dc8163e9150 Chris
   if ($LocalGlobalLocal eq 'local') {
1025
      if ($var{'usecontentsm'} eq 'yes') {
1026
         print WRITEFILE " | <a href=\"$contentsname{$PathContents}$dirnamesingle{$PathContents}$var{'exthtml'}\">Local contents</a>\n";
1027
      }
1028
      # if ($var{'producetree'} eq 'yes') {
1029
         print WRITEFILE " | $var{'textjumpindexlocal'} (";
1030 382:baff1c482d98 Chris
         print WRITEFILE "<a href=\"$var{'filenameindexshortlocal'}$var{'filenameextensionframe'}$dirnamesingle{$PathContents}$var{'exthtml'}\">short</a> | ";
1031
         print WRITEFILE "<a href=\"$var{'filenameindexlonglocal'}$var{'filenameextensionframe'}$dirnamesingle{$PathContents}$var{'exthtml'}\">long</a>)\n";
1032 381:2dc8163e9150 Chris
      # }
1033
   }
1034
   print WRITEFILE "</p>\n\n";
1035
   print WRITEFILE "$var{'codehr'}\n";
1036
}
1037
1038
1039
#========================================================================
1040
# Construct the contents.m files or update
1041
#========================================================================
1042
sub ConstructContentsmFile
1043
{
1044
   local($LocalActDir, @localnames) = @_;
1045
   local(*CFILE, $name,$newline);
1046
   local($contentsfile, $isincontentsonly);
1047
   local(@lines, @autoaddlines, @emptylines);
1048
   local($autoadd) = 'AutoAdd';
1049
   local($autoaddsection) = 0;
1050
   local($emptylineflag) = 0;
1051
   local(%nameincontents);
1052
1053
   # Build the contents file name
1054
   $contentsfile = $LocalActDir.$contentsname{$LocalActDir}.$suffix;
1055
1056
   if (-e $contentsfile) {
1057
      open(CFILE,"<$contentsfile") || die("Cannot open contents file $contentsfile: $!\n");
1058
      while (<CFILE>) {
1059
         # Search for the specified string pattern
1060
         @words = split;
1061
         if ((@words >= 3) && ($words[2] eq '-')) {
1062
            $isincontentsonly = 0;
1063
            foreach $name (@localnames) {
1064
               if ($name eq $words[1]) {    # old
1065
               # if ($mfilename{$name} eq $words[1]) {
1066
                  $isincontentsonly = 1;
1067
                  $nameincontents{$name} = 1;
1068
                  $newline = sprintf("%% %-13s - %s\n", $mfilename{$name}, $apropos{$name});
1069
                  push(@lines, $newline);
1070
               }
1071
            }
1072
            # issue a warning, if file is in contents, but not as file in the directory
1073
            if ($isincontentsonly == 0) {
1074
               print "\rConstructContents: Obsolete entry  $words[1]  in  $contentsfile ! Entry not used.\n";
1075
            }
1076
         } else {
1077
            # look for the AutoAdd section, should be the second word
1078
            if ((@words >= 2) && ($words[1] eq $autoadd)) { $autoaddsection = 1; }
1079
            # push the red line in an array
1080
            push(@lines, $_);
1081
         }
1082
      }
1083
      close(CFILE);
1084
   } else {
1085
      $newline = "% MATLAB Files in directory  $LocalActDir\n%\n";
1086
      push(@lines, $newline);
1087
1088
   }
1089
1090
   # collect the file names, that were not included in original C|contents.m
1091
   foreach $name (@localnames) {
1092
      if (! defined $nameincontents{$name}) {
1093
         if (! ($mfilename{$name} =~ /contents/i)) {
1094
            $newline = sprintf("%% %-13s - %s\n", $mfilename{$name}, $apropos{$name});
1095
            push(@autoaddlines, $newline);
1096
         }
1097
      }
1098
   }
1099
1100
   # write/update C|contents.m only if variable is set
1101
   if ($var{'writecontentsm'} eq 'yes') {
1102
      unlink($contentsfile);
1103
      open(CFILE,">$contentsfile") || die("Cannot open contents file $contentsfile: $!\n");
1104
      # write old C|contents.m or header of new file, as long as comment lines
1105
      foreach $line (@lines) {
1106
         if ($emptylineflag == 0) {
1107
            if ($line =~ /^\s*%/) { print CFILE $line; }
1108
            else { $emptylineflag = 1; push(@emptylines, $line); }
1109
         } else { push(@emptylines, $line); }
1110
      }
1111
      # add header of AutoAdd section
1112
      if (($autoaddsection == 0) && (@autoaddlines > 0)) { print CFILE "%\n% $autoadd\n"; }
1113
      # add autoadd section lines (previously undocumented files
1114
      foreach $line (@autoaddlines) { print CFILE $line; }
1115
      # add tail of original C|contents.m (everything behind first non-comment line)
1116
      foreach $line (@emptylines)   { print CFILE $line; }
1117
      print CFILE "\n";
1118
      close CFILE;
1119
      if ($opt_silent) { print "\r"; }
1120
      print "   Contents file created/updated: $contentsfile\t";
1121
      if (!$opt_silent) { print "\n"; }
1122
   }
1123
}
1124
1125
1126
#========================================================================
1127
# Replace found special characters with their HTMl Entities
1128
#========================================================================
1129
sub SubstituteHTMLEntities {
1130
   local($_) = @_;
1131
1132
   # Replace & <-> &amp;  < <-> &lt;  > <-> &gt;  " <-> &quot;
1133
   s/&/&amp;/g; s/\</&lt;/g; s/\>/&gt;/g; s/\"/&quot;/g;
1134
   return $_;
1135
}
1136
1137
#========================================================================
1138
# Replace found m-filenamestring with full link.
1139
#========================================================================
1140
sub SubstituteName2Link {
1141
   local($_, $funname) = @_;
1142
   local($refstr1, $refstr2, $reffound);
1143
1144
   # Look for something matching in the line
1145
   if ( /(\W+)($funname)(\W+)/i ) {
1146
      $reffound = $2;
1147
      $refstr1 = "<a class=\"mfun\" href=\"$hfileindexpath{$name}$hfilerelpath{$funname}$funname$var{'exthtml'}\">";
1148
      $refstr2 = "<\/a>";
1149
      # Do links only for exact case match
1150
      if ( ($var{'links2filescase'}  eq 'exact') || ($var{'links2filescase'}  eq 'exactvery') ) {
1151
         if ( /(\W+)($funname)(\W+)/g ) {
1152
            s/(\W+)($funname)(\W+)/$1$refstr1$funname$refstr2$3/g;
1153
         }
1154
         else {
1155
            # Print info for not matching case in references, good for check up of files
1156
            if ( ($var{'links2filescase'}  eq 'exactvery') ) {
1157
               print "Diff in case found: $funname  (case of file name)   <->  $reffound  (case in source code)\n";
1158
               print "     (source line)  $_ \n";
1159
            }
1160
         }
1161
      }
1162
      # Do links for exact match and additionally for all upper case (often used in original matlab help text)
1163
      elsif ( ($var{'links2filescase'}  eq 'exactupper') ) {
1164
         s/(\W+)($funname)(\W+)/$1$refstr1$2$refstr2$3/g;
1165
         $funname2 = "\U$funname\E";
1166
         s/(\W+)($funname2)(\W+)/$1$refstr1$2$refstr2$3/g;
1167
      }
1168
      # Do links for all case mixes, this calls for trouble under LINUX/UNIX
1169
      else {  #elsif ( ($var{'links2filescase'}  eq 'all') )
1170
         s/(\W+)($funname)(\W+)/$1$refstr1$2$refstr2$3/ig;
1171
      }
1172
   }
1173
1174
   return $_;
1175
}
1176
1177
#========================================================================
1178
# Construct the html files for each matlab file.
1179
#    Need to reread each matlab file to find the help text.
1180
#    Note that we can't do this in a single loop because sometimes
1181
#    the help text maybe before the function declaration.
1182
#========================================================================
1183
sub ConstructHTMLFiles
1184
{
1185
   local(*MFILE);
1186
   local(*HFILE);
1187
1188
   local($filescreated) = 0;
1189
   local($functionline);
1190
1191
   foreach $name (@names) {
1192
      # Create cross reference information already here, used for keywords as well
1193
      # Construct list of referenced functions
1194
      @xref = @{'depcalls'.$name};    # the functions, that this m-file calls
1195
      @yref = @{'depcalled'.$name};   # the functions, that this m-file is called from
1196
      # print "   depcalls: @{'depcalls'.$name}\n   depcalled: @{'depcalled'.$name}\n";
1197
      # foreach $cname (@names) { next if $cname eq $name; push(@yref,$cname) if grep(/$name/,@{'depcalls'.$cname}); }
1198
1199
1200
      # Open m-file and html-file
1201
      open(MFILE,"<$mfile{$name}");
1202
      open(HFILE,">$hfile{$name}");
1203
1204
      # Write the header of HTML file
1205
      print HFILE "$TextDocTypeHTML\n<html>\n<head>\n$var{'codeheadmeta'}\n$TextMetaCharset\n$var{'csslink'}\n";
1206
1207
      # Write meta tags: use apropos (one line function description) for description
1208
      # and cross reference function names for keywords (any better ideas?)
1209
      print HFILE "<meta name=\"description\" content=\" $apropos{$name} \" />\n";
1210
      print HFILE "<meta name=\"keywords\" content=\" @xref @yref \" />\n";
1211
1212
      # Write Title and start body of html-file
1213
      print HFILE "<title>$var{'texttitlefiles'} $mfilename{$name}</title>\n</head>\n";
1214
      print HFILE "<body $var{'codebodyfiles'}>\n";
1215
      print HFILE "<h1 $var{'codeheader'}>$var{'textheaderfiles'} $mfilename{$name}</h1>\n";
1216
      print HFILE "$var{'codehr'}\n";
1217
1218
      # include links to short/long - local/global index and C|contents.m
1219
      &ConstructLinks2Index(HFILE, $hfileindexpath{$name}, $mfiledir{$name}, 'local');
1220
1221
      # If this is a function, then write out the first line as a synopsis
1222
      if ($mtype{$name} eq "function") {
1223
         print HFILE "<h2 $var{'codeheader'}>Function Synopsis</h2>\n";
1224
         print HFILE "<pre>$synopsis{$name}</pre>\n$var{'codehr'}\n";
1225
      }
1226
1227
      # Look for the matlab help text block
1228
      $functionline = "\n";
1229
      do {
1230
         $_ = <MFILE>;
1231
         # remember functionline, if before help text block
1232
         if (/^\s*function/) { $functionline = $_; }
1233
      } until (/^\s*%/ || eof);
1234
      if (! (eof(MFILE))) {
1235
         print HFILE "<h2 $var{'codeheader'}>Help text</h2>\n";
1236
         print HFILE "<pre>\n";
1237
         while (/^\s*%/) {
1238
            # First remove leading % and white space, then Substitute special characlers
1239
            s/^\s*%//;
1240
            $_ = &SubstituteHTMLEntities($_);
1241
1242
            # check/create cross references
1243
            foreach $funname (@{'all'.$name}) {
1244
               if ($funname =~ /simulink/) { print "\n Simulink - Filename: $name;  scanname: $funname\n"; }
1245
               next if $funname eq $name;
1246
               $_ = &SubstituteName2Link($_, $funname);
1247
            }
1248
            print HFILE $_;
1249
            if (! eof) { $_ = <MFILE>; }
1250
         }
1251
         print HFILE "</pre>\n$var{'codehr'}\n";
1252
      }
1253
1254
      # Write the cross reference information
1255
      if (@xref || @yref) {
1256
         print HFILE "<h2 $var{'codeheader'}>Cross-Reference Information</H2>\n";
1257
         print HFILE "<table border=\"0\" width=\"100%\">\n<tr align=\"left\">\n<th width=\"50%\">";
1258
         if (@xref) {
1259
            print HFILE "This $mtype{$name} calls";
1260
         }
1261
         print HFILE "</th>\n<th width=\"50%\">";
1262
         if (@yref) {
1263
            print HFILE "This $mtype{$name} is called by";
1264
         }
1265
         print HFILE "</th>\n</tr>\n<tr valign=\"top\"><td>";
1266
         if (@xref) {
1267
            print HFILE "\n<ul>\n";
1268
            foreach $cname (sort @xref) {
1269
               print HFILE "<li><a class=\"mfun\" href=\"$hfileindexpath{$name}$hfilerelpath{$cname}$mfilename{$cname}$var{'exthtml'}\">$mfilename{$cname}</a></li>\n";
1270
            }
1271
            print HFILE "</ul>\n";
1272
         }
1273
         print HFILE "</td><td>";
1274
         if (@yref) {
1275
            print HFILE "\n<ul>\n";
1276
            foreach $cname (sort @yref) {
1277
               print HFILE "<li><a class=\"mfun\" href=\"$hfileindexpath{$name}$hfilerelpath{$cname}$mfilename{$cname}$var{'exthtml'}\">$mfilename{$cname}</a></li>\n";
1278
            }
1279
            print HFILE "</ul>\n";
1280
         }
1281
         print HFILE "</td>\n</tr>\n</table>\n";
1282
         print HFILE "$var{'codehr'}\n";
1283
      }
1284
1285
      # Include source text if requested
1286
      if (($var{'includesource'} eq 'yes') && (! ($mfilename{$name} =~ /^contents$/i))) {
1287
         print HFILE "<h2 $var{'codeheader'}>Listing of $mtype{$name} $mfilename{$name}</h2>\n";
1288
         seek(MFILE,0,0);
1289
         print HFILE "<pre>\n";
1290
         $IsStillHelp = 2;
1291
         print HFILE $functionline;    # functionline from scanning of help
1292
         while (<MFILE>) {
1293
            if ($IsStillHelp == 2) {
1294
               next     if (/^\s*$/);
1295
               next     if (/^\s*function/);
1296
               if (/^\s*%/) { $IsStillHelp = 1; next; }
1297
            } elsif ($IsStillHelp == 1) {
1298
               next     if (/^\s*%/);
1299
               $IsStillHelp = 0;
1300
            }
1301
1302
            # Substritute special characters
1303
            $_ = &SubstituteHTMLEntities($_);
1304
1305
            # check for comment in line and format with css em
1306
            s/(.*)%(.*)/$1<em class=\"mcom\">%$2<\/em>/;
1307
1308
            # check/create cross references
1309
            foreach $funname (@{'all'.$name}) {
1310
               next if $funname eq $name;
1311
               $_ = &SubstituteName2Link($_, $funname);
1312
            }
1313
            print HFILE $_;
1314
         }
1315
         print HFILE "</pre>\n$var{'codehr'}\n";
1316
      }
1317
1318
      # Include info about author from authorfile
1319
      &WriteFile2Handle($var{'authorfile'}, HFILE)   ;
1320
1321
      print HFILE "<!--navigate-->\n";
1322
      print HFILE "<!--copyright-->\n";
1323
      print HFILE "</body>\n</html>\n";
1324
      close(MFILE);
1325
      close(HFILE);
1326
1327
      # Print name of finished file
1328
      if ($opt_silent) { print "\r"; }
1329
      print "   HTML-File created: $hfile{$name}\t";
1330
      if (!$opt_silent) { print "\n"; }
1331
      $filescreated++;
1332
   }
1333
1334
   print "\n$PROGRAM: $indexcreated index and $filescreated files created.\n";
1335
}
1336
1337
#========================================================================
1338
# Function:	CheckFileName
1339
# Purpose:	.
1340
#========================================================================
1341
sub CheckFileName {
1342
   local($filename, $description) = @_;
1343
   local(*CHECKFILE);
1344
1345
   open(CHECKFILE,"<$filename") || do {
1346
      if ($description eq '') {$description = 'file';}
1347
      # if (!$opt_silent) { print "Cannot open $description $filename: $!\n"; }
1348
      print "Cannot open $description $filename: $!\n";
1349
      return 1;
1350
   };
1351
   close(CHECKFILE);
1352
   return 0;
1353
1354
}
1355
1356
#========================================================================
1357
# Function:	CheckDirName
1358
# Purpose:	.
1359
#========================================================================
1360
sub CheckDirName {
1361
   local($dirname, $description) = @_;
1362
   local(*CHECKDIR);
1363
1364
   opendir(CHECKDIR,"$dirname") || die ("Cannot open $description directory $dirname: $!\n");
1365
   closedir(CHECKDIR);
1366
}
1367
1368
#========================================================================
1369
# Function:	WriteFile2Handle
1370
# Purpose:	.
1371
#========================================================================
1372
sub WriteFile2Handle {
1373
   local($filename, *WRITEFILE) = @_;
1374
   local(*READFILE);
1375
1376
   if ($filename ne '') {
1377
      open(READFILE,"<$filename");
1378
      @filecontents = <READFILE>;
1379
      close(READFILE);
1380
      print WRITEFILE "@filecontents\n";
1381
      # if (!$opt_silent) {print "      Contents of $filename added\n"};
1382
   }
1383
}
1384
1385
1386
#========================================================================
1387
# Function:	GetConfigFile
1388
# Purpose:	Read user's configuration file, if such exists.
1389
#========================================================================
1390
sub GetConfigFile
1391
{
1392
   local($filename) = @_;
1393
   local(*CONFIG);
1394
   local($value);
1395
1396
   if (&CheckFileName($filename, 'configuration file')) {
1397
      # if (!$opt_silent) { print "   Proceeding using built-in defaults for configuration.\n"; }
1398
      print "   Proceeding using built-in defaults for configuration.\n";
1399
      return 0;
1400
   };
1401
1402
   open(CONFIG,"< $filename");
1403
   while (<CONFIG>) {
1404
      s/#.*$//;
1405
      next if /^\s*$/o;
1406
1407
      # match keyword: process one or more arguments
1408
      # keyword set
1409
      if (/^\s*set\s+(\S+)\s*=\s*(.*)/) {
1410
         # setting a configuration variable
1411
         if (defined $var{$1}) {
1412
            $var{$1} = $2;
1413
            if ($debug > 3) { print "$1:   $var{$1}\n"; }
1414
         }
1415
         else {
1416
            print "$PROGRAM: unknown variable `$1' in configuration file\n"
1417
         }
1418
      } else {
1419
         chop($_);
1420
         print "$PROGRAM: unknown keyword in configuration file in line: `$_'\n"
1421
      }
1422
   }
1423
   close CONFIG;
1424
   1;
1425
}
1426
1427
1428
#------------------------------------------------------------------------
1429
# DisplayHelp - display help text using -h or -help command-line switch
1430
#------------------------------------------------------------------------
1431
sub DisplayHelp
1432
{
1433
   $help=<<EofHelp;
1434
   $PROGRAM v$VERSION - generate html documentation from Matlab m-files
1435
1436
   Usage: $PROGRAM [-h] [-c config_file] [-m|dirmfiles matlab_dir] [-d|dirhtml html_dir]
1437
                   [-i yes|no] [-r yes|no] [-p yes|no] [-quiet|q] [-a authorfile]
1438
1439
   $PROGRAM is a perl script that reads each matlab .m file in a directory
1440
   to produce a corresponding .html file of help documentation and cross
1441
   reference information. An index file is written with links to all of
1442
   the html files produced. The options are:
1443
1444
      -quiet         or -q : be silent, no status information during generation
1445
      -help          or -h : display this help message
1446
      -todo          or -t : print the todo list for $PROGRAM
1447
      -version       or -v : display version
1448
1449
      -configfile    or -c : name of configuration file (default to $var{'configfile'}).
1450
      -dirmfiles     or -m : top level directory containing matlab files to generate html for;
1451
                             default to actual directory.
1452
      -dirhtml       or -d : top level directory for generated html files;
1453
                             default to actual directory.
1454
1455
      -includesource or -i : Include matlab source in the html documentation [yes|no]
1456
                             default to yes.
1457
      -processtree   or -r : create docu for m-file directory and all subdirectories [yes|no];
1458
                             default to yes.
1459
      -producetree   or -p : create multi-level docu identical to directory structure
1460
                             of m-files [yes|no]; default to yes.
1461
      -writecontentsm or -w: update or write contents.m files into the matlab source
1462
                             directories [yes|no]; default to no.
1463
1464
      -authorfile    or -a : name of file including author information, last element in html;
1465
                             default to empty.
1466
1467
   The command line setting overwrite all other settings (built-in and configuration file).
1468
   The configuration file settings overwrite the built-in settings (and not the command
1469
   line settings).
1470
1471
   Typical usages are:
1472
     $PROGRAM
1473
        (use default parameters from perl script, if configuration
1474
         file is found -> generation of docu, else display of help)
1475
1476
     $PROGRAM -dirmfiles matlab -dirhtml html
1477
        (generate html documentation for all m-files in directory matlab,
1478
         place html files in directory html, use built-in defaults for
1479
         all other parameters, this way all m-files in the directory
1480
         matlab and below are converted and the generated html-files are
1481
         placed in the directory html and below producing the same
1482
         directory structure than below matlab)
1483
1484
     $PROGRAM -quiet
1485
        (use built-in parameters from perl script, if configuration
1486
         file is found use these settings as well, do generation,
1487
         no display except critical errors, status of conversion and result)
1488
1489
     $PROGRAM -m toolbox -dirhtml doc/html -r yes -p no
1490
        (convert all m-files in directory toolbox and below and place
1491
         the generated html files in directory doc/html, read all m-files
1492
         recursively, however, the generated html files are placed in one
1493
         directory)
1494
1495
     $PROGRAM -m toolbox -dirhtml doc/html -i no -r no
1496
        (convert all m-files in directory toolbox and place
1497
         the generated html files in directory doc/html, do not read m-files
1498
         recursively, do not include source code in documentation)
1499
1500
EofHelp
1501
1502
   die "$help";
1503
}
1504
1505
#------------------------------------------------------------------------
1506
# DisplayTodo - display ToDo list using -t or -todo command-line switch
1507
#------------------------------------------------------------------------
1508
sub DisplayTodo
1509
{
1510
   $todo=<<EofToDo;
1511
      $PROGRAM v$VERSION - ToDo list
1512
1513
       o	use more than one high level directory
1514
1515
       o	what should/could be done here???
1516
1517
EofToDo
1518
1519
   die "$todo";
1520
}
1521
1522
1523
#------------------------------------------------------------------------
1524
# ListVariables - list all defined variables and their values
1525
#------------------------------------------------------------------------
1526
sub ListVariables
1527
{
1528
   local($value);
1529
1530
   if ($debug > 0) {
1531
      print "List of all variables and their values\n";
1532
      foreach (sort keys %var)
1533
      {
1534
         if ($var{$_} eq '') {
1535
            $value = "empty";
1536
         } else {
1537
            $value = $var{$_};
1538
         }
1539
         print "   $_\n      $value\n";
1540
      }
1541
      print "\n\n";
1542
   }
1543
}
1544
1545
1546
__END__
1547
:endofperl