7

我正在使用专有的开发环境来编译用C和 IEC 61131 语言编写的代码。对于C编译,它使用具有以下构建选项的 GCC 4.1.2:

-fPIC -O0 -g -nostartfiles -Wall -trigraphs -fno-asm

编译是由在 Windows 上使用 Cygwin 运行的程序完成的。

我的问题是,IEC 语言预处理器不是很有用(根本不支持#define),我想使用宏!我不明白为什么 GCC 预处理器会真正关心它正在处理的语言(我的目标语言是结构化文本),所以我想看看是否有人知道如何让它处理不同文件类型的文件然后不会进一步编译(我只是在文件通过 IEC 编译器运行之前寻找宏扩展)。我对编译器选项和环境一无所知,因为我从来不需要处理它们,我只是编写C代码,它会神奇地编译并转移到我的目标系统运行。

我唯一能做的就是添加构建选项并在执行任何操作之前执行一个批处理文件。我认为我最大的希望在于使用批处理文件来处理具有特定扩展名的所有文件,但我什至不知道要使用 gnuinst 文件夹中的哪个可执行文件,更不用说使用什么标志来运行这些文件了。

4

1 回答 1

7

几乎任何 C 预处理器,包括 gcc 的cpp,都会假设其输入是有效的 C 代码。它必须按照 C(或 C++,或 Objective-C)规则对输入进行标记,因为它必须将其输入解析为标记(更准确地说是预处理标记)。高于令牌级别的构造不应该成为问题。

您当然可以使用cppgcc -E预处理不是 C 源代码的文本,但某些输入结构会导致问题。

从评论中举个例子:

$ cat foo.txt
#define ADDTHEM(x, y) ((x) + (y))
ADDTHEM(2, 3)
$ gcc -E - < foo.txt
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"

((2) + (3))

请注意,我必须使用gcc -E - < foo.txt而不是gcc -E foo.txt,因为 gcc.txt默认将文件视为链接器输入文件。

但是,如果您添加一些foo.txt不包含有效 C 预处理器令牌的内容,您可能会遇到问题:

$ cat foo.txt 
#define ADDTHEM(x, y) ((x) + (y))
ADDTHEM(2, 3)
ADDTHEM('c, "s)
$ gcc -E - < foo.txt
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"

((2) + (3))
<stdin>:3:9: warning: missing terminating ' character [enabled by default]
<stdin>:3:0: error: unterminated argument list invoking macro "ADDTHEM"
ADDTHEM

(将 Ada 源代码提供给 C 预处理器的尝试遇到了这种问题,因为 Ada 使用孤立的撇号'字符作为其属性语法。)

因此,如果输入语言不使用不是有效的 C 预处理器标记的东西,您可以这样做。

有关预处理令牌的更多信息,请参阅C 标准的 N1570 草案第 6.4 节。

在我检查GNU cpp 手册之前,我实际上写了上面的内容,上面写着:

C 预处理器仅适用于 C、C++ 和 Objective-C 源代码。过去,它被滥用为通用文本处理器。它将阻塞不遵守 C 的词法规则的输入。例如,撇号将被解释为字符常量的开头,并导致错误。此外,您不能依赖它保留对 C 系列语言不重要的输入特征。如果对 Makefile 进行了预处理,则所有硬标签都将被删除,并且 Makefile 将无法工作。

话虽如此,您通常可以在非 C 的东西上使用 cpp。其他类似 Algol 的编程语言通常是安全的(Pascal、Ada 等)。汇编也是如此,请谨慎行事。`-traditional-cpp' 模式保留更多的空白,否则更宽松。通过编写 C 或 C++ 样式的注释而不是本地语言注释并保持宏简单,可以避免许多问题。

只要有可能,您应该使用适合您编写的语言的预处理器。现代版本的 GNU 汇编器具有宏工具。大多数高级编程语言都有自己的条件编译和包含机制。如果一切都失败了,请尝试真正的通用文本处理器,例如 GNU M4。

(该手册的作者显然忽略了 Ada 属性语法的问题。)

于 2013-08-27T19:09:55.100 回答