如何去除糟糕无用的宏定义

9

我有一份相当庞大的C和C ++代码(~200k loc),其中广泛使用可怕的宏:

/* ... */
#define PRIVATE static
#define BEGIN           {
#define END             }
/* ... */
#define WHILE(e)        while (e) {
#define DO /* yep, it's empty */
#define ENDWHILE        }
/* and it goes on and on, for every keyword of the language */

这是个问题,我想要去掉那个愚蠢的标题,清理代码,并适当地缩进。
起初,我想使用简单的sed替换所有这些宏,但似乎并不简单。 WHILE的情况很棘手(其他语句也是如此)。我不能只用while来替换WHILE,因为左大括号会丢失。当然,由于DO宏没有任何作用,它并不总是出现在代码中。因此,将DO替换为{行不通。
我也不能使用换行符,因为条件经常分成多行:
WHILE (clsr_calibragedf_tabdisque.tab_disque[indice_disque].tab_date[indice_date] NE
                   clsr_calibragedf_tabdate [indice].date) DO
                indice ++;
            ENDWHILE

我能想到的最好解决方案是使用C预处理器来替换特定的宏,而不是扩展#include指令或其他宏。但我找不到这样的工具。

有什么想法吗?


我认为sed会很好,但你需要一个适当的正则表达式来匹配包括表达式和开括号。然后只需用while和RE匹配文本(其中将包括,因此保留,开括号)进行替换即可。 - unwind
问题在于表达式中可能包含多个括号。 - MouleMan
我认为你可以绕过这个问题,因为你知道括号后必须有一个单独的左大括号。例如,像 '\(.+\) \{' 这样的正则表达式在实践中可能有效。 - unwind
我会集中精力于防御:首先确保你有测试让你感到安全,然后逐个替换宏。将“DO”更改为“{”实际上是一个不错的开始,编译器会捕捉你缺少的DO,并且你可以自己替换它们。然后再替换WHILE等。 - Adrian Ratnapala
当然,逐步方法是我的计划的一部分,以确保在清洁过程结束时一切都像以前一样正常工作。 - MouleMan
2个回答

7

呃!怎么办:

  1. 通过一些perl运行程序来以独特的方式注释掉#include指令(例如:/*FIXSTUFF #include <blah.h> FIXSTUFF*/)。您可能还想以类似的方式注释掉其他预处理器内容(例如:#define)。

  2. 检查每个文件,只包括奇怪宏的定义。

  3. 现在对每个文件运行gcc -E,这将预处理宏。

  4. 反转步骤1。

  5. 为了保险起见,运行indent

请注意,C预处理器执行以下操作(从此处窃取):

  1. 三字符替换:预处理器将三字符序列替换为它们代表的字符。
  2. 行拼接:使用转义换行符继续的物理源行将被拼接成逻辑行。
  3. 记号化:预处理器将结果分解为预处理记号和空格。它用空格替换注释。
  4. 宏扩展和指令处理:执行预处理指令行,包括文件包含和条件编译。预处理器同时扩展宏,在C标准的1999年版本中,处理_Pragma操作符。

因此,理论上您将在源代码中丢失三字符(有人会认为这是一个奖励),并可能改变行拼接(在步骤5中使用indent修复)。您需要保护任何其他预处理器指令,如步骤(1)。

祝你好运!


0

Eclipse IDE有一些很棒的搜索和替换工具。您可以将代码导入其中,然后使用文件搜索工具。您可以像这样使用它:

  1. 使用Ctrl + H(或上下文菜单中的搜索>文件...)打开它以搜索一个宏的所有出现

  2. 单击替换...以打开替换窗口并选择替换

  3. 单击预览>以查看所有替换并使用OK应用它们

使用正则表达式

对于更复杂的情况,您可以在文件搜索视图中使用正则表达式选项。例如,以下是如何将其应用于您的WHILE-ENDWHILE宏:

  1. 搜索正则表达式(请参阅反向查找以了解其工作原理):

    WHILE(((?!ENDWHILE).|\s)+)ENDWHILE

  2. 插入替换项 while(\1)

  3. 在预览页面中查看结果并应用

就像我所说的那样,仅仅将“WHILE”替换为“while”是不够的。 - MouleMan
1
可以使用搜索栏中的正则表达式选项,然后在替换时,例如可以使用\1 表示第一组的值,\2 表示第二组,以此类推。 - maxdev
比如说,你有文本“这是一段美丽的文字”,那么你可以使用正则表达式“这是一段([a-zA-Z]+)的文字”,然后在替换字段中使用“该文本是\1”。结果将会是“该文本是美丽的”。 - maxdev
看一下我给出的多行 WHILE 条件的示例,仅进行查找/替换是不够的。 - MouleMan
你可以为此创建一个正则表达式,必须创建一个查找从 WHILE 开始到 ENDWHILE 结束的任何内容的正则表达式,并简单地使用替换 while(\1)。然后,您甚至可以预览以检查是否一切都没有问题。 - maxdev
我在答案中添加了如何操作的示例,希望能有所帮助。 :) - maxdev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接