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

李哲源*_*李哲源 5 c gcc text-processing comments c-preprocessor

我想删除toy.c文件中的所有评论。从从 C/C++ 代码中删除注释我看到我可以使用

gcc -E -fpreprocessed -P -dD toy.c
Run Code Online (Sandbox Code Playgroud)

但是我的一些代码(比如我不想编译的弃用函数)被包裹#if 0和之间endif,就好像它们被注释掉了一样

  • 一方面,上面的命令不会删除这种类型的“注释”,因为它只能在宏扩展期间删除,从而-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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

gcc -E -P toy.c给予

int main (void) {
  return 3;
  }
Run Code Online (Sandbox Code Playgroud)

李哲源*_*李哲源 0

谢谢另外两位的回答。

\n\n

我现在意识到unifdefsunifdef。我很高兴知道这些工具的存在,并且我不是唯一一个想要进行这种代码清理的人。

\n\n

我还写了一个rm_if0_endif.c(附在下面)用于删除#if 0 ... #endif对我来说足够的块。其理念基于文本处理。它扫描输入的 C 脚本,定位#if 0并正确包含endif,以便在字符到字符复制期间可以省略该块。

\n\n

文本处理方法是有限的,因为它#if 0 ... #endif仅针对案例而设计,但这是我现在所需要的。AC程序并不是这种文本处理的唯一方法。Jean-Fran\xc3\xa7ois Fabre\ 的回答演示了如何在 Python 中做到这一点。我也可以在 R 中使用readLinesstartsWith和做类似的事情writeLines。我选择用 C 语言来做这件事,因为我还不是 C 语言的专家,所以这个任务驱使我去学习。这是我的演示rm_if0_endif.c。请注意,该程序可以连接多个 C 文件并为每个文件添加标头。

\n\n

原始输入文件input.c

\n\n
#define foo 3  /* this is a macro */\n\n// a toy function\nint test1 (void) {\n  return foo;\n  }\n\n#if 0\n\n#undef foo\n#define foo 4\n\n#ifdef bar\n  #warning "??"\n#endif\n\n// this is deprecated\nint main (void) {\n  printf("%d\\n", foo);\n  return 0;\n  }\n\n#endif\n\n// another toy\nint test2 (void) {\n  return foo;\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
gcc -E -fpreprocessed -P -dD input.c > gcc_output.c\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n

#define foo 3\nint test1 (void) {\n  return foo;\n  }\n#if 0\n#undef foo\n#define foo 4\n#ifdef bar\n  #warning "??"\n#endif\nint main (void) {\n  printf("%d\\n", foo);\n  return 0;\n  }\n#endif\nint test2 (void) {\n  return foo;\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

最终输出final_output.c我的程序的

\n\n

rm_if0_endif.c具有效用函数pattern_matching和主力函数rm_if0_endif

\n\n
void rm_if0_endif (char *InputFile,\n                   char *OutputFile, char *WriteMode, char *OutputHeader);\n
Run Code Online (Sandbox Code Playgroud)\n\n

下面的附件有一个main函数,做

\n\n
rm_if0_endif("gcc_output.c",\n             "final_output.c", "w", "// this is a demo of \'rm_if0_endif.c\'\\n");\n
Run Code Online (Sandbox Code Playgroud)\n\n

它生产:

\n\n
// this is a demo of \'rm_if0_endif.c\'\n#define foo 3\nint test1 (void) {\n  return foo;\n  }\n\nint test2 (void) {\n  return foo;\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

附录:rm_if0_endif.c

\n\n
#include <stdio.h>\nint pattern_matching (FILE *fp, const char *pattern, int length_pattern) {\n  int flag = 1;\n  int i, c;\n  for (i = 0; i < length_pattern; i++) {\n    c = fgetc(fp);\n    if (c != pattern[i]) {\n      flag = 0; break;\n      }\n    }\n  return flag;\n  }\nvoid rm_if0_endif (char *InputFile,\n                   char *OutputFile, char *WriteMode, char *OutputHeader) {\n  FILE *fp_r = fopen(InputFile, "r");\n  FILE *fp_w = fopen(OutputFile, WriteMode);\n  fpos_t pos;\n  if (fp_r == NULL) perror("error when opening input file!");\n  fputs(OutputHeader, fp_w);\n  int c, i, a1, a2;\n  int if_0_flag, if_flag, endif_flag, EOF_flag;\n  const char *if_0 = "if 0";\n  const char *endif = "endif";\n  EOF_flag = 0;\n  while (EOF_flag == 0) {\n    do {\n      c = fgetc(fp_r);\n      while ((c != \'#\') && (c != EOF)) {\n        fputc(c, fp_w);\n        c = fgetc(fp_r);\n        }\n      if (c == EOF) {\n        EOF_flag = 1; break;\n        }\n      fgetpos(fp_r, &pos);\n      if_0_flag = pattern_matching(fp_r, if_0, 4);\n      fsetpos(fp_r, &pos);\n      if (if_0_flag == 0) fputc(\'#\', fp_w);\n      } while (if_0_flag == 0);\n    if (EOF_flag == 1) break;\n    a1 = 1; a2 = 0;\n    do {\n      c = fgetc(fp_r);\n      while (c != \'#\') c = fgetc(fp_r);\n      fgetpos(fp_r, &pos);\n      if_flag = pattern_matching(fp_r, if_0, 2);\n      fsetpos(fp_r, &pos);\n      if (if_flag == 1) a1++;\n      fgetpos(fp_r, &pos);\n      endif_flag = pattern_matching(fp_r, endif, 5);\n      fsetpos(fp_r, &pos);\n      if (endif_flag == 1) a2++;\n      } while (a1 != a2);\n    for (i = 0; i < 5; i++) c = fgetc(fp_r);\n    if (c == EOF) {\n      EOF_flag == 1;\n      }\n    }\n  fclose(fp_r);\n  fclose(fp_w);\n  }\nint main (void) {\n  rm_if0_endif("gcc_output.c",\n               "final_output.c", "w", "// this is a demo of \'rm_if0_endif.c\'\\n");\n  return 0;\n  }\n
Run Code Online (Sandbox Code Playgroud)\n