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 /*****************************************************************************/
54 /*****************************************************************************/
56 /*****************************************************************************/
60 /* Pointer to the current segment list. Output goes here. */
63 /* Actual names for the segments */
64 static char* SegmentNames[SEG_COUNT];
66 /* We're using a collection for the stack instead of a linked list. Since
67 * functions may not be nested (at least in the current implementation), the
68 * maximum stack depth is 2, so there is not really a need for a better
71 static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
75 /*****************************************************************************/
77 /*****************************************************************************/
81 void InitSegNames (void)
82 /* Initialize the segment names */
84 SegmentNames [SEG_BSS] = xstrdup ("BSS");
85 SegmentNames [SEG_CODE] = xstrdup ("CODE");
86 SegmentNames [SEG_DATA] = xstrdup ("DATA");
87 SegmentNames [SEG_RODATA] = xstrdup ("RODATA");
92 void NewSegName (segment_t Seg, const char* Name)
93 /* Set a new name for a segment */
95 /* Free the old name and set a new one */
96 xfree (SegmentNames [Seg]);
97 SegmentNames [Seg] = xstrdup (Name);
102 int ValidSegName (const char* Name)
103 /* Return true if the given segment name is valid, return false otherwise */
105 /* Must start with '_' or a letter */
106 if ((*Name != '_' && !IsAlpha(*Name)) || strlen(Name) > 80) {
110 /* Can have letters, digits or the underline */
112 if (*Name != '_' && !IsAlNum(*Name)) {
123 static Segments* NewSegments (SymEntry* Func)
124 /* Initialize a Segments structure (set all fields to NULL) */
126 /* Allocate memory */
127 Segments* S = xmalloc (sizeof (Segments));
129 /* Initialize the fields */
130 S->Text = NewTextSeg (Func);
131 S->Code = NewCodeSeg (SegmentNames[SEG_CODE], Func);
132 S->Data = NewDataSeg (SegmentNames[SEG_DATA], Func);
133 S->ROData = NewDataSeg (SegmentNames[SEG_RODATA], Func);
134 S->BSS = NewDataSeg (SegmentNames[SEG_BSS], Func);
135 S->CurDSeg = SEG_DATA;
137 /* Return the new struct */
143 Segments* PushSegments (SymEntry* Func)
144 /* Make the new segment list current but remember the old one */
146 /* Push the current pointer onto the stack */
147 CollAppend (&SegmentStack, CS);
149 /* Create a new Segments structure */
150 CS = NewSegments (Func);
152 /* Return the new struct */
158 void PopSegments (void)
159 /* Pop the old segment list (make it current) */
161 /* Must have something on the stack */
162 PRECONDITION (CollCount (&SegmentStack) > 0);
164 /* Pop the last segment and set it as current */
165 CS = CollPop (&SegmentStack);
170 void UseDataSeg (segment_t DSeg)
171 /* For the current segment list, use the data segment DSeg */
173 /* Check the input */
174 PRECONDITION (CS && DSeg != SEG_CODE);
176 /* Set the new segment to use */
182 struct DataSeg* GetDataSeg (void)
183 /* Return the current data segment */
185 PRECONDITION (CS != 0);
186 switch (CS->CurDSeg) {
187 case SEG_BSS: return CS->BSS;
188 case SEG_DATA: return CS->Data;
189 case SEG_RODATA: return CS->ROData;
191 FAIL ("Invalid data segment");
198 void AddTextLine (const char* Format, ...)
199 /* Add a line of code to the current text segment */
202 va_start (ap, Format);
204 AddTextEntry (CS->Text, Format, ap);
210 void AddCodeLine (const char* Format, ...)
211 /* Add a line of code to the current code segment */
214 va_start (ap, Format);
216 AddCodeEntry (CS->Code, CurTok.LI, Format, ap);
222 void AddDataLine (const char* Format, ...)
223 /* Add a line of data to the current data segment */
226 va_start (ap, Format);
228 AddDataEntry (GetDataSeg(), Format, ap);
234 static void PrintFunctionHeader (const SymEntry* Entry, FILE* F)
236 /* Print a comment with the function signature */
238 "; ---------------------------------------------------------------\n"
240 PrintFuncSig (F, Entry->Name, Entry->Type);
243 "; ---------------------------------------------------------------\n"
249 void OutputSegments (const Segments* S, FILE* F)
250 /* Output the given segments to the file */
252 /* If the code segment is associated with a function, print a function header */
254 PrintFunctionHeader (S->Code->Func, F);
257 /* Output the text segment */
258 OutputTextSeg (S->Text, F);
260 /* Output the three data segments */
261 OutputDataSeg (S->Data, F);
262 OutputDataSeg (S->ROData, F);
263 OutputDataSeg (S->BSS, F);
265 /* Output the code segment */
266 OutputCodeSeg (S->Code, F);