C预处理器的替代

我有兴趣使用C预处理器以外的东西来预处理我的C和Objective-C源代码。 有没有好的select?

一个例子就是允许在C代码中间跳出一个python或者perl片断,然后在这个片断吐出C然后编译成正常的。

您可以使用PHP作为C预处理器。 优点是:

  • 非常类似的语法,所以语法突出显示工作。
  • <??>在标准C中没有使用(非标准C,唯一被破坏的是旧的GCC扩展操作符返回最小值/最大值)
  • 它有丰富的图书馆。
  • 它是完整的。
  • macros的使用非常明确。 (与狡猾的C预处理macros相比)

尽pipe如此,为了debugging预处理代码,需要使用PHP打印#line指令。

 <?php include_once "stdio.h"; ?> int main() { <?php for($i = 0; $i < 20; $i++) echo 'printf("%d\n", '.$i.');'; ?> } 

Cog并不完全是一个预处理器,但它确实在代码中直接生成,并在飞行中生成的东西。

你可能要考虑m4。
http://www.gnu.org/software/m4/

运行代码的想法,其结果被拼接 在一起被称为quasiquotation 。 你运行的代码是反引号的

我知道如何使用Lua解决这个问题。 我用自己写的一个反引用函数string.gsub 。 我已经使用shell语法来进行反引用。 如在shell中, 反引号代码返回一个string ,然后拼接成代码。

下面的prog是带有反引号文本的C代码, antiquote是反引用函数。 我已经使用Lua的特殊string引用双方括号来充分利用。 在实践中,你不会这样做 ; 你会把prog一个单独的文件。

 names = { 'John', 'Paul', 'George', 'Ringo' } local prog = [===[ #include <stdio.h> main() { $(local out = { } for _, n in ipairs(names) do table.insert(out, string.format([[ printf("The name is %%s\n", %q);]], n)) end return table.concat(out, '\n ') ) } ]===] local function antiquote(s) local body = s:match '^%$%((.*)%)$' return assert(loadstring(body))() end prog = prog:gsub('%$%b()', antiquote) io.stdout:write(prog) 

在使用中,程序看起来像这样:

 : nr@curlycoat 1181 ; lua /home/nr/tmp/emit-c.lua #include <stdio.h> main() { printf("The name is %s\n", "John"); printf("The name is %s\n", "Paul"); printf("The name is %s\n", "George"); printf("The name is %s\n", "Ringo"); } 

如果您将问题抽象化了一下,那么您实际上正在为代码寻找一个模板引擎。 正如大多数网站在静态模板中插入dynamic生成的内容一样,您希望将dynamic生成的代码插入到您的程序中。

我目前使用Jinja2 (Python)进行大多数模板工作 – 我发现它在各个方面都是非常可configuration的。

如果你准备用C ++来弄脏你的手,那么Boost里的Waveparsing器就是用这个Spiritrecursion下降parsing器构build的。 这是一个完整的C预处理器,符合C和C ++的所有最新规范(以及Objective C,AFAICS的扩展)。

它是高度模块化的,所以你可以切换自己的驱动程序,可以做你想要的额外。

http://www.boost.org/libs/wave/doc/introduction.html

当然,标准的C预处理器是非常有限的。
我最近做了这样一个工具: https : //github.com/d-ash/perlpp

比如说这个

 <? my @types = ('char', 'int', 'long'); foreach (@types) { ?> <?= $_ ?> read_<?= uc($_) ?>(<?= $_ ?>* v); <? } ?> 

变成这个

 char read_CHAR(char* v); int read_INT(int* v); long read_LONG(long* v); 

语法类似于PHP,但是它使用Perl来代替,并且可以将文本捕获到Perl中。

cxw 编辑 – 经过@ d-ash的批准,我也是perlpp的维护者。 如果您有任何疑问,请随时联系我!

我以前也想过这个问题。 确保你没问题,任何想编译你的代码的人都需要新的预处理工具。 如果你是唯一一个能够处理这个问题的人,那么没有问题,但是如果你想把代码提供给其他人,那么你可能要考虑是否添加一个工具需求是一个好主意。

最简洁的答案是不。” 预处理器与C的语义非常紧密地联系在一起,所以你不能真的将其删除,事实上在某些编译器中,甚至不像以前那样是一个独立的阶段 – 编译Objective C Mac只是parsingObjective C语法。 所以,虽然你可以使用另一个macros处理器(如m4)在将它传递给C之前处理源文本,但不会消除 C预处理器,而是要添加另一个预处理步骤。

但是这里有一个更深的问题:你想通过消除CPP阶段获得什么?

CPP为C代码做了很多重要的事情,你可能不需要重新实现。 你似乎正在寻找可能是一个模板的过程,发出的C代码。

猎豹只是允许你使用python的许多人之一。 还有一些使用python,还有其他语言使用python,但是Cheetah以输出不可知论着称,其中一些模板引擎非常重视HTML / XML。 做你的研究。

我看到2001年的一篇论文介绍了一个python式的预处理器http://ray.cg.tuwien.ac.at/rft/Papers/PYM/pym.html 。 目前尚不清楚任何人正在使用它..

您可以使用自己喜欢的编程语言来构build一个脚本/工具来生成源文件(.c / .cpp或.h,或其他)。 只需#include它们或将它们编译到您的项目中。 #include附近的注释可能有助于识别工具在哪里以及产生了什么。

这可能不像使用“真正的”预处理器那样方便(或干净),但是它可以工作。 那么,这真的取决于你的情况。

我很想看看有什么人想出来的。 我倾向于用Perl编写的预处理器来做小的定制事情。 调用一个调用预处理器的Makefile很容易。 例如,下面是一个调用名为'meta'的程序从'file.c.meta'生成'file.c'的规则。

 % :: %.meta meta $< > $@ 

我正在做'有趣'的事情,像生成自定义适合的C数据结构。 这绝对是我build议探索的一个方向。 我的希望是最终拿出一个大致平行于C ++模板的元库。