将C文件导出到新文件时,删除#if 0和#endif之间的代码

问题描述 投票:2回答:3

我想删除toy.c文件中的所有注释。从Remove comments from C/C++ code我看到我可以使用

gcc -E -fpreprocessed -P -dD toy.c

但是我的一些代码(比如我不想编译的弃用函数)被包装起来between #if 0 and endif, as if they were commented out

  • 一方面,上面的命令不会删除这种类型的“注释”,因为它只能在宏扩展期间删除,这是-fpreprocessed阻止的;
  • 另一方面,我有其他我不想扩展的宏,所以删掉-fpreprocessed是个坏主意。

我看到这里陷入两难境地。有没有办法摆脱这种情况?谢谢。


以下玩具示例“toy.c”足以说明问题。

#define foo 3  /* this is a macro */

// a toy function
int main (void) {
  return foo;
  }

// this is deprecated
#if 0
int main (void) {
  printf("%d\n", foo);
  return 0;
  }
#endif

gcc -E -fpreprocessed -P -dD toy.c给出

#define foo 3
int main (void) {
  return foo;
  }
#if 0
int main (void) {
  printf("%d\n", foo);
  return 0;
  }
#endif

gcc -E -P toy.c给出

int main (void) {
  return 3;
  }
c gcc comments c-preprocessor text-processing
3个回答
3
投票

有一对程序,sunifdef(“unifdef的儿子”,可以从unifdef获得)和coan,可以用来做你想要的。问题Is there a C pre-processor which eliminates #ifdef blocks based on values defined/undefined?有答案讨论这些程序。

例如,给定“xyz37.c”:

#define foo 3  /* this is a macro */

// a toy function
int main (void) {
  return foo;
  }

// this is deprecated
#if 0
int main (void) {
  printf("%d\n", foo);
  }
#endif

使用sunifdef

sunifdef -DDEFINED -ned < xyz37.c

#define foo 3  /* this is a macro */

// a toy function
int main (void) {
  return foo;
  }

// this is deprecated

并给出此文件“xyz23.c”:

#if 0
This is deleted
#else
This is not deleted
#endif

#if 0
Deleted
#endif

#if defined(XYZ)
XYZ is defined
#else
XYZ is not defined
#endif

#if 1
This is persistent
#else
This is inconsistent
#endif

该程序

sunifdef -DDEFINE -ned < xyz23.c

This is not deleted

#if defined(XYZ)
XYZ is defined
#else
XYZ is not defined
#endif

This is persistent

我想,这就是你所追求的。 -DDEFINED选项似乎是必要的;选择您在代码中不使用的任何名称。如果您愿意,可以使用-UNEVER_DEFINE_THIS代替。 -ned选项评估常量项并删除相关代码。没有它,像01这样的常数术语并没有消除。

我已经愉快地使用了sunifdef多年(侵蚀了十年)。我还没有发现它犯了一个错误,我用它来清理一些令人反感的“ifdeffery”。该计划coansunifdef的开发,具有更多功能。


2
投票

预处理器不会例外。你不能在这里使用它来做到这一点。

使用python的简单状态机可以工作。它甚至可以处理嵌套(好吧,也许并非所有情况都像嵌套的#if 0一样,但你可以比较前后的源和手动验证)。也不支持评论代码(但似乎你已覆盖它)

输入(比你的演示稍微复杂一点):

#define foo 3
int main (void) {
  return foo;
  }
#if 0
int main (void) {
  #ifdef DDD
  printf("%d\n", foo);
  #endif
  }
#endif

void other_function()
{}

现在的代码,使用正则表达式检测qazxsw poi&qazxsw poi。

#if

输出文件包含:

#endif

所以嵌套工作,import re rif0 = re.compile("\s*#if\s+0") rif = re.compile("\s*#(if|ifn?def)") endif = re.compile("\s*#endif") if_nesting = 0 if0_nesting = 0 suppress = False with open("input.c") as fin, open("output.c","w") as fout: for l in fin: if rif.match(l): if_nesting += 1 if rif0.match(l): suppress = True if0_nesting = if_nesting elif endif.match(l): if if0_nesting == if_nesting: suppress = False if_nesting -= 1 continue # don't write the #endif if not suppress: fout.write(l)) 部分被成功删除。不是#define foo 3 int main (void) { return foo; } void other_function() {} 可以实现的。


0
投票

谢谢你的另外两个答案。

我现在知道#if 0sed "/#if 0/,/#endif/d。我很高兴知道这些工具的存在,并且我不是唯一一个想要进行这种代码清理的人。

我还写了一个“rm_if0_endif.c”(附后),用于删除unifdef块,这对我来说已经足够了。其理念基于文本处理。它扫描输入C脚本,定位sunifdef和正确的封闭#if 0 ... #endif,以便在char-to-char复制期间可以省略此块。

文本处理方法是有限的,因为它仅针对#if 0案例而设计,但我现在只需要它。 C程序不是这种文本处理的唯一方法。 endif演示了如何在Python中完成它。我也可以在R中做类似的事情,使用#if 0 ... #endifJean-François Fabre's answerreadLines。我之所以选择用C做,因为我还不是C的专家,所以这个任务让我学习。这是我的“rm_if0_endif.c”的演示。请注意,该程序可以连接多个C文件并为每个文件添加标头。

原始输入文件“input.c”

startsWith

gcc预处理输出“gcc_output.c”(作为我程序的输入)

writeLines

#define foo 3  /* this is a macro */

// a toy function
int test1 (void) {
  return foo;
  }

#if 0

#undef foo
#define foo 4

#ifdef bar
  #warning "??"
#endif

// this is deprecated
int main (void) {
  printf("%d\n", foo);
  return 0;
  }

#endif

// another toy
int test2 (void) {
  return foo;
  }

我的程序中的最终输出“final_output.c”

“rm_if0_endif.c”有一个实用函数gcc -E -fpreprocessed -P -dD input.c > gcc_output.c 和一个主力函数#define foo 3 int test1 (void) { return foo; } #if 0 #undef foo #define foo 4 #ifdef bar #warning "??" #endif int main (void) { printf("%d\n", foo); return 0; } #endif int test2 (void) { return foo; }

pattern_matching

下面的附件有一个rm_if0_endif函数

void rm_if0_endif (char *InputFile,
                   char *OutputFile, char *WriteMode, char *OutputHeader);

它产生:

main

附录:“rm_if0_endif.c”

rm_if0_endif("gcc_output.c",
             "final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");
© www.soinside.com 2019 - 2024. All rights reserved.