File: f77tof90

package info (click to toggle)
mpich2 1.2.1.1-5
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 73,904 kB
  • ctags: 65,947
  • sloc: ansic: 343,583; makefile: 55,174; java: 34,959; sh: 27,558; perl: 17,355; cpp: 10,472; python: 9,649; f90: 5,753; fortran: 5,128; cs: 4,019; csh: 152; xml: 91; php: 8
file content (382 lines) | stat: -rwxr-xr-x 11,945 bytes parent folder | download
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
#! /usr/bin/perl -w
# -*- Mode: perl; -*-
#
# f77tof90 indir outdir [ Makefile-template [Make-Append] ]
# For each file in indir/*.[fF], create a corresponding file in outdir
# with .f90/.F90, and with any include "mpif.h" replaced with use mpi
# It also changes to the new comment style, because some compilers
# use the comment style to choose other features of the language
#
# We also allow the file name to be modified to help out Windows, since
# programs in a project need to have distinct names
#
$indir = $ARGV[0];
$outdir = $ARGV[1];
$makeTemplate = $ARGV[2];
$makeAppend   = $ARGV[3];
$convertToFreeForm    = 1;
$convertToNewComments = 1;
# Including a newline variable allows us to handle Unix and DOS source files
$newline = "\n";

%replaceInclude = ( 'iodisp' => 'integer (kind=MPI_OFFSET_KIND) disp',
		    'ioaint' => 'integer (kind=MPI_ADDRESS_KIND) aint',
		    'iooffset' => 'integer (kind=MPI_OFFSET_KIND) offset',
		    'type1aint' => 'integer (kind=MPI_ADDRESS_KIND) aint', 
		    'typeaints' => 'integer (kind=MPI_ADDRESS_KIND) aint, aintv(max_asizev)', 
		    'attr1aints' => 'integer (kind=MPI_ADDRESS_KIND) extrastate, valin, valout, val',
		    'attraints' => 'integer (kind=MPI_ADDRESS_KIND) extrastate, valin, valout, val',
		    'addsize' => 'integer (kind=MPI_ADDRESS_KIND) asize',
                    'add1size' => 'integer (kind=MPI_ADDRESS_KIND) asize',
	    );

%excludePrograms = ();
$debugReplace = 0;
$reportSkipped = 0;
# --------------------------------------------------------------------------
# Check the input arguments
if ($indir eq "" || $outdir eq "") {
    print STDERR "Usage: f77tof90 indir outdir [ makefile-template ]\n";
    exit 1;
}
if ( ! -d $indir) {
    print STDERR "Input directory $indir does not exist\n";
    exit 1;
}
if (! -d $outdir) {
    print STDERR "Output directory $outdir does not exist\n";
    exit 1;
}
# --------------------------------------------------------------------------


