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