Fortran中的CPP/GPP可变参数宏(加上Fortran的//连接)

7
我会尝试编译一个世界著名的数值天气预报代码,主要由Fortran 90编写,广泛使用cpp,并与PGI、Intel和gfortran成功地结合使用。现在,我继承了一个版本,其中专家添加了几百个变参宏。他们使用Intel和fpp,这可能更加重视Fortran,并且可以使所有内容正常工作。我需要使用gfortran,并且无法让cpp在新加入的代码上正常工作。
问题的粗略简化如下 -
预处理代码:
    PRINT *, "Hello" // "Don"
#define adderv(...) (myadd(__VA_ARGS__))
    sumv = adderv(1, 2, 3, 4, 5)

不使用-traditional选项,使用cpp可以处理可变参数宏,但无法处理Fortran连接:

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

另一方面,使用-traditional标志处理连接,但不处理可变宏:
$ 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)

我很难找到一种方法来促进两者的处理。
我已经开始尝试使用,感觉离解决方案还有很长的路要走。它不接受...,也不会扩展__VA_ARGS__。当然,以下内容不再是可变参数宏...
    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__))

我已经在网上搜索了很久,但是没有找到合适的解决方案。目前看来最好的可能性是将所有Fortran连接运算符拆分成单独的行。例如:

PRINT *, "Hello" // "Don"

变成

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

对于我来说,cpp和gpp的内部有些令人生畏,但如果有人看到成功的潜力并能指引我正确的方向,我将非常感激。虽然重构这个庞大的代码不是一个选项,但如果我非常绝望,可以尝试自动化策略(例如将那些连接运算符拆分成单独的行)。


附加信息 - roygvib建议我尝试添加-C标志。最近我们一直在抑制它,因为似乎会在Fortran代码中引入许多C注释。好吧,我去尝试了一下,我觉得我离成功更近了:

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

当我使用-P和-C标志调用时,它自然会通过C++(Fortran连接运算符),但似乎还会生成一些以C注释的版权文本。
   $ /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))

一些研究(删除cpp生成的注释)表明,版权声明的添加可能是cpp相对较新的“特性”。
我无法找到任何简单的方法来抑制它,所以我考虑可能需要构建一个包装脚本(例如mycpp),调用上述cpp,过滤掉任何C风格的注释,然后将其传递给下一阶段。
这不是最理想的解决方案,而且我有点担心,因为整个软件包中还有C代码。理论上,最坏的情况是无法在预处理的C代码中生成注释。
如果有人知道如何简单地抑制版权消息的生成,那我就可以开始工作了。

1
附加 -C 选项(cpp -P -C)可能有帮助...? - roygvib
它确实生成了所需的代码,但问题是它还会作为头文件生成一堆C风格的注释。也许我可以找到一种方法来抑制它的这一部分? - DonMorton
抑制不需要的生成注释的一种方法是修改 cpp 的源代码并构建自己想要的版本。 - John Zwinck
当然,我明白,但这对于这种情况来说并不是一个现实的选择。该代码已经在多个国际环境中用于研究和操作性天气预报已有十年之久。事实上,“我”需要尽力适应他们的方式。 - DonMorton
@VladimirF - 感谢您的指导 - 我已将我的答案移至其应属之处。 - DonMorton
显示剩余6条评论
2个回答

2
至少在下面简单的例子中,我通过安装旧版的cpp解决了问题。 其他研究 已经证实版本4.8会将额外的C注释插入预处理的Fortran代码中,显然这不是一个好事情。解决方案很简单,使用cpp-4.7。
在Ubuntu 16.04上安装比我预想的更加简单。一个简单的
sudo apt-get install cpp-4.7
put the necessary executable in /usr/bin/cpp-4.7

并且预处理以下示例的方式符合我的要求。
$ /usr/bin/cpp-4.7 -C -P t.F90
    PRINT *, "Hello" // "Don"
    sum = (myadd(1, 2, 3, 4, 5))  

0

和DonMorton一样,我正在尝试在Fortran文件中使用cpp -P,因为它使用了__VA_ARGS__和其他内容。如果没有-C选项,则会删除//并添加注释。

因此,我使用另一个答案的想法来删除这些额外行:

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

然后,我得到了预期的结果:

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

但是,仍然存在一个问题。您不能在宏参数中使用//(C++风格的注释):// something将被替换为/* something */

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接