Mercurial > hg > index.cgi
comparison lwasm/section.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 section.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 #include <string.h> | |
23 | |
24 #include <lw_string.h> | |
25 #include <lw_alloc.h> | |
26 | |
27 #include "lwasm.h" | |
28 #include "instab.h" | |
29 | |
30 PARSEFUNC(pseudo_parse_section) | |
31 { | |
32 char *p2; | |
33 char *sn; | |
34 char *opts = NULL; | |
35 sectiontab_t *s; | |
36 | |
37 if (as -> output_format != OUTPUT_OBJ) | |
38 { | |
39 lwasm_register_error(as, l, "Cannot use sections unless using the object target"); | |
40 return; | |
41 } | |
42 | |
43 if (!**p) | |
44 { | |
45 lwasm_register_error(as, l, "Need section name"); | |
46 return; | |
47 } | |
48 | |
49 l -> len = 0; | |
50 | |
51 if (as -> csect) | |
52 { | |
53 lw_expr_destroy(as -> csect -> offset); | |
54 as -> csect -> offset = lw_expr_copy(l -> addr); | |
55 as -> csect = NULL; | |
56 } | |
57 | |
58 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++) | |
59 /* do nothing */ ; | |
60 | |
61 sn = lw_strndup(*p, p2 - *p); | |
62 *p = p2; | |
63 | |
64 if (**p == ',') | |
65 { | |
66 // have opts | |
67 (*p)++; | |
68 | |
69 for (p2 = *p; *p2 && !isspace(*p2); p2++) | |
70 /* do nothing */ ; | |
71 | |
72 opts = lw_strndup(*p, p2 - *p); | |
73 *p = p2; | |
74 } | |
75 | |
76 for (s = as -> sections; s; s = s -> next) | |
77 { | |
78 if (!strcmp(s -> name, sn)) | |
79 break; | |
80 } | |
81 if (s && opts) | |
82 { | |
83 lwasm_register_warning(as, l, "Section flags can only be specified the first time; ignoring duplicate definition"); | |
84 } | |
85 if (!s) | |
86 { | |
87 // create section data structure | |
88 s = lw_alloc(sizeof(sectiontab_t)); | |
89 s -> oblen = 0; | |
90 s -> obsize = 0; | |
91 s -> obytes = NULL; | |
92 s -> name = lw_strdup(sn); | |
93 s -> offset = lw_expr_build(lw_expr_type_special, lwasm_expr_secbase, s); | |
94 s -> flags = section_flag_none; | |
95 s -> reloctab = NULL; | |
96 if (!strcasecmp(sn, "bss") || !strcasecmp(sn, ".bss")) | |
97 { | |
98 s -> flags |= section_flag_bss; | |
99 } | |
100 // parse options | |
101 if (opts) | |
102 { | |
103 // only one option ("bss" or "!bss") | |
104 if (!strcasecmp(opts, "bss")) | |
105 { | |
106 s -> flags |= section_flag_bss; | |
107 } | |
108 else if (!strcasecmp(opts, "!bss")) | |
109 { | |
110 s -> flags &= ~section_flag_bss; | |
111 } | |
112 else | |
113 { | |
114 lwasm_register_error(as, l, "Unrecognized section flag"); | |
115 lw_free(sn); | |
116 lw_free(opts); | |
117 lw_free(s -> name); | |
118 lw_expr_destroy(s -> offset); | |
119 lw_free(s); | |
120 return; | |
121 } | |
122 } | |
123 s -> next = as -> sections; | |
124 as -> sections = s; | |
125 } | |
126 | |
127 lw_expr_destroy(l -> addr); | |
128 l -> addr = lw_expr_copy(s -> offset); | |
129 | |
130 as -> csect = s; | |
131 as -> context = lwasm_next_context(as); | |
132 | |
133 l -> len = 0; | |
134 | |
135 lw_free(opts); | |
136 lw_free(sn); | |
137 } | |
138 | |
139 PARSEFUNC(pseudo_parse_endsection) | |
140 { | |
141 if (as -> output_format != OUTPUT_OBJ) | |
142 { | |
143 lwasm_register_error(as, l, "Cannot use sections unless using the object target"); | |
144 return; | |
145 } | |
146 | |
147 l -> len = 0; | |
148 | |
149 if (!(as -> csect)) | |
150 { | |
151 lwasm_register_error(as, l, "ENDSECTION without SECTION"); | |
152 return; | |
153 } | |
154 | |
155 // save offset in case another instance of the section appears | |
156 lw_expr_destroy(as -> csect -> offset); | |
157 as -> csect -> offset = l -> addr; | |
158 | |
159 // reset address to 0 | |
160 l -> addr = lw_expr_build(lw_expr_type_int, 0); | |
161 as -> csect = NULL; | |
162 | |
163 // end of section is a context break | |
164 as -> context = lwasm_next_context(as); | |
165 | |
166 skip_operand(p); | |
167 } | |
168 | |
169 PARSEFUNC(pseudo_parse_export) | |
170 { | |
171 int after = 0; | |
172 char *sym = NULL; | |
173 exportlist_t *e; | |
174 | |
175 if (as -> output_format != OUTPUT_OBJ) | |
176 { | |
177 lwasm_register_error(as, l, "EXPORT only supported for object target"); | |
178 return; | |
179 } | |
180 | |
181 l -> len = 0; | |
182 | |
183 if (l -> sym) | |
184 { | |
185 sym = lw_strdup(l -> sym); | |
186 l -> symset = 1; | |
187 } | |
188 | |
189 if (l -> sym) | |
190 { | |
191 skip_operand(p); | |
192 } | |
193 | |
194 again: | |
195 if (after || !sym) | |
196 { | |
197 char *p2; | |
198 | |
199 after = 1; | |
200 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++) | |
201 /* do nothing */ ; | |
202 | |
203 sym = lw_strndup(*p, p2 - *p); | |
204 *p = p2; | |
205 } | |
206 if (!sym) | |
207 { | |
208 lwasm_register_error(as, l, "No symbol for EXPORT"); | |
209 return; | |
210 } | |
211 | |
212 // add the symbol to the "export" list (which will be resolved | |
213 // after the parse pass is complete | |
214 e = lw_alloc(sizeof(exportlist_t)); | |
215 e -> next = as -> exportlist; | |
216 e -> symbol = lw_strdup(sym); | |
217 e -> line = l; | |
218 e -> se = NULL; | |
219 as -> exportlist = e; | |
220 lw_free(sym); | |
221 | |
222 if (after && **p == ',') | |
223 { | |
224 (*p)++; | |
225 for (; **p && isspace(**p); (*p)++) | |
226 /* do nothing */ ; | |
227 goto again; | |
228 } | |
229 } | |
230 | |
231 PARSEFUNC(pseudo_parse_extern) | |
232 { | |
233 int after = 0; | |
234 char *sym = NULL; | |
235 importlist_t *e; | |
236 | |
237 if (as -> output_format != OUTPUT_OBJ) | |
238 { | |
239 lwasm_register_error(as, l, "IMPORT only supported for object target"); | |
240 return; | |
241 } | |
242 | |
243 l -> len = 0; | |
244 | |
245 if (l -> sym) | |
246 { | |
247 sym = lw_strdup(l -> sym); | |
248 l -> symset = 1; | |
249 } | |
250 | |
251 if (l -> sym) | |
252 { | |
253 skip_operand(p); | |
254 } | |
255 | |
256 again: | |
257 if (after || !sym) | |
258 { | |
259 char *p2; | |
260 | |
261 after = 1; | |
262 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++) | |
263 /* do nothing */ ; | |
264 | |
265 sym = lw_strndup(*p, p2 - *p); | |
266 *p = p2; | |
267 } | |
268 if (!sym) | |
269 { | |
270 lwasm_register_error(as, l, "No symbol for IMPORT"); | |
271 return; | |
272 } | |
273 | |
274 // add the symbol to the "export" list (which will be resolved | |
275 // after the parse pass is complete | |
276 e = lw_alloc(sizeof(importlist_t)); | |
277 e -> next = as -> importlist; | |
278 e -> symbol = lw_strdup(sym); | |
279 as -> importlist = e; | |
280 lw_free(sym); | |
281 | |
282 if (after && **p == ',') | |
283 { | |
284 (*p)++; | |
285 for (; **p && isspace(**p); (*p)++) | |
286 /* do nothing */ ; | |
287 goto again; | |
288 } | |
289 } | |
290 | |
291 PARSEFUNC(pseudo_parse_extdep) | |
292 { | |
293 int after = 0; | |
294 char *sym = NULL; | |
295 importlist_t *e; | |
296 | |
297 if (as -> output_format != OUTPUT_OBJ) | |
298 { | |
299 lwasm_register_error(as, l, "EXTDEP only supported for object target"); | |
300 return; | |
301 } | |
302 | |
303 if (!as -> csect) | |
304 { | |
305 lwasm_register_error(as, l, "EXTDEP must be within a section"); | |
306 return; | |
307 } | |
308 | |
309 l -> len = 0; | |
310 | |
311 if (l -> sym) | |
312 sym = lw_strdup(l -> sym); | |
313 | |
314 if (l -> sym) | |
315 { | |
316 skip_operand(p); | |
317 } | |
318 | |
319 again: | |
320 if (after || !sym) | |
321 { | |
322 char *p2; | |
323 | |
324 after = 1; | |
325 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++) | |
326 /* do nothing */ ; | |
327 | |
328 sym = lw_strndup(*p, p2 - *p); | |
329 } | |
330 if (!sym) | |
331 { | |
332 lwasm_register_error(as, l, "No symbol for EXTDEP"); | |
333 return; | |
334 } | |
335 | |
336 // create a zero-width dependency | |
337 { | |
338 lw_expr_t e; | |
339 e = lw_expr_build(lw_expr_type_int, 0); | |
340 lwasm_emitexpr(l, e, 0); | |
341 lw_expr_destroy(e); | |
342 } | |
343 | |
344 if (after && **p == ',') | |
345 { | |
346 (*p)++; | |
347 for (; **p && isspace(**p); (*p)++) | |
348 /* do nothing */ ; | |
349 goto again; | |
350 } | |
351 } |