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 }