comparison files.c @ 6:0601b6e8e53d

checkpoint - can find files
author David A. Holland
date Sun, 19 Dec 2010 18:55:51 -0500
parents
children b8167949474a
comparison
equal deleted inserted replaced
5:7c489c73d62b 6:0601b6e8e53d
1 #include <stdarg.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <err.h>
8
9 #include "array.h"
10 #include "files.h"
11
12 struct place {
13 struct seenfile *file;
14 unsigned line;
15 unsigned column;
16 };
17
18 struct incdir {
19 const char *name;
20 bool issystem;
21 };
22
23 struct seenfile {
24 struct place includedfrom;
25 char *name;
26 bool fromsystemdir;
27 };
28
29 DECLARRAY(incdir);
30 DECLARRAY(seenfile);
31 DEFARRAY(incdir, );
32 DEFARRAY(seenfile, );
33
34 static struct incdirarray quotepath, bracketpath;
35 static struct seenfilearray seenfiles;
36 static bool overall_failure;
37
38 ////////////////////////////////////////////////////////////
39 // management
40
41 #define DESTROYALL(T) \
42 static \
43 void \
44 T##array_destroyall(struct T##array *arr) \
45 { \
46 unsigned i, num; \
47 struct T *t; \
48 \
49 num = T##array_num(arr); \
50 for (i=0; i<num; i++) { \
51 t = T##array_get(arr, i); \
52 T##_destroy(t); \
53 } \
54 T##array_setsize(arr, 0); \
55 }
56
57 static
58 struct incdir *
59 incdir_create(const char *name, bool issystem)
60 {
61 struct incdir *id;
62
63 id = domalloc(sizeof(*id));
64 id->name = name;
65 id->issystem = issystem;
66 return id;
67 }
68
69 static
70 void
71 incdir_destroy(struct incdir *id)
72 {
73 free(id);
74 }
75
76 static
77 struct seenfile *
78 seenfile_create(const struct place *from, char *name, bool fromsystemdir)
79 {
80 struct seenfile *sf;
81
82 sf = domalloc(sizeof(*sf));
83 sf->includedfrom = *from;
84 sf->name = name;
85 sf->fromsystemdir = fromsystemdir;
86 return sf;
87 }
88
89 static
90 void
91 seenfile_destroy(struct seenfile *sf)
92 {
93 free(sf->name);
94 free(sf);
95 }
96
97 void
98 files_init(void)
99 {
100 incdirarray_init(&quotepath);
101 incdirarray_init(&bracketpath);
102 }
103
104 DESTROYALL(incdir);
105 DESTROYALL(seenfile);
106
107 void
108 files_cleanup(void)
109 {
110 seenfilearray_destroyall(&seenfiles);
111 seenfilearray_cleanup(&seenfiles);
112
113 incdirarray_destroyall(&quotepath);
114 incdirarray_cleanup(&quotepath);
115 incdirarray_destroyall(&bracketpath);
116 incdirarray_cleanup(&bracketpath);
117 }
118
119 ////////////////////////////////////////////////////////////
120 // path setup
121
122 void
123 files_addquotepath(const char *dir, bool issystem)
124 {
125 struct incdir *id;
126
127 id = incdir_create(dir, issystem);
128 incdirarray_add(&quotepath, id, NULL);
129 }
130
131 void
132 files_addbracketpath(const char *dir, bool issystem)
133 {
134 struct incdir *id;
135
136 id = incdir_create(dir, issystem);
137 incdirarray_add(&bracketpath, id, NULL);
138 }
139
140 ////////////////////////////////////////////////////////////
141 // places and complaints
142
143 #define NOWHERE_LINE 0
144 #define BUILTIN_LINE 1
145 #define COMMANDLINE_LINE 2
146
147 static struct place scratchplace;
148 static bool scratchplace_inuse;
149
150 static
151 bool
152 place_isnowhere(const struct place *p)
153 {
154 return p->file == NULL && p->line == NOWHERE_LINE;
155 }
156
157 static
158 bool
159 place_isbuiltin(const struct place *p)
160 {
161 return p->file == NULL && p->line == BUILTIN_LINE;
162 }
163
164 static
165 bool
166 place_iscommandline(const struct place *p)
167 {
168 return p->file == NULL && p->line == COMMANDLINE_LINE;
169 }
170
171 struct place *
172 place_gettemporary(void)
173 {
174 assert(!scratchplace_inuse);
175 scratchplace_inuse = true;
176 return &scratchplace;
177 }
178
179 void
180 place_puttemporary(struct place *p)
181 {
182 assert(scratchplace_inuse);
183 assert(p == &scratchplace);
184 scratchplace_inuse = false;
185 }
186
187 void
188 place_setnowhere(struct place *p)
189 {
190 p->file = NULL;
191 p->line = NOWHERE_LINE;
192 p->column = 0;
193 }
194
195 void
196 place_setbuiltin(struct place *p, unsigned num)
197 {
198 p->file = NULL;
199 p->line = BUILTIN_LINE;
200 p->column = num;
201 }
202
203 void
204 place_setcommandline(struct place *p, unsigned column)
205 {
206 p->file = NULL;
207 p->line = COMMANDLINE_LINE;
208 p->column = column;
209 }
210
211 static
212 void
213 place_print(const struct place *p)
214 {
215 if (place_iscommandline(p)) {
216 fprintf(stderr, "<command-line>:1:%u", p->column);
217 } else if (place_isbuiltin(p)) {
218 fprintf(stderr, "<built-in>:%u:1", p->column);
219 } else {
220 fprintf(stderr, "%s:%u:%u", p->file->name, p->line, p->column);
221 }
222 }
223
224 static
225 void
226 place_printfrom(const struct place *p)
227 {
228 if (!place_isnowhere(&p->file->includedfrom)) {
229 place_printfrom(&p->file->includedfrom);
230 }
231 fprintf(stderr, "In file included from ");
232 fprintf(stderr, ":\n");
233 }
234
235 void
236 complain(const struct place *p, const char *fmt, ...)
237 {
238 va_list ap;
239
240 if (!place_isnowhere(&p->file->includedfrom)) {
241 place_printfrom(&p->file->includedfrom);
242 }
243 place_print(p);
244 fprintf(stderr, ": ");
245 va_start(ap, fmt);
246 vfprintf(stderr, fmt, ap);
247 va_end(ap);
248 fprintf(stderr, "\n");
249 }
250
251 void
252 complain_fail(void)
253 {
254 overall_failure = true;
255 }
256
257 bool
258 complain_failed(void)
259 {
260 return overall_failure;
261 }
262
263 ////////////////////////////////////////////////////////////
264 // parsing
265
266 void
267 file_read(struct seenfile *sf, int fd);
268
269 ////////////////////////////////////////////////////////////
270 // path search
271
272 static
273 int
274 file_tryopen(const char *file)
275 {
276 int fd;
277
278 fd = open(file, O_RDONLY);
279 if (fd < 0) {
280 return -1;
281 }
282 /* XXX: do we need to do anything here or is this function pointless?*/
283 return fd;
284 }
285
286 static
287 void
288 file_search(struct place *place, struct incdirarray *path, const char *name)
289 {
290 unsigned i, num;
291 struct incdir *id;
292 struct seenfile *sf;
293 char *file;
294 int fd;
295
296 assert(place != NULL);
297
298 num = incdirarray_num(path);
299 for (i=0; i<num; i++) {
300 id = incdirarray_get(path, i);
301 file = dostrdup3(id->name, "/", name);
302 fd = file_tryopen(file);
303 if (fd >= 0) {
304 sf = seenfile_create(place, file, id->issystem);
305 seenfilearray_add(&seenfiles, sf, NULL);
306 file_read(sf, fd);
307 close(fd);
308 return;
309 }
310 free(file);
311 }
312 complain(place, "Include file %s not found", name);
313 complain_fail();
314 }
315
316 void
317 file_readquote(struct place *place, const char *name)
318 {
319 file_search(place, &quotepath, name);
320 }
321
322 void
323 file_readbracket(struct place *place, const char *name)
324 {
325 file_search(place, &bracketpath, name);
326 }
327
328 void
329 file_readabsolute(struct place *place, const char *name)
330 {
331 struct seenfile *sf;
332 int fd;
333
334 assert(place != NULL);
335
336 fd = file_tryopen(name);
337 if (fd < 0) {
338 warn("%s", name);
339 die();
340 }
341 sf = seenfile_create(place, dostrdup(name), false);
342 seenfilearray_add(&seenfiles, sf, NULL);
343 file_read(sf, fd);
344 close(fd);
345 }