【问题标题】:Expanding a single macro in C or C++ source files在 C 或 C++ 源文件中扩展单个宏
【发布时间】:2013-01-08 18:31:04
【问题描述】:

我有大量的 c++ 源文件,我想通过扩展我指定的单个函数宏来转换它们,并且保留所有其他预处理指令不变。宏的参数通常会涉及括号和大括号以及括号保护的逗号,因此使用 sed 和 kin 执行此操作似乎并不直接。

更新: 我们的代码大量使用宏来生成样板(例如 swig 的帮助代码)。当我们更好地弄清楚如何做某些事情时,各种宏不再做任何非常有趣的事情(例如,只是声明一些函数),许多人抱怨它们使代码更难阅读。我想将不那么有趣的宏扩展为简单的 C++ 代码。

【问题讨论】:

  • 我能问一下为什么吗?无论您实际尝试做什么,都可能有更好的策略。
  • 未经测试(因此评论不回答)..您可能会运行全局搜索和替换,将#include更改为//#include,然后运行gcc -E -DWHATEVER并在结果上反转初始搜索和替换......或者编写一个有限的解析器或正则表达式......
  • @johannes:哦,谢谢!我考虑过运行 pp,但没有考虑评论包含... :( 但是您需要评论 all pp 语句才能使其正常工作。

标签: c++ c c-preprocessor


【解决方案1】:

我通过在 python 中使用正则表达式来完成这类事情。您可以编写一个相当短的脚本来处理大量文件并在每个文件上运行一些正则表达式。正则表达式可能是最耗时的部分。

【讨论】:

  • 当参数都很简单(没有嵌套的括号)时,我使用过它,但我的理解是在正则表达式中匹配嵌套的括号会很困难。
  • 如果不确切知道你要做什么就很难说,但我认为它应该仍然可行。
  • 绝对不可行...我需要编译器本身(或者实际上是 m4)来进行宏扩展。
  • 是的,根据定义,这不可能使用正则表达式,因为解析嵌套的括号需要上下文无关的语法。您可以对内部没有括号的简单表达式执行此操作,但很难知道您是否搞砸了任何复杂的表达式。这就是为什么如果预处理器(知道如何解析宏表达式)可以做到这一点是理想的。
【解决方案2】:

我也有类似的需求:摆脱(扩展)那些用于处理古老的 C89 之前的编译器的无用的原型隐藏宏,同时保留其他所有内容。

来自<stdio.h>的示例:

int     _EXFUN(vfprintf, (FILE *__restrict, const char *__restrict, __VALIST)
               _ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int     _EXFUN(vprintf, (const char *, __VALIST)
               _ATTRIBUTE ((__format__ (__printf__, 1, 0))));
int     _EXFUN(vsprintf, (char *__restrict, const char *__restrict, __VALIST)
               _ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int     _EXFUN(fgetc, (FILE *));
char *  _EXFUN(fgets, (char *__restrict, int, FILE *__restrict));
int     _EXFUN(fputc, (int, FILE *));

这里我需要将宏 _EXFUN(name,proto) 扩展为 name proto。请注意,某些宏调用跨越多行。

解决方案是使用像m4 这样的宏处理器,因为它与#include 指令和其他宏处理无关(不像cppgcc -E):

$ m4 '-D_EXFUN=$1$2' stdio.h
int     vfprintf(FILE *__restrict, const char *__restrict, __VALIST)
               _ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int     vprintf(const char *, __VALIST)
               _ATTRIBUTE ((__format__ (__printf__, 1, 0)));
int     vsprintf(char *__restrict, const char *__restrict, __VALIST)
               _ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int     fgetc(FILE *);
char *  fgets(char *__restrict, int, FILE *__restrict);
int     fputc(int, FILE *);

【讨论】:

    【解决方案3】:
    • 创建undef.h 文件
    • #undef 填充你不想展开的所有宏
    • 最后一行包含extern int LandMarkSoYouCanFindThis;
    • 对于每个文件
      • 在文件的最后一个包含之后注入#include "undef.h"
      • 通过cpp运行文件
      • 使用 LandMark 将所有内容从包含中删除
      • 合并回原始文件。

    您可以通过根据#undefing 仅选定的宏和#undefing 所有宏之间的差异生成补丁来自动执行最后一步。

    【讨论】:

      猜你喜欢
      • 2014-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2011-03-01
      • 2015-01-27
      • 1970-01-01
      相关资源
      最近更新 更多