自定义gcc预处理器

自定义gcc预处理器,gcc,c-preprocessor,Gcc,C Preprocessor,你能给我一个编写自定义gcc预处理器的例子吗 我的目标是用适当的CRC32计算值替换类似SID(“foo”)的宏。对于任何其他宏,我希望使用标准cpp预处理器 使用-没有集成的cpp-B选项似乎可以实现这一目标,但是我找不到任何简单的使用示例。警告:危险而丑陋的黑客行为。现在闭上眼睛,通过在gcc命令行中添加“-no integrated cpp”和“-B”开关,您可以钩住自己的预处理器-“无集成cpp”意味着gcc在使用其内部搜索路径之前会在“-B”路径中搜索其预处理器。如果用“-e”选项调用

你能给我一个编写自定义gcc预处理器的例子吗

我的目标是用适当的CRC32计算值替换类似SID(“foo”)的宏。对于任何其他宏,我希望使用标准cpp预处理器

使用
-没有集成的cpp-B
选项似乎可以实现这一目标,但是我找不到任何简单的使用示例。

警告:危险而丑陋的黑客行为。现在闭上眼睛,通过在gcc命令行中添加“-no integrated cpp”和“-B”开关,您可以钩住自己的预处理器-“无集成cpp”意味着gcc在使用其内部搜索路径之前会在“-B”路径中搜索其预处理器。如果用“-e”选项调用“cc1”、“cc1+”或“c1bOb'程序(这些是C、C++和Obje- C编译器),则可以识别预处理器的调用。当您看到此选项时,可以自己进行预处理。当没有“-E”选项时,将所有参数传递给原始程序。当有这样一个选项时,您可以自己进行预处理,并将处理后的文件传递给原始编译器

看起来是这样的:

> cat cc1
#!/bin/sh

echo "My own special preprocessor -- $@"

/usr/lib/gcc/i486-linux-gnu/4.3/cc1 $@
exit $?

> chmod 755 cc1
> gcc -no-integrated-cpp -B$PWD x.c
My own special preprocessor -- -E -quiet x.c -mtune=generic -o /tmp/cc68tIbc.i
My own special preprocessor -- -fpreprocessed /tmp/cc68tIbc.i -quiet -dumpbase x.c -mtune=generic -auxbase x -o /tmp/cc0WGHdh.s
本例调用原始预处理器,但打印附加消息和参数。您可以用自己的预处理器替换脚本

糟糕的黑客行为结束了。现在您可以睁开眼睛了。

一种方法是,在编译之前,只“重写”SID宏调用,使其符合您的要求,而将预处理器的其余部分留给编译器自己处理

我们的系统就是这样一个系统,它可以应用于许多语言,包括C语言,特别是GCC 2/3/4系列编译器

要使用DMS实现这个想法,您可以使用其 在编译步骤之前检查源代码。DMS可以解析代码,而无需扩展预处理器指令build 抽象表示它的语法树,在AST上执行转换,然后将结果作为可编译的C文本输出

您将使用的特定转换规则是:

rule replace_SID_invocation(s:STRING):expression->expression
          = "SID(\s)" -> ComputeCRC32(s);
其中ComputeCRC32是按其说明执行的自定义代码。(DMS包括一个CRC32实现,因此这方面的自定义代码非常短

DMS对于这项任务来说是一个巨大的锤子。你可以使用PERL来实现一些非常类似的东西。PERL(或其他字符串匹配/替换黑客)的区别在于a)它可能会在你不需要替换的地方找到模式,例如

  ... QSID("foo")... // this isn't a SID invocation
您可以通过仔细编码模式匹配来修复此问题,b)无法匹配在意外情况下发现的SID调用:

  ...   SID  ( /* master login id */  "Joel" )  ... // need to account for formatting and whitespace
和c)无法处理文本字符串本身中显示的各种转义字符:

  ...   SID("f\no\072") ...  // need to handle all of GCC's weird escapes
DMS的C前端为您处理所有逃逸;上面的ComputeCRC32函数将看到包含实际预期字符的字符串,而不是源代码中看到的原始文本

所以这实际上是一个你是否关心黑暗角落案件的问题,或者你是否认为你可能有更多的特殊处理要做


考虑到您描述问题的方式,我很想先采用Perl方法,简单地将有趣的案例定为非法。如果你做不到这一点,那么大锤是有意义的。

这并不是在回答你的问题,但是你是否考虑过编写一个支持脚本,将你的模板文件(例如
example.c.tmpl
),计算CRC并替换成输出文件(例如
example.c
)作为制作过程的一部分?在我的情况下,这很不方便,因为我没有特殊的模板,这些SID宏可以在源代码中的任何地方。当然,我可以添加一个定制目标,通过一个简单的脚本更改SID宏处理所有*.cpp源,然后将损坏的源传递给gcc……但我认为使用定制预处理器可能更优雅。您是否尝试过标准方法:#undef SID#define SID?我认为您应该更仔细地重新阅读最初的帖子。这个问题无法用标准预处理器解决。嗯……如果我错了,请纠正我,但我认为使用这种方法,我可以替换SID宏,将结果保存到某个临时文件,然后将标准预处理器应用到该临时文件。否?@pachanga是的,您需要提取输入和输出文件的命令行选项,并为处理器的输出写入第二个tempfile(我相信您需要保留文件扩展名)。然后,通过修补输入文件参数,将处理后的文件作为输入文件传递给原始(TM)预处理器。但所有其他参数保持原样,因为其中一些是位置相关的(如-I、-D或-U)。原始(TM)预处理器完成后,清理temp文件,并带着原始(TM)预处理器的退出代码离开。稍有改进:您可以自动找到哪个对应的预处理器会这样运行:g++--print prog name=cc1plus,使过滤器变为:#/bin/sh echo“自己的特殊预处理器;args=$@”$(g++--print prog name=cc1plus)$@exit$?最好是
exec$(${COLLECT\u GCC}--print prog name=cc1)$@