# --------------------------------------------------------------------------
opendir( DIR, "$indir" );
my @filelist = ();
while ($file = readdir(DIR)) {
    # Extract the extension
    if ($file =~ /^(.*)\.([^\.]*)$/) {
	$name = $1;
	$ext  = $2;
	# Special handling for C files, if any
	if ($ext eq "c") {
	    my $name90 = $name;
	    $name90 =~ s/f/f90/g;
	    &ConvertCFile( "$indir/$file", "$outdir/$name90.c.new" );
	    &ReplaceIfDifferent( "$outdir/$name90.c", 
				 "$outdir/$name90.c.new" );
	    next;
	}
	# Skip if the file isn't a Fortran source file
	if ($ext ne "f" && $ext ne "F") { next; }
	&ConvertToF90( "$indir/$file", "$outdir/${name}90.${ext}90.new" );
	&ReplaceIfDifferent( "$outdir/${name}90.${ext}90", 
			     "$outdir/${name}90.${ext}90.new" );
	$filelist[$#filelist+1] = $file;
    }
}
closedir( DIR );

# &CreateMakefile( "filelist", $outdir );
if (defined($makeTemplate) && $makeTemplate ne "" &&
    -s "$indir/$makeTemplate") {
    &ConvertMakefile( $indir, $outdir, $makeTemplate );
    if (defined($makeAppend) && -s "$outdir/$makeAppend") {
	# If there is a makeAppend in the output directory, then 
	# append that to the generated makefile
	&AppendFile( "$outdir/$makeAppend", "$outdir/$makeTemplate.new" );
    }
    &ReplaceIfDifferent( "$outdir/$makeTemplate", 
			 "$outdir/$makeTemplate.new" );
}
if (-s "$indir/testlist" || -s "$indir/testlist.in") {
    # We allow both testlist.in and testlist as source files;
    # testlist.in gets priority
    my $filename = "testlist";
    if (-s "$indir/testlist.in") {
	$filename = "testlist.in";
    }
    &ConvertTestlist( $indir, $outdir, $filename );
    
    if (-s "$outdir/testlist.ap") {
	&AppendFile( "$outdir/testlist.ap", "$outdir/$filename.new" );
    }
    &ReplaceIfDifferent( "$outdir/$filename", "$outdir/$filename.new" );
}

exit 0;

# -----------------------------------------------------------------------------

sub ConvertToF90 {
    my $infile = $_[0];
    my $outfile = $_[1];
    
    open (INF, "<$infile" ) || die "Could not open $infile\n";
    open (OUTF, ">$outfile" ) || die "Could not open $outfile\n";

    print OUTF "! This file created from $infile with f77tof90\n";
    my $lastLine = "";
    my $firstline = 1;
    while (<INF>) {
	if (/\r/) { $newline = "\r\n"; }
	# Remove any end-of-line characters
	s/[\r\n]*//g;
        # The implicit none must not come before the use mpi statement,
	# but in F77, it must come before the include mpif.h statement.
	# Rather than try and fix this, rely on the F77 versions to 
	# catch undeclared variables
        if (/[Ii][Mm][Pp][Ll][Ii][Cc][Ii][Tt]\s+[Nn][Oo][Nn][Ee]/) { next; }
	if (/^(\s*)include\s+[\'\"]mpif\.h/) {
	    $_ = "$1use mpi";
	}
	# Allow the insertion of Fortran 90 only statements, such as
	# interface definitions
        if (/^CF90/) {
	    s/^CF90/    /;
	}
	# Since we use interface statements for the error handlers,
	# remove their external declaration
	if (/^\s+external myerrhanfunc/) {
	    s/^\s/!/;
	}
	if ($convertToNewComments) {
	    s/^C/!/;
	    s/^c/!/;
	}	
	# Update the special includes that are used to provide 
	# address or offset sized types with ones the use the
	# Fortran90 KIND style
	if (/^(\s*)include\s+[\'\"]([\/\.\w]+)\.h[\"\']/) {
	    my $leading     = $1;
	    my $includename = $2;
	    if (defined($replaceInclude{$includename})) {
		$_ = $leading . $replaceInclude{$includename} . "\n";
	    }
	}

	# We need to handle the special case of the program
	# name in spawn commands
	if (/(.*)\"([\.\/\w]*spawn[^\"]*)\"(.*)/) {
	    my $before = $1;
	    my $name = $2;
	    my $after = $3;
	    $_ = $before . "\"" . $name . "90" . "\"" . $after;
	}

	# We could also detect continuations in column six and 
	# convert to free-form input by holding one line back.
	if ($convertToFreeForm) {
	    if (/^     \S(.*)/) {
		$leftover = $1;
		# This line contains a continuation marker
		# Add a continuation marker to the previous line if
		# it doesn't already have one
		if (! ($lastline =~ /\&\s*$/) ) {
	  	    $lastline .= " &";	   
		}
		$_ = "      \&$leftover";
	    }
	}
	print OUTF "$lastline$newline" if (! $firstline);
	$firstline = 0;
	$lastline = $_;
    }
    print OUTF "$lastline$newline";

    close (INF);
    close (OUTF);
}

#
# A very simple routine for creating a version of a C file that refers
# to F90 instead of F77.
sub ConvertCFile {
    my $infile = $_[0];
    my $outfile = $_[1];
    
    open (INF, "<$infile" ) || die "Could not open $infile\n";
    open (OUTF, ">$outfile" ) || die "Could not open $outfile\n";

    print OUTF "/* This file created from $infile with f77tof90 */\n";
    while (<INF>) {
	if (/\r/) { $newline = "\r\n"; }
	# Remove any end-of-line characters
	s/[\r\n]*//g;
	# replace F77 with F90, mostly for CPP tests, except for name
	# mapping
	if (! /F77_NAME/) {
	    s/F77/F90/g;
	}
	print OUTF "$_$newline";
    }

    close (INF);
    close (OUTF);
}

# Create a makefile from a template.  Replace @EXECS@ with the programs
# in the filelist.
# CreateMakefile( "filelist", $outdir )
sub CreateMakefile {
    my $filelist = $_[0];
    my $outdir   = $_[1];

    print STDERR "This function is not implemented\n";
    return 0;
}

#
# Take an existing makefile and perform the following transformations:
# .f -> .f90, .F -> .F90
# Others as necessary
# ConvertMakefile( indir, outdir, filename )
# By providing the filename, we can accept Makefile, Makefile.in, Makefile.ap,
# Makefile.sm, or even nonstandard names such as buildscript.
sub ConvertMakefile {
    my ($indir, $outdir, $filename) = @_;
    %excludePrograms = ();

    open( INF, "<$indir/$filename" ) || die "Cannot open $indir/$filename\n";
    open( OUTF, ">$outdir/$filename.new" ) || die "Cannot open $outdir/$filename.new\n";
    print OUTF "# This $filename generated automatically by f77tof90\n";
    print OUTF "# from $indir/$filename.  DO NOT EDIT\n"; 
    while (<INF>) {
        # First, check for sources that are not present.  These
	# may be derived files (see f77/io for an example).  For now,
	# we'll skip these
	if (/^(\w+)_SOURCES\s*=\s*(\w+\.f)/) {
	    my $sourcebase = $1;
	    my $sourcename = $2;
	    if (! -s "$indir/$sourcename") {
		print "Skipping source file $indir/$sourcename because it is not present\n" if $reportSkipped;
		$excludePrograms{$sourcebase} = 1;
		next; 
	    }
	}
        # convert program names from foof.f to foof90.f90
        s/f_SOURCES/f90_SOURCES/g;
	if (/f\.f/) {
	    s/f\.f/f90.f90/g;
	}
	else {
	    # Move files to f90
	    s/\.f/.f90/g;
	}
	s/mtestf\.o/mtestf90.o/;
	s/\.F/.F90/g;
	s/f77/f90/g;
	s/F77/F90/g;
	# Update any per-program LDADD values
        s/f_LDADD/f90_LDADD/g;
	#
	# Handle special cases:  
	# Force the c2f2c test to use the f90 compiler
	s/c2f2cf90_SOURCES.*/c2f2cf90_SOURCES = c2f2cf90.f90 c2f902c.c/;
	s/c2f2ciof90_SOURCES.*/c2f2ciof90_SOURCES = c2f2ciof90.f90 c2f902cio.c/;
#	s/c2f2ciof90_LDADD/c2f2cfio90_LDADD/g;
	s/c2f2cwinf90_SOURCES.*/c2f2cwinf90_SOURCES = c2f2cwinf90.f90 c2f902cwin.c/;

	if (/EXTRA_PROGRAMS/) {
	    s/allocmemf/allocmemf90/;   # allocmemf test is special 
	}
	# Handle the special case of C programs (used for f2d/c2f testing)
	if (/(\w+)_SOURCES(\s*=\s*)(\w+)\.c\s*$/) {
	    my $progname = $1;
	    my $spacing  = $2;
	    my $name     = $3;
	    $name =~ s/f/f90/;
	    $progname =~ s/f/f90/;
	    $_ = "$progname" . "_SOURCES" . $spacing . $name . ".c\n";
	}

	# Eventually need some way to update directory paths (particularly
	# relative ones) and add F90 compile rules when not present.
	print OUTF $_;
    }

    close( INF );
    close( OUTF );
    # The check on a file change is handled in the routine that calls this
    # because we may append to this file first.
}

# Append infile to the end of inout file
#( infile, inoutfile )
sub AppendFile { 
    my $infile = $_[0];
    my $outfile = $_[1];
    
    open( INA, "<$infile" ) || die "Cannot open $infile\n";
    open( OUTA, ">>$outfile" ) || die "Cannot open $outfile\n";
    while (<INA>) {
        print OUTA $_;
    }
    close(INA);
    close(OUTA);
}

#
# Replace old file with new file only if new file is different
# Otherwise, remove new filename 
sub ReplaceIfDifferent {
    my ($oldfilename,$newfilename) = @_;
    my $rc = 1;
    if (-s $oldfilename) { 
	$rc = system "cmp -s $newfilename $oldfilename";
	$rc >>= 8;   # Shift right to get exit status
    }
    if ($rc != 0) {
	print STDERR "Replacing $oldfilename\n";
	if ($debugReplace && -s $oldfilename) {
	    print STDERR "Differences are:";
	    system "diff $newfilename $oldfilename";
	}
	# The files differ.  Replace the old file 
	# with the new one
	if (-s $oldfilename) {
	    unlink $oldfilename;
	}
	rename $newfilename, $oldfilename || 
	    die "Could not replace $oldfilename";
    }
    else {
	unlink $newfilename;
    }
}

# Change the names of the tests.  Remove any that were skipped from the 
# Makefile.  Check for a  testlist.in before testlist
sub ConvertTestlist {
    my ($indir, $outdir, $filename) = @_;

    open( INF, "<$indir/$filename" ) || die "Cannot open $indir/$filename\n";
    open( OUTF, ">$outdir/$filename.new" ) || die "Cannot open $outdir/$filename.new\n";
    print OUTF "# This file generated by f77tof90\n";
    while (<INF>) {
	if (/^(\w+)\s/) {
	    my $sourcebase = $1;
	    if (defined($excludePrograms{$sourcebase})) { next; }
	}
	if (/^(\w+f)\s+(.*)/) {
	    $_ = $1 . "90 "  . $2 . "\n";
	}
	elsif (/^c2fmult(\w*)\s+(.*)/) {
	    # This is a special case for programs that are not Fortran
	    # programs but are part of the Fortran tests; principly, these
	    # are the tests of MPI handle conversion
	    # note the \w* instead of \w+; this allows us to match both
	    # c2fmult.c and c2fmultio.c
	    $_ = "c2f90mult$1 $2\n";
	}
	elsif (/^\@ALLOCMEMF\@/) {
	    # This is a special case for an optional feature (using
	    # Cray-style pointers for MPI_Alloc_mem).
	    $_ = "\@ALLOCMEMF90\@\n";
	}
	print OUTF $_;
    }
    close INF;
    close OUTF;

}