Mercurial > ~dholland > hg > tradcpp > index.cgi
annotate files.c @ 64:f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
Also, don't pass the string length to the directive processing
functions, as half of them weren't honoring it. Instead, ensure that
the directive line is terminated at the place the directive processing
functions should stop looking at it.
author | David A. Holland |
---|---|
date | Sun, 31 Mar 2013 02:04:56 -0400 |
parents | 2e25e55dba6b |
children | 980ed7cb620a |
rev | line source |
---|---|
30 | 1 /*- |
2 * Copyright (c) 2010 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 | |
6 | 30 #include <stdbool.h> |
31 #include <stdio.h> | |
32 #include <stdlib.h> | |
13 | 33 #include <string.h> |
6 | 34 #include <unistd.h> |
35 #include <fcntl.h> | |
36 #include <err.h> | |
37 | |
38 #include "array.h" | |
15 | 39 #include "mode.h" |
8 | 40 #include "place.h" |
6 | 41 #include "files.h" |
15 | 42 #include "directive.h" |
6 | 43 |
44 struct incdir { | |
45 const char *name; | |
46 bool issystem; | |
47 }; | |
48 | |
47
2e25e55dba6b
Fix inline usage as per the version in dholland-make2.
David A. Holland
parents:
39
diff
changeset
|
49 DECLARRAY(incdir, static __unused); |
2e25e55dba6b
Fix inline usage as per the version in dholland-make2.
David A. Holland
parents:
39
diff
changeset
|
50 DEFARRAY(incdir, static); |
6 | 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 { | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
73 dofree(id, sizeof(*id)); |
6 | 74 } |
75 | |
76 void | |
77 files_init(void) | |
78 { | |
79 incdirarray_init("epath); | |
80 incdirarray_init(&bracketpath); | |
81 } | |
82 | |
9 | 83 DESTROYALL_ARRAY(incdir, ); |
6 | 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); | |
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); | |
113 } | |
114 | |
115 //////////////////////////////////////////////////////////// | |
116 // parsing | |
117 | |
15 | 118 static |
119 size_t | |
120 findnl(const char *buf, size_t start, size_t limit) | |
121 { | |
122 size_t i; | |
123 | |
124 for (i=start; i<limit; i++) { | |
125 if (buf[i] == '\n') { | |
126 return i; | |
127 } | |
128 } | |
129 return limit; | |
130 } | |
131 | |
132 static | |
6 | 133 void |
28 | 134 file_read(const struct placefile *pf, int fd, const char *name, bool toplevel) |
15 | 135 { |
136 struct place linestartplace, nextlinestartplace, ptmp; | |
137 size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp; | |
138 ssize_t result; | |
139 bool ateof = false; | |
140 char *buf; | |
141 | |
142 place_setfilestart(&linestartplace, pf); | |
143 nextlinestartplace = linestartplace; | |
144 | |
145 bufmax = 128; | |
146 bufend = 0; | |
147 linestart = 0; | |
148 lineend = 0; | |
149 buf = domalloc(bufmax); | |
150 | |
151 while (1) { | |
152 if (lineend >= bufend) { | |
153 /* do not have a whole line in the buffer; read more */ | |
154 if (linestart > 0 && bufend > linestart) { | |
155 /* slide to beginning of buffer */ | |
156 memmove(buf, buf+linestart, bufend-linestart); | |
157 bufend -= linestart; | |
158 lineend -= linestart; | |
159 linestart = 0; | |
160 } | |
161 if (bufend >= bufmax) { | |
162 /* need bigger buffer */ | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
163 buf = dorealloc(buf, bufmax, bufmax*2); |
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
164 bufmax = bufmax*2; |
15 | 165 } |
166 | |
167 if (ateof) { | |
168 /* don't read again, in case it's a socket */ | |
169 result = 0; | |
170 } else { | |
171 result = read(fd, buf+bufend, bufmax - bufend); | |
172 } | |
173 | |
174 if (result == -1) { | |
175 /* read error */ | |
176 warn("%s", name); | |
177 complain_fail(); | |
178 } else if (result == 0 && bufend == linestart) { | |
179 /* eof */ | |
180 ateof = true; | |
181 break; | |
182 } else if (result == 0) { | |
183 /* eof in middle of line */ | |
184 ateof = true; | |
185 ptmp = linestartplace; | |
186 ptmp.column += bufend - linestart; | |
187 complain(&ptmp, "No newline at end of file"); | |
188 if (mode.werror) { | |
189 complain_fail(); | |
190 } | |
191 assert(bufend < bufmax); | |
192 lineend = bufend++; | |
193 buf[lineend] = '\n'; | |
194 } else { | |
195 tmp = bufend; | |
196 bufend += (size_t)result; | |
197 lineend = findnl(buf, tmp, bufend); | |
198 } | |
199 /* loop in case we still don't have a whole line */ | |
200 continue; | |
201 } | |
202 | |
203 /* have a line */ | |
204 assert(buf[lineend] == '\n'); | |
205 buf[lineend] = '\0'; | |
206 nextlinestart = lineend+1; | |
207 nextlinestartplace.line++; | |
208 | |
209 /* check for CR/NL */ | |
210 if (lineend > 0 && buf[lineend-1] == '\r') { | |
211 buf[lineend-1] = '\0'; | |
212 lineend--; | |
213 } | |
214 | |
215 /* check for continuation line */ | |
216 if (lineend > 0 && buf[lineend-1]=='\\') { | |
217 lineend--; | |
218 tmp = nextlinestart - lineend; | |
219 if (bufend > nextlinestart) { | |
220 memmove(buf+lineend, buf+nextlinestart, | |
221 bufend - nextlinestart); | |
222 } | |
223 bufend -= tmp; | |
224 nextlinestart -= tmp; | |
225 lineend = findnl(buf, lineend, bufend); | |
226 /* might not have a whole line, so loop */ | |
227 continue; | |
228 } | |
229 | |
230 /* line now goes from linestart to lineend */ | |
231 assert(buf[lineend] == '\0'); | |
232 if (lineend > linestart) { | |
233 directive_gotline(&linestartplace, | |
234 buf+linestart, lineend-linestart); | |
235 } | |
236 | |
237 linestart = nextlinestart; | |
238 lineend = findnl(buf, linestart, bufend); | |
239 linestartplace = nextlinestartplace; | |
240 } | |
241 | |
28 | 242 if (toplevel) { |
243 directive_goteof(&linestartplace); | |
244 } | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
245 dofree(buf, bufmax); |
15 | 246 } |
6 | 247 |
248 //////////////////////////////////////////////////////////// | |
249 // path search | |
250 | |
251 static | |
13 | 252 char * |
253 mkfilename(const char *dir, const char *file) | |
254 { | |
255 size_t dlen, flen, rlen; | |
256 char *ret; | |
257 bool needslash = false; | |
258 | |
259 dlen = strlen(dir); | |
260 flen = strlen(file); | |
261 if (dlen > 0 && dir[dlen-1] != '/') { | |
262 needslash = true; | |
263 } | |
264 | |
265 rlen = dlen + (needslash ? 1 : 0) + flen; | |
266 ret = domalloc(rlen + 1); | |
267 strcpy(ret, dir); | |
268 if (needslash) { | |
269 strcat(ret, "/"); | |
270 } | |
271 strcat(ret, file); | |
272 return ret; | |
273 } | |
274 | |
275 static | |
6 | 276 int |
277 file_tryopen(const char *file) | |
278 { | |
279 int fd; | |
280 | |
15 | 281 /* XXX check for non-regular files */ |
282 | |
6 | 283 fd = open(file, O_RDONLY); |
284 if (fd < 0) { | |
285 return -1; | |
286 } | |
15 | 287 |
6 | 288 return fd; |
289 } | |
290 | |
291 static | |
292 void | |
293 file_search(struct place *place, struct incdirarray *path, const char *name) | |
294 { | |
295 unsigned i, num; | |
296 struct incdir *id; | |
13 | 297 const struct placefile *pf; |
6 | 298 char *file; |
299 int fd; | |
300 | |
301 assert(place != NULL); | |
302 | |
303 num = incdirarray_num(path); | |
304 for (i=0; i<num; i++) { | |
305 id = incdirarray_get(path, i); | |
13 | 306 file = mkfilename(id->name, name); |
6 | 307 fd = file_tryopen(file); |
308 if (fd >= 0) { | |
13 | 309 pf = place_addfile(place, file, id->issystem); |
28 | 310 file_read(pf, fd, file, false); |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
311 dostrfree(file); |
6 | 312 close(fd); |
313 return; | |
314 } | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
315 dostrfree(file); |
6 | 316 } |
317 complain(place, "Include file %s not found", name); | |
318 complain_fail(); | |
319 } | |
320 | |
321 void | |
322 file_readquote(struct place *place, const char *name) | |
323 { | |
324 file_search(place, "epath, name); | |
325 } | |
326 | |
327 void | |
328 file_readbracket(struct place *place, const char *name) | |
329 { | |
330 file_search(place, &bracketpath, name); | |
331 } | |
332 | |
333 void | |
334 file_readabsolute(struct place *place, const char *name) | |
335 { | |
13 | 336 const struct placefile *pf; |
6 | 337 int fd; |
338 | |
339 assert(place != NULL); | |
340 | |
24 | 341 if (name == NULL) { |
342 fd = STDIN_FILENO; | |
343 pf = place_addfile(place, "<standard-input>", false); | |
344 } else { | |
345 fd = file_tryopen(name); | |
346 if (fd < 0) { | |
347 warn("%s", name); | |
348 die(); | |
349 } | |
350 pf = place_addfile(place, name, false); | |
6 | 351 } |
24 | 352 |
28 | 353 file_read(pf, fd, name, true); |
24 | 354 |
355 if (name != NULL) { | |
356 close(fd); | |
357 } | |
6 | 358 } |