-void g_segname (segment_t Seg, const char* Name)
-/* Set the name of a segment */
+void g_segname (segment_t Seg)
+/* Emit the name of a segment if necessary */
{
- DataSeg* S;
-
- /* Remember the new name */
- NewSegName (Seg, Name);
-
/* Emit a segment directive for the data style segments */
+ DataSeg* S;
switch (Seg) {
case SEG_RODATA: S = CS->ROData; break;
case SEG_DATA: S = CS->Data; break;
default: S = 0; break;
}
if (S) {
- DS_AddLine (S, ".segment\t\"%s\"", Name);
+ DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg));
}
}
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
+/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
void g_usebss (void);
/* Switch to the bss segment */
-void g_segname (segment_t Seg, const char* Name);
-/* Set the name of a segment */
+void g_segname (segment_t Seg);
+/* Emit the name of a segment if necessary */
CheckSegName (Arg);
/* Set the name */
- NewSegName (SEG_BSS, Arg);
+ SetSegName (SEG_BSS, Arg);
}
CheckSegName (Arg);
/* Set the name */
- NewSegName (SEG_CODE, Arg);
+ SetSegName (SEG_CODE, Arg);
}
CheckSegName (Arg);
/* Set the name */
- NewSegName (SEG_DATA, Arg);
+ SetSegName (SEG_DATA, Arg);
}
CheckSegName (Arg);
/* Set the name */
- NewSegName (SEG_RODATA, Arg);
+ SetSegName (SEG_RODATA, Arg);
}
static void SegNamePragma (StrBuf* B, segment_t Seg)
/* Handle a pragma that expects a segment name parameter */
{
- StrBuf S;
+ ident Ident;
+ StrBuf S;
+ const char* Name;
- if (SB_GetString (B, &S)) {
+ /* Try to read an identifier */
+ int Push = 0;
+ if (SB_GetSym (B, Ident)) {
- /* Get the string */
- const char* Name = SB_GetConstBuf (&S);
+ /* Check if we have a first argument named "pop" */
+ if (strcmp (Ident, "pop") == 0) {
- /* Check if the name is valid */
- if (ValidSegName (Name)) {
+ /* Pop the old value */
+ PopSegName (Seg);
- /* Set the new name */
- g_segname (Seg, Name);
+ /* Set the segment name */
+ g_segname (Seg);
- } else {
+ /* Done */
+ return;
- /* Segment name is invalid */
- Error ("Illegal segment name: `%s'", Name);
+ /* Check if we have a first argument named "push" */
+ } else if (strcmp (Ident, "push") == 0) {
- }
+ Push = 1;
+ SB_SkipWhite (B);
+ if (SB_Get (B) != ',') {
+ Error ("Comma expected");
+ return;
+ }
+ SB_SkipWhite (B);
- } else {
+ } else {
+ Error ("Invalid pragma arguments");
+ return;
+ }
+ }
+
+ /* A string argument must follow */
+ if (!SB_GetString (B, &S)) {
Error ("String literal expected");
+ return;
+ }
+
+ /* Get the string */
+ Name = SB_GetConstBuf (&S);
+
+ /* Check if the name is valid */
+ if (!ValidSegName (Name)) {
+ /* Segment name is invalid */
+ Error ("Illegal segment name: `%s'", Name);
+ return;
+ }
+
+ /* Set the new name */
+ if (Push) {
+ PushSegName (Seg, Name);
+ } else {
+ SetSegName (Seg, Name);
}
+ g_segname (Seg);
/* Call the string buf destructor */
DoneStrBuf (&S);
if (IS_GetCount (Stack) < 2) {
Error ("Cannot pop, stack is empty");
} else {
- IS_Drop (Stack);
+ IS_Drop (Stack);
}
/* No other arguments allowed */
return;
#include "coll.h"
#include "scanner.h"
#include "segnames.h"
+#include "strstack.h"
#include "xmalloc.h"
/* cc65 */
#include "codeent.h"
#include "codeseg.h"
#include "dataseg.h"
+#include "error.h"
#include "textseg.h"
#include "segments.h"
Segments* GS = 0;
/* Actual names for the segments */
-static char* SegmentNames[SEG_COUNT];
+static StrStack SegmentNames[SEG_COUNT];
/* We're using a collection for the stack instead of a linked list. Since
* functions may not be nested (at least in the current implementation), the
void InitSegNames (void)
/* Initialize the segment names */
{
- SegmentNames [SEG_BSS] = xstrdup (SEGNAME_BSS);
- SegmentNames [SEG_CODE] = xstrdup (SEGNAME_CODE);
- SegmentNames [SEG_DATA] = xstrdup (SEGNAME_DATA);
- SegmentNames [SEG_RODATA] = xstrdup (SEGNAME_RODATA);
+ SS_Push (&SegmentNames[SEG_BSS], SEGNAME_BSS);
+ SS_Push (&SegmentNames[SEG_CODE], SEGNAME_CODE);
+ SS_Push (&SegmentNames[SEG_DATA], SEGNAME_DATA);
+ SS_Push (&SegmentNames[SEG_RODATA], SEGNAME_RODATA);
}
-void NewSegName (segment_t Seg, const char* Name)
+void SetSegName (segment_t Seg, const char* Name)
/* Set a new name for a segment */
{
- /* Free the old name and set a new one */
- xfree (SegmentNames [Seg]);
- SegmentNames [Seg] = xstrdup (Name);
+ SS_Set (&SegmentNames[Seg], Name);
+}
+
+
+
+void PushSegName (segment_t Seg, const char* Name)
+/* Push the current segment name and set a new name for a segment */
+{
+ if (SS_IsFull (&SegmentNames[Seg])) {
+ Error ("Segment name stack overflow");
+ } else {
+ SS_Push (&SegmentNames[Seg], Name);
+ }
+}
+
+
+
+void PopSegName (segment_t Seg)
+/* Restore a segment name from the segment name stack */
+{
+ if (SS_GetCount (&SegmentNames[Seg]) < 2) {
+ Error ("Segment name stack is empty");
+ } else {
+ SS_Drop (&SegmentNames[Seg]);
+ }
+}
+
+
+
+const char* GetSegName (segment_t Seg)
+/* Get the name of the given segment */
+{
+ return SS_Get (&SegmentNames[Seg]);
}
/* Initialize the fields */
S->Text = NewTextSeg (Func);
- S->Code = NewCodeSeg (SegmentNames[SEG_CODE], Func);
- S->Data = NewDataSeg (SegmentNames[SEG_DATA], Func);
- S->ROData = NewDataSeg (SegmentNames[SEG_RODATA], Func);
- S->BSS = NewDataSeg (SegmentNames[SEG_BSS], Func);
+ S->Code = NewCodeSeg (GetSegName (SEG_CODE), Func);
+ S->Data = NewDataSeg (GetSegName (SEG_DATA), Func);
+ S->ROData = NewDataSeg (GetSegName (SEG_RODATA), Func);
+ S->BSS = NewDataSeg (GetSegName (SEG_BSS), Func);
S->CurDSeg = SEG_DATA;
/* Return the new struct */
void InitSegNames (void);
/* Initialize the segment names */
-void NewSegName (segment_t Seg, const char* Name);
+void SetSegName (segment_t Seg, const char* Name);
/* Set a new name for a segment */
+void PushSegName (segment_t Seg, const char* Name);
+/* Push the current segment name and set a new name for a segment */
+
+void PopSegName (segment_t Seg);
+/* Restore a segment name from the segment name stack */
+
+const char* GetSegName (segment_t Seg);
+/* Get the name of the given segment */
+
Segments* PushSegments (struct SymEntry* Func);
/* Make the new segment list current but remember the old one */