]> git.sur5r.net Git - cc65/blob - src/cc65/segments.c
Fixed _textcolor definition.
[cc65] / src / cc65 / segments.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                segments.c                                 */
4 /*                                                                           */
5 /*                   Lightweight segment management stuff                    */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2001-2009, 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 <stdarg.h>
37 #include <string.h>
38
39 /* common */
40 #include "chartype.h"
41 #include "check.h"
42 #include "coll.h"
43 #include "scanner.h"
44 #include "segnames.h"
45 #include "strstack.h"
46 #include "xmalloc.h"
47
48 /* cc65 */
49 #include "codeent.h"
50 #include "codeseg.h"
51 #include "dataseg.h"
52 #include "error.h"
53 #include "textseg.h"
54 #include "segments.h"
55
56
57
58 /*****************************************************************************/
59 /*                                   Data                                    */
60 /*****************************************************************************/
61
62
63
64 /* Pointer to the current segment list. Output goes here. */
65 Segments* CS = 0;
66
67 /* Pointer to the global segment list */
68 Segments* GS = 0;
69
70 /* Actual names for the segments */
71 static StrStack SegmentNames[SEG_COUNT];
72
73 /* We're using a collection for the stack instead of a linked list. Since
74 ** functions may not be nested (at least in the current implementation), the
75 ** maximum stack depth is 2, so there is not really a need for a better
76 ** implementation.
77 */
78 static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
79
80
81
82 /*****************************************************************************/
83 /*                                   Code                                    */
84 /*****************************************************************************/
85
86
87
88 void InitSegNames (void)
89 /* Initialize the segment names */
90 {
91     SS_Push (&SegmentNames[SEG_BSS], SEGNAME_BSS);
92     SS_Push (&SegmentNames[SEG_CODE], SEGNAME_CODE);
93     SS_Push (&SegmentNames[SEG_DATA], SEGNAME_DATA);
94     SS_Push (&SegmentNames[SEG_RODATA], SEGNAME_RODATA);
95 }
96
97
98
99 void SetSegName (segment_t Seg, const char* Name)
100 /* Set a new name for a segment */
101 {
102     SS_Set (&SegmentNames[Seg], Name);
103 }
104
105
106
107 void PushSegName (segment_t Seg, const char* Name)
108 /* Push the current segment name and set a new name for a segment */
109 {
110     if (SS_IsFull (&SegmentNames[Seg])) {
111         Error ("Segment name stack overflow");
112     } else {
113         SS_Push (&SegmentNames[Seg], Name);
114     }
115 }
116
117
118
119 void PopSegName (segment_t Seg)
120 /* Restore a segment name from the segment name stack */
121 {
122     if (SS_GetCount (&SegmentNames[Seg]) < 2) {
123         Error ("Segment name stack is empty");
124     } else {
125         SS_Drop (&SegmentNames[Seg]);
126     }
127 }
128
129
130
131 const char* GetSegName (segment_t Seg)
132 /* Get the name of the given segment */
133 {
134     return SS_Get (&SegmentNames[Seg]);
135 }
136
137
138
139 static Segments* NewSegments (SymEntry* Func)
140 /* Initialize a Segments structure (set all fields to NULL) */
141 {
142     /* Allocate memory */
143     Segments* S = xmalloc (sizeof (Segments));
144
145     /* Initialize the fields */
146     S->Text     = NewTextSeg (Func);
147     S->Code     = NewCodeSeg (GetSegName (SEG_CODE), Func);
148     S->Data     = NewDataSeg (GetSegName (SEG_DATA), Func);
149     S->ROData   = NewDataSeg (GetSegName (SEG_RODATA), Func);
150     S->BSS      = NewDataSeg (GetSegName (SEG_BSS), Func);
151     S->CurDSeg  = SEG_DATA;
152
153     /* Return the new struct */
154     return S;
155 }
156
157
158
159 Segments* PushSegments (SymEntry* Func)
160 /* Make the new segment list current but remember the old one */
161 {
162     /* Push the current pointer onto the stack */
163     CollAppend (&SegmentStack, CS);
164
165     /* Create a new Segments structure */
166     CS = NewSegments (Func);
167
168     /* Return the new struct */
169     return CS;
170 }
171
172
173
174 void PopSegments (void)
175 /* Pop the old segment list (make it current) */
176 {
177     /* Must have something on the stack */
178     PRECONDITION (CollCount (&SegmentStack) > 0);
179
180     /* Pop the last segment and set it as current */
181     CS = CollPop (&SegmentStack);
182 }
183
184
185
186 void CreateGlobalSegments (void)
187 /* Create the global segments and remember them in GS */
188 {
189     GS = PushSegments (0);
190 }
191
192
193
194 void UseDataSeg (segment_t DSeg)
195 /* For the current segment list, use the data segment DSeg */
196 {
197     /* Check the input */
198     PRECONDITION (CS && DSeg != SEG_CODE);
199
200     /* Set the new segment to use */
201     CS->CurDSeg = DSeg;
202 }
203
204
205
206 struct DataSeg* GetDataSeg (void)
207 /* Return the current data segment */
208 {
209     PRECONDITION (CS != 0);
210     switch (CS->CurDSeg) {
211         case SEG_BSS:     return CS->BSS;
212         case SEG_DATA:    return CS->Data;
213         case SEG_RODATA:  return CS->ROData;
214         default:
215             FAIL ("Invalid data segment");
216             return 0;
217     }
218 }
219
220
221
222 void AddTextLine (const char* Format, ...)
223 /* Add a line of code to the current text segment */
224 {
225     va_list ap;
226     va_start (ap, Format);
227     CHECK (CS != 0);
228     TS_AddVLine (CS->Text, Format, ap);
229     va_end (ap);
230 }
231
232
233
234 void AddCodeLine (const char* Format, ...)
235 /* Add a line of code to the current code segment */
236 {
237     va_list ap;
238     va_start (ap, Format);
239     CHECK (CS != 0);
240     CS_AddVLine (CS->Code, CurTok.LI, Format, ap);
241     va_end (ap);
242 }
243
244
245
246 void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo)
247 /* Add a code entry to the current code segment */
248 {
249     CHECK (CS != 0);
250     CS_AddEntry (CS->Code, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI));
251 }
252
253
254
255 void AddDataLine (const char* Format, ...)
256 /* Add a line of data to the current data segment */
257 {
258     va_list ap;
259     va_start (ap, Format);
260     CHECK (CS != 0);
261     DS_AddVLine (GetDataSeg(), Format, ap);
262     va_end (ap);
263 }
264
265
266
267 int HaveGlobalCode (void)
268 /* Return true if the global code segment contains entries (which is an error) */
269 {
270     return (CS_GetEntryCount (GS->Code) > 0);
271 }
272
273
274
275 void RemoveGlobalCode (void)
276 /* Remove all code from the global code segment. Used for error recovery. */
277 {
278     CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code));
279 }
280
281
282
283 void OutputSegments (const Segments* S)
284 /* Output the given segments to the output file */
285 {
286     /* Output the function prologue if the segments came from a function */
287     CS_OutputPrologue (S->Code);
288
289     /* Output the text segment */
290     TS_Output (S->Text);
291
292     /* Output the three data segments */
293     DS_Output (S->Data);
294     DS_Output (S->ROData);
295     DS_Output (S->BSS);
296
297     /* Output the code segment */
298     CS_Output (S->Code);
299
300     /* Output the code segment epiloque */
301     CS_OutputEpilogue (S->Code);
302 }