C预处理器的替换

Ken*_*Ken 40 c objective-c c-preprocessor

我有兴趣使用C预处理器以外的东西来预处理我的C和Objective-C源代码.有好的选择吗?

一个例子是允许一个人逃脱到C代码中间的python或perl片段,并且片段吐出C然后编译为正常.

mil*_*bug 53

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

  • 非常类似的语法,因此语法突出显示起作用.
  • <?并且?>不用于标准C(使用非标准C,唯一被破坏的是旧的GCC扩展运算符,它返回最小值/最大值)
  • 它的图书馆很丰富.
  • 这是完整的.
  • 宏的用法非常明确.(与偷偷摸摸的C预处理器宏相比)

但是为了认真使用,调试预处理代码需要PHP打印#line指令.

<?php include_once "stdio.h"; ?>

int main()
{
    <?php
        for($i = 0; $i < 20; $i++)
            echo 'printf("%d\n", '.$i.');';
    ?>
}
Run Code Online (Sandbox Code Playgroud)

  • 由于现在正在推特上传播,Reddit等人请记住 - 只因为你_can_或_could_并不意味着你_should_. (42认同)
  • 这很有趣 (3认同)
  • 我终于找到了首字母缩略词的真正含义:"P"HP"H"eader"P"reprocesser.它是预处理`.h`文件的完美工具. (3认同)
  • @Esko:实际上,如果您想在编译期间动态生成代码,我认为这是一个很棒的想法 - 特别是如果 C 预处理器对于您想要做的事情来说不够强大。 (2认同)

Mic*_*hne 10

Cog并不完全是一个预处理器,但它确实在代码中内嵌并在运行中生成内容.


Nor*_*sey 9

运行代码的想法,然后拼接其结果称为quasiquotation.您运行的代码是反引号.

我知道如何使用Lua解决这个问题.我已经使用string.gsub我自己编写反引号函数.我已经使用shell语法进行反引号.与在shell中一样,反引号代码返回一个字符串,然后将其拼接到代码中.

下面prog是带反引号文本的C代码,antiquote是反引号函数.我已经使用Lua的特殊字符串引用双方括号来充分利用它. 在实践中你不会这样做 ; 你要放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)
Run Code Online (Sandbox Code Playgroud)

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

: 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");
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*ole 7

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

  • `m4`真的非常多才多艺,但是语法真是太残酷了.我真的希望我们有一个更现代的unix宏处理器,但是一个从C编译,就像古老的`m4`. (3认同)
  • 对我来说,m4感觉太像科学项目,而不像预处理器语言.上次我看,它没有循环结构,而是有如何使用递归制作一个指令.我认为这是一个明确的信号,表明作者对我自己的利益过于聪明. (2认同)
  • 我写了一篇关于将m4与C一起使用的博客文章,这可能有助于一些入门:http://kvanberendonck.id.au/using-m4-with-c/ (2认同)

phi*_*red 5

如果你已准备好接受一些C++,那么Boost中的Wave解析器就是使用Spirit递归下降解析器构建的.它是一个完整的C预处理器,符合C和C++的所有最新规范(以及扩展,Objective C,AFAICS).

它是高度模块化的,因此您可以切换自己的驱动程序,这可以做您想要的额外功能.

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


Mor*_*uhr 5

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

我目前使用Jinja2(Python)进行大多数模板工作 - 我发现它在各方面都是非常可配置的.


小智 5

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

例如这个

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

变成了这个

char read_CHAR(char* v);
int read_INT(int* v);
long read_LONG(long* v);
Run Code Online (Sandbox Code Playgroud)

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

cxw 编辑 - 在@ d-ash的批准下,我也是perlpp的维护者.如果您有任何疑问,请随时给我留言!