我想删除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;
}
有一对程序,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
选项评估常量项并删除相关代码。没有它,像0
和1
这样的常数术语并没有消除。
我已经愉快地使用了sunifdef
多年(侵蚀了十年)。我还没有发现它犯了一个错误,我用它来清理一些令人反感的“ifdeffery”。该计划coan
是sunifdef
的开发,具有更多功能。
预处理器不会例外。你不能在这里使用它来做到这一点。
使用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()
{}
可以实现的。
谢谢你的另外两个答案。
我现在知道#if 0
和sed "/#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 ... #endif
,Jean-François Fabre's answer和readLines
。我之所以选择用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");