annotate src/fftw-3.3.3/api/genf03.pl @ 169:223a55898ab9 tip default

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