将 C 文件导出到新文件时删除#if 0 和#endif 之间的代码
Remove code between #if 0 and #endif when exporting a C file to a new one
我想删除 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。
- 一方面,上面的命令不会删除这种类型的 "comment" 因为它只能在宏扩展期间删除,
-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;
}
预处理器不会产生异常。您不能在此处使用它来执行此操作。
使用 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()
{}
现在是代码,使用正则表达式检测 #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
可以达到的。
有一对程序,sunifdef
("Son of unifdef
", which is available from unifdef) and coan
, that can be used to do what you want. The question 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
的开发,具有更多功能。
感谢另外两位的回答。
我现在知道 unifdef
and sunifdef
。我很高兴知道这些工具的存在,而且我不是唯一一个想做这种代码清理的人。
我还写了一个rm_if0_endif.c
(附在下面)用于删除对我来说足够的#if 0 ... #endif
块。它的理念是基于文本处理。它扫描输入的 C 脚本,定位 #if 0
和正确的封闭 endif
,以便在 char-to-char 复制期间可以省略此块。
文本处理方法是有限的,因为它是为 #if 0 ... #endif
案例设计的,但这是我现在所需要的。 C 程序不是这种文本处理的唯一方法。 Jean-François Fabre's answer 在 Python 中演示了如何操作。我也可以在 R 中做类似的事情,使用 readLines
、startsWith
和 writeLines
。我选择用 C 来做,因为我还不是 C 的专家,所以这个任务促使我去学习。这是我的 rm_if0_endif.c
的演示。请注意,该程序可以连接多个 C 文件并为每个文件添加 header。
原始输入文件input.c
#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;
}
gcc pre-processing 输出 "gcc_output.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;
}
我程序的最终输出final_output.c
rm_if0_endif.c
具有效用函数 pattern_matching
和主力函数 rm_if0_endif
:
void rm_if0_endif (char *InputFile,
char *OutputFile, char *WriteMode, char *OutputHeader);
下面的附件有一个main
函数,做
rm_if0_endif("gcc_output.c",
"final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");
它产生:
// this is a demo of 'rm_if0_endif.c'
#define foo 3
int test1 (void) {
return foo;
}
int test2 (void) {
return foo;
}
附录:rm_if0_endif.c
#include <stdio.h>
int pattern_matching (FILE *fp, const char *pattern, int length_pattern) {
int flag = 1;
int i, c;
for (i = 0; i < length_pattern; i++) {
c = fgetc(fp);
if (c != pattern[i]) {
flag = 0; break;
}
}
return flag;
}
void rm_if0_endif (char *InputFile,
char *OutputFile, char *WriteMode, char *OutputHeader) {
FILE *fp_r = fopen(InputFile, "r");
FILE *fp_w = fopen(OutputFile, WriteMode);
fpos_t pos;
if (fp_r == NULL) perror("error when opening input file!");
fputs(OutputHeader, fp_w);
int c, i, a1, a2;
int if_0_flag, if_flag, endif_flag, EOF_flag;
const char *if_0 = "if 0";
const char *endif = "endif";
EOF_flag = 0;
while (EOF_flag == 0) {
do {
c = fgetc(fp_r);
while ((c != '#') && (c != EOF)) {
fputc(c, fp_w);
c = fgetc(fp_r);
}
if (c == EOF) {
EOF_flag = 1; break;
}
fgetpos(fp_r, &pos);
if_0_flag = pattern_matching(fp_r, if_0, 4);
fsetpos(fp_r, &pos);
if (if_0_flag == 0) fputc('#', fp_w);
} while (if_0_flag == 0);
if (EOF_flag == 1) break;
a1 = 1; a2 = 0;
do {
c = fgetc(fp_r);
while (c != '#') c = fgetc(fp_r);
fgetpos(fp_r, &pos);
if_flag = pattern_matching(fp_r, if_0, 2);
fsetpos(fp_r, &pos);
if (if_flag == 1) a1++;
fgetpos(fp_r, &pos);
endif_flag = pattern_matching(fp_r, endif, 5);
fsetpos(fp_r, &pos);
if (endif_flag == 1) a2++;
} while (a1 != a2);
for (i = 0; i < 5; i++) c = fgetc(fp_r);
if (c == EOF) {
EOF_flag == 1;
}
}
fclose(fp_r);
fclose(fp_w);
}
int main (void) {
rm_if0_endif("gcc_output.c",
"final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");
return 0;
}
我想删除 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。
- 一方面,上面的命令不会删除这种类型的 "comment" 因为它只能在宏扩展期间删除,
-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;
}
预处理器不会产生异常。您不能在此处使用它来执行此操作。
使用 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()
{}
现在是代码,使用正则表达式检测 #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
可以达到的。
有一对程序,sunifdef
("Son of unifdef
", which is available from unifdef) and coan
, that can be used to do what you want. The question 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
的开发,具有更多功能。
感谢另外两位的回答。
我现在知道 unifdef
and sunifdef
。我很高兴知道这些工具的存在,而且我不是唯一一个想做这种代码清理的人。
我还写了一个rm_if0_endif.c
(附在下面)用于删除对我来说足够的#if 0 ... #endif
块。它的理念是基于文本处理。它扫描输入的 C 脚本,定位 #if 0
和正确的封闭 endif
,以便在 char-to-char 复制期间可以省略此块。
文本处理方法是有限的,因为它是为 #if 0 ... #endif
案例设计的,但这是我现在所需要的。 C 程序不是这种文本处理的唯一方法。 Jean-François Fabre's answer 在 Python 中演示了如何操作。我也可以在 R 中做类似的事情,使用 readLines
、startsWith
和 writeLines
。我选择用 C 来做,因为我还不是 C 的专家,所以这个任务促使我去学习。这是我的 rm_if0_endif.c
的演示。请注意,该程序可以连接多个 C 文件并为每个文件添加 header。
原始输入文件input.c
#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;
}
gcc pre-processing 输出 "gcc_output.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;
}
我程序的最终输出final_output.c
rm_if0_endif.c
具有效用函数 pattern_matching
和主力函数 rm_if0_endif
:
void rm_if0_endif (char *InputFile,
char *OutputFile, char *WriteMode, char *OutputHeader);
下面的附件有一个main
函数,做
rm_if0_endif("gcc_output.c",
"final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");
它产生:
// this is a demo of 'rm_if0_endif.c'
#define foo 3
int test1 (void) {
return foo;
}
int test2 (void) {
return foo;
}
附录:rm_if0_endif.c
#include <stdio.h>
int pattern_matching (FILE *fp, const char *pattern, int length_pattern) {
int flag = 1;
int i, c;
for (i = 0; i < length_pattern; i++) {
c = fgetc(fp);
if (c != pattern[i]) {
flag = 0; break;
}
}
return flag;
}
void rm_if0_endif (char *InputFile,
char *OutputFile, char *WriteMode, char *OutputHeader) {
FILE *fp_r = fopen(InputFile, "r");
FILE *fp_w = fopen(OutputFile, WriteMode);
fpos_t pos;
if (fp_r == NULL) perror("error when opening input file!");
fputs(OutputHeader, fp_w);
int c, i, a1, a2;
int if_0_flag, if_flag, endif_flag, EOF_flag;
const char *if_0 = "if 0";
const char *endif = "endif";
EOF_flag = 0;
while (EOF_flag == 0) {
do {
c = fgetc(fp_r);
while ((c != '#') && (c != EOF)) {
fputc(c, fp_w);
c = fgetc(fp_r);
}
if (c == EOF) {
EOF_flag = 1; break;
}
fgetpos(fp_r, &pos);
if_0_flag = pattern_matching(fp_r, if_0, 4);
fsetpos(fp_r, &pos);
if (if_0_flag == 0) fputc('#', fp_w);
} while (if_0_flag == 0);
if (EOF_flag == 1) break;
a1 = 1; a2 = 0;
do {
c = fgetc(fp_r);
while (c != '#') c = fgetc(fp_r);
fgetpos(fp_r, &pos);
if_flag = pattern_matching(fp_r, if_0, 2);
fsetpos(fp_r, &pos);
if (if_flag == 1) a1++;
fgetpos(fp_r, &pos);
endif_flag = pattern_matching(fp_r, endif, 5);
fsetpos(fp_r, &pos);
if (endif_flag == 1) a2++;
} while (a1 != a2);
for (i = 0; i < 5; i++) c = fgetc(fp_r);
if (c == EOF) {
EOF_flag == 1;
}
}
fclose(fp_r);
fclose(fp_w);
}
int main (void) {
rm_if0_endif("gcc_output.c",
"final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");
return 0;
}