CPP/GPP in Fortran variadic macro (plus Fortran // concatenation)

921 views Asked by At

I'm trying to compile a huge, world-renowned numerical weather prediction code - written mostly in Fortran 90 - that uses cpp extensively, and successfully, with PGI, Intel and gfortran. Now, I've inherited a version where experts have added several hundred cases of variadic macros. They use Intel and fpp, which is presumably a little more Fortran-centric, and can get it all to work. I need to use gfortran, and have not been able to get cpp to work on this code with its new additions.

A gross simplification of the problem is as follows -

Code to preprocess:

    PRINT *, "Hello" // "Don"
#define adderv(...) (myadd(__VA_ARGS__))
    sumv = adderv(1, 2, 3, 4, 5)

Using cpp without the -traditional option will handle the variadic macro, but not the Fortran concatenation:

$ cpp -P t.F90
    PRINT *, "Hello"
    sumv = (myadd(1, 2, 3, 4, 5))

On the other hand, using the -traditional flag handles the concatenation, but not the variadic macro:

$ cpp -P -traditional t.F90 
t.F90:2:0: error: syntax error in macro parameter list
 #define adderv(...) (myadd(__VA_ARGS__))
 ^
    PRINT *, "Hello" // "Don"
    sumv = adderv(1, 2, 3, 4, 5)

I'm really struggling to find a way to facilitate the processing of both.

I've started by playing with gpp, and feel like I'm getting close, but the reality is I might still be a long way from a solution. It doesn't accept the ... and, it doesn't expand __VA_ARGS__. Of course, the following isn't really a variadic macro any more...

    PRINT *, "Hello" // "Don"
#define adderv() (myadd(__VA_ARGS__))
    sumv = adderv(1, 2, 3, 4, 5)



$ gpp t.F90
    PRINT *, "Hello" // "Don"
    sumv = (myadd(__VA_ARGS__))

I've scoured the web to no avail, and the best possibility I've seen so far, which strikes me as possibly ugly and painful, is to split all my Fortran concatenation operators into separate lines. i.e.

PRINT *, "Hello" // "Don"

becomes

PRINT *, "Hello" /&
&              / "Don"

The innards of cpp and gpp are a bit intimidating to me, but if anybody sees the potential for success and might point me in the right direction, I'd be very appreciative. Restructuring this huge code really isn't an option, though an automated strategy (such as splitting those concat operators into separate lines) might be, if I'm desperate enough.


Additional information - roygvib suggested I try adding the -C flag. We had been suppressing it lately because it seemed to introduce many C comments into the Fortran code. Well, I went ahead and tried this, and I think I'm closer:

$ cat t.f90
        PRINT *, "Hello" // "Don"
    #define adderv(...) (myadd(__VA_ARGS__))
        sumv = adderv(1, 2, 3, 4, 5)

When I invoke with -P and -C flags, naturally it passes through the C++ (Fortran concat operator), but it also seems to generate some C-commented copyright text:

   $ /lib/cpp -P -C  t.F90
   /* Copyright (C) 1991-2014 Free Software Foundation, Inc.
      This file is part of the GNU C Library.
   .
   .
   .
   /* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /       Unicode 6.0.  */
   /* We do not support C11 <threads.h>.  */
       PRINT *, "Hello" // "Don"
       sumv = (myadd(1, 2, 3, 4, 5))

A little bit of research ( Remove the comments generated by cpp ) is suggesting that this addition of the copyright may be a relatively new "feature" of cpp.

I can't see any simple way to suppress this, so I'm thinking I may need to build a wrapper script (e.g. mycpp) that calls cpp as above, filters out any C-style comments, then passes that to the next stage.

It's not optimal, and I'm a little leery because this whole package also has C code in it. Theoretically, though, I think that the worst thing that would happen would be failure to generate comments in preprocessed C code.

If anybody has knowledge as to how I might simply suppress the generation of that copyright message, I might be in business.

2

There are 2 answers

0
DonMorton On BEST ANSWER

At least in the context of the simple example described below, I resolved the problem by installing an older cpp. Other research had confirmed that version 4.8 was inserting additional C comments into preprocessed Fortran code, which obviously isn't a good thing. The solution was simple, use cpp-4.7.

Installation (on Ubuntu 16.04) was more straightforward than I had anticipated. A simple

sudo apt-get install cpp-4.7
put the necessary executable in /usr/bin/cpp-4.7

and that preprocesses the following examples the way I want.

$ /usr/bin/cpp-4.7 -C -P t.F90
    PRINT *, "Hello" // "Don"
    sum = (myadd(1, 2, 3, 4, 5))  
0
Stef1611 On

Like DonMorton, I am trying to use cpp -P with fortran files because __VA_ARGS__ and others things are used. As without -C option // are removed and comments are added.

So, I removed these extralines using the ideas of another answer :

cpp -P -C t.F90 |  sed '/\/\*.*\*\// d; /\/\*/,/\*\// d'

And, I get, as expected :

PRINT *, "Hello" // "Don"
sumv = (myadd(1, 2, 3, 4, 5))

But, there is still a problem. You could not use // (C++ style comments) in macro args : // something is replaced by /* something */