Fortran 90 with C/C++ style macro (e.g. # define S

2019-06-14 15:02发布

问题:

I am recently working with a F90 code project. I am using gfortran (linux and MinGW) to compile it. There is something interesting in file loct.F90.

#  define TYPE real(4)
#  define SUBNAME(x) s ## x
#  include "loct_inc.F90"
#  undef SUBNAME
#  undef TYPE

#  define TYPE real(8)
#  define SUBNAME(x) d ## x
#  include "loct_inc.F90"
#  undef SUBNAME
#  undef TYPE
...

The loct_inc.F90 file looks like this:

subroutine SUBNAME(loct_pointer_copy_1)(o, i)
...
end subroutine SUBNAME(loct_pointer_copy_1)


subroutine SUBNAME(loct_pointer_copy_2)(o, i)
...
end subroutine SUBNAME(loct_pointer_copy_2)


...

I think in the file loct.F90 the author used sets of macros (C/C++ style). Each set is used to define a data type (e.g. real(4), real(8), character, etc). The file loct_inc.F90 provide a set of function which is the same except the type of the variables. These two files works together as a template of c++ in my opinion.

In the end one should have a set of subroutines:

sloct_pointer_copy_1(o, i)
sloct_pointer_copy_2(o, i)
...

dloct_pointer_copy_1(o, i)
dloct_pointer_copy_2(o, i)
...

But when I tried to compile loct.F90 (gfortran -c loct.F90), I get some errors.

basic/loct_inc.F90:21.13: Included at basic/loct.F90:256:

subroutine s ## loct_pointer_copy_1(o, i) 1 Error: Syntax error in SUBROUTINE statement at (1)

It seems gfortran replace SUBNAME(loct_pointer_copy_1)(o, i) with s ## loct_pointer_copy_1(o, i). But according to c++ macro, the correct replace should be sloct_pointer_copy_1(o, i).

Could anyone tell me why this happened?

回答1:

GNU Fortran uses the GNU C Preprocessor in traditional mode, in which mode the macro pasting operator ## is not available. That's why Fortran projects which were written to also compile with the GNU toolchain perform explicit preprocessing in additional Makefile targets, e.g. all *.F90 are first preprocessed with cpp to temporary .f90 files which are then compiled.