]> git.sur5r.net Git - cc65/blob - src/cc65/segments.c
2c6f3e3cd704e77387b3f5209e562195c98bb2fa
[cc65] / src / cc65 / segments.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                segments.c                                 */
4 /*                                                                           */
5 /*                   Lightweight segment management stuff                    */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2001      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
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 <stdarg.h>
37 #include <string.h>
38
39 /* common */
40 #include "chartype.h"
41 #include "check.h"
42 #include "coll.h"
43 #include "xmalloc.h"
44
45 /* cc65 */
46 #include "codeseg.h"
47 #include "dataseg.h"
48 #include "textseg.h"
49 #include "segments.h"
50
51
52
53 /*****************************************************************************/
54 /*                                   Data                                    */
55 /*****************************************************************************/
56
57
58
59 /* Pointer to the current segment list. Output goes here. */
60 Segments* CS = 0;
61
62 /* Actual names for the segments */
63 static char* SegmentNames[SEG_COUNT];
64
65 /* We're using a collection for the stack instead of a linked list. Since
66  * functions may not be nested (at least in the current implementation), the
67  * maximum stack depth is 2, so there is not really a need for a better
68  * implementation.
69  */
70 static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
71
72
73
74 /*****************************************************************************/
75 /*                                   Code                                    */
76 /*****************************************************************************/
77
78
79
80 void InitSegNames (void)
81 /* Initialize the segment names */
82 {
83     SegmentNames [SEG_BSS]      = xstrdup ("BSS");
84     SegmentNames [SEG_CODE]     = xstrdup ("CODE");
85     SegmentNames [SEG_DATA]     = xstrdup ("DATA");
86     SegmentNames [SEG_RODATA]   = xstrdup ("RODATA");
87 }
88
89
90
91 void NewSegName (segment_t Seg, const char* Name)
92 /* Set a new name for a segment */
93 {
94     /* Free the old name and set a new one */
95     xfree (SegmentNames [Seg]);
96     SegmentNames [Seg] = xstrdup (Name);
97 }
98
99
100
101 int ValidSegName (const char* Name)
102 /* Return true if the given segment name is valid, return false otherwise */
103 {
104     /* Must start with '_' or a letter */
105     if ((*Name != '_' && !IsAlpha(*Name)) || strlen(Name) > 80) {
106         return 0;
107     }
108
109     /* Can have letters, digits or the underline */
110     while (*++Name) {
111         if (*Name != '_' && !IsAlNum(*Name)) {
112             return 0;
113         }
114     }
115
116     /* Name is ok */
117     return 1;
118 }
119
120
121
122 static Segments* NewSegments (SymEntry* Func)
123 /* Initialize a Segments structure (set all fields to NULL) */
124 {
125     /* Allocate memory */
126     Segments* S = xmalloc (sizeof (Segments));
127
128     /* Initialize the fields */
129     S->Text     = NewTextSeg (Func);
130     S->Code     = NewCodeSeg (SegmentNames[SEG_CODE], Func);
131     S->Data     = NewDataSeg (SegmentNames[SEG_DATA], Func);
132     S->ROData   = NewDataSeg (SegmentNames[SEG_RODATA], Func);
133     S->BSS      = NewDataSeg (SegmentNames[SEG_BSS], Func);
134     S->CurDSeg  = SEG_DATA;
135
136     /* Return the new struct */
137     return S;
138 }
139
140
141
142 Segments* PushSegments (SymEntry* Func)
143 /* Make the new segment list current but remember the old one */
144 {
145     /* Push the current pointer onto the stack */
146     CollAppend (&SegmentStack, CS);
147
148     /* Create a new Segments structure */
149     CS = NewSegments (Func);
150
151     /* Return the new struct */
152     return CS;
153 }
154
155
156
157 void PopSegments (void)
158 /* Pop the old segment list (make it current) */
159 {
160     /* Must have something on the stack */
161     PRECONDITION (CollCount (&SegmentStack) > 0);
162
163     /* Pop the last segment and set it as current */
164     CS = CollPop (&SegmentStack);
165 }
166
167
168
169 void UseDataSeg (segment_t DSeg)
170 /* For the current segment list, use the data segment DSeg */
171 {
172     /* Check the input */
173     PRECONDITION (CS && DSeg != SEG_CODE);
174
175     /* Set the new segment to use */
176     CS->CurDSeg = DSeg;
177 }
178
179
180
181 struct DataSeg* GetDataSeg (void)
182 /* Return the current data segment */
183 {
184     PRECONDITION (CS != 0);
185     switch (CS->CurDSeg) {
186         case SEG_BSS:     return CS->BSS;
187         case SEG_DATA:    return CS->Data;
188         case SEG_RODATA:  return CS->ROData;
189         default:          FAIL ("Invalid data segment");
190     }
191 }
192
193
194
195 void AddTextLine (const char* Format, ...)
196 /* Add a line of code to the current text segment */
197 {
198     va_list ap;
199     va_start (ap, Format);
200     CHECK (CS != 0);
201     AddTextEntry (CS->Text, Format, ap);
202     va_end (ap);
203 }
204
205
206
207 void AddCodeLine (const char* Format, ...)
208 /* Add a line of code to the current code segment */
209 {
210     va_list ap;
211     va_start (ap, Format);
212     CHECK (CS != 0);
213     AddCodeEntry (CS->Code, Format, ap);
214     va_end (ap);
215 }
216
217
218
219 void AddDataLine (const char* Format, ...)
220 /* Add a line of data to the current data segment */
221 {
222     va_list ap;
223     va_start (ap, Format);
224     CHECK (CS != 0);
225     AddDataEntry (GetDataSeg(), Format, ap);
226     va_end (ap);
227 }
228
229
230
231 static void PrintFunctionHeader (const SymEntry* Entry, FILE* F)
232 {
233     /* Print a comment with the function signature */
234     fprintf (F,
235              "; ---------------------------------------------------------------\n"
236              "; ");
237     PrintFuncSig (F, Entry->Name, Entry->Type);
238     fprintf (F,
239              "\n"
240              "; ---------------------------------------------------------------\n"
241              "\n");
242 }
243
244
245
246 void OutputSegments (const Segments* S, FILE* F)
247 /* Output the given segments to the file */
248 {
249     /* If the code segment is associated with a function, print a function header */
250     if (S->Code->Func) {
251         PrintFunctionHeader (S->Code->Func, F);
252     }
253
254     /* Output the text segment */
255     OutputTextSeg (S->Text, F);
256
257     /* Output the three data segments */
258     OutputDataSeg (S->Data, F);
259     OutputDataSeg (S->ROData, F);
260     OutputDataSeg (S->BSS, F);
261
262     /* Output the code segment */
263     OutputCodeSeg (S->Code, F);
264 }
265
266
267