Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /* |
2 | * include [-i "{string}"] [ {FILE} ] | |
3 | * recursively expands files included in {FILE}, where "inclusion" | |
4 | * is specified by | |
5 | * ^{include_cmd} "file", or | |
6 | * ^{include_cmd} <file> | |
7 | * {include_cmd} is {string} if -i option used, or | |
8 | * is default to '#include'. | |
9 | * | |
10 | */ | |
11 | ||
12 | char *Version= "$Id: include.c,v 1.1 2008/04/18 06:19:50 nhussain Exp $"; | |
13 | ||
14 | #include <stdio.h> | |
15 | ||
16 | #define YES 1 | |
17 | #define NO 0 | |
18 | #define streq(a,b) !strcmp(a,b) | |
19 | #define strleq(a,b) !strncmp(a,b, strlen(a)) | |
20 | #define skip_to_eoln(in) while(getc(in) != '\n') | |
21 | ||
22 | typedef enum { | |
23 | M_NORMAL, | |
24 | M_PAL, | |
25 | M_last | |
26 | } MODE; | |
27 | MODE mode= M_NORMAL; | |
28 | ||
29 | char ABSOLUTE_PATH= 1; | |
30 | char ignore=NO; /*ignore missing file, continue to process*/ | |
31 | char *incCmd= "#include"; | |
32 | char *comment= "//"; | |
33 | int len_incCmd; | |
34 | char *incDir[80]={"."}; /*first to search is current dir*/ | |
35 | int last_incDir= 0; /*incDir[0] is .*/ | |
36 | char *directory(); | |
37 | /* char *directory(char *name, char *dir); */ | |
38 | ||
39 | usage_and_exit(msg1, msg2) | |
40 | char *msg1, *msg2; | |
41 | { | |
42 | if(msg1 != NULL) { | |
43 | char format[256]; | |
44 | if(msg2 && *msg2) { sprintf(format, "%s\n", msg1); | |
45 | fprintf(stderr, format, msg2); | |
46 | }else { fprintf(stderr, "%s\n", msg1); | |
47 | } | |
48 | } | |
49 | fprintf(stderr, "usage: include [{options}] [{FILE}]\n"); | |
50 | fprintf(stderr, "options: [default]\n"); | |
51 | fprintf(stderr, "\t -i {string}: use {string} as include_cmd. [#include]\n"); | |
52 | fprintf(stderr, "\t where include_cmd is used as follows: \n"); | |
53 | fprintf(stderr, "\t ^{include_cmd} \"{file}\",or \n"); | |
54 | fprintf(stderr, "\t ^{include_cmd} <{file}> \n"); | |
55 | fprintf(stderr, "\t ^{include_cmd} {file} \n"); | |
56 | fprintf(stderr, "\t -pal: print line number and file name for pal.\n"); | |
57 | fprintf(stderr, "\t -I {directory}: include files directory for search after .\n"); | |
58 | fprintf(stderr, "\t -o {outFile}: output to file {outFile}. [stdout]\n"); | |
59 | fprintf(stderr, "\t -abs|-rel: include file uses absolute or relative paths. [absolute=%d]\n", | |
60 | ABSOLUTE_PATH); | |
61 | exit(0); | |
62 | } | |
63 | ||
64 | main(argc, argv) | |
65 | int argc; | |
66 | char *argv[]; | |
67 | { | |
68 | FILE *in, *out; | |
69 | int idx=1; | |
70 | char *outfile=0, *infile; | |
71 | char dir[100]; /*prefix to a relative path*/ | |
72 | ||
73 | if(argc <= 1) usage_and_exit(""); | |
74 | ||
75 | while(argv[idx][0] == '-') { | |
76 | if(streq(argv[idx], "-h") ) { | |
77 | usage_and_exit(""); | |
78 | }else if(streq(argv[idx], "-c") && argc>=idx+2) { //comment prefix | |
79 | comment= argv[idx+1]; | |
80 | idx+= 2; | |
81 | }else if(streq(argv[idx], "-I") ) { //include dir | |
82 | incDir[++last_incDir]= argv[idx+1]; | |
83 | idx+= 2; | |
84 | }else if(streq(argv[idx], "-i") && argc>=idx+2) { //include prefix | |
85 | incCmd= argv[idx+1]; | |
86 | idx+= 2; | |
87 | }else if(streq(argv[idx], "-o") && argc>=idx+2) { | |
88 | outfile= argv[idx+1]; | |
89 | idx+= 2; | |
90 | }else if(streq(argv[idx], "-pal") ) { | |
91 | mode= M_PAL; | |
92 | idx+= 1; | |
93 | }else if(streq(argv[idx], "-abs")) { | |
94 | ABSOLUTE_PATH= 1; | |
95 | idx+= 1; | |
96 | }else if(streq(argv[idx], "-rel")) { | |
97 | ABSOLUTE_PATH= 0; | |
98 | idx+= 1; | |
99 | }else{ usage_and_exit("illegal arguments:%s", argv[idx]); | |
100 | } | |
101 | } | |
102 | if(argc == idx) { | |
103 | infile= (char*) strdup("stdin"); | |
104 | in=stdin; | |
105 | incDir[0]= "."; | |
106 | }else{ | |
107 | infile= (char*) strdup(argv[idx]); | |
108 | in= fopen(argv[idx], "r"); | |
109 | if(in == NULL) usage_and_exit("in file '%s' not found!", argv[idx]); | |
110 | directory(argv[idx], dir); | |
111 | incDir[0]= dir; | |
112 | } | |
113 | if(outfile == NULL) { out= stdout; | |
114 | }else{ out= fopen(outfile, "w"); | |
115 | if(out == NULL) usage_and_exit("can't open output file: %s!", outfile); | |
116 | } | |
117 | len_incCmd= strlen(incCmd); | |
118 | include(infile, in, out, 1); | |
119 | ||
120 | print_NOT_FOUND(); | |
121 | exit(0); | |
122 | } | |
123 | ||
124 | void | |
125 | DirName(path, dirname) //path: in; dirname: out | |
126 | char *path, *dirname; | |
127 | { | |
128 | int i; | |
129 | strcpy(dirname, path); | |
130 | for(i= strlen(dirname); i>=0; --i) { | |
131 | if(dirname[i] == '/') { | |
132 | dirname[i+1]= 0; | |
133 | return; | |
134 | } | |
135 | } | |
136 | dirname[0]= 0; | |
137 | } | |
138 | ||
139 | ||
140 | int | |
141 | include(currFile, in, out, depth) | |
142 | char *currFile; | |
143 | FILE *in; | |
144 | FILE *out; | |
145 | int depth; | |
146 | { | |
147 | char *oldDir; | |
148 | char newDir[100]; /*directory for the include file X, which is needed*/ | |
149 | /* for files included in X using relative path*/ | |
150 | char dirname[100]; | |
151 | ||
152 | #define FNAME_LEN 200 | |
153 | char line[256], incFile[FNAME_LEN], closing; | |
154 | FILE *inc_fd, *find_and_open_file(); | |
155 | int linenum=0, return_from_include=0, missingFile; | |
156 | ||
157 | if(mode==M_PAL) | |
158 | fprintf(out, "# line 1 %s\n", currFile); | |
159 | DirName(currFile, dirname); | |
160 | ||
161 | while( fgets(line, 256, in) ) { | |
162 | int i, j=0; | |
163 | ++ linenum; | |
164 | if( !strncmp(incCmd, line, len_incCmd) && /*match starting 1st column*/ | |
165 | (line[i=len_incCmd]==' ' || line[i]=='\t') ) { | |
166 | while(line[++i]== ' ' || line[i]=='\t') ; /*skip more ws*/ | |
167 | /* | |
168 | * if(line[i] != '"' && line[i]!='<') | |
169 | * usage_and_exit("illegal syntax of 'include_cmd': %s !!", line); | |
170 | * closing= line[i] == '"' ? '"' : '>'; | |
171 | */ | |
172 | if(ABSOLUTE_PATH==0) { //relative path in include file | |
173 | strcpy(incFile, dirname); | |
174 | j= strlen(incFile); | |
175 | } | |
176 | if(line[i] != '"' && line[i]!='<') incFile[j++]= line[i]; | |
177 | while(line[++i] != '"' && line[i] != '>' && !isspace(line[i]) && line[i]) { | |
178 | if(i>=FNAME_LEN) | |
179 | usage_and_exit("include file name too long (>FNAME_LEN): %s!", line); | |
180 | incFile[j++]= line[i]; | |
181 | } | |
182 | ||
183 | if(mode != M_PAL) { | |
184 | fprintf(out, "###depth=%d include ==> %s", depth, line); | |
185 | } | |
186 | /*ignore the rest of the line*/ | |
187 | incFile[j]= 0; | |
188 | inc_fd= find_and_open_file(incFile, newDir); | |
189 | if(inc_fd==0 && mode==M_PAL) { | |
190 | fprintf(stderr, "\t %s\n", incFile); | |
191 | fprintf(stderr, "\t ^-- %s\n", currFile); | |
192 | return(1); | |
193 | } | |
194 | ||
195 | oldDir= incDir[0]; /*save current directory before*/ | |
196 | incDir[0]= newDir; /* move to newDir*/ | |
197 | missingFile= include(incFile, inc_fd, out, depth+1); /*recursively include*/ | |
198 | if(missingFile && mode==M_PAL) { | |
199 | fprintf(stderr, "\t ^-- %s\n", currFile); | |
200 | return(1); | |
201 | } | |
202 | ||
203 | incDir[0]= oldDir; | |
204 | ||
205 | return_from_include= 1; | |
206 | }else{ | |
207 | if(mode==M_PAL && return_from_include) | |
208 | fprintf(out, "# line %d %s\n", linenum, currFile); | |
209 | return_from_include= 0; | |
210 | fprintf(out, "%s%s", strleq(comment,line)? "" : | |
211 | ABSOLUTE_PATH? "": dirname, line); | |
212 | } | |
213 | } | |
214 | ||
215 | return(0); /*OK*/ | |
216 | } | |
217 | ||
218 | #include <stdio.h> | |
219 | #include <sys/types.h> | |
220 | #include <sys/stat.h> | |
221 | ||
222 | #define MAX_NOT_FOUND 100 | |
223 | char *NOT_FOUND[MAX_NOT_FOUND]; | |
224 | int last_NOT_FOUND= -1; | |
225 | ||
226 | int | |
227 | print_NOT_FOUND() | |
228 | { | |
229 | int i; | |
230 | if(last_NOT_FOUND < 0) return; | |
231 | for(i=0; i<=last_NOT_FOUND; ++i) { | |
232 | fprintf(stderr, "file not found: %s.\n", NOT_FOUND[i]); | |
233 | } | |
234 | usage_and_exit(""); | |
235 | } | |
236 | ||
237 | ||
238 | FILE | |
239 | *find_and_open_file(file, newDir) | |
240 | char *file, *newDir; | |
241 | { | |
242 | int i; | |
243 | FILE *fd; | |
244 | char incFile[100]; | |
245 | ||
246 | //if(file[0] == '/') { /*absolute path, use no parent dirInfo*/ | |
247 | fd= fopen(file, "r"); | |
248 | if(fd){ directory(file, newDir); /*obtain dir info from file*/ | |
249 | return(fd); /*found, done*/ | |
250 | } | |
251 | //}else | |
252 | for(i=0; i<=last_incDir; ++i) { /*include file has a relative path*/ | |
253 | sprintf(incFile, "%s/%s", incDir[i], file); | |
254 | fd= fopen(incFile, "r"); | |
255 | if(fd){ directory(incFile, newDir); | |
256 | return(fd); /*found, done*/ | |
257 | } | |
258 | } | |
259 | ||
260 | fprintf(stderr, "include ERR: file not found: %s.\n", file); | |
261 | exit(1); | |
262 | ||
263 | if(0) { | |
264 | if(++ last_NOT_FOUND >= MAX_NOT_FOUND) { | |
265 | print_NOT_FOUND(); | |
266 | } else { | |
267 | NOT_FOUND[last_NOT_FOUND]= (char*) malloc( strlen(file)+ 1); | |
268 | strcpy(NOT_FOUND[last_NOT_FOUND], file); | |
269 | } | |
270 | } | |
271 | return(NULL); | |
272 | } | |
273 | ||
274 | ||
275 | char | |
276 | *directory(name, dir) /*return directory part of a path*/ | |
277 | char *name; | |
278 | char *dir; | |
279 | { /* and write '*dir'*/ | |
280 | extern char *strchr(); | |
281 | char *ptr, *q; /*ptr points to next '/', q char after*/ | |
282 | strcpy(dir, name); | |
283 | q= dir; | |
284 | while( ptr=strchr(q,'/') ) { q= ptr+1; } | |
285 | if(q == dir) { /*not moved at all, i.e. no '/' in path*/ | |
286 | strcpy(dir, "."); /*directory of root file is . */ | |
287 | }else{ *(q-1)= 0; /*cut dir from last '/'*/ | |
288 | } | |
289 | return(dir); | |
290 | } | |
291 |