* include [-i "{string}"] [ {FILE} ]
* recursively expands files included in {FILE}, where "inclusion"
* ^{include_cmd} "file", or
* {include_cmd} is {string} if -i option used, or
* is default to '#include'.
char *Version
= "$Id: include.c,v 1.1 2008/04/18 06:19:50 nhussain Exp $";
#define streq(a,b) !strcmp(a,b)
#define strleq(a,b) !strncmp(a,b, strlen(a))
#define skip_to_eoln(in) while(getc(in) != '\n')
char ignore
=NO
; /*ignore missing file, continue to process*/
char *incCmd
= "#include";
char *incDir
[80]={"."}; /*first to search is current dir*/
int last_incDir
= 0; /*incDir[0] is .*/
/* char *directory(char *name, char *dir); */
usage_and_exit(msg1
, msg2
)
if(msg2
&& *msg2
) { sprintf(format
, "%s\n", msg1
);
fprintf(stderr
, format
, msg2
);
}else { fprintf(stderr
, "%s\n", msg1
);
fprintf(stderr
, "usage: include [{options}] [{FILE}]\n");
fprintf(stderr
, "options: [default]\n");
fprintf(stderr
, "\t -i {string}: use {string} as include_cmd. [#include]\n");
fprintf(stderr
, "\t where include_cmd is used as follows: \n");
fprintf(stderr
, "\t ^{include_cmd} \"{file}\",or \n");
fprintf(stderr
, "\t ^{include_cmd} <{file}> \n");
fprintf(stderr
, "\t ^{include_cmd} {file} \n");
fprintf(stderr
, "\t -pal: print line number and file name for pal.\n");
fprintf(stderr
, "\t -I {directory}: include files directory for search after .\n");
fprintf(stderr
, "\t -o {outFile}: output to file {outFile}. [stdout]\n");
fprintf(stderr
, "\t -abs|-rel: include file uses absolute or relative paths. [absolute=%d]\n",
char *outfile
=0, *infile
;
char dir
[100]; /*prefix to a relative path*/
if(argc
<= 1) usage_and_exit("");
while(argv
[idx
][0] == '-') {
if(streq(argv
[idx
], "-h") ) {
}else if(streq(argv
[idx
], "-c") && argc
>=idx
+2) { //comment prefix
}else if(streq(argv
[idx
], "-I") ) { //include dir
incDir
[++last_incDir
]= argv
[idx
+1];
}else if(streq(argv
[idx
], "-i") && argc
>=idx
+2) { //include prefix
}else if(streq(argv
[idx
], "-o") && argc
>=idx
+2) {
}else if(streq(argv
[idx
], "-pal") ) {
}else if(streq(argv
[idx
], "-abs")) {
}else if(streq(argv
[idx
], "-rel")) {
}else{ usage_and_exit("illegal arguments:%s", argv
[idx
]);
infile
= (char*) strdup("stdin");
infile
= (char*) strdup(argv
[idx
]);
in
= fopen(argv
[idx
], "r");
if(in
== NULL
) usage_and_exit("in file '%s' not found!", argv
[idx
]);
directory(argv
[idx
], dir
);
if(outfile
== NULL
) { out
= stdout
;
}else{ out
= fopen(outfile
, "w");
if(out
== NULL
) usage_and_exit("can't open output file: %s!", outfile
);
len_incCmd
= strlen(incCmd
);
include(infile
, in
, out
, 1);
DirName(path
, dirname
) //path: in; dirname: out
for(i
= strlen(dirname
); i
>=0; --i
) {
include(currFile
, in
, out
, depth
)
char newDir
[100]; /*directory for the include file X, which is needed*/
/* for files included in X using relative path*/
char line
[256], incFile
[FNAME_LEN
], closing
;
FILE *inc_fd
, *find_and_open_file();
int linenum
=0, return_from_include
=0, missingFile
;
fprintf(out
, "# line 1 %s\n", currFile
);
DirName(currFile
, dirname
);
while( fgets(line
, 256, in
) ) {
if( !strncmp(incCmd
, line
, len_incCmd
) && /*match starting 1st column*/
(line
[i
=len_incCmd
]==' ' || line
[i
]=='\t') ) {
while(line
[++i
]== ' ' || line
[i
]=='\t') ; /*skip more ws*/
* if(line[i] != '"' && line[i]!='<')
* usage_and_exit("illegal syntax of 'include_cmd': %s !!", line);
* closing= line[i] == '"' ? '"' : '>';
if(ABSOLUTE_PATH
==0) { //relative path in include file
strcpy(incFile
, dirname
);
if(line
[i
] != '"' && line
[i
]!='<') incFile
[j
++]= line
[i
];
while(line
[++i
] != '"' && line
[i
] != '>' && !isspace(line
[i
]) && line
[i
]) {
usage_and_exit("include file name too long (>FNAME_LEN): %s!", line
);
fprintf(out
, "###depth=%d include ==> %s", depth
, line
);
/*ignore the rest of the line*/
inc_fd
= find_and_open_file(incFile
, newDir
);
if(inc_fd
==0 && mode
==M_PAL
) {
fprintf(stderr
, "\t %s\n", incFile
);
fprintf(stderr
, "\t ^-- %s\n", currFile
);
oldDir
= incDir
[0]; /*save current directory before*/
incDir
[0]= newDir
; /* move to newDir*/
missingFile
= include(incFile
, inc_fd
, out
, depth
+1); /*recursively include*/
if(missingFile
&& mode
==M_PAL
) {
fprintf(stderr
, "\t ^-- %s\n", currFile
);
if(mode
==M_PAL
&& return_from_include
)
fprintf(out
, "# line %d %s\n", linenum
, currFile
);
fprintf(out
, "%s%s", strleq(comment
,line
)? "" :
ABSOLUTE_PATH
? "": dirname
, line
);
#define MAX_NOT_FOUND 100
char *NOT_FOUND
[MAX_NOT_FOUND
];
if(last_NOT_FOUND
< 0) return;
for(i
=0; i
<=last_NOT_FOUND
; ++i
) {
fprintf(stderr
, "file not found: %s.\n", NOT_FOUND
[i
]);
*find_and_open_file(file
, newDir
)
//if(file[0] == '/') { /*absolute path, use no parent dirInfo*/
if(fd
){ directory(file
, newDir
); /*obtain dir info from file*/
return(fd
); /*found, done*/
for(i
=0; i
<=last_incDir
; ++i
) { /*include file has a relative path*/
sprintf(incFile
, "%s/%s", incDir
[i
], file
);
if(fd
){ directory(incFile
, newDir
);
return(fd
); /*found, done*/
fprintf(stderr
, "include ERR: file not found: %s.\n", file
);
if(++ last_NOT_FOUND
>= MAX_NOT_FOUND
) {
NOT_FOUND
[last_NOT_FOUND
]= (char*) malloc( strlen(file
)+ 1);
strcpy(NOT_FOUND
[last_NOT_FOUND
], file
);
*directory(name
, dir
) /*return directory part of a path*/
char *ptr
, *q
; /*ptr points to next '/', q char after*/
while( ptr
=strchr(q
,'/') ) { q
= ptr
+1; }
if(q
== dir
) { /*not moved at all, i.e. no '/' in path*/
strcpy(dir
, "."); /*directory of root file is . */
}else{ *(q
-1)= 0; /*cut dir from last '/'*/