File: | src/libexec/tradcpp/files.c |
Warning: | line 238, column 5 Value stored to 'ateof' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /*- |
2 | * Copyright (c) 2010, 2013 The NetBSD Foundation, Inc. |
3 | * All rights reserved. |
4 | * |
5 | * This code is derived from software contributed to The NetBSD Foundation |
6 | * by David A. Holland. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | * POSSIBILITY OF SUCH DAMAGE. |
28 | */ |
29 | |
30 | #include <stdio.h> |
31 | #include <stdlib.h> |
32 | #include <string.h> |
33 | #include <unistd.h> |
34 | #include <fcntl.h> |
35 | #include <errno(*__errno()).h> |
36 | |
37 | #include "bool.h" |
38 | #include "array.h" |
39 | #include "mode.h" |
40 | #include "place.h" |
41 | #include "files.h" |
42 | #include "directive.h" |
43 | |
44 | struct incdir { |
45 | const char *name; |
46 | bool issystem; |
47 | }; |
48 | |
49 | DECLARRAY(incdir, static UNUSED)struct incdirarray { struct array arr; }; static __attribute__ ((__unused__)) struct incdirarray *incdirarray_create(void); static __attribute__((__unused__)) void incdirarray_destroy(struct incdirarray *a); static __attribute__((__unused__)) void incdirarray_init (struct incdirarray *a); static __attribute__((__unused__)) void incdirarray_cleanup(struct incdirarray *a); static __attribute__ ((__unused__)) unsigned incdirarray_num(const struct incdirarray *a); static __attribute__((__unused__)) struct incdir *incdirarray_get (const struct incdirarray *a, unsigned index_); static __attribute__ ((__unused__)) void incdirarray_set(struct incdirarray *a, unsigned index_, struct incdir *val); static __attribute__((__unused__ )) void incdirarray_setsize(struct incdirarray *a, unsigned num ); static __attribute__((__unused__)) void incdirarray_add(struct incdirarray *a, struct incdir *val, unsigned *index_ret); static __attribute__((__unused__)) void incdirarray_insert(struct incdirarray *a, unsigned index_); static __attribute__((__unused__)) void incdirarray_remove(struct incdirarray *a, unsigned index_); |
50 | DEFARRAY(incdir, static)static void incdirarray_init(struct incdirarray *a) { array_init (&a->arr); } static void incdirarray_cleanup(struct incdirarray *a) { array_cleanup(&a->arr); } static struct incdirarray *incdirarray_create(void) { struct incdirarray *a; a = domalloc (sizeof(*a)); incdirarray_init(a); return a; } static void incdirarray_destroy (struct incdirarray *a) { incdirarray_cleanup(a); dofree(a, sizeof (*a)); } static unsigned incdirarray_num(const struct incdirarray *a) { return array_num(&a->arr); } static struct incdir * incdirarray_get(const struct incdirarray *a, unsigned index_ ) { return (struct incdir *)array_get(&a->arr, index_) ; } static void incdirarray_set(struct incdirarray *a, unsigned index_, struct incdir *val) { array_set(&a->arr, index_ , (void *)val); } static void incdirarray_setsize(struct incdirarray *a, unsigned num) { array_setsize(&a->arr, num); } static void incdirarray_add(struct incdirarray *a, struct incdir *val , unsigned *ret) { array_add(&a->arr, (void *)val, ret ); } static void incdirarray_insert(struct incdirarray *a, unsigned index_) { array_insert(&a->arr, index_); } static void incdirarray_remove(struct incdirarray *a, unsigned index_) { array_remove(&a->arr, index_); }; |
51 | |
52 | static struct incdirarray quotepath, bracketpath; |
53 | |
54 | //////////////////////////////////////////////////////////// |
55 | // management |
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 | dofree(id, sizeof(*id)); |
74 | } |
75 | |
76 | void |
77 | files_init(void) |
78 | { |
79 | incdirarray_init("epath); |
80 | incdirarray_init(&bracketpath); |
81 | } |
82 | |
83 | DESTROYALL_ARRAY(incdir, )void incdirarray_destroyall(struct incdirarray *arr); void incdirarray_destroyall (struct incdirarray *arr) { unsigned i, num; struct incdir *t ; num = incdirarray_num(arr); for (i=0; i<num; i++) { t = incdirarray_get (arr, i); incdir_destroy(t); } incdirarray_setsize(arr, 0); }; |
84 | |
85 | void |
86 | files_cleanup(void) |
87 | { |
88 | incdirarray_destroyall("epath); |
89 | incdirarray_cleanup("epath); |
90 | incdirarray_destroyall(&bracketpath); |
91 | incdirarray_cleanup(&bracketpath); |
92 | } |
93 | |
94 | //////////////////////////////////////////////////////////// |
95 | // path setup |
96 | |
97 | void |
98 | files_addquotepath(const char *dir, bool issystem) |
99 | { |
100 | struct incdir *id; |
101 | |
102 | id = incdir_create(dir, issystem); |
103 | incdirarray_add("epath, id, NULL((void *)0)); |
104 | } |
105 | |
106 | void |
107 | files_addbracketpath(const char *dir, bool issystem) |
108 | { |
109 | struct incdir *id; |
110 | |
111 | id = incdir_create(dir, issystem); |
112 | incdirarray_add(&bracketpath, id, NULL((void *)0)); |
113 | } |
114 | |
115 | //////////////////////////////////////////////////////////// |
116 | // parsing |
117 | |
118 | /* |
119 | * Find the end of the logical line. End of line characters that are |
120 | * commented out do not count. |
121 | */ |
122 | static |
123 | size_t |
124 | findeol(const char *buf, size_t start, size_t limit) |
125 | { |
126 | size_t i; |
127 | int incomment = 0; |
128 | bool inquote = false0; |
129 | char quote = '\0'; |
130 | |
131 | for (i=start; i<limit; i++) { |
132 | if (incomment) { |
133 | if (i+1 < limit && buf[i] == '*' && buf[i+1] == '/') { |
134 | i++; |
135 | incomment = 0; |
136 | } |
137 | } else if (!inquote && i+1 < limit && |
138 | buf[i] == '/' && buf[i+1] == '*') { |
139 | i++; |
140 | incomment = 1; |
141 | } else if (i+1 < limit && |
142 | buf[i] == '\\' && buf[i+1] != '\n') { |
143 | i++; |
144 | } else if (!inquote && (buf[i] == '"' || buf[i] == '\'')) { |
145 | inquote = true1; |
146 | quote = buf[i]; |
147 | } else if (inquote && buf[i] == quote) { |
148 | inquote = false0; |
149 | } else if (buf[i] == '\n') { |
150 | return i; |
151 | } |
152 | } |
153 | return limit; |
154 | } |
155 | |
156 | static |
157 | unsigned |
158 | countnls(const char *buf, size_t start, size_t limit) |
159 | { |
160 | size_t i; |
161 | unsigned count = 0; |
162 | |
163 | for (i=start; i<limit; i++) { |
164 | if (buf[i] == '\n') { |
165 | count++; |
166 | if (count == 0) { |
167 | /* just return the max and error downstream */ |
168 | return count - 1; |
169 | } |
170 | } |
171 | } |
172 | return count; |
173 | } |
174 | |
175 | static |
176 | void |
177 | file_read(const struct placefile *pf, int fd, const char *name, bool toplevel) |
178 | { |
179 | struct lineplace places; |
180 | struct place ptmp; |
181 | size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp; |
182 | ssize_t result; |
183 | bool ateof = false0; |
184 | char *buf; |
185 | |
186 | place_setfilestart(&places.current, pf); |
187 | places.nextline = places.current; |
188 | |
189 | if (name) { |
190 | debuglog(&places.current, "Reading file %s", name); |
191 | } else { |
192 | debuglog(&places.current, "Reading standard input"); |
193 | } |
194 | |
195 | bufmax = 128; |
196 | bufend = 0; |
197 | linestart = 0; |
198 | lineend = 0; |
199 | buf = domalloc(bufmax); |
200 | |
201 | while (1) { |
202 | if (lineend >= bufend) { |
203 | /* do not have a whole line in the buffer; read more */ |
204 | assert(bufend >= linestart)((bufend >= linestart) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 204, __func__, "bufend >= linestart")); |
205 | if (linestart > 0 && bufend > linestart) { |
206 | /* slide to beginning of buffer */ |
207 | memmove(buf, buf+linestart, bufend-linestart); |
208 | bufend -= linestart; |
209 | lineend -= linestart; |
210 | linestart = 0; |
211 | } |
212 | if (bufend >= bufmax) { |
213 | /* need bigger buffer */ |
214 | buf = dorealloc(buf, bufmax, bufmax*2); |
215 | bufmax = bufmax*2; |
216 | /* just in case someone's screwing around */ |
217 | if (bufmax > 0xffffffff) { |
218 | complain(&places.current, |
219 | "Input line too long"); |
220 | die(); |
221 | } |
222 | } |
223 | |
224 | if (ateof) { |
225 | /* don't read again, in case it's a socket */ |
226 | result = 0; |
227 | } else { |
228 | result = read(fd, buf+bufend, bufmax - bufend); |
229 | } |
230 | |
231 | if (result == -1) { |
232 | /* read error */ |
233 | complain(NULL((void *)0), "%s: %s", |
234 | name, strerror(errno(*__errno()))); |
235 | complain_fail(); |
236 | } else if (result == 0 && bufend == linestart) { |
237 | /* eof */ |
238 | ateof = true1; |
Value stored to 'ateof' is never read | |
239 | break; |
240 | } else if (result == 0) { |
241 | /* eof in middle of line */ |
242 | ateof = true1; |
243 | ptmp = places.current; |
244 | place_addcolumns(&ptmp, bufend - linestart); |
245 | if (buf[bufend - 1] == '\n') { |
246 | complain(&ptmp, "Unclosed comment"); |
247 | complain_fail(); |
248 | } else { |
249 | complain(&ptmp, |
250 | "No newline at end of file"); |
251 | } |
252 | if (mode.werror) { |
253 | complain_fail(); |
254 | } |
255 | assert(bufend < bufmax)((bufend < bufmax) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 255, __func__, "bufend < bufmax")); |
256 | lineend = bufend++; |
257 | buf[lineend] = '\n'; |
258 | } else { |
259 | bufend += (size_t)result; |
260 | lineend = findeol(buf, linestart, bufend); |
261 | } |
262 | /* loop in case we still don't have a whole line */ |
263 | continue; |
264 | } |
265 | |
266 | /* have a line */ |
267 | assert(buf[lineend] == '\n')((buf[lineend] == '\n') ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 267, __func__, "buf[lineend] == '\\n'")); |
268 | buf[lineend] = '\0'; |
269 | nextlinestart = lineend+1; |
270 | place_addlines(&places.nextline, 1); |
271 | |
272 | /* check for CR/NL */ |
273 | if (lineend > 0 && buf[lineend-1] == '\r') { |
274 | buf[lineend-1] = '\0'; |
275 | lineend--; |
276 | } |
277 | |
278 | /* check for continuation line */ |
279 | if (lineend > 0 && buf[lineend-1]=='\\') { |
280 | lineend--; |
281 | tmp = nextlinestart - lineend; |
282 | if (bufend > nextlinestart) { |
283 | memmove(buf+lineend, buf+nextlinestart, |
284 | bufend - nextlinestart); |
285 | } |
286 | bufend -= tmp; |
287 | nextlinestart -= tmp; |
288 | lineend = findeol(buf, linestart, bufend); |
289 | /* might not have a whole line, so loop */ |
290 | continue; |
291 | } |
292 | |
293 | /* line now goes from linestart to lineend */ |
294 | assert(buf[lineend] == '\0')((buf[lineend] == '\0') ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 294, __func__, "buf[lineend] == '\\0'")); |
295 | |
296 | /* count how many commented-out newlines we swallowed */ |
297 | place_addlines(&places.nextline, |
298 | countnls(buf, linestart, lineend)); |
299 | |
300 | /* process the line (even if it's empty) */ |
301 | directive_gotline(&places, buf+linestart, lineend-linestart); |
302 | |
303 | linestart = nextlinestart; |
304 | lineend = findeol(buf, linestart, bufend); |
305 | places.current = places.nextline; |
306 | } |
307 | |
308 | if (toplevel) { |
309 | directive_goteof(&places.current); |
310 | } |
311 | dofree(buf, bufmax); |
312 | } |
313 | |
314 | //////////////////////////////////////////////////////////// |
315 | // path search |
316 | |
317 | static |
318 | char * |
319 | mkfilename(struct place *place, const char *dir, const char *file) |
320 | { |
321 | size_t dlen, flen, rlen; |
322 | char *ret; |
323 | bool needslash = false0; |
324 | |
325 | if (dir == NULL((void *)0)) { |
326 | dir = place_getparsedir(place); |
327 | } |
328 | |
329 | dlen = strlen(dir); |
330 | flen = strlen(file); |
331 | if (dlen > 0 && dir[dlen-1] != '/') { |
332 | needslash = true1; |
333 | } |
334 | |
335 | rlen = dlen + (needslash ? 1 : 0) + flen; |
336 | ret = domalloc(rlen + 1); |
337 | snprintf(ret, rlen+1, "%s%s%s", dir, needslash ? "/" : "", file); |
338 | return ret; |
339 | } |
340 | |
341 | static |
342 | int |
343 | file_tryopen(const char *file) |
344 | { |
345 | int fd; |
346 | |
347 | /* XXX check for non-regular files */ |
348 | |
349 | fd = open(file, O_RDONLY0x0000); |
350 | if (fd == -1) { |
351 | if (errno(*__errno()) != ENOENT2 && errno(*__errno()) != ENOTDIR20) { |
352 | complain(NULL((void *)0), "%s: %s", file, strerror(errno(*__errno()))); |
353 | } |
354 | return -1; |
355 | } |
356 | |
357 | return fd; |
358 | } |
359 | |
360 | static |
361 | void |
362 | file_search(struct place *place, struct incdirarray *path, const char *name) |
363 | { |
364 | unsigned i, num; |
365 | struct incdir *id; |
366 | const struct placefile *pf; |
367 | char *file; |
368 | int fd; |
369 | |
370 | assert(place != NULL)((place != ((void *)0)) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 370, __func__, "place != NULL")); |
371 | |
372 | if (name[0] == '/') { |
373 | fd = file_tryopen(name); |
374 | if (fd >= 0) { |
375 | pf = place_addfile(place, name, true1); |
376 | file_read(pf, fd, name, false0); |
377 | close(fd); |
378 | return; |
379 | } |
380 | } else { |
381 | num = incdirarray_num(path); |
382 | for (i=0; i<num; i++) { |
383 | id = incdirarray_get(path, i); |
384 | file = mkfilename(place, id->name, name); |
385 | fd = file_tryopen(file); |
386 | if (fd >= 0) { |
387 | pf = place_addfile(place, file, id->issystem); |
388 | file_read(pf, fd, file, false0); |
389 | dostrfree(file); |
390 | close(fd); |
391 | return; |
392 | } |
393 | dostrfree(file); |
394 | } |
395 | } |
396 | complain(place, "Include file %s not found", name); |
397 | complain_fail(); |
398 | } |
399 | |
400 | void |
401 | file_readquote(struct place *place, const char *name) |
402 | { |
403 | file_search(place, "epath, name); |
404 | } |
405 | |
406 | void |
407 | file_readbracket(struct place *place, const char *name) |
408 | { |
409 | file_search(place, &bracketpath, name); |
410 | } |
411 | |
412 | void |
413 | file_readabsolute(struct place *place, const char *name) |
414 | { |
415 | const struct placefile *pf; |
416 | int fd; |
417 | |
418 | assert(place != NULL)((place != ((void *)0)) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 418, __func__, "place != NULL")); |
419 | |
420 | if (name == NULL((void *)0)) { |
421 | fd = STDIN_FILENO0; |
422 | pf = place_addfile(place, "<standard-input>", false0); |
423 | } else { |
424 | fd = file_tryopen(name); |
425 | if (fd < 0) { |
426 | complain(NULL((void *)0), "%s: %s", name, strerror(errno(*__errno()))); |
427 | die(); |
428 | } |
429 | pf = place_addfile(place, name, false0); |
430 | } |
431 | |
432 | file_read(pf, fd, name, true1); |
433 | |
434 | if (name != NULL((void *)0)) { |
435 | close(fd); |
436 | } |
437 | } |