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

如何在C中自动内联包含的文件?,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

我使用的是第三方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"
静态无效
随机向量(gsl向量*v,gsl向量*r)
{
尺寸i;
对于(i=0;isize;++i)
{
双vi=\uuuux0*gsl\urng\u均匀(r)-(uuux1;/*in[-1,1]*/
gsl_向量_集(v,i,vi);
}
}
#包括“测试脉冲c”
#包括“test_.c”
#包括“测试中位数c”
#包括“test_rmedian.c”
是否有一种方法(例如gcc选项)可以自动将原始C文件转换为包含“test_pulse.C”等的文件? 手动执行此操作将很容易,但我必须处理许多此类情况


[UPDATE]因为C文件还包括一些头文件(.h文件),我不需要将其放入转换文件中。因此,使用gcc“-E”选项(如下面的注释所示)是不合适的。

我的解决方案有一些警告,但通常情况下,当所有行都以
#
作为第一个字符,并以
c“
结尾,并且没有一行以
$
开头时,您可以有一个如下的小管道:

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

这样做的目的是,它在所有以hashtag开头并以
c“
结尾的行上用美元符号替换hashtag。然后它执行
gcc-E
,然后将所有美元符号还原为hashtags。

一种可能是一个小型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]*[\r\n]?$", REG_EXTENDED);
    if (rc_comp) {
        regerror(rc_comp, &regex, msgbuf, sizeof(msgbuf));
        fprintf(stderr, "regcomp failed: %s\n", 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: %s\n", 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;
}
#包括
#包括
#包括
#包括
#包括
#定义最大线2048
带错误的无效退出(const char*msg);
无效备份(常量字符*文件名);
作废进程(字符*文件名);
无效包括(字符*文件名、文件*fpout、regmatch\u t*pmatch、字符*行);
无效副本(文件*fpin,文件*fpout);
文件*输入文件(常量字符*输入文件\名称,常量字符*模式);
文件*备份\文件(常量字符*输入\文件\名称,常量字符*模式);
int main(int argc,char*argv[]){
如果(argc!=2){
fprintf(标准,“用法:包括”;\n);
出口(1);
}
备份(argv[1]);
过程(argv[1]);
返回0;
}
无效退出错误(const char*msg){
佩罗尔(味精);
出口(1);
}
无效进程(字符*文件名){
FILE*fpin=backup_文件(文件名为“r”);
FILE*fpout=input_文件(文件名,“w”);
regex_t regex;
char-msgbuf[100];
regmatch_t pmatch[2];
int rc_comp=regcomp(®ex,“^包括[\\t]+\”([a-zA-Z0-9\\/]+\.c)\“[\t]*[\r\n]?$”,注册扩展);
if(rc_公司){
regerror(rc_comp和regex、msgbuf、sizeof(msgbuf));
fprintf(stderr,“regcomp失败:%s\n”,msgbuf);
出口(1);
}
char*line=NULL;
尺寸长度=最大线;
while((getline(&line,&len,fpin))!=-1){
int rc_exec=regexec(®ex,第2行,pmatch,0);
开关(rc_exec){
案例0:{
包括(文件名、fpout、pmatch、行);
打破
}
案例注册编号:
如果(fputs(线,fpout)=EOF){
退出带有错误的_(“写入输出失败”);
}
打破
违约:
regerror(rc_exec和regex、msgbuf、sizeof(msgbuf));
fprintf(stderr,“regexec失败:%s\n”,msgbuf);
出口(1);
}
}
regfree(®ex);
自由线;
fclose(fpin);
fclose(fpout);
}
无效包括(字符*文件名,文件*输出,正则匹配*匹配,字符*行){
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”,匹配);
char*include_file_name=malloc(strlen(dirname(filename))+sizeof(char)+strlen(match)+1);
strcpy(包括文件名、目录名(文件名));
strcat(包括文件名“/”;
strcat(包括文件名、匹配项);
FILE*fp_include=输入_文件(include_文件名,“r”);
副本(fp_包括,fpout);
fclose(包括fp_);
fputs(“\n”,fpout);//确保添加换行符,以防.c中缺少该换行符
免费(比赛);
免费(包括文件名);
}
无效副本(文件*fpin,文件*fpout){
char*line=NULL;
尺寸长度=最大线;
while((getline(&line,&len,fpin))!=-1){
如果(fputs(线,fpout)=EOF){
退出带有错误的_(“写入输出失败”);
}
}
自由线;
}
无效备份(常量字符*文件名){
FILE*fpin=input_文件(文件名,“r”);
FILE*fpout=备份文件(文件名,“w”);
复印件(fpin、fpout);
fclose(fpin);
fclose(fpout);
}
文件*输入文件(常量字符*输入文件\名称,常量字符*模式){
文件*fp;
if((fp=fopen(输入文件名,模式))==NULL){
退出_时出现_错误(“输入文件有问题”);
}
返回fp;
}
文件*备份\文件(常量字符*输入\文件\名称,常量字符*模式){
char*bak=malloc(strlen(输入文件名)+strlen(“.bak”)+1);
strcpy(bak,输入文件名);
strcat(bak,“.bak”);
文件*fp;
if((fp=fopen(bak,mode))==NULL){
退出时出现错误(“备份文件有问题”);
}
免费(bak);
返回fp;
}

-E
选项可能满足您的需要。
-P
选项有时是另一种选择。可能是
gcc-E
?请参阅,如果“包含的”C文件应用于其他C模块,我认为更好的方法是创建一个包含现在包含的C模块的库。通过这种方式,您可以将代码与库链接,而不必在C代码中包含C模块。为了清楚起见,您是希望获得预处理器的结果,还是只希望包含文件而不接触宏等