]> git.sur5r.net Git - cc65/blob - src/cc65/segments.c
dd7817b8887149d68ead2401edad3c0b0c411653
[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 "scanner.h"
44 #include "segnames.h"
45 #include "xmalloc.h"
46
47 /* cc65 */
48 #include "codeent.h"
49 #include "codeseg.h"
50 #include "dataseg.h"
51 #include "textseg.h"
52 #include "segments.h"
53
54
55
56 /*****************************************************************************/
57 /*                                   Data                                    */
58 /*****************************************************************************/
59
60
61
62 /* Pointer to the current segment list. Output goes here. */
63 Segments* CS = 0;
64
65 /* Pointer to the global segment list */
66 Segments* GS = 0;
67
68 /* Actual names for the segments */
69 static char* SegmentNames[SEG_COUNT];
70
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
74  * implementation.
75  */
76 static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
77
78
79
80 /*****************************************************************************/
81 /*                                   Code                                    */
82 /*****************************************************************************/
83
84
85
86 void InitSegNames (void)
87 /* Initialize the segment names */
88 {
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);
93 }
94
95
96
97 void NewSegName (segment_t Seg, const char* Name)
98 /* Set a new name for a segment */
99 {
100     /* Free the old name and set a new one */
101     xfree (SegmentNames [Seg]);
102     SegmentNames [Seg] = xstrdup (Name);
103 }
104
105
106
107 static Segments* NewSegments (SymEntry* Func)
108 /* Initialize a Segments structure (set all fields to NULL) */
109 {
110     /* Allocate memory */
111     Segments* S = xmalloc (sizeof (Segments));
112
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;
120
121     /* Return the new struct */
122     return S;
123 }
124
125
126
127 Segments* PushSegments (SymEntry* Func)
128 /* Make the new segment list current but remember the old one */
129 {
130     /* Push the current pointer onto the stack */
131     CollAppend (&SegmentStack, CS);
132
133     /* Create a new Segments structure */
134     CS = NewSegments (Func);
135
136     /* Return the new struct */
137     return CS;
138 }
139
140
141
142 void PopSegments (void)
143 /* Pop the old segment list (make it current) */
144 {
145     /* Must have something on the stack */
146     PRECONDITION (CollCount (&SegmentStack) > 0);
147
148     /* Pop the last segment and set it as current */
149     CS = CollPop (&SegmentStack);
150 }
151
152
153
154 void UseDataSeg (segment_t DSeg)
155 /* For the current segment list, use the data segment DSeg */
156 {
157     /* Check the input */
158     PRECONDITION (CS && DSeg != SEG_CODE);
159
160     /* Set the new segment to use */
161     CS->CurDSeg = DSeg;
162 }
163
164
165
166 struct DataSeg* GetDataSeg (void)
167 /* Return the current data segment */
168 {
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;
174         default:
175             FAIL ("Invalid data segment");
176             return 0;
177     }
178 }
179
180
181
182 void AddTextLine (const char* Format, ...)
183 /* Add a line of code to the current text segment */
184 {
185     va_list ap;
186     va_start (ap, Format);
187     CHECK (CS != 0);
188     TS_AddVLine (CS->Text, Format, ap);
189     va_end (ap);
190 }
191
192
193
194 void AddCodeLine (const char* Format, ...)
195 /* Add a line of code to the current code segment */
196 {
197     va_list ap;
198     va_start (ap, Format);
199     CHECK (CS != 0);
200     CS_AddVLine (CS->Code, CurTok.LI, Format, ap);
201     va_end (ap);
202 }
203
204
205
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 */
208 {
209     CHECK (CS != 0);
210     CS_AddEntry (CS->Code, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI));
211 }
212
213
214
215 void AddDataLine (const char* Format, ...)
216 /* Add a line of data to the current data segment */
217 {
218     va_list ap;
219     va_start (ap, Format);
220     CHECK (CS != 0);
221     DS_AddVLine (GetDataSeg(), Format, ap);
222     va_end (ap);
223 }
224
225
226
227 void OutputSegments (const Segments* S, FILE* F)
228 /* Output the given segments to the file */
229 {
230     /* Output the function prologue if the segments came from a function */
231     CS_OutputPrologue (S->Code, F);
232
233     /* Output the text segment */
234     TS_Output (S->Text, F);
235
236     /* Output the three data segments */
237     DS_Output (S->Data, F);
238     DS_Output (S->ROData, F);
239     DS_Output (S->BSS, F);
240
241     /* Output the code segment */
242     CS_Output (S->Code, F);
243
244     /* Output the code segment epiloque */
245     CS_OutputEpilogue (S->Code, F);
246 }
247
248
249