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

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

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

root / src / fftw-3.3.8 / api / genf03.pl @ 167:bd3cc4d1df30

History | View | Annotate | Download (7.38 KB)

1
#!/usr/bin/perl -w
2
# Generate Fortran 2003 interfaces from a sequence of C function declarations
3
# of the form (one per line):
4
#     extern <type> <name>(...args...)
5
#     extern <type> <name>(...args...)
6
#     ...
7
# with no line breaks within a given function.  (It's too much work to
8
# write a general parser, since we just have to handle FFTW's header files.)
9

    
10
sub canonicalize_type {
11
    my($type);
12
    ($type) = @_;
13
    $type =~ s/ +/ /g;
14
    $type =~ s/^ //;
15
    $type =~ s/ $//;
16
    $type =~ s/([^\* ])\*/$1 \*/g;
17
    return $type;
18
}
19

    
20
# C->Fortran map of supported return types
21
%return_types = (
22
    "int" => "integer(C_INT)",
23
    "ptrdiff_t" => "integer(C_INTPTR_T)",
24
    "size_t" => "integer(C_SIZE_T)",
25
    "double" => "real(C_DOUBLE)",
26
    "float" => "real(C_FLOAT)",
27
    "long double" => "real(C_LONG_DOUBLE)",
28
    "__float128" => "real(16)",
29
    "fftw_plan" => "type(C_PTR)",
30
    "fftwf_plan" => "type(C_PTR)",
31
    "fftwl_plan" => "type(C_PTR)",
32
    "fftwq_plan" => "type(C_PTR)",
33
    "void *" => "type(C_PTR)",
34
    "char *" => "type(C_PTR)",
35
    "double *" => "type(C_PTR)",
36
    "float *" => "type(C_PTR)",
37
    "long double *" => "type(C_PTR)",
38
    "__float128 *" => "type(C_PTR)",
39
    "fftw_complex *" => "type(C_PTR)",
40
    "fftwf_complex *" => "type(C_PTR)",
41
    "fftwl_complex *" => "type(C_PTR)",
42
    "fftwq_complex *" => "type(C_PTR)",
43
    );
44

    
45
# C->Fortran map of supported argument types
46
%arg_types = (
47
    "int" => "integer(C_INT), value",
48
    "unsigned" => "integer(C_INT), value",
49
    "size_t" => "integer(C_SIZE_T), value",
50
    "ptrdiff_t" => "integer(C_INTPTR_T), value",
51

    
52
    "fftw_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
53
    "fftwf_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
54
    "fftwl_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
55
    "fftwq_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
56

    
57
    "double" => "real(C_DOUBLE), value",
58
    "float" => "real(C_FLOAT), value",
59
    "long double" => "real(C_LONG_DOUBLE), value",
60
    "__float128" => "real(16), value",
61

    
62
    "fftw_complex" => "complex(C_DOUBLE_COMPLEX), value",
63
    "fftwf_complex" => "complex(C_DOUBLE_COMPLEX), value",
64
    "fftwl_complex" => "complex(C_LONG_DOUBLE), value",
65
    "fftwq_complex" => "complex(16), value",
66

    
67
    "fftw_plan" => "type(C_PTR), value",
68
    "fftwf_plan" => "type(C_PTR), value",
69
    "fftwl_plan" => "type(C_PTR), value",
70
    "fftwq_plan" => "type(C_PTR), value",
71
    "const fftw_plan" => "type(C_PTR), value",
72
    "const fftwf_plan" => "type(C_PTR), value",
73
    "const fftwl_plan" => "type(C_PTR), value",
74
    "const fftwq_plan" => "type(C_PTR), value",
75

    
76
    "const int *" => "integer(C_INT), dimension(*), intent(in)",
77
    "ptrdiff_t *" => "integer(C_INTPTR_T), intent(out)",
78
    "const ptrdiff_t *" => "integer(C_INTPTR_T), dimension(*), intent(in)",
79

    
80
    "const fftw_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
81
    "const fftwf_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
82
    "const fftwl_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
83
    "const fftwq_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
84

    
85
    "double *" => "real(C_DOUBLE), dimension(*), intent(out)",
86
    "float *" => "real(C_FLOAT), dimension(*), intent(out)",
87
    "long double *" => "real(C_LONG_DOUBLE), dimension(*), intent(out)",
88
    "__float128 *" => "real(16), dimension(*), intent(out)",
89

    
90
    "fftw_complex *" => "complex(C_DOUBLE_COMPLEX), dimension(*), intent(out)",
91
    "fftwf_complex *" => "complex(C_FLOAT_COMPLEX), dimension(*), intent(out)",
92
    "fftwl_complex *" => "complex(C_LONG_DOUBLE_COMPLEX), dimension(*), intent(out)",
93
    "fftwq_complex *" => "complex(16), dimension(*), intent(out)",
94

    
95
    "const fftw_iodim *" => "type(fftw_iodim), dimension(*), intent(in)",
96
    "const fftwf_iodim *" => "type(fftwf_iodim), dimension(*), intent(in)",
97
    "const fftwl_iodim *" => "type(fftwl_iodim), dimension(*), intent(in)",
98
    "const fftwq_iodim *" => "type(fftwq_iodim), dimension(*), intent(in)",
99

    
100
    "const fftw_iodim64 *" => "type(fftw_iodim64), dimension(*), intent(in)",
101
    "const fftwf_iodim64 *" => "type(fftwf_iodim64), dimension(*), intent(in)",
102
    "const fftwl_iodim64 *" => "type(fftwl_iodim64), dimension(*), intent(in)",
103
    "const fftwq_iodim64 *" => "type(fftwq_iodim64), dimension(*), intent(in)",
104

    
105
    "void *" => "type(C_PTR), value",
106
    "FILE *" => "type(C_PTR), value",
107

    
108
    "const char *" => "character(C_CHAR), dimension(*), intent(in)",
109

    
110
    "fftw_write_char_func" => "type(C_FUNPTR), value",
111
    "fftwf_write_char_func" => "type(C_FUNPTR), value",
112
    "fftwl_write_char_func" => "type(C_FUNPTR), value",
113
    "fftwq_write_char_func" => "type(C_FUNPTR), value",
114
    "fftw_read_char_func" => "type(C_FUNPTR), value",
115
    "fftwf_read_char_func" => "type(C_FUNPTR), value",
116
    "fftwl_read_char_func" => "type(C_FUNPTR), value",
117
    "fftwq_read_char_func" => "type(C_FUNPTR), value",
118

    
119
    # Although the MPI standard defines this type as simply "integer",
120
    # if we use integer without a 'C_' kind in a bind(C) interface then
121
    # gfortran complains.  Instead, since MPI also requires the C type
122
    # MPI_Fint to match Fortran integers, we use the size of this type
123
    # (extracted by configure and substituted by the Makefile).
124
    "MPI_Comm" => "integer(C_MPI_FINT), value"
125
    );
