summaryrefslogtreecommitdiff
path: root/lib/sbin/InterLatex.pl
blob: cb558948a0c973bcb12233cfcd4af8c27b4d6538 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
#!/usr/bin/perl -s

#use strict;
use vars qw($cctk_home $debug $verbose $h $help $document_type $outdir $directory $thornlist); 

#/*@@
#  @file      InterLatex.pl
#  @date      Sun Mar  3 19:05:41 CET 2002
#  @author    Ian Kelley
#  @desc 
#  This program will take as input a thornlist, and outputs a latex table    
#  that contains the information in the thorns' interface.ccl file(s).  This latex
#  table can then be used as a stand-alone document, or as a section of a large
#  "ThornGuide"         
#  @enddesc 
#  @version 
#@@*/

#########################
# ->> InterLatex.pl <<- #
#########################################################################
#                                                                       #
#                      standard help function                           #
#                                                                       #
#########################################################################
if ($h || $help) {
   print "--> InterLatex.pl <--\n";
   print "Options:\n";
   print "\t-thornlist=     : thornlist to process\n";
   print "\t-directory=     : directory of arrangements (default arrangements/)\n";
   print "\t-outdir=        : directory to dump output files, default is .\n";
   print "\t-document_type= : create a 'document' or 'section'\n";
   print "\t-cctk_home=     : root directory of cactus installation\n";
   print "\n";
   print "\t-verbose        : gives verbose output to screen\n";
   print "\t-debug          : debug mode, does not produce output files\n";
   print "\t-h|-help        : this screen\n";
   print "Example:\n";
   print "\t\$ perl -s lib/sbin/InterLatex.pl -outdir=/tmp/ -thornlist=WaveToyC.th -document_type=document \n";
   exit 0;
}

# setup the cctk_home, if it doesn't exist, we leave it blank
$cctk_home  .= '/' if (($cctk_home !~ /\/$/) && (defined $cctk_home));

# set up the sbin dir, tacking cctk_home on the front
my $sbin_dir = "${cctk_home}lib/sbin";

##############
# REQUIRE(S) #
##############

# common procedures used to create the thornguide(s)
require "$sbin_dir/ThornUtils.pm";

# for use of create_parametere_database
require "$sbin_dir/interface_parser.pl";
require "$sbin_dir/CSTUtils.pl";

# for reading of the thornlist routine: %thorns = &ReadThornlist($thornlist)
require "$sbin_dir/MakeUtils.pl";

#####################
# INITIAL VARIABLES #
#####################

my $start_directory = `pwd`;
chomp ($start_directory);

my @valid_groups = qw(private public protected);

# fixed width of table
my $width = "150mm";

# spacing between tables
my $spacing      = "3mm";

# maximum number of cells in a table before we split the table
my $cellsintable = 6;

# set some defaults
$document_type  ||= 'section';

# set some variables in ThornUtils(.pm) namespace
$ThornUtils::cctk_home          = $cctk_home;
$ThornUtils::start_directory    = $start_directory;
$ThornUtils::verbose            = $verbose;
$ThornUtils::debug              = $debug;

##################
# INITIALIZATION #
##################
my %thorns;
my %arrangements;
my %system_database;
my %interface_database;
my %arrangements_database;
my %pathsToThorns;

my @listOfThorns;

ThornUtils::CreateSystemDatabase(\%system_database);

# get/setup the output directory and the arrangements directory
$outdir                 = ThornUtils::SetupOutputDirectory($outdir);
my $arrangements_dir    = ThornUtils::GetArrangementsDir($directory);

# determine thornlist, create one if one doesn't exist
if (defined $thornlist) {
   # provided by MakeUtils.pl, returns a hash with a list of the thorns in our thornlist
   %thorns       = &ReadThornlist($thornlist);
   @listOfThorns = sort keys %thorns;
} else {
   # we don't have a thornlist, go find all thorns in arrangements directory
   @listOfThorns = ThornUtils::CreateThornlist($arrangements_dir);
}

# returns a hash with keys as Arrangment/Thorn and values of the location of the interface.ccl file
%pathsToThorns         =  ThornUtils::GetThornPaths(\@listOfThorns, $arrangements_dir, "interface.ccl", 1);

# run the interface parser from 'interface_parser.pl'
%interface_database    = &create_interface_database(scalar(keys %system_database), %system_database, %pathsToThorns);

# parse up the output we just got into more of a tree-like format
%arrangements_database = &ReadInterfaceDatabase(\%interface_database);

