X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fsegments.c;h=57f1a80479f7f39243f1a43c8821d461a2515381;hb=3f4096d3030095605f28b4cfa73563c53a563df6;hp=b4f5ee88ba689c9244b0dbbc521b2e0627dd71e9;hpb=b3af17126c3ac6178e45b090555bed5f34507eaf;p=cc65 diff --git a/src/cc65/segments.c b/src/cc65/segments.c index b4f5ee88b..57f1a8047 100644 --- a/src/cc65/segments.c +++ b/src/cc65/segments.c @@ -41,12 +41,15 @@ #include "check.h" #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" @@ -65,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 @@ -85,41 +88,50 @@ static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER; void InitSegNames (void) /* Initialize the segment names */ { - SegmentNames [SEG_BSS] = xstrdup ("BSS"); - SegmentNames [SEG_CODE] = xstrdup ("CODE"); - SegmentNames [SEG_DATA] = xstrdup ("DATA"); - SegmentNames [SEG_RODATA] = xstrdup ("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); } -int ValidSegName (const char* Name) -/* Return true if the given segment name is valid, return false otherwise */ +void PushSegName (segment_t Seg, const char* Name) +/* Push the current segment name and set a new name for a segment */ { - /* Must start with '_' or a letter */ - if ((*Name != '_' && !IsAlpha(*Name)) || strlen(Name) > 80) { - return 0; + if (SS_IsFull (&SegmentNames[Seg])) { + Error ("Segment name stack overflow"); + } else { + SS_Push (&SegmentNames[Seg], Name); } +} + - /* Can have letters, digits or the underline */ - while (*++Name) { - if (*Name != '_' && !IsAlNum(*Name)) { - return 0; - } + +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]); } +} + - /* Name is ok */ - return 1; + +const char* GetSegName (segment_t Seg) +/* Get the name of the given segment */ +{ + return SS_Get (&SegmentNames[Seg]); } @@ -132,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 */ @@ -244,17 +256,18 @@ void AddDataLine (const char* Format, ...) -static void PrintFunctionHeader (const SymEntry* Entry, FILE* F) +int HaveGlobalCode (void) +/* Return true if the global code segment contains entries (which is an error) */ { - /* Print a comment with the function signature */ - fprintf (F, - "; ---------------------------------------------------------------\n" - "; "); - PrintFuncSig (F, Entry->Name, Entry->Type); - fprintf (F, - "\n" - "; ---------------------------------------------------------------\n" - "\n"); + return (CS_GetEntryCount (GS->Code) > 0); +} + + + +void RemoveGlobalCode (void) +/* Remove all code from the global code segment. Used for error recovery. */ +{ + CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code)); } @@ -262,10 +275,8 @@ static void PrintFunctionHeader (const SymEntry* Entry, FILE* F) void OutputSegments (const Segments* S, FILE* F) /* Output the given segments to the file */ { - /* If the code segment is associated with a function, print a function header */ - if (S->Code->Func) { - PrintFunctionHeader (S->Code->Func, F); - } + /* Output the function prologue if the segments came from a function */ + CS_OutputPrologue (S->Code, F); /* Output the text segment */ TS_Output (S->Text, F); @@ -277,6 +288,9 @@ void OutputSegments (const Segments* S, FILE* F) /* Output the code segment */ CS_Output (S->Code, F); + + /* Output the code segment epiloque */ + CS_OutputEpilogue (S->Code, F); }