Спасибо за два других ответа.
Теперь мне известно о unifdef и sunifdef . Я счастлив узнать о существовании этих инструментов и о том, что я не единственный, кто хочет проводить такую очистку кода.
Я также написал "rm_if0_endif.c" (прилагается ниже) для удаления блока #if 0 ... #endif
, что мне достаточно. Его философия основана на обработке текста. Он сканирует входной сценарий C, определяющий местоположение #if 0
и правильное вложение endif
, так что этот блок можно опустить при копировании с символа на символ.
Подход к обработке текста ограничен, так как он предназначен только для #if 0 ... #endif
случая, но это все, что мне нужно на данный момент. Программа на C - не единственный способ обработки текста такого рода. Ответ Жана-Франсуа Фабра демонстрирует, как это сделать на Python. Я также могу сделать нечто подобное в R, используя readLines
, startsWith
и writeLines
. Я решил сделать это на C, так как я еще не эксперт в C, поэтому эта задача заставляет меня учиться. Вот демонстрация моего "rm_if0_endif.c" . Обратите внимание, что программа может объединить несколько файлов C и добавить заголовок для каждого файла.
исходный файл ввода "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 "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;
}