1 /*****************************************************************************/
2 /* */
3 /* condes.c */
4 /* */
5 /* Module constructor/destructor support */
6 /* */
7 /* */
8 /* */
9 /* (C) 2000-2012, 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 "addrsize.h"
40 #include "check.h"
41 #include "coll.h"
42 #include "filepos.h"
43 #include "fragdefs.h"
44 #include "xmalloc.h"
45
46 /* ld65 */
47 #include "condes.h"
48 #include "exports.h"
49 #include "fragment.h"
50 #include "segments.h"
51 #include "spool.h"
52
53
54
55 /*****************************************************************************/
56 /* Data */
57 /*****************************************************************************/
58
59
60
61 /* Struct describing one condes type */
62 typedef struct ConDesDesc ConDesDesc;
63 struct ConDesDesc {
64 Collection ExpList; /* List of exported symbols */
65 unsigned SegName; /* Name of segment the table is in */
66 unsigned Label; /* Name of table label */
67 unsigned CountSym; /* Name of symbol for entry count */
68 unsigned char Order; /* Table order (increasing/decreasing) */
69 ConDesImport Import; /* Forced import if any */
70 };
71
72 /* Array for all types */
73 static ConDesDesc ConDes[CD_TYPE_COUNT] = {
74 {
75 STATIC_COLLECTION_INITIALIZER,
76 INVALID_STRING_ID,
77 INVALID_STRING_ID,
78 INVALID_STRING_ID,
79 cdIncreasing,
80 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
81 },{
82 STATIC_COLLECTION_INITIALIZER,
83 INVALID_STRING_ID,
84 INVALID_STRING_ID,
85 INVALID_STRING_ID,
86 cdIncreasing,
87 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
88 },{
89 STATIC_COLLECTION_INITIALIZER,
90 INVALID_STRING_ID,
91 INVALID_STRING_ID,
92 INVALID_STRING_ID,
93 cdIncreasing,
94 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
95 },{
96 STATIC_COLLECTION_INITIALIZER,
97 INVALID_STRING_ID,
98 INVALID_STRING_ID,
99 INVALID_STRING_ID,
100 cdIncreasing,
101 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
102 },{
103 STATIC_COLLECTION_INITIALIZER,
104 INVALID_STRING_ID,
105 INVALID_STRING_ID,
106 INVALID_STRING_ID,
107 cdIncreasing,
108 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
109 },{
110 STATIC_COLLECTION_INITIALIZER,
111 INVALID_STRING_ID,
112 INVALID_STRING_ID,
113 INVALID_STRING_ID,
114 cdIncreasing,
115 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
116 },{
117 STATIC_COLLECTION_INITIALIZER,
118 INVALID_STRING_ID,
119 INVALID_STRING_ID,
120 INVALID_STRING_ID,
121 cdIncreasing,
122 { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
123 },
124 };
125
126
127
128 /*****************************************************************************/
129 /* Internally used function to create the condes tables */
130 /*****************************************************************************/
131
132
133
ConDesCompare(void * Data,const void * E1,const void * E2)134 static int ConDesCompare (void* Data, const void* E1, const void* E2)
135 /* Compare function to sort the exports */
136 {
137 int Cmp;
138
139 /* Data is actually a pointer to a ConDesDesc from the table, E1 and
140 ** E2 are exports from the collection. Get the condes type and cast
141 ** the void pointers to object pointers.
142 */
143 ConDesDesc* CD = ((ConDesDesc*) Data);
144 int Type = CD - ConDes;
145 const Export* Exp1 = (const Export*) E1;
146 const Export* Exp2 = (const Export*) E2;
147
148 /* Get the priorities of the two exports */
149 unsigned Prio1 = Exp1->ConDes[Type];
150 unsigned Prio2 = Exp2->ConDes[Type];
151
152 /* Compare the priorities for this condes type */
153 if (Prio1 < Prio2) {
154 Cmp = -1;
155 } else if (Prio1 > Prio2) {
156 Cmp = 1;
157 } else {
158 /* Use the name in this case */
159 Cmp = SB_Compare (GetStrBuf (Exp1->Name), GetStrBuf (Exp2->Name));
160 }
161
162 /* Reverse the result for decreasing order */
163 if (CD->Order == cdIncreasing) {
164 return Cmp;
165 } else {
166 return -Cmp;
167 }
168 }
169
170
171
ConDesCreateOne(ConDesDesc * CD)172 static void ConDesCreateOne (ConDesDesc* CD)
173 /* Create one table if requested */
174 {
175 Segment* Seg; /* Segment for table */
176 Section* Sec; /* Section for table */
177 unsigned Count; /* Number of exports */
178 unsigned I;
179
180 /* Check if this table has a segment and table label defined. If not,
181 ** creation was not requested in the config file - ignore it.
182 */
183 if (CD->SegName == INVALID_STRING_ID || CD->Label == INVALID_STRING_ID) {
184 return;
185 }
186
187 /* Check if there is an import for the table label. If not, there is no
188 ** reference to the table and we would just waste memory creating the
189 ** table.
190 */
191 if (!IsUnresolved (CD->Label)) {
192 return;
193 }
194
195 /* Sort the collection of exports according to priority */
196 CollSort (&CD->ExpList, ConDesCompare, CD);
197
198 /* Get the segment for the table, create it if needed */
199 Seg = GetSegment (CD->SegName, ADDR_SIZE_ABS, 0);
200
201 /* Create a new section for the table */
202 Sec = NewSection (Seg, 1, ADDR_SIZE_ABS);
203
204 /* Walk over the exports and create a fragment for each one. We will use
205 ** the exported expression without copying it, since it's cheap and there
206 ** is currently no place where it gets changed (hope this will not hunt
207 ** me later...).
208 */
209 Count = CollCount (&CD->ExpList);
210 for (I = 0; I < Count; ++I) {
211
212 /* Get the export */
213 Export* E = CollAt (&CD->ExpList, I);
214
215 /* Create the fragment */
216 Fragment* F = NewFragment (FRAG_EXPR, 2, Sec);
217
218 /* Set the expression pointer */
219 F->Expr = E->Expr;
220 }
221
222 /* Define the table start as an export, offset into section is zero
223 ** (the section only contains the table).
224 */
225 CreateSectionExport (CD->Label, Sec, 0);
226
227 /* If we have a CountSym name given AND if it is referenced, define it
228 ** with the number of elements in the table.
229 */
230 if (CD->CountSym) {
231 CreateConstExport (CD->CountSym, Count);
232 }
233 }
234
235
236
237 /*****************************************************************************/
238 /* Code */
239 /*****************************************************************************/
240
241
242
ConDesAddExport(struct Export * E)243 void ConDesAddExport (struct Export* E)
244 /* Add the given export to the list of constructors/destructor */
245 {
246 unsigned Type;
247
248 /* Insert the export into all tables for which declarations exist */
249 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
250 unsigned Prio = E->ConDes[Type];
251 if (Prio != CD_PRIO_NONE) {
252 CollAppend (&ConDes[Type].ExpList, E);
253 }
254 }
255 }
256
257
258
ConDesSetSegName(unsigned Type,unsigned SegName)259 void ConDesSetSegName (unsigned Type, unsigned SegName)
260 /* Set the segment name where the table should go */
261 {
262 /* Check the parameters */
263 PRECONDITION (Type <= CD_TYPE_MAX && SegName != 0);
264
265 /* Setting the segment name twice is bad */
266 CHECK (ConDes[Type].SegName == INVALID_STRING_ID);
267
268 /* Set the name */
269 ConDes[Type].SegName = SegName;
270 }
271
272
273
ConDesGetImport(unsigned Type)274 const ConDesImport* ConDesGetImport (unsigned Type)
275 /* Get the forced import for the given ConDes type. Returns NULL if there is
276 ** no forced import for this type.
277 */
278 {
279 const ConDesImport* Import;
280
281 /* Check the parameters */
282 PRECONDITION (Type <= CD_TYPE_MAX);
283
284 /* Return the import */
285 Import = &ConDes[Type].Import;
286 return (Import->Name != INVALID_STRING_ID)? Import : 0;
287 }
288
289
290
ConDesSetImport(unsigned Type,const ConDesImport * Import)291 void ConDesSetImport (unsigned Type, const ConDesImport* Import)
292 /* Set the forced import for the given ConDes type */
293 {
294 /* Check the parameters */
295 PRECONDITION (Type <= CD_TYPE_MAX && Import != 0);
296
297 /* Setting the import twice is bad */
298 CHECK (ConDes[Type].Import.Name == INVALID_STRING_ID);
299
300 /* Set the import and its position */
301 ConDes[Type].Import = *Import;
302 }
303
304
305
ConDesSetLabel(unsigned Type,unsigned Name)306 void ConDesSetLabel (unsigned Type, unsigned Name)
307 /* Set the label for the given ConDes type */
308 {
309 /* Check the parameters */
310 PRECONDITION (Type <= CD_TYPE_MAX && Name != 0);
311
312 /* Setting the label twice is bad */
313 CHECK (ConDes[Type].Label == INVALID_STRING_ID);
314
315 /* Set the name */
316 ConDes[Type].Label = Name;
317 }
318
319
320
ConDesSetCountSym(unsigned Type,unsigned Name)321 void ConDesSetCountSym (unsigned Type, unsigned Name)
322 /* Set the name for the given ConDes count symbol */
323 {
324 /* Check the parameters */
325 PRECONDITION (Type <= CD_TYPE_MAX && Name != 0);
326
327 /* Setting the symbol twice is bad */
328 CHECK (ConDes[Type].CountSym == INVALID_STRING_ID);
329
330 /* Set the name */
331 ConDes[Type].CountSym = Name;
332 }
333
334
335
ConDesSetOrder(unsigned Type,ConDesOrder Order)336 void ConDesSetOrder (unsigned Type, ConDesOrder Order)
337 /* Set the sorting oder for the given ConDes table */
338 {
339 /* Check the parameters */
340 PRECONDITION (Type <= CD_TYPE_MAX);
341
342 /* Set the order */
343 ConDes[Type].Order = Order;
344 }
345
346
347
ConDesHasSegName(unsigned Type)348 int ConDesHasSegName (unsigned Type)
349 /* Return true if a segment name is already defined for this ConDes type */
350 {
351 /* Check the parameters */
352 PRECONDITION (Type <= CD_TYPE_MAX);
353
354 return (ConDes[Type].SegName != INVALID_STRING_ID);
355 }
356
357
358
ConDesHasLabel(unsigned Type)359 int ConDesHasLabel (unsigned Type)
360 /* Return true if a label is already defined for this ConDes type */
361 {
362 /* Check the parameters */
363 PRECONDITION (Type <= CD_TYPE_MAX);
364
365 return (ConDes[Type].Label != INVALID_STRING_ID);
366 }
367
368
369
ConDesCreate(void)370 void ConDesCreate (void)
371 /* Create the condes tables if requested */
372 {
373 unsigned Type;
374
375 /* Walk over the descriptor array and create a table for each entry */
376 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
377 ConDesCreateOne (ConDes + Type);
378 }
379 }
380
381
382
ConDesDump(void)383 void ConDesDump (void)
384 /* Dump ConDes data to stdout for debugging */
385 {
386 unsigned Type;
387 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
388 Collection* ExpList = &ConDes[Type].ExpList;
389 printf ("CONDES(%u): %u symbols\n", Type, CollCount (ExpList));
390 }
391 }
392