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 }