annotate src/fftw-3.3.8/api/genf03.pl @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents d0c2a83c1364
children
rev   line source
Chris@82 1 #!/usr/bin/perl -w
Chris@82 2 # Generate Fortran 2003 interfaces from a sequence of C function declarations
Chris@82 3 # of the form (one per line):
Chris@82 4 # extern <type> <name>(...args...)
Chris@82 5 # extern <type> <name>(...args...)
Chris@82 6 # ...
Chris@82 7 # with no line breaks within a given function. (It's too much work to
Chris@82 8 # write a general parser, since we just have to handle FFTW's header files.)
Chris@82 9
Chris@82 10 sub canonicalize_type {
Chris@82 11 my($type);
Chris@82 12 ($type) = @_;
Chris@82 13 $type =~ s/ +/ /g;
Chris@82 14 $type =~ s/^ //;
Chris@82 15 $type =~ s/ $//;
Chris@82 16 $type =~ s/([^\* ])\*/$1 \*/g;
Chris@82 17 return $type;
Chris@82 18 }
Chris@82 19
Chris@82 20 # C->Fortran map of supported return types
Chris@82 21 %return_types = (
Chris@82 22 "int" => "integer(C_INT)",
Chris@82 23 "ptrdiff_t" => "integer(C_INTPTR_T)",
Chris@82 24 "size_t" => "integer(C_SIZE_T)",
Chris@82 25 "double" => "real(C_DOUBLE)",
Chris@82 26 "float" => "real(C_FLOAT)",
Chris@82 27 "long double" => "real(C_LONG_DOUBLE)",
Chris@82 28 "__float128" => "real(16)",
Chris@82 29 "fftw_plan" => "type(C_PTR)",
Chris@82 30 "fftwf_plan" => "type(C_PTR)",
Chris@82 31 "fftwl_plan" => "type(C_PTR)",
Chris@82 32 "fftwq_plan" => "type(C_PTR)",
Chris@82 33 "void *" => "type(C_PTR)",
Chris@82 34 "char *" => "type(C_PTR)",
Chris@82 35 "double *" => "type(C_PTR)",
Chris@82 36 "float *" => "type(C_PTR)",
Chris@82 37 "long double *" => "type(C_PTR)",
Chris@82 38 "__float128 *" => "type(C_PTR)",
Chris@82 39 "fftw_complex *" => "type(C_PTR)",
Chris@82 40 "fftwf_complex *" => "type(C_PTR)",
Chris@82 41 "fftwl_complex *" => "type(C_PTR)",
Chris@82 42 "fftwq_complex *" => "type(C_PTR)",
Chris@82 43 );
Chris@82 44
Chris@82 45 # C->Fortran map of supported argument types
Chris@82 46 %arg_types = (
Chris@82 47 "int" => "integer(C_INT), value",
Chris@82 48 "unsigned" => "integer(C_INT), value",
Chris@82 49 "size_t" => "integer(C_SIZE_T), value",
Chris@82 50 "ptrdiff_t" => "integer(C_INTPTR_T), value",
Chris@82 51
Chris@82 52 "fftw_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
Chris@82 53 "fftwf_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
Chris@82 54 "fftwl_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
Chris@82 55 "fftwq_r2r_kind" => "integer(C_FFTW_R2R_KIND), value",
Chris@82 56
Chris@82 57 "double" => "real(C_DOUBLE), value",
Chris@82 58 "float" => "real(C_FLOAT), value",
Chris@82 59 "long double" => "real(C_LONG_DOUBLE), value",
Chris@82 60 "__float128" => "real(16), value",
Chris@82 61
Chris@82 62 "fftw_complex" => "complex(C_DOUBLE_COMPLEX), value",
Chris@82 63 "fftwf_complex" => "complex(C_DOUBLE_COMPLEX), value",
Chris@82 64 "fftwl_complex" => "complex(C_LONG_DOUBLE), value",
Chris@82 65 "fftwq_complex" => "complex(16), value",
Chris@82 66
Chris@82 67 "fftw_plan" => "type(C_PTR), value",
Chris@82 68 "fftwf_plan" => "type(C_PTR), value",
Chris@82 69 "fftwl_plan" => "type(C_PTR), value",
Chris@82 70 "fftwq_plan" => "type(C_PTR), value",
Chris@82 71 "const fftw_plan" => "type(C_PTR), value",
Chris@82 72 "const fftwf_plan" => "type(C_PTR), value",
Chris@82 73 "const fftwl_plan" => "type(C_PTR), value",
Chris@82 74 "const fftwq_plan" => "type(C_PTR), value",
Chris@82 75
Chris@82 76 "const int *" => "integer(C_INT), dimension(*), intent(in)",
Chris@82 77 "ptrdiff_t *" => "integer(C_INTPTR_T), intent(out)",
Chris@82 78 "const ptrdiff_t *" => "integer(C_INTPTR_T), dimension(*), intent(in)",
Chris@82 79
Chris@82 80 "const fftw_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
Chris@82 81 "const fftwf_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
Chris@82 82 "const fftwl_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
Chris@82 83 "const fftwq_r2r_kind *" => "integer(C_FFTW_R2R_KIND), dimension(*), intent(in)",
Chris@82 84
Chris@82 85 "double *" => "real(C_DOUBLE), dimension(*), intent(out)",
Chris@82 86 "float *" => "real(C_FLOAT), dimension(*), intent(out)",
Chris@82 87 "long double *" => "real(C_LONG_DOUBLE), dimension(*), intent(out)",
Chris@82 88 "__float128 *" => "real(16), dimension(*), intent(out)",
Chris@82 89
Chris@82 90 "fftw_complex *" => "complex(C_DOUBLE_COMPLEX), dimension(*), intent(out)",
Chris@82 91 "fftwf_complex *" => "complex(C_FLOAT_COMPLEX), dimension(*), intent(out)",
Chris@82 92 "fftwl_complex *" => "complex(C_LONG_DOUBLE_COMPLEX), dimension(*), intent(out)",
Chris@82 93 "fftwq_complex *" => "complex(16), dimension(*), intent(out)",
Chris@82 94
Chris@82 95 "const fftw_iodim *" => "type(fftw_iodim), dimension(*), intent(in)",
Chris@82 96 "const fftwf_iodim *" => "type(fftwf_iodim), dimension(*), intent(in)",
Chris@82 97 "const fftwl_iodim *" => "type(fftwl_iodim), dimension(*), intent(in)",
Chris@82 98 "const fftwq_iodim *" => "type(fftwq_iodim), dimension(*), intent(in)",
Chris@82 99
Chris@82 100 "const fftw_iodim64 *" => "type(fftw_iodim64), dimension(*), intent(in)",
Chris@82 101 "const fftwf_iodim64 *" => "type(fftwf_iodim64), dimension(*), intent(in)",
Chris@82 102 "const fftwl_iodim64 *" => "type(fftwl_iodim64), dimension(*), intent(in)",
Chris@82 103 "const fftwq_iodim64 *" => "type(fftwq_iodim64), dimension(*), intent(in)",
Chris@82 104
Chris@82 105 "void *" => "type(C_PTR), value",
Chris@82 106 "FILE *" => "type(C_PTR), value",
Chris@82 107
Chris@82 108 "const char *" => "character(C_CHAR), dimension(*), intent(in)",
Chris@82 109
Chris@82 110 "fftw_write_char_func" => "type(C_FUNPTR), value",
Chris@82 111 "fftwf_write_char_func" => "type(C_FUNPTR), value",
Chris@82 112 "fftwl_write_char_func" => "type(C_FUNPTR), value",
Chris@82 113 "fftwq_write_char_func" => "type(C_FUNPTR), value",
Chris@82 114 "fftw_read_char_func" => "type(C_FUNPTR), value",
Chris@82 115 "fftwf_read_char_func" => "type(C_FUNPTR), value",
Chris@82 116 "fftwl_read_char_func" => "type(C_FUNPTR), value",
Chris@82 117 "fftwq_read_char_func" => "type(C_FUNPTR), value",
Chris@82 118
Chris@82 119 # Although the MPI standard defines this type as simply "integer",
Chris@82 120 # if we use integer without a 'C_' kind in a bind(C) interface then
Chris@82 121 # gfortran complains. Instead, since MPI also requires the C type
Chris@82 122 # MPI_Fint to match Fortran integers, we use the size of this type
Chris@82 123 # (extracted by configure and substituted by the Makefile).
Chris@82 124 "MPI_Comm" => "integer(C_MPI_FINT), value"
Chris@82 125 );
Chris@82 126
Chris@82 127 while (<>) {
Chris@82 128 next if /^ *$/;
Chris@82 129 if (/^ *extern +([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) *\((.*)\) *$/) {
Chris@82 130 $ret = &canonicalize_type($1);
Chris@82 131 $name = $2;
Chris@82 132
Chris@82 133 $args = $3;
Chris@82 134 $args =~ s/^ *void *$//;
Chris@82 135
Chris@82 136 $bad = ($ret ne "void") && !exists($return_types{$ret});
Chris@82 137 foreach $arg (split(/ *, */, $args)) {
Chris@82 138 $arg =~ /^([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) *$/;
Chris@82 139 $argtype = &canonicalize_type($1);
Chris@82 140 $bad = 1 if !exists($arg_types{$argtype});
Chris@82 141 }
Chris@82 142 if ($bad) {
Chris@82 143 print "! Unable to generate Fortran interface for $name\n";
Chris@82 144 next;
Chris@82 145 }
Chris@82 146
Chris@82 147 # any function taking an MPI_Comm arg needs a C wrapper (grr).
Chris@82 148 if ($args =~ /MPI_Comm/) {
Chris@82 149 $cname = $name . "_f03";
Chris@82 150 }
Chris@82 151 else {
Chris@82 152 $cname = $name;
Chris@82 153 }
Chris@82 154
Chris@82 155 # Fortran has a 132-character line-length limit by default (grr)
Chris@82 156 $len = 0;
Chris@82 157
Chris@82 158 print " "; $len = $len + length(" ");
Chris@82 159 if ($ret eq "void") {
Chris@82 160 $kind = "subroutine"
Chris@82 161 }
Chris@82 162 else {
Chris@82 163 print "$return_types{$ret} ";
Chris@82 164 $len = $len + length("$return_types{$ret} ");
Chris@82 165 $kind = "function"
Chris@82 166 }
Chris@82 167 print "$kind $name("; $len = $len + length("$kind $name(");
Chris@82 168 $len0 = $len;
Chris@82 169
Chris@82 170 $argnames = $args;
Chris@82 171 $argnames =~ s/([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) */$2/g;
Chris@82 172 $comma = "";
Chris@82 173 foreach $argname (split(/ *, */, $argnames)) {
Chris@82 174 if ($len + length("$comma$argname") + 3 > 132) {
Chris@82 175 printf ", &\n%*s", $len0, "";
Chris@82 176 $len = $len0;
Chris@82 177 $comma = "";
Chris@82 178 }
Chris@82 179 print "$comma$argname";
Chris@82 180 $len = $len + length("$comma$argname");
Chris@82 181 $comma = ",";
Chris@82 182 }
Chris@82 183 print ") "; $len = $len + 2;
Chris@82 184
Chris@82 185 if ($len + length("bind(C, name='$cname')") > 132) {
Chris@82 186 printf "&\n%*s", $len0 - length("$name("), "";
Chris@82 187 }
Chris@82 188 print "bind(C, name='$cname')\n";
Chris@82 189
Chris@82 190 print " import\n";
Chris@82 191 foreach $arg (split(/ *, */, $args)) {
Chris@82 192 $arg =~ /^([a-zA-Z_0-9 ]+[ \*]) *([a-zA-Z_0-9]+) *$/;
Chris@82 193 $argtype = &canonicalize_type($1);
Chris@82 194 $argname = $2;
Chris@82 195 $ftype = $arg_types{$argtype};
Chris@82 196
Chris@82 197 # Various special cases for argument types:
Chris@82 198 if ($name =~ /_flops$/ && $argtype eq "double *") {
Chris@82 199 $ftype = "real(C_DOUBLE), intent(out)"
Chris@82 200 }
Chris@82 201 if ($name =~ /_execute/ && ($argname eq "ri" ||
Chris@82 202 $argname eq "ii" ||
Chris@82 203 $argname eq "in")) {
Chris@82 204 $ftype =~ s/intent\(out\)/intent(inout)/;
Chris@82 205 }
Chris@82 206
Chris@82 207 print " $ftype :: $argname\n"
Chris@82 208 }
Chris@82 209
Chris@82 210 print " end $kind $name\n";
Chris@82 211 print " \n";
Chris@82 212 }
Chris@82 213 }