Mercurial > hg-old > index.cgi
comparison lwasm/struct.c @ 389:fbb7bfed8076
Added in structure support and fixed up some warts in the listing code (by adding more warts)
author | lost@l-w.ca |
---|---|
date | Wed, 14 Jul 2010 22:33:55 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
388:8991eb507d2d | 389:fbb7bfed8076 |
---|---|
1 /* | |
2 struct.c | |
3 Copyright © 2010 William Astle | |
4 | |
5 This file is part of LWASM. | |
6 | |
7 LWASM is free software: you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation, either version 3 of the License, or (at your option) any later | |
10 version. | |
11 | |
12 This program is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 more details. | |
16 | |
17 You should have received a copy of the GNU General Public License along with | |
18 this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 Contains stuff associated with structure processing | |
21 */ | |
22 | |
23 #include <config.h> | |
24 | |
25 #include <string.h> | |
26 | |
27 #include <lw_alloc.h> | |
28 #include <lw_string.h> | |
29 | |
30 #include "lwasm.h" | |
31 #include "instab.h" | |
32 | |
33 PARSEFUNC(pseudo_parse_struct) | |
34 { | |
35 structtab_t *s; | |
36 | |
37 if (as -> instruct) | |
38 { | |
39 lwasm_register_error(as, l, "Attempt to define a structure inside a structure"); | |
40 return; | |
41 } | |
42 | |
43 if (l -> sym == NULL) | |
44 { | |
45 lwasm_register_error(as, l, "Structure definition with no effect - no symbol"); | |
46 return; | |
47 } | |
48 | |
49 for (s = as -> structs; s; s = s -> next) | |
50 { | |
51 if (!strcmp(s -> name, l -> sym)) | |
52 break; | |
53 } | |
54 | |
55 if (s) | |
56 { | |
57 lwasm_register_error(as, l, "Duplicate structure definition"); | |
58 return; | |
59 } | |
60 | |
61 as -> instruct = 1; | |
62 | |
63 s = lw_alloc(sizeof(structtab_t)); | |
64 s -> name = lw_strdup(l -> sym); | |
65 s -> next = as -> structs; | |
66 s -> fields = NULL; | |
67 s -> size = 0; | |
68 as -> structs = s; | |
69 as -> cstruct = s; | |
70 | |
71 skip_operand(p); | |
72 | |
73 l -> len = 0; | |
74 l -> symset = 1; | |
75 } | |
76 | |
77 void pseudo_endstruct_aux(asmstate_t *as, line_t *l, structtab_field_t *e, const char *prefix, int *coff) | |
78 { | |
79 char *symname = NULL; | |
80 lw_expr_t te1, te2; | |
81 | |
82 while (e) | |
83 { | |
84 if (e -> name) | |
85 0 == asprintf(&symname, "%s.%s", prefix, e -> name); | |
86 else | |
87 0 == asprintf(&symname, "%s.____%d", prefix, *coff); | |
88 | |
89 // register the symbol | |
90 te1 = lw_expr_build(lw_expr_type_int, *coff); | |
91 te2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, te1, l -> addr); | |
92 register_symbol(as, l, symname, te2, symbol_flag_nocheck); | |
93 lw_expr_destroy(te2); | |
94 lw_expr_destroy(te1); | |
95 | |
96 if (e -> substruct) | |
97 { | |
98 char *t; | |
99 0 == asprintf(&t, "sizeof{%s}", symname); | |
100 te1 = lw_expr_build(lw_expr_type_int, e -> substruct -> size); | |
101 register_symbol(as, l, t, te1, symbol_flag_nocheck); | |
102 lw_expr_destroy(te1); | |
103 lw_free(t); | |
104 pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff); | |
105 } | |
106 else | |
107 { | |
108 *coff += e -> size; | |
109 } | |
110 e = e -> next; | |
111 } | |
112 } | |
113 | |
114 | |
115 PARSEFUNC(pseudo_parse_endstruct) | |
116 { | |
117 char *t; | |
118 int coff = 0; | |
119 lw_expr_t te; | |
120 | |
121 if (as -> instruct == 0) | |
122 { | |
123 lwasm_register_warning(as, l, "endstruct without struct"); | |
124 skip_operand(p); | |
125 return; | |
126 } | |
127 | |
128 0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name); | |
129 te = lw_expr_build(lw_expr_type_int, as -> cstruct -> size); | |
130 register_symbol(as, l, t, te, symbol_flag_nocheck); | |
131 lw_expr_destroy(te); | |
132 lw_free(t); | |
133 | |
134 l -> soff = as -> cstruct -> size; | |
135 as -> instruct = 0; | |
136 | |
137 skip_operand(p); | |
138 | |
139 pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff); | |
140 | |
141 l -> len = 0; | |
142 } | |
143 | |
144 void register_struct_entry(asmstate_t *as, line_t *l, int size, structtab_t *ss) | |
145 { | |
146 structtab_field_t *e, *e2; | |
147 | |
148 l -> soff = as -> cstruct -> size; | |
149 e = lw_alloc(sizeof(structtab_field_t)); | |
150 e -> next = NULL; | |
151 e -> size = size; | |
152 if (l -> sym) | |
153 e -> name = lw_strdup(l -> sym); | |
154 else | |
155 e -> name = NULL; | |
156 e -> substruct = ss; | |
157 if (as -> cstruct -> fields) | |
158 { | |
159 for (e2 = as -> cstruct -> fields; e2 -> next; e2 = e2 -> next) | |
160 /* do nothing */ ; | |
161 e2 -> next = e; | |
162 } | |
163 else | |
164 { | |
165 as -> cstruct -> fields = e; | |
166 } | |
167 as -> cstruct -> size += size; | |
168 } | |
169 | |
170 int expand_struct(asmstate_t *as, line_t *l, char **p, char *opc) | |
171 { | |
172 structtab_t *s; | |
173 char *t; | |
174 lw_expr_t te; | |
175 int addr = 0; | |
176 | |
177 debug_message(as, 200, "Checking for structure expansion: %s", opc); | |
178 | |
179 for (s = as -> structs; s; s = s -> next) | |
180 { | |
181 if (!strcmp(opc, s -> name)) | |
182 break; | |
183 } | |
184 | |
185 if (!s) | |
186 return -1; | |
187 | |
188 debug_message(as, 10, "Expanding structure: %s", opc); | |
189 | |
190 if (!(l -> sym)) | |
191 { | |
192 lwasm_register_error(as, l, "Cannot declare a structure without a symbol name."); | |
193 return; | |
194 } | |
195 | |
196 l -> len = s -> size; | |
197 | |
198 if (as -> instruct) | |
199 0 == asprintf(&t, "sizeof(%s.%s}", as -> cstruct -> name, l -> sym); | |
200 else | |
201 0 == asprintf(&t, "sizeof{%s}", l -> sym); | |
202 te = lw_expr_build(lw_expr_type_int, s -> size); | |
203 register_symbol(as, l, t, te, symbol_flag_nocheck); | |
204 lw_expr_destroy(te); | |
205 lw_free(t); | |
206 | |
207 if (as -> instruct) | |
208 0 == asprintf(&t, "%s.%s", as -> cstruct -> name, l -> sym); | |
209 else | |
210 t = lw_strdup(l -> sym); | |
211 pseudo_endstruct_aux(as, l, s -> fields, t, &addr); | |
212 lw_free(t); | |
213 l -> symset = 1; | |
214 if (as -> instruct) | |
215 register_struct_entry(as, l, s -> size, s); | |
216 return 0; | |
217 } | |
218 |