126

    
127
while (<>) {
128
    next if /^ *$/;
129
    if (/^ *extern +([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) *\((.*)\) *$/) {
130
	$ret = &canonicalize_type($1);
131
	$name = $2;
132

    
133
	$args = $3;
134
	$args =~ s/^ *void *$//;
135

    
136
	$bad = ($ret ne "void") && !exists($return_types{$ret});	
137
	foreach $arg (split(/ *, */, $args)) {
138
	    $arg =~ /^([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) *$/;
139
	    $argtype = &canonicalize_type($1);
140
	    $bad = 1 if !exists($arg_types{$argtype});
141
	}
142
	if ($bad) {
143
	    print "! Unable to generate Fortran interface for $name\n";
144
	    next;
145
	}
146

    
147
	# any function taking an MPI_Comm arg needs a C wrapper (grr).
148
	if ($args =~ /MPI_Comm/) {
149
	    $cname = $name . "_f03";
150
	}
151
	else {
152
	    $cname = $name;
153
	}
154

    
155
	# Fortran has a 132-character line-length limit by default (grr)
156
	$len = 0;
157

    
158
	print "    "; $len = $len + length("    ");
159
	if ($ret eq "void") {
160
	    $kind = "subroutine"
161
	}
162
	else {
163
	    print "$return_types{$ret} ";
164
	    $len = $len + length("$return_types{$ret} ");
165
	    $kind = "function"
166
	}
167
	print "$kind $name("; $len = $len + length("$kind $name(");
168
	$len0 = $len;
169
	
170
	$argnames = $args;
171
	$argnames =~ s/([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) */$2/g;
172
	$comma = "";
173
	foreach $argname (split(/ *, */, $argnames)) {
174
	    if ($len + length("$comma$argname") + 3 > 132) {
175
		printf ", &\n%*s", $len0, "";
176
		$len = $len0;
177
		$comma = "";
178
	    }
179
	    print "$comma$argname";
180
	    $len = $len + length("$comma$argname");
181
	    $comma = ",";
182
	}
183
	print ") "; $len = $len + 2;
184

    
185
	if ($len + length("bind(C, name='$cname')") > 132) {
186
	    printf "&\n%*s", $len0 - length("$name("), "";
187
	}
188
	print "bind(C, name='$cname')\n";
189

    
190
	print "      import\n";
191
	foreach $arg (split(/ *, */, $args)) {
192
	    $arg =~ /^([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) *$/;
193
	    $argtype = &canonicalize_type($1);
194
	    $argname = $2;
195
	    $ftype = $arg_types{$argtype};
196

    
197
	    # Various special cases for argument types:
198
	    if ($name =~ /_flops$/ && $argtype eq "double *") {
199
		$ftype = "real(C_DOUBLE), intent(out)" 
200
	    }
201
	    if ($name =~ /_execute/ && ($argname eq "ri" ||
202
					$argname eq "ii" || 
203
					$argname eq "in")) {
204
		$ftype =~ s/intent\(out\)/intent(inout)/;
205
	    }
206

    
207
	    print "      $ftype :: $argname\n"
208
	}
209

    
210
	print "    end $kind $name\n";
211
	print "    \n";
212
    }
213
}