#include "chartype.h"
#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"
/* 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
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]);
}
/* 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 */
case SEG_BSS: return CS->BSS;
case SEG_DATA: return CS->Data;
case SEG_RODATA: return CS->ROData;
- default: FAIL ("Invalid data segment");
+ default:
+ FAIL ("Invalid data segment");
+ return 0;
}
}
va_list ap;
va_start (ap, Format);
CHECK (CS != 0);
- AddTextEntry (CS->Text, Format, ap);
+ TS_AddVLine (CS->Text, Format, ap);
va_end (ap);
}
va_list ap;
va_start (ap, Format);
CHECK (CS != 0);
- AddCodeEntry (CS->Code, Format, ap);
+ CS_AddVLine (CS->Code, CurTok.LI, Format, ap);
va_end (ap);
}
+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, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI));
+}
+
+
+
void AddDataLine (const char* Format, ...)
/* Add a line of data to the current data segment */
{
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 RemoveGlobalCode (void)
+/* Remove all code from the global code segment. Used for error recovery. */
+{
+ CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code));
}
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 */
- OutputTextSeg (S->Text, F);
+ TS_Output (S->Text, F);
/* Output the three data segments */
- OutputDataSeg (S->Data, F);
- OutputDataSeg (S->ROData, F);
- OutputDataSeg (S->BSS, F);
+ DS_Output (S->Data, F);
+ DS_Output (S->ROData, F);
+ DS_Output (S->BSS, F);
/* Output the code segment */
- OutputCodeSeg (S->Code, F);
+ CS_Output (S->Code, F);
+
+ /* Output the code segment epiloque */
+ CS_OutputEpilogue (S->Code, F);
}