1 /*****************************************************************************/
5 /* Lightweight segment management stuff */
9 /* (C) 2001 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
56 /*****************************************************************************/
58 /*****************************************************************************/
62 /* Pointer to the current segment list. Output goes here. */
65 /* Pointer to the global segment list */
68 /* Actual names for the segments */
69 static char* SegmentNames[SEG_COUNT];
71 /* We're using a collection for the stack instead of a linked list. Since
72 * functions may not be nested (at least in the current implementation), the
73 * maximum stack depth is 2, so there is not really a need for a better
76 static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
80 /*****************************************************************************/
82 /*****************************************************************************/
86 void InitSegNames (void)
87 /* Initialize the segment names */
89 SegmentNames [SEG_BSS] = xstrdup (SEGNAME_BSS);
90 SegmentNames [SEG_CODE] = xstrdup (SEGNAME_CODE);
91 SegmentNames [SEG_DATA] = xstrdup (SEGNAME_DATA);
92 SegmentNames [SEG_RODATA] = xstrdup (SEGNAME_RODATA);
97 void NewSegName (segment_t Seg, const char* Name)
98 /* Set a new name for a segment */
100 /* Free the old name and set a new one */
101 xfree (SegmentNames [Seg]);
102 SegmentNames [Seg] = xstrdup (Name);
107 static Segments* NewSegments (SymEntry* Func)
108 /* Initialize a Segments structure (set all fields to NULL) */
110 /* Allocate memory */
111 Segments* S = xmalloc (sizeof (Segments));
113 /* Initialize the fields */
114 S->Text = NewTextSeg (Func);
115 S->Code = NewCodeSeg (SegmentNames[SEG_CODE], Func);
116 S->Data = NewDataSeg (SegmentNames[SEG_DATA], Func);
117 S->ROData = NewDataSeg (SegmentNames[SEG_RODATA], Func);
118 S->BSS = NewDataSeg (SegmentNames[SEG_BSS], Func);
119 S->CurDSeg = SEG_DATA;
121 /* Return the new struct */
127 Segments* PushSegments (SymEntry* Func)
128 /* Make the new segment list current but remember the old one */
130 /* Push the current pointer onto the stack */
131 CollAppend (&SegmentStack, CS);
133 /* Create a new Segments structure */
134 CS = NewSegments (Func);
136 /* Return the new struct */
142 void PopSegments (void)
143 /* Pop the old segment list (make it current) */
145 /* Must have something on the stack */
146 PRECONDITION (CollCount (&SegmentStack) > 0);
148 /* Pop the last segment and set it as current */
149 CS = CollPop (&SegmentStack);
154 void UseDataSeg (segment_t DSeg)
155 /* For the current segment list, use the data segment DSeg */
157 /* Check the input */
158 PRECONDITION (CS && DSeg != SEG_CODE);
160 /* Set the new segment to use */
166 struct DataSeg* GetDataSeg (void)
167 /* Return the current data segment */
169 PRECONDITION (CS != 0);
170 switch (CS->CurDSeg) {
171 case SEG_BSS: return CS->BSS;
172 case SEG_DATA: return CS->Data;
173 case SEG_RODATA: return CS->ROData;
175 FAIL ("Invalid data segment");
182 void AddTextLine (const char* Format, ...)
183 /* Add a line of code to the current text segment */
186 va_start (ap, Format);
188 TS_AddVLine (CS->Text, Format, ap);
194 void AddCodeLine (const char* Format, ...)
195 /* Add a line of code to the current code segment */
198 va_start (ap, Format);
200 CS_AddVLine (CS->Code, CurTok.LI, Format, ap);
206 void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo)
207 /* Add a code entry to the current code segment */
210 CS_AddEntry (CS->Code, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI));
215 void AddDataLine (const char* Format, ...)
216 /* Add a line of data to the current data segment */
219 va_start (ap, Format);
221 DS_AddVLine (GetDataSeg(), Format, ap);
227 void OutputSegments (const Segments* S, FILE* F)
228 /* Output the given segments to the file */
230 /* Output the function prologue if the segments came from a function */
231 CS_OutputPrologue (S->Code, F);
233 /* Output the text segment */
234 TS_Output (S->Text, F);
236 /* Output the three data segments */
237 DS_Output (S->Data, F);
238 DS_Output (S->ROData, F);
239 DS_Output (S->BSS, F);
241 /* Output the code segment */
242 CS_Output (S->Code, F);
244 /* Output the code segment epiloque */
245 CS_OutputEpilogue (S->Code, F);