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