Mercurial > ~dholland > hg > tradcpp > index.cgi
comparison files.c @ 15:f6177d3ed5c2
handle directives
author | David A. Holland |
---|---|
date | Sun, 19 Dec 2010 21:42:01 -0500 |
parents | 120629a5d6bf |
children | daa801fe719e |
comparison
equal
deleted
inserted
replaced
14:5045b9678bb0 | 15:f6177d3ed5c2 |
---|---|
5 #include <unistd.h> | 5 #include <unistd.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <err.h> | 7 #include <err.h> |
8 | 8 |
9 #include "array.h" | 9 #include "array.h" |
10 #include "mode.h" | |
10 #include "place.h" | 11 #include "place.h" |
11 #include "files.h" | 12 #include "files.h" |
13 #include "directive.h" | |
12 | 14 |
13 struct incdir { | 15 struct incdir { |
14 const char *name; | 16 const char *name; |
15 bool issystem; | 17 bool issystem; |
16 }; | 18 }; |
82 } | 84 } |
83 | 85 |
84 //////////////////////////////////////////////////////////// | 86 //////////////////////////////////////////////////////////// |
85 // parsing | 87 // parsing |
86 | 88 |
87 void | 89 static |
88 file_read(const struct placefile *pf, int fd); | 90 size_t |
91 findnl(const char *buf, size_t start, size_t limit) | |
92 { | |
93 size_t i; | |
94 | |
95 for (i=start; i<limit; i++) { | |
96 if (buf[i] == '\n') { | |
97 return i; | |
98 } | |
99 } | |
100 return limit; | |
101 } | |
102 | |
103 static | |
104 void | |
105 file_read(const struct placefile *pf, int fd, const char *name) | |
106 { | |
107 struct place linestartplace, nextlinestartplace, ptmp; | |
108 size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp; | |
109 ssize_t result; | |
110 bool ateof = false; | |
111 char *buf; | |
112 | |
113 place_setfilestart(&linestartplace, pf); | |
114 nextlinestartplace = linestartplace; | |
115 | |
116 bufmax = 128; | |
117 bufend = 0; | |
118 linestart = 0; | |
119 lineend = 0; | |
120 buf = domalloc(bufmax); | |
121 | |
122 while (1) { | |
123 if (lineend >= bufend) { | |
124 /* do not have a whole line in the buffer; read more */ | |
125 if (linestart > 0 && bufend > linestart) { | |
126 /* slide to beginning of buffer */ | |
127 memmove(buf, buf+linestart, bufend-linestart); | |
128 bufend -= linestart; | |
129 lineend -= linestart; | |
130 linestart = 0; | |
131 } | |
132 if (bufend >= bufmax) { | |
133 /* need bigger buffer */ | |
134 bufmax *= 2; | |
135 buf = dorealloc(buf, bufmax); | |
136 } | |
137 | |
138 if (ateof) { | |
139 /* don't read again, in case it's a socket */ | |
140 result = 0; | |
141 } else { | |
142 result = read(fd, buf+bufend, bufmax - bufend); | |
143 } | |
144 | |
145 if (result == -1) { | |
146 /* read error */ | |
147 warn("%s", name); | |
148 complain_fail(); | |
149 } else if (result == 0 && bufend == linestart) { | |
150 /* eof */ | |
151 ateof = true; | |
152 break; | |
153 } else if (result == 0) { | |
154 /* eof in middle of line */ | |
155 ateof = true; | |
156 ptmp = linestartplace; | |
157 ptmp.column += bufend - linestart; | |
158 complain(&ptmp, "No newline at end of file"); | |
159 if (mode.werror) { | |
160 complain_fail(); | |
161 } | |
162 assert(bufend < bufmax); | |
163 lineend = bufend++; | |
164 buf[lineend] = '\n'; | |
165 } else { | |
166 tmp = bufend; | |
167 bufend += (size_t)result; | |
168 lineend = findnl(buf, tmp, bufend); | |
169 } | |
170 /* loop in case we still don't have a whole line */ | |
171 continue; | |
172 } | |
173 | |
174 /* have a line */ | |
175 assert(buf[lineend] == '\n'); | |
176 buf[lineend] = '\0'; | |
177 nextlinestart = lineend+1; | |
178 nextlinestartplace.line++; | |
179 | |
180 /* check for CR/NL */ | |
181 if (lineend > 0 && buf[lineend-1] == '\r') { | |
182 buf[lineend-1] = '\0'; | |
183 lineend--; | |
184 } | |
185 | |
186 /* check for continuation line */ | |
187 if (lineend > 0 && buf[lineend-1]=='\\') { | |
188 lineend--; | |
189 tmp = nextlinestart - lineend; | |
190 if (bufend > nextlinestart) { | |
191 memmove(buf+lineend, buf+nextlinestart, | |
192 bufend - nextlinestart); | |
193 } | |
194 bufend -= tmp; | |
195 nextlinestart -= tmp; | |
196 lineend = findnl(buf, lineend, bufend); | |
197 /* might not have a whole line, so loop */ | |
198 continue; | |
199 } | |
200 | |
201 /* line now goes from linestart to lineend */ | |
202 assert(buf[lineend] == '\0'); | |
203 if (lineend > linestart) { | |
204 directive_gotline(&linestartplace, | |
205 buf+linestart, lineend-linestart); | |
206 } | |
207 | |
208 linestart = nextlinestart; | |
209 lineend = findnl(buf, linestart, bufend); | |
210 linestartplace = nextlinestartplace; | |
211 } | |
212 | |
213 directive_goteof(&linestartplace); | |
214 free(buf); | |
215 } | |
89 | 216 |
90 //////////////////////////////////////////////////////////// | 217 //////////////////////////////////////////////////////////// |
91 // path search | 218 // path search |
92 | 219 |
93 static | 220 static |
118 int | 245 int |
119 file_tryopen(const char *file) | 246 file_tryopen(const char *file) |
120 { | 247 { |
121 int fd; | 248 int fd; |
122 | 249 |
250 /* XXX check for non-regular files */ | |
251 | |
123 fd = open(file, O_RDONLY); | 252 fd = open(file, O_RDONLY); |
124 if (fd < 0) { | 253 if (fd < 0) { |
125 return -1; | 254 return -1; |
126 } | 255 } |
127 /* XXX: do we need to do anything here or is this function pointless?*/ | 256 |
128 return fd; | 257 return fd; |
129 } | 258 } |
130 | 259 |
131 static | 260 static |
132 void | 261 void |
145 id = incdirarray_get(path, i); | 274 id = incdirarray_get(path, i); |
146 file = mkfilename(id->name, name); | 275 file = mkfilename(id->name, name); |
147 fd = file_tryopen(file); | 276 fd = file_tryopen(file); |
148 if (fd >= 0) { | 277 if (fd >= 0) { |
149 pf = place_addfile(place, file, id->issystem); | 278 pf = place_addfile(place, file, id->issystem); |
279 file_read(pf, fd, file); | |
150 free(file); | 280 free(file); |
151 file_read(pf, fd); | |
152 close(fd); | 281 close(fd); |
153 return; | 282 return; |
154 } | 283 } |
155 free(file); | 284 free(file); |
156 } | 285 } |
182 if (fd < 0) { | 311 if (fd < 0) { |
183 warn("%s", name); | 312 warn("%s", name); |
184 die(); | 313 die(); |
185 } | 314 } |
186 pf = place_addfile(place, name, false); | 315 pf = place_addfile(place, name, false); |
187 file_read(pf, fd); | 316 file_read(pf, fd, name); |
188 close(fd); | 317 close(fd); |
189 } | 318 } |