【问题标题】:CPP/GPP in Fortran variadic macro (plus Fortran // concatenation)Fortran 可变参数宏中的 CPP/GPP(加上 Fortran // 连接)
【发布时间】:2016-12-26 19:15:31
【问题描述】:

我正在尝试编译一个巨大的、世界知名的数值天气预报代码 - 主要用 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)

我真的很难找到一种方法来促进两者的处理。

我从玩 gpp 开始,感觉我已经接近了,但现实是我可能距离解决方案还有很长的路要走。它不接受... 并且不扩展__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 cmets。好吧,我继续尝试了这个,我想我更接近了:

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

当我使用 -P 和 -C 标志调用时,它自然会通过 C++(Fortran concat 运算符),但它似乎也会生成一些 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))

一点点研究 (Remove the comments generated by cpp) 表明版权的添加可能是 cpp 的一个相对较新的“功能”。

我看不到任何简单的方法来抑制这种情况,所以我想我可能需要构建一个像上面那样调用 cpp 的包装脚本(例如 mycpp),过滤掉任何 C-样式 cmets,然后将其传递到下一个阶段。

这不是最优的,我有点怀疑,因为整个包中也有 C 代码。不过从理论上讲,我认为最糟糕的情况是无法在预处理的 C 代码中生成 cmets。

如果有人知道我可以如何简单地禁止生成该版权信息,我可能会做生意。

【问题讨论】:

  • 附加 -C 选项 (cpp -P -C) 可能有帮助...?
  • 确实会生成想要的代码,但问题是它还会生成一堆C风格的cmets作为header。也许我可以找到一种方法来抑制它的那部分?
  • 抑制不希望生成的 cmets 的一种方法是修改 cpp 的源并构建您自己的版本来满足您的需求。
  • 约翰·兹温克,我已经想到了。我不知道(还)是否可以隔离 cpp 以进行简单的更改,或者我是否必须将其绑定到完整的 gcc 环境中,我有点不愿意深入研究。
  • 没有 -traditional 的 CPP 与 Fortran 不兼容。忘记可变参数宏和其他高级功能,并在stackoverflow.com/questions/tagged/fortran+c-preprocessor 中研究那些已经可用的 Q/A

标签: fortran c-preprocessor variadic


【解决方案1】:

至少在下面描述的简单示例的上下文中,我通过安装较旧的 cpp 解决了问题。 Other research 已确认 4.8 版将额外的 C cmets 插入到预处理的 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))  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 2013-11-09
    • 1970-01-01
    • 2018-08-28
    相关资源
    最近更新 更多