]> git.sur5r.net Git - cc65/blob - src/ld65/condes.c
Adjusted C declarations to the changed static driver names.
[cc65] / src / ld65 / condes.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
393
394