]> git.sur5r.net Git - cc65/blobdiff - src/cc65/segments.c
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / src / cc65 / segments.c
index 3dad3ab892838e92abd8731294a2ba984d3fc904..cdbd05e39b7a804290ba7b4a66a3108766c47f30 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                               segments.c                                 */
+/*                                segments.c                                 */
 /*                                                                           */
-/*                  Lightweight segment management stuff                    */
+/*                   Lightweight segment management stuff                    */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2001      Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2001-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 #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"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 /* Pointer to the current segment list. Output goes here. */
 Segments* CS = 0;
 
+/* Pointer to the global segment list */
+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
@@ -73,7 +80,7 @@ static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -81,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]);
 }
 
 
@@ -127,12 +143,12 @@ static Segments* NewSegments (SymEntry* Func)
     Segments* S = xmalloc (sizeof (Segments));
 
     /* 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->CurDSeg         = SEG_DATA;
+    S->Text     = NewTextSeg (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 */
     return S;
@@ -167,6 +183,14 @@ void PopSegments (void)
 
 
 
+void CreateGlobalSegments (void)
+/* Create the global segments and remember them in GS */
+{
+    GS = PushSegments (0);
+}
+
+
+
 void UseDataSeg (segment_t DSeg)
 /* For the current segment list, use the data segment DSeg */
 {
@@ -184,12 +208,12 @@ struct DataSeg* GetDataSeg (void)
 {
     PRECONDITION (CS != 0);
     switch (CS->CurDSeg) {
-       case SEG_BSS:     return CS->BSS;
-       case SEG_DATA:    return CS->Data;
-       case SEG_RODATA:  return CS->ROData;
-       default:
-           FAIL ("Invalid data segment");
-           return 0;
+        case SEG_BSS:     return CS->BSS;
+        case SEG_DATA:    return CS->Data;
+        case SEG_RODATA:  return CS->ROData;
+        default:
+            FAIL ("Invalid data segment");
+            return 0;
     }
 }
 
@@ -201,7 +225,7 @@ void AddTextLine (const char* Format, ...)
     va_list ap;
     va_start (ap, Format);
     CHECK (CS != 0);
-    AddTextEntry (CS->Text, Format, ap);
+    TS_AddVLine (CS->Text, Format, ap);
     va_end (ap);
 }
 
@@ -213,17 +237,17 @@ void AddCodeLine (const char* Format, ...)
     va_list ap;
     va_start (ap, Format);
     CHECK (CS != 0);
-    CS_AddEntryLine (CS->Code, CurTok.LI, Format, ap);
+    CS_AddVLine (CS->Code, CurTok.LI, Format, ap);
     va_end (ap);
 }
 
 
 
-void AddCode (struct CodeEntry* E)
+void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo)
 /* Add a code entry to the current code segment */
 {
     CHECK (CS != 0);
-    CS_AddEntry (CS->Code, E, CurTok.LI);
+    CS_AddEntry (CS->Code, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI));
 }
 
 
@@ -234,45 +258,47 @@ void AddDataLine (const char* Format, ...)
     va_list ap;
     va_start (ap, Format);
     CHECK (CS != 0);
-    AddDataEntry (GetDataSeg(), Format, ap);
+    DS_AddVLine (GetDataSeg(), Format, ap);
     va_end (ap);
 }
 
 
 
-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 OutputSegments (const Segments* S, FILE* F)
-/* Output the given segments to the file */
+void RemoveGlobalCode (void)
+/* Remove all code from the global code segment. Used for error recovery. */
 {
-    /* If the code segment is associated with a function, print a function header */
-    if (S->Code->Func) {
-               PrintFunctionHeader (S->Code->Func, F);
-    }
+    CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code));
+}
+
+
+
+void OutputSegments (const Segments* S)
+/* Output the given segments to the output file */
+{
+    /* Output the function prologue if the segments came from a function */
+    CS_OutputPrologue (S->Code);
 
     /* Output the text segment */
-    OutputTextSeg (S->Text, F);
+    TS_Output (S->Text);
 
     /* Output the three data segments */
-    OutputDataSeg (S->Data, F);
-    OutputDataSeg (S->ROData, F);
-    OutputDataSeg (S->BSS, F);
+    DS_Output (S->Data);
+    DS_Output (S->ROData);
+    DS_Output (S->BSS);
 
     /* Output the code segment */
-    CS_Output (S->Code, F);
+    CS_Output (S->Code);
+
+    /* Output the code segment epiloque */
+    CS_OutputEpilogue (S->Code);
 }