254
|
1 /*
|
|
2 struct.c
|
|
3 Copyright © 2009 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 definition.
|
|
21
|
|
22 Structures have their own name space. Macros will shadow structures so it's
|
|
23 a good idea to make sure no structures are name the same as macros.
|
|
24 */
|
|
25
|
|
26 #include <config.h>
|
|
27
|
|
28 #include <ctype.h>
|
|
29 #include <stdlib.h>
|
|
30 #include <string.h>
|
|
31 #include "lwasm.h"
|
|
32 #include "instab.h"
|
|
33 #include "util.h"
|
|
34
|
|
35 OPFUNC(pseudo_struct)
|
|
36 {
|
|
37 structtab_t *m;
|
|
38
|
|
39 // actually define a structure
|
|
40 if (as -> instruct)
|
|
41 {
|
|
42 register_error(as, l, 1, "Attempt to define a structure inside a structure");
|
|
43 return;
|
|
44 }
|
|
45
|
|
46 as -> instruct = 1;
|
|
47
|
|
48 // don't actually do anything if not pass 1
|
|
49 if (as -> passnum != 1)
|
|
50 return;
|
|
51
|
|
52
|
|
53 if (!l -> sym)
|
|
54 {
|
|
55 register_error(as, l, 1, "Structure definition with no effect - no symbol");
|
|
56 return;
|
|
57 }
|
|
58
|
|
59 // search for macro by same name...
|
|
60 for (m = as -> structs; m; m = m -> next)
|
|
61 {
|
|
62 if (!strcmp(m -> name, l -> sym))
|
|
63 break;
|
|
64 }
|
|
65 if (m)
|
|
66 {
|
|
67 register_error(as, l, 1, "Duplicate structure definition");
|
|
68 return;
|
|
69 }
|
|
70
|
|
71 m = lwasm_alloc(sizeof(structtab_t));
|
|
72 m -> name = lwasm_strdup(l -> sym);
|
|
73 m -> next = as -> structs;
|
|
74 m -> fields = NULL;
|
|
75 m -> size = 0;
|
|
76 as -> structs = m;
|
|
77 as -> cstruct = m;
|
|
78
|
|
79 while (**p && !isspace(**p))
|
|
80 (*p)++;
|
|
81 }
|
|
82
|
|
83
|
|
84
|
|
85 pseudo_endstruct_aux(asmstate_t *as, lwasm_line_t *l, struct struct_sym_e *e, const char *prefix, int *coff)
|
|
86 {
|
|
87 char *symname = NULL;
|
|
88
|
|
89 while (e)
|
|
90 {
|
|
91 if (e -> name)
|
|
92 0 == asprintf(&symname, "%s.%s", prefix, e -> name);
|
|
93 else
|
|
94 0 == asprintf(&symname, "%s.___%d", prefix, *coff);
|
|
95
|
|
96 // register symbol "symname" as global at coff
|
|
97 lwasm_register_symbol(as, l, symname, *coff, SYMBOL_NOCHECK);
|
|
98
|
|
99 if (e -> substruct)
|
|
100 {
|
|
101 char * t;
|
|
102 0 == asprintf(&t, "sizeof{%s}", symname);
|
|
103 lwasm_register_symbol(as, l, t, e -> substruct -> size, SYMBOL_NOCHECK);
|
|
104 lwasm_free(t);
|
|
105 pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff);
|
|
106 }
|
|
107 else
|
|
108 {
|
|
109 *coff += e -> size;
|
|
110 }
|
|
111
|
|
112 lwasm_free(symname);
|
|
113 e = e -> next;
|
|
114 }
|
|
115 }
|
|
116
|
|
117 OPFUNC(pseudo_endstruct)
|
|
118 {
|
|
119 int coff = 0;
|
|
120 char *t;
|
|
121
|
|
122 as -> instruct = 0;
|
|
123
|
|
124 if (as -> passnum != 1)
|
|
125 return;
|
|
126
|
|
127 // now register the global symbols for the structure
|
|
128 // this is a recursive process
|
|
129 0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name);
|
|
130 lwasm_register_symbol(as, l, t, as -> cstruct -> size, SYMBOL_NOCHECK);
|
|
131 lwasm_free(t);
|
|
132
|
|
133 pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff);
|
|
134 }
|
|
135
|
|
136
|
|
137 int expand_struct(asmstate_t *as, lwasm_line_t *l, char **p, char *opc)
|
|
138 {
|
|
139 structtab_t *s;
|
|
140 int addr;
|
|
141 char *t;
|
|
142
|
|
143 if (as -> passnum != 1)
|
|
144 return 0;
|
|
145
|
|
146 for (s = as -> structs; s; s = s -> next)
|
|
147 {
|
|
148 if (!strcmp(opc, s -> name))
|
|
149 break;
|
|
150 }
|
|
151 if (!s)
|
|
152 return -1;
|
|
153
|
|
154 if (!(l -> sym))
|
|
155 {
|
|
156 register_error(as, l, 1, "Cannot declare a structure without a symbol name.");
|
|
157 return;
|
|
158 }
|
|
159
|
|
160 l -> nocodelen = s -> size;
|
|
161
|
|
162 addr = as -> addr;
|
|
163 as -> addr += s -> size;
|
|
164
|
|
165 // now register the global symbols for the structure
|
|
166 // this is a recursive process
|
|
167 0 == asprintf(&t, "sizeof{%s}", l -> sym);
|
|
168 lwasm_register_symbol(as, l, t, s -> size, SYMBOL_NOCHECK);
|
|
169 lwasm_free(t);
|
|
170
|
|
171 pseudo_endstruct_aux(as, l, s -> fields, l -> sym, &addr);
|
|
172
|
|
173 return 0;
|
|
174 }
|