Mercurial > hg > index.cgi
comparison lwasm/input.c @ 0:2c24602be78f
Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
author | lost@l-w.ca |
---|---|
date | Wed, 19 Jan 2011 22:27:17 -0700 |
parents | |
children | 7317fbe024af |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:2c24602be78f |
---|---|
1 /* | |
2 input.c | |
3 | |
4 Copyright © 2010 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 /* | |
23 This file is used to handle reading input files. It serves to encapsulate | |
24 the entire input system to make porting to different media and systems | |
25 less difficult. | |
26 */ | |
27 | |
28 #include <errno.h> | |
29 #include <stdio.h> | |
30 #include <string.h> | |
31 | |
32 #include <lw_alloc.h> | |
33 #include <lw_stringlist.h> | |
34 #include <lw_string.h> | |
35 #include "lwasm.h" | |
36 | |
37 /* | |
38 Data type for storing input buffers | |
39 */ | |
40 | |
41 enum input_types_e | |
42 { | |
43 input_type_file, // regular file, no search path | |
44 input_type_include, // include path, start from "local" | |
45 input_type_string, // input from a string | |
46 | |
47 input_type_error // invalid input type | |
48 }; | |
49 | |
50 struct input_stack | |
51 { | |
52 struct input_stack *next; | |
53 int type; | |
54 void *data; | |
55 int data2; | |
56 char *filespec; | |
57 }; | |
58 | |
59 #define IS ((struct input_stack *)(as -> input_data)) | |
60 | |
61 void input_init(asmstate_t *as) | |
62 { | |
63 struct input_stack *t; | |
64 | |
65 if (as -> file_dir) | |
66 lw_stack_destroy(as -> file_dir); | |
67 as -> file_dir = lw_stack_create(lw_free); | |
68 as -> includelist = lw_stack_create(lw_free); | |
69 lw_stringlist_reset(as -> input_files); | |
70 while (IS) | |
71 { | |
72 t = IS; | |
73 as -> input_data = IS -> next; | |
74 lw_free(t); | |
75 } | |
76 } | |
77 | |
78 void input_pushpath(asmstate_t *as, char *fn) | |
79 { | |
80 /* take apart fn into path and filename then push the path */ | |
81 /* onto the current file path stack */ | |
82 | |
83 /* also add it to the list of files included */ | |
84 char *dn, *dp; | |
85 int o; | |
86 | |
87 dn = lw_strdup(fn); | |
88 lw_stack_push(as -> includelist, dn); | |
89 | |
90 dn = lw_strdup(fn); | |
91 dp = dn + strlen(dn); | |
92 | |
93 while (--dp != dn) | |
94 { | |
95 if (*dp == '/') | |
96 break; | |
97 } | |
98 if (*dp == '/') | |
99 *dp = '\0'; | |
100 | |
101 if (dp == dn) | |
102 { | |
103 lw_free(dn); | |
104 dn = lw_strdup("."); | |
105 lw_stack_push(as -> file_dir, dn); | |
106 return; | |
107 } | |
108 dp = lw_strdup(dn); | |
109 lw_free(dn); | |
110 lw_stack_push(as -> file_dir, dp); | |
111 } | |
112 | |
113 void input_openstring(asmstate_t *as, char *s, char *str) | |
114 { | |
115 struct input_stack *t; | |
116 | |
117 t = lw_alloc(sizeof(struct input_stack)); | |
118 t -> filespec = lw_strdup(s); | |
119 | |
120 t -> type = input_type_string; | |
121 t -> data = lw_strdup(str); | |
122 t -> data2 = 0; | |
123 t -> next = IS; | |
124 as -> input_data = t; | |
125 t -> filespec = lw_strdup(s); | |
126 } | |
127 | |
128 void input_open(asmstate_t *as, char *s) | |
129 { | |
130 struct input_stack *t; | |
131 char *s2; | |
132 char *p, *p2; | |
133 | |
134 t = lw_alloc(sizeof(struct input_stack)); | |
135 t -> filespec = lw_strdup(s); | |
136 | |
137 for (s2 = s; *s2 && (*s2 != ':'); s2++) | |
138 /* do nothing */ ; | |
139 if (!*s2) | |
140 { | |
141 t -> type = input_type_file; | |
142 } | |
143 else | |
144 { | |
145 char *ts; | |
146 | |
147 ts = lw_strndup(s, s2 - s); | |
148 s = s2 + 1; | |
149 if (!strcmp(ts, "include")) | |
150 t -> type = input_type_include; | |
151 else if (!strcmp(ts, "file")) | |
152 t -> type = input_type_file; | |
153 else | |
154 t -> type = input_type_error; | |
155 | |
156 lw_free(ts); | |
157 } | |
158 t -> next = as -> input_data; | |
159 as -> input_data = t; | |
160 | |
161 switch (IS -> type) | |
162 { | |
163 case input_type_include: | |
164 /* first check for absolute path and if so, skip path */ | |
165 if (*s == '/') | |
166 { | |
167 /* absolute path */ | |
168 IS -> data = fopen(s, "rb"); | |
169 debug_message(as, 1, "Opening (abs) %s", s); | |
170 if (!IS -> data) | |
171 { | |
172 lw_error("Cannot open file '%s': %s", s, strerror(errno)); | |
173 } | |
174 input_pushpath(as, s); | |
175 return; | |
176 } | |
177 | |
178 /* relative path, check relative to "current file" directory */ | |
179 p = lw_stack_top(as -> file_dir); | |
180 0 == asprintf(&p2, "%s/%s", p, s); | |
181 debug_message(as, 1, "Open: (cd) %s\n", p2); | |
182 IS -> data = fopen(p2, "rb"); | |
183 if (IS -> data) | |
184 { | |
185 input_pushpath(as, p2); | |
186 lw_free(p2); | |
187 return; | |
188 } | |
189 debug_message(as, 2, "Failed to open: (cd) %s (%s)\n", p2, strerror(errno)); | |
190 lw_free(p2); | |
191 | |
192 /* now check relative to entries in the search path */ | |
193 lw_stringlist_reset(as -> include_list); | |
194 while (p = lw_stringlist_current(as -> include_list)) | |
195 { | |
196 0 == asprintf(&p2, "%s/%s", p, s); | |
197 debug_message(as, 1, "Open (sp): %s\n", p2); | |
198 IS -> data = fopen(p2, "rb"); | |
199 if (IS -> data) | |
200 { | |
201 input_pushpath(as, p2); | |
202 lw_free(p2); | |
203 return; | |
204 } | |
205 debug_message(as, 2, "Failed to open: (sp) %s (%s)\n", p2, strerror(errno)); | |
206 lw_free(p2); | |
207 lw_stringlist_next(as -> include_list); | |
208 } | |
209 lw_error("Cannot open include file '%s': %s", s, strerror(errno)); | |
210 break; | |
211 | |
212 case input_type_file: | |
213 debug_message(as, 1, "Opening (reg): %s\n", s); | |
214 IS -> data = fopen(s, "rb"); | |
215 | |
216 if (!IS -> data) | |
217 { | |
218 lw_error("Cannot open file '%s': %s", s, strerror(errno)); | |
219 } | |
220 input_pushpath(as, s); | |
221 return; | |
222 } | |
223 | |
224 lw_error("Cannot figure out how to open '%s'.", t -> filespec); | |
225 } | |
226 | |
227 FILE *input_open_standalone(asmstate_t *as, char *s) | |
228 { | |
229 char *s2; | |
230 FILE *fp; | |
231 char *p, *p2; | |
232 | |
233 /* first check for absolute path and if so, skip path */ | |
234 if (*s == '/') | |
235 { | |
236 /* absolute path */ | |
237 debug_message(as, 2, "Open file (st abs) %s", s); | |
238 fp = fopen(s, "rb"); | |
239 if (!fp) | |
240 { | |
241 return NULL; | |
242 } | |
243 return fp; | |
244 } | |
245 | |
246 /* relative path, check relative to "current file" directory */ | |
247 p = lw_stack_top(as -> file_dir); | |
248 0 == asprintf(&p2, "%s/%s", p, s); | |
249 debug_message(as, 2, "Open file (st cd) %s", p2); | |
250 fp = fopen(p2, "rb"); | |
251 if (fp) | |
252 { | |
253 lw_free(p2); | |
254 return fp; | |
255 } | |
256 lw_free(p2); | |
257 | |
258 /* now check relative to entries in the search path */ | |
259 lw_stringlist_reset(as -> include_list); | |
260 while (p = lw_stringlist_current(as -> include_list)) | |
261 { | |
262 0 == asprintf(&p2, "%s/%s", p, s); | |
263 debug_message(as, 2, "Open file (st ip) %s", p2); | |
264 fp = fopen(p2, "rb"); | |
265 if (fp) | |
266 { | |
267 lw_free(p2); | |
268 return fp; | |
269 } | |
270 lw_free(p2); | |
271 lw_stringlist_next(as -> include_list); | |
272 } | |
273 | |
274 return NULL; | |
275 } | |
276 | |
277 char *input_readline(asmstate_t *as) | |
278 { | |
279 char *s; | |
280 char linebuff[2049]; | |
281 int lbloc; | |
282 int eol = 0; | |
283 | |
284 /* if no file is open, open one */ | |
285 nextfile: | |
286 if (!IS) { | |
287 s = lw_stringlist_current(as -> input_files); | |
288 if (!s) | |
289 return NULL; | |
290 lw_stringlist_next(as -> input_files); | |
291 input_open(as, s); | |
292 } | |
293 | |
294 switch (IS -> type) | |
295 { | |
296 case input_type_file: | |
297 case input_type_include: | |
298 /* read from a file */ | |
299 lbloc = 0; | |
300 for (;;) | |
301 { | |
302 int c, c2; | |
303 c = fgetc(IS -> data); | |
304 if (c == EOF) | |
305 { | |
306 if (lbloc == 0) | |
307 { | |
308 struct input_stack *t; | |
309 fclose(IS -> data); | |
310 lw_free(lw_stack_pop(as -> file_dir)); | |
311 lw_free(IS -> filespec); | |
312 t = IS -> next; | |
313 lw_free(IS); | |
314 as -> input_data = t; | |
315 goto nextfile; | |
316 } | |
317 linebuff[lbloc] = '\0'; | |
318 eol = 1; | |
319 } | |
320 else if (c == '\r') | |
321 { | |
322 linebuff[lbloc] = '\0'; | |
323 eol = 1; | |
324 c2 = fgetc(IS -> data); | |
325 if (c2 == EOF) | |
326 c = EOF; | |
327 else if (c2 != '\n') | |
328 ungetc(c2, IS -> data); | |
329 } | |
330 else if (c == '\n') | |
331 { | |
332 linebuff[lbloc] = '\0'; | |
333 eol = 1; | |
334 c2 = fgetc(IS -> data); | |
335 if (c2 == EOF) | |
336 c = EOF; | |
337 else if (c2 != '\r') | |
338 ungetc(c2, IS -> data); | |
339 } | |
340 else | |
341 { | |
342 if (lbloc < 2048) | |
343 linebuff[lbloc++] = c; | |
344 } | |
345 if (eol) | |
346 { | |
347 s = lw_strdup(linebuff); | |
348 return s; | |
349 } | |
350 } | |
351 | |
352 case input_type_string: | |
353 /* read from a string */ | |
354 if (((char *)(IS -> data))[IS -> data2] == '\0') | |
355 { | |
356 struct input_stack *t; | |
357 lw_free(IS -> data); | |
358 lw_free(IS -> filespec); | |
359 t = IS -> next; | |
360 lw_free(IS); | |
361 as -> input_data = t; | |
362 goto nextfile; | |
363 } | |
364 s = (char *)(IS -> data); | |
365 lbloc = 0; | |
366 for (;;) | |
367 { | |
368 int c; | |
369 c = s[IS -> data2]; | |
370 if (c) | |
371 IS -> data2++; | |
372 if (c == '\0') | |
373 { | |
374 linebuff[lbloc] = '\0'; | |
375 eol = 1; | |
376 } | |
377 else if (c == '\r') | |
378 { | |
379 linebuff[lbloc] = '\0'; | |
380 eol = 1; | |
381 if (s[IS -> data2] == '\n') | |
382 IS -> data2++; | |
383 } | |
384 else if (c == '\n') | |
385 { | |
386 linebuff[lbloc] = '\0'; | |
387 eol = 1; | |
388 if (s[IS -> data2] == '\r') | |
389 IS -> data2++; | |
390 } | |
391 else | |
392 { | |
393 if (lbloc < 2048) | |
394 linebuff[lbloc++] = c; | |
395 } | |
396 if (eol) | |
397 { | |
398 s = lw_strdup(linebuff); | |
399 return s; | |
400 } | |
401 } | |
402 | |
403 default: | |
404 lw_error("Problem reading from unknown input type"); | |
405 } | |
406 } | |
407 | |
408 char *input_curspec(asmstate_t *as) | |
409 { | |
410 if (IS) | |
411 return IS -> filespec; | |
412 return NULL; | |
413 } |