1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* symentry.c */ |
4 | /* */ |
5 | /* Symbol table entries for the cc65 C compiler */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2000-2013, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | #include <string.h> |
37 | |
38 | /* common */ |
39 | #include "xmalloc.h" |
40 | |
41 | /* cc65 */ |
42 | #include "anonname.h" |
43 | #include "declare.h" |
44 | #include "error.h" |
45 | #include "symentry.h" |
46 | |
47 | |
48 | |
49 | /*****************************************************************************/ |
50 | /* Code */ |
51 | /*****************************************************************************/ |
52 | |
53 | |
54 | |
55 | SymEntry* NewSymEntry (const char* Name, unsigned Flags) |
56 | /* Create a new symbol table with the given name */ |
57 | { |
58 | /* Get the length of the name */ |
59 | unsigned Len = strlen (Name); |
60 | |
61 | /* Allocate memory for the symbol entry */ |
62 | SymEntry* E = xmalloc (sizeof (SymEntry) + Len); |
63 | |
64 | /* Initialize the entry */ |
65 | E->NextHash = 0; |
66 | E->PrevSym = 0; |
67 | E->NextSym = 0; |
68 | E->Link = 0; |
69 | E->Owner = 0; |
70 | E->Flags = Flags; |
71 | E->Type = 0; |
72 | E->Attr = 0; |
73 | E->AsmName = 0; |
74 | E->V.BssName = 0; |
75 | memcpy (E->Name, Name, Len+1); |
76 | |
77 | /* Return the new entry */ |
78 | return E; |
79 | } |
80 | |
81 | |
82 | |
83 | void FreeSymEntry (SymEntry* E) |
84 | /* Free a symbol entry */ |
85 | { |
86 | unsigned i; |
87 | |
88 | TypeFree (E->Type); |
89 | xfree (E->AsmName); |
90 | |
91 | if (E->Flags & SC_LABEL) { |
92 | for (i = 0; i < CollCount (E->V.L.DefsOrRefs); i++) { |
93 | xfree (CollAt (E->V.L.DefsOrRefs, i)); |
94 | } |
95 | |
96 | DoneCollection (E->V.L.DefsOrRefs); |
97 | } |
98 | |
99 | xfree (E); |
100 | } |
101 | |
102 | |
103 | |
104 | void DumpSymEntry (FILE* F, const SymEntry* E) |
105 | /* Dump the given symbol table entry to the file in readable form */ |
106 | { |
107 | static const struct { |
108 | const char* Name; |
109 | unsigned Val; |
110 | } Flags [] = { |
111 | /* Beware: Order is important! */ |
112 | { "SC_TYPEDEF" , SC_TYPEDEF }, |
113 | { "SC_BITFIELD" , SC_BITFIELD }, |
114 | { "SC_STRUCTFIELD" , SC_STRUCTFIELD }, |
115 | { "SC_UNION" , SC_UNION }, |
116 | { "SC_STRUCT" , SC_STRUCT }, |
117 | { "SC_AUTO" , SC_AUTO }, |
118 | { "SC_REGISTER" , SC_REGISTER }, |
119 | { "SC_STATIC" , SC_STATIC }, |
120 | { "SC_EXTERN" , SC_EXTERN }, |
121 | { "SC_ENUM" , SC_ENUM }, |
122 | { "SC_CONST" , SC_CONST }, |
123 | { "SC_LABEL" , SC_LABEL }, |
124 | { "SC_PARAM" , SC_PARAM }, |
125 | { "SC_FUNC" , SC_FUNC }, |
126 | { "SC_STORAGE" , SC_STORAGE }, |
127 | { "SC_DEF" , SC_DEF }, |
128 | { "SC_REF" , SC_REF }, |
129 | { "SC_ZEROPAGE" , SC_ZEROPAGE }, |
130 | }; |
131 | |
132 | unsigned I; |
133 | unsigned SymFlags; |
134 | |
135 | /* Print the name */ |
136 | fprintf (F, "%s:\n" , E->Name); |
137 | |
138 | /* Print the assembler name if we have one */ |
139 | if (E->AsmName) { |
140 | fprintf (F, " AsmName: %s\n" , E->AsmName); |
141 | } |
142 | |
143 | /* Print the flags */ |
144 | SymFlags = E->Flags; |
145 | fprintf (F, " Flags:" ); |
146 | for (I = 0; I < sizeof (Flags) / sizeof (Flags[0]) && SymFlags != 0; ++I) { |
147 | if ((SymFlags & Flags[I].Val) == Flags[I].Val) { |
148 | SymFlags &= ~Flags[I].Val; |
149 | fprintf (F, " %s" , Flags[I].Name); |
150 | } |
151 | } |
152 | if (SymFlags != 0) { |
153 | fprintf (F, " 0x%05X" , SymFlags); |
154 | } |
155 | fprintf (F, "\n" ); |
156 | |
157 | /* Print the type */ |
158 | fprintf (F, " Type: " ); |
159 | if (E->Type) { |
160 | PrintType (F, E->Type); |
161 | } else { |
162 | fprintf (F, "(none)" ); |
163 | } |
164 | fprintf (F, "\n" ); |
165 | } |
166 | |
167 | |
168 | |
169 | int SymIsOutputFunc (const SymEntry* Sym) |
170 | /* Return true if this is a function that must be output */ |
171 | { |
172 | /* Symbol must be a function which is defined and either extern or |
173 | ** static and referenced. |
174 | */ |
175 | return IsTypeFunc (Sym->Type) && |
176 | SymIsDef (Sym) && |
177 | (Sym->Flags & (SC_REF | SC_EXTERN)); |
178 | } |
179 | |
180 | |
181 | |
182 | const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType) |
183 | /* Return an attribute for this symbol or NULL if the attribute does not exist */ |
184 | { |
185 | /* Beware: We may not even have a collection */ |
186 | if (Sym->Attr) { |
187 | unsigned I; |
188 | for (I = 0; I < CollCount (Sym->Attr); ++I) { |
189 | |
190 | /* Get the next attribute */ |
191 | const DeclAttr* A = CollConstAt (Sym->Attr, I); |
192 | |
193 | /* If this is the one we're searching for, return it */ |
194 | if (A->AttrType == AttrType) { |
195 | return A; |
196 | } |
197 | } |
198 | } |
199 | |
200 | /* Not found */ |
201 | return 0; |
202 | } |
203 | |
204 | |
205 | |
206 | void SymUseAttr (SymEntry* Sym, struct Declaration* D) |
207 | /* Use the attributes from the declaration for this symbol */ |
208 | { |
209 | /* We cannot specify attributes twice */ |
210 | if ((Sym->Flags & SC_HAVEATTR) != 0) { |
211 | if (D->Attributes != 0) { |
212 | Error ("Attributes must be specified in the first declaration" ); |
213 | } |
214 | return; |
215 | } |
216 | |
217 | /* Move the attributes */ |
218 | Sym->Attr = D->Attributes; |
219 | D->Attributes = 0; |
220 | Sym->Flags |= SC_HAVEATTR; |
221 | } |
222 | |
223 | |
224 | |
225 | void SymSetAsmName (SymEntry* Sym) |
226 | /* Set the assembler name for an external symbol from the name of the symbol */ |
227 | { |
228 | unsigned Len; |
229 | |
230 | /* Cannot be used to change the name */ |
231 | PRECONDITION (Sym->AsmName == 0); |
232 | |
233 | /* The assembler name starts with an underline */ |
234 | Len = strlen (Sym->Name); |
235 | Sym->AsmName = xmalloc (Len + 2); |
236 | Sym->AsmName[0] = '_'; |
237 | memcpy (Sym->AsmName+1, Sym->Name, Len+1); |
238 | } |
239 | |
240 | |
241 | |
242 | void CvtRegVarToAuto (SymEntry* Sym) |
243 | /* Convert a register variable to an auto variable */ |
244 | { |
245 | /* Change the storage class */ |
246 | Sym->Flags = (Sym->Flags & ~(SC_REGISTER | SC_STATIC | SC_EXTERN)) | SC_AUTO; |
247 | |
248 | /* Transfer the stack offset from register save area to actual offset */ |
249 | Sym->V.Offs = Sym->V.R.SaveOffs; |
250 | } |
251 | |
252 | |
253 | |
254 | void ChangeSymType (SymEntry* Entry, Type* T) |
255 | /* Change the type of the given symbol */ |
256 | { |
257 | TypeFree (Entry->Type); |
258 | Entry->Type = TypeDup (T); |
259 | } |
260 | |
261 | |
262 | |
263 | void ChangeAsmName (SymEntry* Entry, const char* NewAsmName) |
264 | /* Change the assembler name of the symbol */ |
265 | { |
266 | xfree (Entry->AsmName); |
267 | Entry->AsmName = xstrdup (NewAsmName); |
268 | } |
269 | |
270 | |
271 | |
272 | int HasAnonName (const SymEntry* Entry) |
273 | /* Return true if the symbol entry has an anonymous name */ |
274 | { |
275 | return IsAnonName (Entry->Name); |
276 | } |
277 | |