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