if ($debug) {
   ThornUtils::Dump(\%arrangements_database);
   print "\n";
   exit 0;
} else {
   ThornUtils::ProcessAllArrangements(\%arrangements_database);
}

print "\nFinished.\n";

#########################################################################
#                 END OF MAIN SECTION OF THE PROGRAM                    # 
#########################################################################

#########################################################################
#                     BEGINNING OF SUB-ROUTINES                         #
#########################################################################

#/*@@
#  @routine   ReadInterfaceDatabase
#  @date      Sun Mar  3 01:54:37 CET 2002
#  @author    Ian Kelley
#  @desc 
#     Will parse up the interfaceDatabase created by create_interface_database in 
#     interface_parser.pl.   Creates (then returns) a hash of hash of hashes, etc
#     that contains all the information split up into more of a tree structure for
#     easy iteration and printing.
#     
#     Creates something in the form of:
#        $newDatabase{"CactusWave"}->{"WaveToyC"}->{"add"}->{"header"} = "something.h somethingother.h";
#
#  @enddesc 
#  @version 
#@@*/
sub ReadInterfaceDatabase 
{
   my (%interfaceDatabase)      = %{$_[0]};

   my %newDatabase;

   foreach (sort keys %interfaceDatabase)
   {
      print STDERR "\n--> [$_] = [$interfaceDatabase{$_}]" if ($debug || $verbose);

      # save he original key, as we will make it all lower case later
      # and need the original for hash keys
      my $old_key = $_;

      # just in case they have declared it, but put nothing in it.
      # if they did, don't waste our time parsing it.
      #next if (! $interfaceDatabase{$old_key} =~ /\w/);

      # drop the keys to lower-case, as they are all upper-case
      tr/A-Z/a-z/;
      /^(.*?)\/(.*?)( |$)/;

      my ($arrangement, $thorn) = ($1, $2);

      next if /^implementation/;
      next if ($interfaceDatabase{$old_key} !~ /\w/);
   

      # try to categorize things, we have a few exceptions in here we have to deal with so that hash variables
      # are not overwriting their old values.  This whole process will give us a hash in the form of:
      #     $newDatabase{"CactusWave"}->{"WaveToyC"}->{"add"}->{"header"} = "something.h somethingother.h";
      if (/^([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)$/) {
             $newDatabase{$arrangement}->{$thorn}->{$2}->{$3}->{$4}->{$5}->{$6} = $interfaceDatabase{$old_key}; 
      } elsif (/^([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)$/) {
          if ($2 eq "add" || $2 eq "uses" || $2 eq "provides") {
             $newDatabase{$arrangement}->{$thorn}->{$2}->{$4}->{$5} = $interfaceDatabase{$old_key};
          } else {
             $newDatabase{$arrangement}->{$thorn}->{$2}->{$3}->{$4}->{$5} = $interfaceDatabase{$old_key};
          }
      } elsif (/^([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)$/) {
         if ($2 eq "group") {
               $newDatabase{$arrangement}->{$thorn}->{"group details"}->{$3}->{$4} = $interfaceDatabase{$old_key};
         } else {
               $newDatabase{$arrangement}->{$thorn}->{$2}->{$3}->{$4} = $interfaceDatabase{$old_key};
         }
      } elsif (/^([^\s]+) ([^\s]+) ([^\s]+)$/) {
          $newDatabase{$arrangement}->{$thorn}->{$2}->{$3} = $interfaceDatabase{$old_key};
      } elsif (/^([^\s]+) ([^\s]+)$/) { 
          $newDatabase{$arrangement}->{$thorn}->{$2} = $interfaceDatabase{$old_key};
      } else {
         print "\n--> Confused: [$_] = [$interfaceDatabase{$_}]";
      }
 
   }

   return %newDatabase;
}

#/*@@
#  @routine   ProcessOneThorn
#  @date      Sun Mar  3 01:54:37 CET 2002
#  @author    Ian Kelley
#  @desc 
#     This function is called by ThornUtils::ProcessOneArrangement, the main section of this program
#     calls ThornUtils::ProcessAllArrangements which calls ProcessOneArrangement.  Things are simply 
#     split up this way so that if later things ever wanted to be changed around more, then can be.
#
#  @enddesc 
#  @version 
#@@*/
sub ProcessOneThorn 
{
   # get the thorn hash
   my (%thorn)      = %{$_[0]};
   my $arrangement  = $_[1];
   my $thorn        = $_[2];

   # open up the output file
   my $ofh = ThornUtils::StartDocument("inter", $thorn, $outdir, $arrangement, "Interfaces", $document_type);
   
   # print out the table   
   &LatexTableElement(\%thorn);

   # close the output file
   ThornUtils::EndDocument($ofh, $document_type);
}


#/*@@
#  @routine   LatexTableElement
#  @date      Sun Mar  3 01:54:37 CET 2002
#  @author    Ian Kelley
#  @desc 
#    Takes whatever table element is currently reffered to by $table    
#    and prints it out into a LaTeX table.  Only nifty things it curr.  
#    does is NOT print ranges for BOOLEAN and SHARED elements.          
#
#  @enddesc 
#  @version 
#@@*/
sub LatexTableElement 
{
   # get the stuff passed in, first is a hash of the given variable, second is the name of the variable,
   # and third is the to-date longest variable in the thorn (for latex column formatting)
   my %thorn      = %{$_[0]};

   # get the different properties of the variable, and clean then up so we can output good latex
   my $variable_name = ThornUtils::CleanForLatex($_[1]);
   my @temp; 

   print "\n\\vspace\{$spacing\} \\subsection\*\{General\}";

   # print out implementations and inheriting
   PrintVar("Implements", $thorn{"implements"});
   PrintVar("Inherits",   $thorn{"inherits"}) if ($thorn{"inherits"} !~ /^$/);


   # now we are going to go through and print out stuff for each group type (public, private, protected, etc)
   my $printgridtitle = 1;
   foreach my $group_scope (@valid_groups) 
   {
      next if (! defined $thorn{$group_scope});

      my @groups = split/\s+/, $thorn{$group_scope}->{"groups"};

      next if (@groups < 1);

      print "\n\\subsection\*\{Grid Variables\}" if ($printgridtitle);

      my $gs_scope = $group_scope;
      $gs_scope    =~ tr/a-z/A-Z/;

      print "\n\\vspace\{5mm\}\\subsubsection\{$gs_scope GROUPS\}\n";
      print "\n\\vspace\{5mm\}\n\n\\begin\{tabular*\}\{$width\}\{|c|c\@\{\\extracolsep\{\\fill\}\}|rl|\} \\hline \n";
      print "~ \{\\bf Group Names\} ~ & ~ \{\\bf Variable Names\} ~  &\{\\bf Details\} ~ & ~\\\\ \n";
      print "\\hline \n";

      $printgridtitle = 0;
      my $counter     = 0;

      # where @groups is all the different groups for this thorn in this particular storage type (e.g private)
      foreach my $group (@groups) 
      {
         $group =~ tr/A-Z/a-z/;
         next if ($thorn{"group"}->{$group} =~ /^$/);
  
         # so we are splitting the table every so often, otherwise it could overrun off the page
         if (( ! ($counter % $cellsintable)) && ($counter ne 0) )
         {
            print "\\end\{tabular*\} \n\n";
            print "\n\n\\vspace\{5mm\}";
            print "\n\\vspace\{5mm\}\n\n\\begin\{tabular*\}\{$width\}\{|c|c\@\{\\extracolsep\{\\fill\}\}|rl|\} \\hline \n";
            print "~ \{\\bf Group Names\} ~ & ~ \{\\bf Variable Names\} ~  &\{\\bf Details\} ~ & ~ \\\\ \n";
            print "\\hline \n";
         }

         # print group name
         print ThornUtils::ToLower(ThornUtils::CleanForLatex($group));
         my $firstpass = 1;

         my @group_variables = split/\s+/, ThornUtils::CleanForLatex($thorn{"group"}{$group});

         $counter++;

         # now we are just dealing with one group, so we are going to go print out the details for it.
         my $var_counter = 0;
         foreach my $group_detail (sort keys %{$thorn{"group details"}->{$group}}) 
         {
            my $value = ThornUtils::CleanForLatex(ThornUtils::CleanFromC($thorn{"group details"}->{$group}->{$group_detail}));

            # print nothign as we are dealing with the same group
            if (! $firstpass) {
               print "~ &"; 
	       $firstpass = 0;
            }

            my $new_counter = 1;

            # split things (group properties) onto different lines if need be
            if (@temp = split/,/, $value) 
            {
               foreach my $val (@temp) 
               {
                  if ($new_counter--) {
                     print " & $group_variables[$var_counter] & " . ExpandGroupName($group_detail) . " & $val \\\\ \n";  
                  } else {
                     print "& ~ & " .  ExpandGroupName($group_detail) ." & $val \\\\ \n";
                  }
               }
            } else {
               print "$group_variables[$var_counter] & " . ExpandGroupName($group_detail) . " & $value \\\\ \n"; 
            }

            $var_counter++;
         } #foreach %{thorn...}

         print "\\hline \n";
      } #foreach @groups

      print "\\end\{tabular*\} \n\n";
      delete $thorn{$group_scope};
   } # foreach @valid_groups

   print "\n\n\\vspace\{5mm\}";

   # now we are going to print out some extra information that is general to the thorn
   PrintHeaderOrFunction("Adds Header", $thorn{"add"}->{"header"},        $thorn{"add"});
   PrintHeaderOrFunction("Uses Header", $thorn{"uses"}->{"header"},       $thorn{"uses"});
   PrintHeaderOrFunction("Provides",    $thorn{"provides"}->{"function"}, $thorn{"provides"});
} 

#/*@@
#  @routine   PrintVar
#  @date      Sun Mar  3 01:54:37 CET 2002
#  @author    Ian Kelley
#  @desc 
#     Used to  print out a variable by spitting it if we need to, used for printing stuff like
#     what a group "inherits" or "implements"
#
#  @enddesc 
#  @version 
#@@*/
sub PrintVar 
{
   my $title = shift;
   my $var   = shift;

   my %alias = %{$_[0]};
   
   my @temp;

   return if ($var !~ /\w/);

   print "\n\n\\noindent \{\\bf ". ThornUtils::Translate(ThornUtils::CleanForLatex($title)) ."\}: ";

   if (@temp = split/\s+/, $var)
   {
      foreach (@temp) {
         print "\n\n" . ThornUtils::ToLower(ThornUtils::CleanForLatex($_));
      }
   } else {
      print "\n\n" . ThornUtils::ToLower(ThornUtils::CleanForLatex($var));
   }
   print "\n\\vspace\{2mm\}";
}

#/*@@
#  @routine   PrintHeaderOrFunction
#  @date      Sun Mar  3 01:54:37 CET 2002
#  @author    Ian Kelley
#  @desc 
#     Very similar to &PrintVar, but does not lowercase stuff and deals with optional aliasing of what
#     it is including.  This is used to print out headers/functions/etc it addes, uses or provides. 
#
#  @enddesc 
#  @version 
#@@*/
sub PrintHeaderOrFunction
{
   my $title = shift;
   my $var   = shift;

   my %alias = %{$_[0]};
   
   my @temp;

   return if ($var !~ /\w/);

   print "\n\n\\noindent \{\\bf ". ThornUtils::Translate(ThornUtils::CleanForLatex($title)) ."\}: ";

   if (@temp = split/\s+/, $var)
   {
      foreach (@temp) 
      {
         my $lc_var = $_;
         $lc_var =~ tr/A-Z/a-z/;

         print "\n\n" . ThornUtils::CleanForLatex($_);

         if ( (defined $alias{$lc_var}) && ($alias{$lc_var}->{"to"} ne $_) ) {
            print " to " . ThornUtils::CleanForLatex($alias{$lc_var}->{"to"});
         }
      }
   } else {
      my $lc_var = $var;
      $lc_var =~ tr/A-Z/a-z/;
      
      print "\n\n" . ThornUtils::CleanForLatex($var);

      if ( (defined $alias{$lc_var}) && ($alias{$lc_var}->{"to"} ne $var) ) {
         print " to " . ThornUtils::CleanForLatex($alias{$lc_var}->{"to"});
      }
   }
   print "\n\\vspace\{2mm\}";
}

#/*@@
#  @routine   ExpandGroupName
#  @date      Sun Mar  3 01:54:37 CET 2002
#  @author    Ian Kelley
#  @desc 
#     When we are printing out the properties of a group, sometimes we want to expand the 
#     names of stuff out to be more descriptive.  This function provides that.
#
#  @enddesc 
#  @version 
#@@*/
sub ExpandGroupName 
{
   my $name = shift;

   if ($name eq "gtype") {
       return "group type";
    } elsif ($name eq "dim") { 
       return "dimensions";
    } elsif ($name eq "distrib") { 
       return "distribution";
    } elsif ($name eq "vtype") { 
       return "variable type";
    } elsif ($name eq "timelevels") { 
       return "timelevels";
    } else {
       return ThornUtils::ToLower(ThornUtils::CleanForLatex($name));
    }
}