From 40dc3582a9a50be2be845090b2580d3b837450cc Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 8 Mar 2004 22:33:27 +0000 Subject: [PATCH] Allow push/pop arguments for segment name #pragmas git-svn-id: svn://svn.cc65.org/cc65/trunk@2907 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codegen.c | 12 +++----- src/cc65/codegen.h | 6 ++-- src/cc65/main.c | 8 +++--- src/cc65/pragma.c | 67 +++++++++++++++++++++++++++++++++++---------- src/cc65/segments.c | 58 ++++++++++++++++++++++++++++++--------- src/cc65/segments.h | 11 +++++++- 6 files changed, 118 insertions(+), 44 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index f6c5a69d4..060d3a9d4 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -237,15 +237,11 @@ void g_usebss (void) -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; @@ -253,7 +249,7 @@ void g_segname (segment_t Seg, const char* Name) default: S = 0; break; } if (S) { - DS_AddLine (S, ".segment\t\"%s\"", Name); + DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg)); } } diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 258bb6b2d..72feb2eac 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ +/* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -122,8 +122,8 @@ void g_usedata (void); 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 */ diff --git a/src/cc65/main.c b/src/cc65/main.c index 80ceaf7eb..85dc615c9 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -340,7 +340,7 @@ static void OptBssName (const char* Opt attribute ((unused)), const char* Arg) CheckSegName (Arg); /* Set the name */ - NewSegName (SEG_BSS, Arg); + SetSegName (SEG_BSS, Arg); } @@ -361,7 +361,7 @@ static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg) CheckSegName (Arg); /* Set the name */ - NewSegName (SEG_CODE, Arg); + SetSegName (SEG_CODE, Arg); } @@ -408,7 +408,7 @@ static void OptDataName (const char* Opt attribute ((unused)), const char* Arg) CheckSegName (Arg); /* Set the name */ - NewSegName (SEG_DATA, Arg); + SetSegName (SEG_DATA, Arg); } @@ -605,7 +605,7 @@ static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg CheckSegName (Arg); /* Set the name */ - NewSegName (SEG_RODATA, Arg); + SetSegName (SEG_RODATA, Arg); } diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index 5ee35a234..2872515cf 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -155,30 +155,67 @@ static void StringPragma (StrBuf* B, void (*Func) (const char*)) 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 { - Error ("String literal expected"); + } 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); } @@ -237,7 +274,7 @@ static void FlagPragma (StrBuf* B, IntStack* Stack) if (IS_GetCount (Stack) < 2) { Error ("Cannot pop, stack is empty"); } else { - IS_Drop (Stack); + IS_Drop (Stack); } /* No other arguments allowed */ return; diff --git a/src/cc65/segments.c b/src/cc65/segments.c index dabb4a4a6..57f1a8047 100644 --- a/src/cc65/segments.c +++ b/src/cc65/segments.c @@ -42,12 +42,14 @@ #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" @@ -66,7 +68,7 @@ Segments* CS = 0; 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 @@ -86,20 +88,50 @@ static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER; 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]); } @@ -112,10 +144,10 @@ static Segments* NewSegments (SymEntry* Func) /* 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 */ diff --git a/src/cc65/segments.h b/src/cc65/segments.h index 81496ed1f..6d6ad2fac 100644 --- a/src/cc65/segments.h +++ b/src/cc65/segments.h @@ -105,9 +105,18 @@ extern Segments* GS; 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 */