如何在C中自动内联包含的文件?
我使用的是第三方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
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(®ex, "^#include[ \\t]+\"([a-zA-Z0-9_\\/]+\\.c)\"[ \t]*[\r\n]?$", REG_EXTENDED);
if (rc_comp) {
regerror(rc_comp, ®ex, 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(®ex, 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, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "regexec failed: %s\n", msgbuf);
exit(1);
}
}
regfree(®ex);
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模块。为了清楚起见,您是希望获得预处理器的结果,还是只希望包含文件而不接触宏等