comparison lwasm/input.c @ 329:c15cca3ae6a2

Created first pass of input layer
author lost
date Sun, 28 Feb 2010 05:01:31 +0000
parents 591d01b343b9
children 81c005b82775
comparison
equal deleted inserted replaced
328:591d01b343b9 329:c15cca3ae6a2
25 This file is used to handle reading input files. It serves to encapsulate 25 This file is used to handle reading input files. It serves to encapsulate
26 the entire input system to make porting to different media and systems 26 the entire input system to make porting to different media and systems
27 less difficult. 27 less difficult.
28 */ 28 */
29 29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <string.h>
33
30 #include <lw_alloc.h> 34 #include <lw_alloc.h>
31 #include <lw_stringlist.h> 35 #include <lw_stringlist.h>
32 36 #include <lw_string.h>
33 struct input_layer 37 #include "lwasm.h"
34 { 38
35 lw_stringlist_t inputlist; 39 /*
36 struct input_layer *nextlayer; 40 Data type for storing input buffers
37 41 */
38 FILE *fp; 42
43 enum input_types_e
44 {
45 input_type_file, // regular file, no search path
46 input_type_include, // include path, start from "local"
47 input_type_string, // input from a string
48
49 input_type_error // invalid input type
39 }; 50 };
40 51
41 52 struct input_stack
42 static struct input_layer *layerstack = NULL; 53 {
43 54 struct input_stack *next;
44 void input_push(lw_stringlist_t list) 55 int type;
45 { 56 void *data;
46 struct input_layer *i; 57 int data2;
47 58 char *filespec;
48 i = lw_alloc(sizeof(struct input_layer)); 59 };
49 i -> nextlayer = layerstack; 60
50 layerstack = i; 61 static struct input_stack *is = NULL;
51 i -> inputlist = lw_stringlist_copy(list); 62
52 } 63 void input_init(asmstate_t *as)
53 64 {
54 /* fetch a line of input from the top of the input stack */ 65 struct input_stack *t;
55 /* return NULL if no input left */ 66
56 char *input_fetchline(void) 67 lw_stringlist_reset(as -> input_files);
57 { 68 while (is)
58 again: 69 {
59 if (!layerstack) 70 t = is;
60 return NULL; 71 is = is -> next;
61 72 lw_free(t);
62 if (!layerstack -> fp) 73 }
63 { 74 }
64 // no open file 75
65 char *fn; 76 void input_pushpath(asmstate_t *as, char *fn)
77 {
78 /* take apart fn into path and filename then push the path */
79 /* onto the current file path stack */
80 char *dn, *dp;
81 int o;
82
83 dn = lw_strdup(fn);
84 dp = dn + strlen(dp);
85
86 while (--dp != dn)
87 {
88 if (*dp == '/')
89 break;
90 }
91 if (*dp == '/')
92 *dp = '\0';
93
94 if (dp == dn)
95 {
96 lw_free(dn);
97 dn = lw_strdup(".");
98 lw_stack_push(as -> file_dir, dn);
99 return;
100 }
101 dp = lw_strdup(dn);
102 lw_free(dn);
103 lw_stack_push(as -> file_dir, dp);
104 }
105
106 void input_openstring(asmstate_t *as, char *s, char *str)
107 {
108 struct input_stack *t;
109
110 t = lw_alloc(sizeof(struct input_stack));
111 t -> filespec = lw_strdup(s);
112
113 t -> type = input_type_string;
114 t -> data = lw_strdup(str);
115 t -> data2 = 0;
116 t -> next = is;
117 is = t;
118 t -> filespec = lw_strdup(s);
119 }
120
121 void input_open(asmstate_t *as, char *s)
122 {
123 struct input_stack *t;
124 char *s2;
125 char *p, *p2;
126
127 t = lw_alloc(sizeof(struct input_stack));
128 t -> filespec = lw_strdup(s);
129
130 for (s2 = s; *s2 && *s2 != ':'; s2++)
131 /* do nothing */ ;
132 if (!s2)
133 {
134 t -> type = input_type_file;
135 }
136 else
137 {
138 char *ts;
66 139
67 fn = lw_stringlist_current(layerstack -> inputlist); 140 ts = lw_strndup(s, s2 - s);
68 lw_stringlist_next(layerstack -> inputlist); 141 s = s2 + 1;
69 if (!fn)
70 {
71 struct input_list *t;
72 t = layerstack;
73 layerstack = layerstack -> nextlayer;
74 lw_stringlist_destroy(t -> inputlist);
75 lw_free(t);
76 goto again;
77 }
78 142
79 // open the file here 143 if (!strcmp(ts, "include"))
80 } 144 t -> type = input_type_include;
81 145 else if (!strcmp(ts, "file"))
82 146 t -> type = input_type_file;
83 } 147 else
148 t -> type = input_type_error;
149 }
150
151 t -> next = is;
152 is = t;
153
154 switch (is -> type)
155 {
156 case input_type_include:
157 /* first check for absolute path and if so, skip path */
158 if (*s == '/')
159 {
160 /* absolute path */
161 is -> data = fopen(s, "rb");
162 if (!is -> data)
163 {
164 lw_error("Cannot open file '%s': %s", s, strerror(errno));
165 }
166 input_pushpath(as, s);
167 break;
168 }
169
170 /* relative path, check relative to "current file" directory */
171 p = lw_stack_top(as -> file_dir);
172 0 == asprintf(&p2, "%s/%s", p, s);
173 is -> data = fopen(p2, "rb");
174 if (is -> data)
175 {
176 input_pushpath(as, p2);
177 lw_free(p2);
178 break;
179 }
180 lw_free(p2);
181
182 /* now check relative to entries in the search path */
183 lw_stringlist_reset(as -> include_list);
184 while (p = lw_stringlist_current(as -> include_list))
185 {
186 0 == asprintf(&p2, "%s/%s", p, s);
187 is -> data = fopen(p2, "rb");
188 if (is -> data)
189 {
190 input_pushpath(as, p2);
191 lw_free(p2);
192 return;
193 }
194 lw_free(p2);
195 lw_stringlist_next(as -> include_list);
196 }
197 lw_error("Cannot open include file '%s': %s", s, strerror(errno));
198
199 case input_type_file:
200 is -> data = fopen(s, "rb");
201
202 if (!is -> data)
203 {
204 lw_error("Cannot open file '%s': %s", s, strerror(errno));
205 }
206 input_pushpath(as, s);
207 return;
208 }
209
210 lw_error("Cannot figure out how to open '%s'.", s);
211 }
212
213 char *input_readline(asmstate_t *as)
214 {
215 char *s;
216 char linebuff[2049];
217 int lbloc;
218 int eol = 0;
219
220 /* if no file is open, open one */
221 nextfile:
222 if (!is) {
223 s = lw_stringlist_current(as -> input_files);
224 if (!s)
225 return NULL;
226 lw_stringlist_next(as -> input_files);
227 input_open(as, s);
228 }
229
230 switch (is -> type)
231 {
232 case input_type_file:
233 case input_type_include:
234 /* read from a file */
235 for (;;)
236 {
237 int c, c2;
238 c = fgetc(is -> data);
239 lbloc = 0;
240 if (c == EOF)
241 {
242 if (lbloc == 0)
243 {
244 struct input_stack *t;
245 fclose(is -> data);
246 lw_free(lw_stack_pop(as -> file_dir));
247 lw_free(is -> filespec);
248 t = is -> next;
249 lw_free(is);
250 is = t;
251 goto nextfile;
252 }
253 linebuff[lbloc] = '\0';
254 eol = 1;
255 }
256 else if (c == '\r')
257 {
258 linebuff[lbloc] = '\0';
259 eol = 1;
260 c2 = fgetc(is -> data);
261 if (c2 == EOF)
262 c = EOF;
263 else if (c2 != '\n')
264 ungetc(c2, is -> data);
265 }
266 else if (c == '\n')
267 {
268 linebuff[lbloc] = '\0';
269 eol = 1;
270 c2 = fgetc(is -> data);
271 if (c2 == EOF)
272 c = EOF;
273 else if (c2 != '\r')
274 ungetc(c2, is -> data);
275 }
276 else
277 {
278 if (lbloc < 2048)
279 linebuff[lbloc++] = c;
280 }
281 if (eol)
282 {
283 s = lw_strdup(linebuff);
284 return s;
285 }
286 }
287
288 case input_type_string:
289 /* read from a string */
290 if (((char *)(is -> data))[is -> data2] == '\0')
291 {
292 struct input_stack *t;
293 lw_free(is -> data);
294 lw_free(is -> filespec);
295 t = is -> next;
296 lw_free(is);
297 is = t;
298 goto nextfile;
299 }
300 s = (char *)(is -> data);
301 lbloc = 0;
302 for (;;)
303 {
304 int c;
305 c = s[is -> data2];
306 if (c)
307 is -> data2++;
308 if (c == '\0')
309 {
310 linebuff[lbloc] = '\0';
311 eol = 1;
312 }
313 else if (c == '\r')
314 {
315 linebuff[lbloc] = '\0';
316 eol = 1;
317 if (s[is -> data2] == '\n')
318 is -> data2++;
319 }
320 else if (c == '\n')
321 {
322 linebuff[lbloc] = '\0';
323 eol = 1;
324 if (s[is -> data2] == '\r')
325 is -> data2++;
326 }
327 else
328 {
329 if (lbloc < 2048)
330 linebuff[lbloc++] = c;
331 }
332 if (eol)
333 {
334 s = lw_strdup(linebuff);
335 return s;
336 }
337 }
338
339 default:
340 lw_error("Problem reading from unknown input type");
341 }
342 }