如何在 C 中自动内联包含的文件?

  • 本文关键字:包含 文件 c
  • 更新时间 :
  • 英文 :


我正在使用一个第三方 C 文件,该文件下面有一个片段。

static void
random_vector(gsl_vector * v, gsl_rng * r)
{
size_t i;
for (i = 0; i < v->size; ++i)
{
double vi = __x0 * gsl_rng_uniform(r) - __x1; /* in [-1,1] */
gsl_vector_set(v, i, vi);
}
}
#include "test_impulse.c"
#include "test_gaussian.c"
#include "test_median.c"
#include "test_rmedian.c"

有没有办法,例如 gcc 选项,自动将原始 C 文件转换为包含"test_impulse.c"等的文件? 手动执行此操作很容易,但我将不得不处理很多此类情况。

[更新] 因为 C 文件还包括一些头文件(.h 文件(,我不需要将它们放入转换后的文件中。因此,按照以下评论中的建议,使用 gcc "-E" 选项是不行的。

我的解决方案有一些警告,但一般来说,当所有行都#为第一个字符并以c"结尾并且没有一行以$开头时,您可以有一个看起来像这样的小管道:

sed -E 's/^#(.*[^c]")$/$1/' ORIGINAL | 
gcc -E - | 
sed -E 's/^$(.*)$/#1/' > FINAL

这样做的作用是,它将以主题标签开头并以c"结尾的所有行上用美元符号替换主题标签。然后它执行gcc -E,然后将所有美元符号恢复为主题标签。

一种可能性是执行包含.c文件的小型C程序。

优点是它可以很容易地适应(例如,如果你想将嵌入的.c文件移动到另一个位置,等等(。

用于 *NIX 操作系统的简单 C 程序可能类似于以下代码,大概需要针对您的特定用例进行一些轻微的自定义。

与此类操作一样,在应用程序之前备份输入!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#include <libgen.h>

#define MAX_LINE 2048
void exit_with_error(const char *msg);
void backup(const char *filename);
void process(char *filename);
void include(char *filename, FILE *fpout, regmatch_t *pmatch, char *line);
void copy(FILE *fpin, FILE *fpout);
FILE *input_file(const char *input_file_name, const char *mode);
FILE *backup_file(const char *input_file_name, const char *mode);

int main(int argc, char *argv[]) {
if(argc != 2) {
fprintf(stderr, "usage: incl <file.c>n");
exit(1);
}
backup(argv[1]);
process(argv[1]);
return 0;
}
void exit_with_error(const char *msg) {
perror(msg);
exit(1);
}
void process(char *filename) {
FILE *fpin = backup_file(filename, "r");
FILE *fpout = input_file(filename, "w");
regex_t regex;
char msgbuf[100];
regmatch_t pmatch[2];
int rc_comp = regcomp(&regex, "^#include[ \t]+"([a-zA-Z0-9_\/]+\.c)"[ t]*[rn]?$", REG_EXTENDED);
if (rc_comp) {
regerror(rc_comp, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "regcomp failed: %sn", msgbuf);
exit(1);
}
char *line = NULL;
size_t len = MAX_LINE;
while((getline(&line, &len, fpin)) != -1) {
int rc_exec = regexec(&regex, line, 2, pmatch, 0);
switch (rc_exec) {
case 0: {
include(filename, fpout, pmatch, line);
break;
}
case REG_NOMATCH:
if(fputs(line, fpout) == EOF) {
exit_with_error("writing output failed");
}
break;
default:
regerror(rc_exec, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "regexec failed: %sn", msgbuf);
exit(1);
}
}
regfree(&regex);
free(line);
fclose(fpin);
fclose(fpout);
}
void include(char *filename, FILE *fpout, regmatch_t *pmatch, char *line) {
char *match = calloc(pmatch[1].rm_eo - pmatch[1].rm_so + 1, sizeof(char));
strncpy(match, line + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);
fprintf(fpout, "// -- %s --n", match);
char *include_file_name = malloc(strlen(dirname(filename)) + sizeof(char) + strlen(match) + 1);
strcpy(include_file_name, dirname(filename));
strcat(include_file_name, "/");
strcat(include_file_name, match);
FILE *fp_include = input_file(include_file_name, "r");
copy(fp_include, fpout);
fclose(fp_include);
fputs("n", fpout); //make sure to add newline in case it is missing in the .c
free(match);
free(include_file_name);
}
void copy(FILE *fpin, FILE *fpout) {
char *line = NULL;
size_t len = MAX_LINE;
while((getline(&line, &len, fpin)) != -1) {
if(fputs(line, fpout) == EOF) {
exit_with_error("writing output failed");
}
}
free(line);
}

void backup(const char *filename) {
FILE *fpin = input_file(filename, "r");
FILE *fpout = backup_file(filename, "w");
copy(fpin, fpout);
fclose(fpin);
fclose(fpout);
}
FILE *input_file(const char *input_file_name, const char *mode) {
FILE *fp;
if((fp = fopen(input_file_name, mode)) == NULL) {
exit_with_error("problem with input file");
}
return fp;
}
FILE *backup_file(const char *input_file_name, const char *mode) {
char *bak = malloc(strlen(input_file_name) + strlen(".bak") + 1);
strcpy(bak, input_file_name);
strcat(bak, ".bak");
FILE *fp;
if((fp = fopen(bak, mode)) == NULL) {
exit_with_error("problem with backup file");
}
free(bak);
return fp;
}

最新更新