在C或c++源文件中展开单个宏

Expanding a single macro in C or C++ source files

本文关键字:单个宏 源文件 c++      更新时间:2023-10-16

我有大量的c++源文件,我想通过扩展我指定的单个函数宏来转换它们,而不改变所有其他预处理指令。宏的参数通常涉及父括号、大括号和受父括号保护的逗号,因此使用sed和kin似乎不太直接。

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

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

我也有类似的需求:摆脱(扩展)那些无用的隐藏原型的宏,这些宏用于处理古老的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 *);
    创建undef.h文件
  • #undef填充所有你不想扩展的宏
  • 包含extern int LandMarkSoYouCanFindThis;作为最后一行
  • 每个文件
    • 在最后一个包含文件后注入#include "undef.h"
    • 通过cpp
    • 运行文件
    • 使用LandMark来切断包含
    • 的所有内容

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