Mercurial > hg-old > index.cgi
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 } |