/* Warning level */
-unsigned WarnLevel = 1;
+unsigned WarnLevel = 1;
/* Statistics */
unsigned ErrorCount = 0;
unsigned char Level;
const char* Msg;
} Warnings [WARN_COUNT-1] = {
- { 2, "Symbol `%s' is defined but never used" },
- { 2, "Symbol `%s' is imported but never used" },
- { 1, "Cannot track processor status byte" },
- { 1, "Suspicious address expression" },
- { 0, "User warning: %s" },
+ { 2, "Symbol `%s' is defined but never used" },
+ { 2, "Symbol `%s' is imported but never used" },
+ { 1, "Cannot track processor status byte" },
+ { 1, "Suspicious address expression" },
+ { 0, "Unnamed .PROCs are deprecated, please use .SCOPE" },
+ { 1, "Address size mismatch for symbol `%s'" },
+ { 0, "User warning: %s" },
};
if (Warnings [WarnNum-1].Level <= WarnLevel) {
"`.ENDMACRO' expected",
"Option key expected",
"`=' expected",
+ "Address size specifier expected",
"Command is only valid in 65816 mode",
"User error: %s",
"String constant too long",
"Illegal character to start local symbols",
"Illegal use of local symbol",
"Illegal segment name: `%s'",
- "Illegal segment attribute",
"Illegal macro package name",
"Illegal emulation feature",
"Illegal scope specifier",
"Macro parameter expected",
"Circular reference in symbol definition",
"Symbol `%s' redeclaration mismatch",
+ "Address size mismatch for symbol `%s'",
"Alignment value must be a power of 2",
"Duplicate `.ELSE'",
"Conditional assembly branch was never closed",
WARN_IMPORT_NOT_REFERENCED,
WARN_CANNOT_TRACK_STATUS,
WARN_SUSPICIOUS_ADDREXPR,
+ WARN_UNNAMED_PROC,
+ WARN_ADDR_SIZE_MISMATCH,
WARN_USER,
WARN_COUNT /* Warning count */
};
/* Error numbers */
enum Errors {
ERR_NONE, /* No error */
- ERR_NOT_IMPLEMENTED, /* Command/operation not implemented */
+ ERR_NOT_IMPLEMENTED, /* Command/operation not implemented */
ERR_CANNOT_OPEN_INCLUDE,
ERR_CANNOT_READ_INCLUDE,
ERR_INCLUDE_NESTING,
ERR_ENDMACRO_EXPECTED,
ERR_OPTION_KEY_EXPECTED,
ERR_EQ_EXPECTED,
+ ERR_ADDR_SIZE_EXPECTED,
ERR_816_MODE_ONLY,
ERR_USER,
ERR_STRING_TOO_LONG,
ERR_ILLEGAL_ADDR_MODE,
ERR_ILLEGAL_LOCALSTART,
ERR_ILLEGAL_LOCAL_USE,
- ERR_ILLEGAL_SEGMENT,
- ERR_ILLEGAL_SEG_ATTR,
+ ERR_ILLEGAL_SEGMENT,
ERR_ILLEGAL_MACPACK,
ERR_ILLEGAL_FEATURE,
ERR_ILLEGAL_SCOPE,
ERR_MACRO_PARAM_EXPECTED,
ERR_CIRCULAR_REFERENCE,
ERR_SYM_REDECL_MISMATCH,
+ ERR_ADDR_SIZE_MISMATCH,
ERR_ALIGN,
ERR_DUPLICATE_ELSE,
ERR_OPEN_IF,
FAT_NESTING,
FAT_IF_NESTING,
FAT_TOO_MANY_SYMBOLS,
- FAT_COUNT /* Fatal error count */
+ FAT_COUNT /* Fatal error count */
};
if (RelocMode) {
/* Create SegmentBase + Offset */
Root = NewExprNode (EXPR_PLUS);
- Root->Left = GenSectionExpr (GetSegNum ());
+ Root->Left = GenSectionExpr (GetCurrentSegNum ());
Root->Right = GenLiteralExpr (GetPC ());
} else {
/* Absolute mode, just return PC value */
/* Create *+Offs */
if (RelocMode) {
N = NewExprNode (EXPR_PLUS);
- N->Left = GenSectionExpr (GetSegNum ());
+ N->Left = GenSectionExpr (GetCurrentSegNum ());
N->Right = GenLiteralExpr (GetPC () + Offs);
} else {
N = GenLiteralExpr (GetPC () + Offs);
break;
case EXPR_SECTION:
- if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
+ if (GetSegAddrSize (N->V.SegNum) == ADDR_SIZE_ZP) {
*IsByte = 1;
}
break;
#include <time.h>
/* common */
+#include "addrsize.h"
#include "chartype.h"
#include "cmdline.h"
#include "print.h"
}
/* Mark the symbol as defined */
- SymDef (Sym, GenLiteralExpr (Val), SYM_DEFAULT);
+ SymDef (Sym, GenLiteralExpr (Val), ADDR_SIZE_DEFAULT, SF_NONE);
}
*/
if (Tok == TOK_EQ || Tok == TOK_ASSIGN) {
/* If it's an assign token, we have a label */
- unsigned Flags = (Tok == TOK_ASSIGN)? SYM_LABEL : SYM_DEFAULT;
+ unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE;
/* Skip the '=' */
NextTok ();
/* Define the symbol with the expression following the '=' */
- SymDef (Sym, Expression(), Flags);
+ SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
/* Don't allow anything after a symbol definition */
Done = 1;
} else {
- /* Define the symbol flags */
- unsigned Flags = IsZPSeg ()? SYM_ZP | SYM_LABEL : SYM_LABEL;
/* Define a label */
- SymDef (Sym, GenCurrentPC (), Flags);
+ SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
/* Skip the colon. If NoColonLabels is enabled, allow labels
* without a colon if there is no whitespace before the
* identifier.
/* Enter the base lexical level. We must do that here, since we may
* define symbols using -D.
*/
- SymEnterLevel ("");
+ SymEnterLevel ("", ADDR_SIZE_DEFAULT);
/* Check the parameters */
I = 1;
+static unsigned OptionalAddrSize (void)
+/* If a colon follows, parse an optional address size spec and return it.
+ * Otherwise return ADDR_SIZE_DEFAULT.
+ */
+{
+ unsigned AddrSize = ADDR_SIZE_DEFAULT;
+ if (Tok == TOK_COLON) {
+ NextTok ();
+ AddrSize = ParseAddrSize ();
+ NextTok ();
+ }
+ return AddrSize;
+}
+
+
+
static void SetBoolOption (unsigned char* Flag)
/* Read a on/off/+/- option and set flag accordingly */
{
-static void ExportImport (void (*SymFunc) (const char*))
+static void ExportImport (void (*Func) (SymEntry*, unsigned, unsigned),
+ unsigned DefAddrSize, unsigned Flags)
/* Export or import symbols */
{
+ SymEntry* Sym;
+ unsigned AddrSize;
+
while (1) {
+
+ /* We need an identifier here */
if (Tok != TOK_IDENT) {
ErrorSkip (ERR_IDENT_EXPECTED);
- break;
+ return;
}
- SymFunc (SVal);
- NextTok ();
+
+ /* Find the symbol table entry, allocate a new one if necessary */
+ Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
+
+ /* Skip the name */
+ NextTok ();
+
+ /* Get an optional address size */
+ AddrSize = OptionalAddrSize ();
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ AddrSize = DefAddrSize;
+ }
+
+ /* Call the actual import/export function */
+ Func (Sym, AddrSize, Flags);
+
+ /* More symbols? */
if (Tok == TOK_COMMA) {
NextTok ();
} else {
break;
default:
- Error (ERR_ILLEGAL_SEG_ATTR);
+ Error (ERR_ILLEGAL_ASSERT_ACTION);
}
NextTok ();
ConsumeComma ();
static void DoExport (void)
/* Export a symbol */
{
- ExportImport (SymExport);
+ ExportImport (SymExport, ADDR_SIZE_DEFAULT, SF_NONE);
}
static void DoExportZP (void)
/* Export a zeropage symbol */
{
- ExportImport (SymExportZP);
+ ExportImport (SymExport, ADDR_SIZE_ZP, SF_NONE);
}
static void DoForceImport (void)
/* Do a forced import on a symbol */
{
- ExportImport (SymImportForced);
+ ExportImport (SymImport, ADDR_SIZE_DEFAULT, SF_FORCED);
}
static void DoGlobal (void)
/* Declare a global symbol */
{
- ExportImport (SymGlobal);
+ ExportImport (SymGlobal, ADDR_SIZE_DEFAULT, SF_NONE);
}
static void DoGlobalZP (void)
/* Declare a global zeropage symbol */
{
- ExportImport (SymGlobalZP);
+ ExportImport (SymGlobal, ADDR_SIZE_ZP, SF_NONE);
}
static void DoImport (void)
/* Import a symbol */
{
- ExportImport (SymImport);
+ ExportImport (SymImport, ADDR_SIZE_DEFAULT, SF_NONE);
}
static void DoImportZP (void)
/* Import a zero page symbol */
{
- ExportImport (SymImportZP);
+ ExportImport (SymImport, ADDR_SIZE_ZP, SF_NONE);
}
/* Start a new lexical scope */
{
if (Tok == TOK_IDENT) {
- /* The new scope has a name */
- SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
- unsigned Flags = SYM_LABEL;
- if (IsZPSeg ()) {
- Flags |= SYM_ZP;
- }
- SymDef (Sym, GenCurrentPC (), Flags);
- SymEnterLevel (SVal);
- NextTok ();
+
+ unsigned AddrSize;
+
+ /* The new scope has a name. Remember it. */
+ char Name[sizeof(SVal)];
+ strcpy (Name, SVal);
+
+ /* Search for the symbol, generate a new one if needed */
+ SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
+
+ /* Skip the scope name */
+ NextTok ();
+
+ /* Read an optional address size specifier */
+ AddrSize = OptionalAddrSize ();
+
+ /* Mark the symbol as defined */
+ SymDef (Sym, GenCurrentPC (), AddrSize, SF_LABEL);
+
+ /* Enter a new scope with the given name */
+ SymEnterLevel (Name, AddrSize);
+
} else {
+
+ /* A .PROC statement without a name */
char Buf[sizeof (SVal)];
- SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"));
+ SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"), ADDR_SIZE_DEFAULT);
+ Warning (WARN_UNNAMED_PROC);
+
}
}
}
/* Get the current segment and push it */
- CollAppend (&SegStack, DupSegDef (GetCurrentSeg ()));
+ CollAppend (&SegStack, DupSegDef (GetCurrentSegDef ()));
}
static void DoSegment (void)
/* Switch to another segment */
{
- static const char* AttrTab [] = {
- "ZEROPAGE", "DIRECT",
- "ABSOLUTE",
- "FAR", "LONG"
- };
char Name [sizeof (SVal)];
SegDef Def;
Def.Name = Name;
- Def.Type = SEGTYPE_DEFAULT;
if (Tok != TOK_STRCON) {
ErrorSkip (ERR_STRCON_EXPECTED);
strcpy (Name, SVal);
NextTok ();
- /* Check for an optional segment attribute */
- if (Tok == TOK_COMMA) {
- NextTok ();
- if (Tok != TOK_IDENT) {
- ErrorSkip (ERR_IDENT_EXPECTED);
- } else {
- int Attr = GetSubKey (AttrTab, sizeof (AttrTab) / sizeof (AttrTab [0]));
- switch (Attr) {
-
- case 0:
- case 1:
- /* Zeropage */
- Def.Type = SEGTYPE_ZP;
- break;
-
- case 2:
- /* Absolute */
- Def.Type = SEGTYPE_ABS;
- break;
-
- case 3:
- case 4:
- /* Far */
- Def.Type = SEGTYPE_FAR;
- break;
-
- default:
- Error (ERR_ILLEGAL_SEG_ATTR);
- }
- NextTok ();
- }
- }
+ /* Check for an optional address size modifier */
+ Def.AddrSize = OptionalAddrSize ();
/* Set the segment */
UseSeg (&Def);
#include <sys/stat.h>
/* common */
+#include "addrsize.h"
#include "chartype.h"
#include "check.h"
#include "fname.h"
+unsigned ParseAddrSize (void)
+/* Check if the next token is a keyword that denotes an address size specifier.
+ * If so, return the corresponding address size constant, otherwise output an
+ * error message and return ADDR_SIZE_DEFAULT.
+ */
+{
+ static const char* Keys[] = {
+ "DIRECT", "ZEROPAGE", "ZP",
+ "ABSOLUTE", "ABS", "NEAR",
+ "FAR",
+ };
+
+ /* Check for an identifier */
+ if (Tok != TOK_IDENT) {
+ Error (ERR_ADDR_SIZE_EXPECTED);
+ return ADDR_SIZE_DEFAULT;
+ }
+
+ /* Search for the attribute */
+ switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
+ case 0:
+ case 1:
+ case 2: return ADDR_SIZE_FAR;
+ case 3:
+ case 4:
+ case 5: return ADDR_SIZE_ABS;
+ case 6: return ADDR_SIZE_FAR;
+ default:
+ Error (ERR_ADDR_SIZE_EXPECTED);
+ return ADDR_SIZE_DEFAULT;
+ }
+}
+
+
+
void InitScanner (const char* InFile)
/* Initialize the scanner, open the given input file */
{
* or -1 if the keyword was not found.
*/
+unsigned ParseAddrSize (void);
+/* Check if the next token is a keyword that denotes an address size specifier.
+ * If so, return the corresponding address size constant, otherwise output an
+ * error message and return ADDR_SIZE_DEFAULT.
+ */
+
void InitScanner (const char* InFile);
/* Initialize the scanner, open the given input file */
int RelocMode = 1;
unsigned long AbsPC = 0; /* PC if in absolute mode */
-
-
-typedef struct Segment Segment;
-struct Segment {
- Segment* List; /* List of all segments */
- Fragment* Root; /* Root of fragment list */
- Fragment* Last; /* Pointer to last fragment */
- unsigned long FragCount; /* Number of fragments */
- unsigned Num; /* Segment number */
- unsigned Align; /* Segment alignment */
- unsigned long PC;
- SegDef* Def; /* Segment definition (name and type) */
-};
-
-
+/* Segment initializer macro */
#define SEG(segdef, num, prev) \
{ prev, 0, 0, 0, num, 0, 0, segdef }
/* Definitions for predefined segments */
-SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, SEGTYPE_ABS);
-SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, SEGTYPE_ZP);
-SegDef DataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA, SEGTYPE_ABS);
-SegDef BssSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS, SEGTYPE_ABS);
-SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA, SEGTYPE_ABS);
-SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE, SEGTYPE_ABS);
+SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, ADDR_SIZE_ABS);
+SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, ADDR_SIZE_ZP);
+SegDef DataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA, ADDR_SIZE_ABS);
+SegDef BssSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS, ADDR_SIZE_ABS);
+SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA, ADDR_SIZE_ABS);
+SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE, ADDR_SIZE_ABS);
/* Predefined segments */
static Segment NullSeg = SEG (&NullSegDef, 5, NULL);
static Segment* SegmentLast = &NullSeg;
/* Currently active segment */
-static Segment* ActiveSeg = &CodeSeg;
+Segment* ActiveSeg = &CodeSeg;
-static Segment* NewSegment (const char* Name, unsigned SegType)
+static Segment* NewSegment (const char* Name, unsigned AddrSize)
/* Create a new segment, insert it into the global list and return it */
{
Segment* S;
S->Num = SegmentCount++;
S->Align = 0;
S->PC = 0;
- S->Def = NewSegDef (Name, SegType);
+ S->Def = NewSegDef (Name, AddrSize);
/* Insert it into the segment list */
SegmentLast->List = S;
while (Seg) {
if (strcmp (Seg->Def->Name, D->Name) == 0) {
/* We found this segment. Check if the type is identical */
- if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) {
+ if (D->AddrSize != ADDR_SIZE_DEFAULT &&
+ Seg->Def->AddrSize != D->AddrSize) {
Error (ERR_SEG_ATTR_MISMATCH);
/* Use the new attribute to avoid errors */
- Seg->Def->Type = D->Type;
+ Seg->Def->AddrSize = D->AddrSize;
}
ActiveSeg = Seg;
return;
}
/* Segment is not in list, create a new one */
- if (D->Type == SEGTYPE_DEFAULT) {
- Seg = NewSegment (D->Name, SEGTYPE_ABS);
+ if (D->AddrSize == ADDR_SIZE_DEFAULT) {
+ Seg = NewSegment (D->Name, ADDR_SIZE_ABS);
} else {
- Seg = NewSegment (D->Name, D->Type);
+ Seg = NewSegment (D->Name, D->AddrSize);
}
ActiveSeg = Seg;
}
-const SegDef* GetCurrentSeg (void)
-/* Get a pointer to the segment defininition of the current segment */
-{
- return ActiveSeg->Def;
-}
-
-
-
-unsigned GetSegNum (void)
-/* Get the number of the current segment */
-{
- return ActiveSeg->Num;
-}
-
-
-
void SegAlign (unsigned Power, int Val)
/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
* actual fill value will be determined by the linker), otherwise use the
-int IsZPSeg (void)
-/* Return true if the current segment is a zeropage segment */
-{
- return (ActiveSeg->Def->Type == SEGTYPE_ZP);
-}
-
-
-
-int IsFarSeg (void)
-/* Return true if the current segment is a far segment */
-{
- return (ActiveSeg->Def->Type == SEGTYPE_FAR);
-}
-
-
-
-unsigned GetSegType (unsigned SegNum)
-/* Return the type of the segment with the given number */
+unsigned GetSegAddrSize (unsigned SegNum)
+/* Return the address size of the segment with the given number */
{
/* Search for the segment */
Segment* S = SegmentList;
FAIL ("Invalid segment number");
}
- /* Return the segment type */
- return S->Def->Type;
+ /* Return the address size */
+ return S->Def->AddrSize;
}
ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
ObjWrite32 (Seg->PC); /* Size */
ObjWrite8 (Seg->Align); /* Segment alignment */
- ObjWrite8 (Seg->Def->Type); /* Type of the segment */
+ ObjWrite8 (Seg->Def->AddrSize); /* Address size of the segment */
ObjWriteVar (Seg->FragCount); /* Number of fragments */
/* Now walk through the fragment list for this segment and write the
/* common */
#include "fragdefs.h"
+#include "inline.h"
#include "segdefs.h"
/* ca65 */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
+/* Segment definition */
+typedef struct Segment Segment;
+struct Segment {
+ Segment* List; /* List of all segments */
+ Fragment* Root; /* Root of fragment list */
+ Fragment* Last; /* Pointer to last fragment */
+ unsigned long FragCount; /* Number of fragments */
+ unsigned Num; /* Segment number */
+ unsigned Align; /* Segment alignment */
+ unsigned long PC;
+ SegDef* Def; /* Segment definition (name and type) */
+};
+
/* Are we in absolute mode or in relocatable mode? */
-extern int RelocMode;
+extern int RelocMode;
/* Definitions for predefined segments */
extern SegDef NullSegDef;
extern SegDef RODataSegDef;
extern SegDef CodeSegDef;
+/* Currently active segment */
+extern Segment* ActiveSeg;
+
/*****************************************************************************/
void UseSeg (const SegDef* D);
/* Use the given segment */
-const SegDef* GetCurrentSeg (void);
+#if defined(HAVE_INLINE)
+INLINE const SegDef* GetCurrentSegDef (void)
/* Get a pointer to the segment defininition of the current segment */
+{
+ return ActiveSeg->Def;
+}
+#else
+# define GetCurrentSegDef() (ActiveSeg->Def)
+#endif
-unsigned GetSegNum (void);
+#if defined(HAVE_INLINE)
+INLINE unsigned GetCurrentSegNum (void)
/* Get the number of the current segment */
+{
+ return ActiveSeg->Num;
+}
+#else
+# define GetCurrentSegNum() (ActiveSeg->Num)
+#endif
+
+#if defined(HAVE_INLINE)
+INLINE unsigned GetCurrentSegAddrSize (void)
+/* Get the address size of the current segment */
+{
+ return ActiveSeg->Def->AddrSize;
+}
+#else
+# define GetCurrentSegAddrSize() (ActiveSeg->Def->AddrSize)
+#endif
void SegAlign (unsigned Power, int Val);
/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
* given value.
*/
-int IsZPSeg (void);
-/* Return true if the current segment is a zeropage segment */
-
-int IsFarSeg (void);
-/* Return true if the current segment is a far segment */
-
-unsigned GetSegType (unsigned SegNum);
-/* Return the type of the segment with the given number */
+unsigned GetSegAddrSize (unsigned SegNum);
+/* Return the address size of the segment with the given number */
unsigned long GetPC (void);
/* Get the program counter of the current segment */
/*****************************************************************************/
/* */
-/* symentry.c */
+/* symentry.c */
/* */
/* Symbol table entry forward for the ca65 macroassembler */
/* */
#include <string.h>
/* common */
+#include "addrsize.h"
#include "xmalloc.h"
/* ca65 */
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
+static unsigned SymAddrSize (const SymEntry* S)
+/* Get the default address size for a symbol. */
+{
+ /* Local symbols are always near (is this ok?) */
+ if (IsLocalNameId (S->Name)) {
+ return ADDR_SIZE_ABS;
+ }
+
+ /* Return the address size of the enclosing scope */
+ return S->SymTab->AddrSize;
+}
+
+
+
SymEntry* NewSymEntry (const char* Name)
/* Allocate a symbol table entry, initialize and return it */
{
SymEntry* S = xmalloc (sizeof (SymEntry));
/* Initialize the entry */
- S->Left = 0;
- S->Right = 0;
- S->Locals = 0;
- S->SymTab = 0;
- S->Pos = CurPos;
- S->Flags = 0;
- S->V.Expr = 0;
- S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
+ S->Left = 0;
+ S->Right = 0;
+ S->Locals = 0;
+ S->SymTab = 0;
+ S->Pos = CurPos;
+ S->Flags = 0;
+ S->V.Expr = 0;
+ S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
+ S->ExportSize = ADDR_SIZE_DEFAULT;
+ S->AddrSize = ADDR_SIZE_DEFAULT;
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
- S->Name = GetStringId (Name);
+ S->Name = GetStringId (Name);
/* Insert it into the list of all entries */
S->List = SymList;
-void SymDef (SymEntry* S, ExprNode* Expr, unsigned Flags)
+void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
/* Define a new symbol */
{
if (S->Flags & SF_IMPORT) {
return;
}
- /* Set the symbol data */
+ /* Map a default address size to a real value */
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ AddrSize = SymAddrSize (S);
+ }
+
+ /* Set the symbol value */
if (IsConstExpr (Expr)) {
/* Expression is const, store the value */
S->Flags |= SF_CONST;
/* Not const, store the expression */
S->V.Expr = Expr;
}
- S->Flags |= SF_DEFINED;
- if (Flags & SYM_ZP) {
- S->Flags |= SF_ZP;
+
+ /* If the symbol is marked as global, export it */
+ if (S->Flags & SF_GLOBAL) {
+ S->ExportSize = S->AddrSize;
+ S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
}
- if (Flags & SYM_LABEL) {
- S->Flags |= SF_LABEL;
+
+ /* Mark the symbol as defined and use the given address size */
+ S->Flags |= (SF_DEFINED | Flags);
+ S->AddrSize = AddrSize;
+
+ /* If the symbol is exported, check the address sizes */
+ if (S->Flags & SF_EXPORT) {
+ if (S->AddrSize > S->ExportSize) {
+ Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S));
+ }
}
/* If the symbol is a ZP symbol, check if the value is in correct range */
- if (S->Flags & SF_ZP) {
+ if (S->AddrSize == ADDR_SIZE_ZP) {
/* Already marked as ZP symbol by some means */
if (!IsByteExpr (Expr)) {
Error (ERR_RANGE);
+void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
+/* Mark the given symbol as an imported symbol */
+{
+ /* Don't accept local symbols */
+ if (IsLocalNameId (S->Name)) {
+ Error (ERR_ILLEGAL_LOCAL_USE);
+ return;
+ }
+
+ if (S->Flags & SF_DEFINED) {
+ Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S));
+ S->Flags |= SF_MULTDEF;
+ return;
+ }
+ if (S->Flags & SF_EXPORT) {
+ /* The symbol is already marked as exported symbol */
+ Error (ERR_SYM_ALREADY_EXPORT, GetSymName (S));
+ return;
+ }
+
+ /* Map a default address size to a real value */
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ AddrSize = SymAddrSize (S);
+ }
+
+ /* If the symbol is marked as import or global, check the symbol flags,
+ * then do silently remove the global flag
+ */
+ if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
+ if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
+ AddrSize != S->AddrSize) {
+ Error (ERR_SYM_REDECL_MISMATCH, GetSymName (S));
+ }
+ S->Flags &= ~SF_GLOBAL;
+ }
+
+ /* Set the symbol data */
+ S->Flags |= (SF_IMPORT | Flags);
+ S->AddrSize = AddrSize;
+}
+
+
+
+void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
+/* Mark the given symbol as an exported symbol */
+{
+ /* Don't accept local symbols */
+ if (IsLocalNameId (S->Name)) {
+ Error (ERR_ILLEGAL_LOCAL_USE);
+ return;
+ }
+
+ /* Check if it's ok to export the symbol */
+ if (S->Flags & SF_IMPORT) {
+ /* The symbol is already marked as imported external symbol */
+ Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S));
+ return;
+ }
+
+ /* Map a default address size to a real value */
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ AddrSize = SymAddrSize (S);
+ }
+
+ /* If the symbol was already marked as an export or global, check if
+ * this was done specifiying the same address size. In case of a global
+ * declaration, silently remove the global flag.
+ */
+ if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
+ if (S->ExportSize != AddrSize) {
+ Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
+ }
+ S->Flags &= ~SF_GLOBAL;
+ }
+ S->ExportSize = AddrSize;
+
+ /* If the symbol is already defined, check symbol size against the
+ * exported size.
+ */
+ if (S->Flags & SF_DEFINED) {
+ if (S->AddrSize > S->ExportSize) {
+ Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S));
+ }
+ }
+
+ /* Set the symbol data */
+ S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
+}
+
+
+
+void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
+/* Mark the given symbol as a global symbol, that is, as a symbol that is
+ * either imported or exported.
+ */
+{
+ /* Don't accept local symbols */
+ if (IsLocalNameId (S->Name)) {
+ Error (ERR_ILLEGAL_LOCAL_USE);
+ return;
+ }
+
+ /* Map a default address size to a real value */
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ AddrSize = SymAddrSize (S);
+ }
+
+ /* If the symbol is already marked as import or export, check the
+ * size of the definition, then bail out.
+ */
+ if (S->Flags & SF_IMPORT) {
+ if (AddrSize != S->AddrSize) {
+ Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
+ }
+ return;
+ }
+ if (S->Flags & SF_EXPORT) {
+ if (AddrSize != S->ExportSize) {
+ Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
+ }
+ return;
+ }
+
+ /* If the symbol is already defined, export it. Otherwise mark it as
+ * global.
+ */
+ if (S->Flags & SF_DEFINED) {
+ /* The symbol is defined, export it */
+ if (S->ExportSize != AddrSize) {
+ Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
+ }
+ S->Flags |= (SF_EXPORT | Flags);
+ S->ExportSize = AddrSize;
+ } else {
+ S->Flags |= (SF_GLOBAL | Flags);
+ S->AddrSize = AddrSize;
+ }
+}
+
+
+
int SymIsDef (const SymEntry* S)
/* Return true if the given symbol is already defined */
{
#define SF_DEFINED 0x4000 /* Defined */
#define SF_REFERENCED 0x8000 /* Referenced */
-/* Flags used in SymDef */
-#define SYM_DEFAULT 0x00
-#define SYM_ZP 0x01
-#define SYM_LABEL 0x02
-
/* Arguments for SymFind... */
#define SYM_FIND_EXISTING 0
#define SYM_ALLOC_NEW 1
SymEntry* Sym; /* Symbol (if trampoline entry) */
} V;
Collection ExprRefs; /* Expressions using this symbol */
+ unsigned char ExportSize; /* Export address size */
+ unsigned char AddrSize; /* Address size of label */
unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */
/* ...actually value+1 (used as flag) */
unsigned Name; /* Name index in global string pool */
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
-void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned Flags);
+void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned AddrSize, unsigned Flags);
/* Mark a symbol as defined */
void SymRef (SymEntry* Sym);
/* Mark the given symbol as referenced */
+void SymImport (SymEntry* Sym, unsigned AddrSize, unsigned Flags);
+/* Mark the given symbol as an imported symbol */
+
+void SymExport (SymEntry* Sym, unsigned AddrSize, unsigned Flags);
+/* Mark the given symbol as an exported symbol */
+
+void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags);
+/* Mark the given symbol as a global symbol, that is, as a symbol that is
+ * either imported or exported.
+ */
+
int SymIsDef (const SymEntry* Sym);
/* Return true if the given symbol is already defined */
#include <string.h>
/* common */
+#include "addrsize.h"
#include "check.h"
#include "hashstr.h"
#include "symdefs.h"
-static unsigned SymTableSize (unsigned Level)
+static unsigned ScopeTableSize (unsigned Level)
/* Get the size of a table for the given lexical level */
{
switch (Level) {
-static SymTable* NewSymTable (SymTable* Parent, const char* Name)
+static SymTable* NewSymTable (SymTable* Parent, unsigned AddrSize, const char* Name)
/* Allocate a symbol table on the heap and return it */
{
/* Determine the lexical level and the number of table slots */
unsigned Level = Parent? Parent->Level + 1 : 0;
- unsigned Slots = SymTableSize (Level);
+ unsigned Slots = ScopeTableSize (Level);
/* Allocate memory */
SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
S->Left = 0;
S->Right = 0;
S->Childs = 0;
+ S->AddrSize = AddrSize;
+ S->Type = 0;
S->Level = Level;
S->TableSlots = Slots;
S->TableEntries = 0;
-void SymEnterLevel (const char* ScopeName)
+void SymEnterLevel (const char* ScopeName, unsigned AddrSize)
/* Enter a new lexical level */
{
/* ### Check existing scope */
+ /* Map a default address size to something real */
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ /* Use the segment address size */
+ AddrSize = GetCurrentSegAddrSize ();
+ }
+
/* Create the new table */
CurrentScope = NewSymTable (CurrentScope, ScopeName);
}
-SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags)
+SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
/* Find a scope in the given enclosing scope */
{
SymTable** T = &Parent->Childs;
}
/* Create a new scope if requested and we didn't find one */
- if (*T == 0 && Flags == SYM_ALLOC_NEW) {
+ if (*T == 0 && AllocNew) {
*T = NewSymTable (Parent, Name);
}
-static void SymImportInternal (const char* Name, unsigned Flags)
-/* Mark the given symbol as an imported symbol */
-{
- SymEntry* S;
-
- /* Don't accept local symbols */
- if (IsLocalName (Name)) {
- Error (ERR_ILLEGAL_LOCAL_USE);
- return;
- }
-
- /* Do we have such a symbol? */
- S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
- if (S->Flags & SF_DEFINED) {
- Error (ERR_SYM_ALREADY_DEFINED, Name);
- S->Flags |= SF_MULTDEF;
- return;
- }
- if (S->Flags & SF_EXPORT) {
- /* The symbol is already marked as exported symbol */
- Error (ERR_SYM_ALREADY_EXPORT, Name);
- return;
- }
-
- /* If the symbol is marked as global, check the symbol flags, then do
- * silently remove the global flag
- */
- if (S->Flags & SF_GLOBAL) {
- if ((Flags & (SF_ZP | SF_FORCED)) != (S->Flags & (SF_ZP | SF_FORCED))) {
- Error (ERR_SYM_REDECL_MISMATCH, Name);
- }
- S->Flags &= ~SF_GLOBAL;
- }
-
- /* Set the symbol data */
- S->Flags |= (SF_IMPORT | Flags);
-}
-
-
-
-void SymImport (const char* Name)
-/* Mark the given symbol as an imported symbol */
-{
- SymImportInternal (Name, SF_NONE);
-}
-
-
-
-void SymImportZP (const char* Name)
-/* Mark the given symbol as a forced imported symbol */
-{
- SymImportInternal (Name, SF_ZP);
-}
-
-
-
-void SymImportForced (const char* Name)
-/* Mark the given symbol as a forced imported symbol */
-{
- SymImportInternal (Name, SF_FORCED);
-}
-
-
-
-static void SymExportInternal (const char* Name, unsigned Flags)
-/* Mark the given symbol as an exported symbol */
-{
- SymEntry* S;
-
- /* Don't accept local symbols */
- if (IsLocalName (Name)) {
- Error (ERR_ILLEGAL_LOCAL_USE);
- return;
- }
-
- /* Do we have such a symbol? */
- S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
- if (S->Flags & SF_IMPORT) {
- /* The symbol is already marked as imported external symbol */
- Error (ERR_SYM_ALREADY_IMPORT, Name);
- return;
- }
-
- /* If the symbol is marked as global, check the symbol size, then do
- * silently remove the global flag
- */
- if (S->Flags & SF_GLOBAL) {
- if ((Flags & SF_ZP) != (S->Flags & SF_ZP)) {
- Error (ERR_SYM_REDECL_MISMATCH, Name);
- }
- S->Flags &= ~SF_GLOBAL;
- }
-
- /* Set the symbol data */
- S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
-}
-
-
-
-void SymExport (const char* Name)
-/* Mark the given symbol as an exported symbol */
-{
- SymExportInternal (Name, SF_NONE);
-}
-
-
-
-void SymExportZP (const char* Name)
-/* Mark the given symbol as an exported zeropage symbol */
-{
- SymExportInternal (Name, SF_ZP);
-}
-
-
-
-static void SymGlobalInternal (const char* Name, unsigned Flags)
-/* Mark the given symbol as a global symbol, that is, as a symbol that is
- * either imported or exported.
- */
-{
- SymEntry* S;
-
- /* Don't accept local symbols */
- if (IsLocalName (Name)) {
- Error (ERR_ILLEGAL_LOCAL_USE);
- return;
- }
-
- /* Search for this symbol, create a new entry if needed */
- S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
-
- /* If the symbol is already marked as import or export, check the
- * size of the definition, then bail out. */
- if (S->Flags & SF_IMPORT || S->Flags & SF_EXPORT) {
- if ((Flags & SF_ZP) != (S->Flags & SF_ZP)) {
- Error (ERR_SYM_REDECL_MISMATCH, Name);
- }
- return;
- }
-
- /* Mark the symbol */
- S->Flags |= (SF_GLOBAL | Flags);
-}
-
-
-
-void SymGlobal (const char* Name)
-/* Mark the given symbol as a global symbol, that is, as a symbol that is
- * either imported or exported.
- */
-{
- SymGlobalInternal (Name, SF_NONE);
-}
-
-
-
-void SymGlobalZP (const char* Name)
-/* Mark the given symbol as a global zeropage symbol, that is, as a symbol
- * that is either imported or exported.
- */
-{
- SymGlobalInternal (Name, SF_ZP);
-}
-
-
-
void SymConDes (const char* Name, unsigned Type, unsigned Prio)
/* Mark the given symbol as a module constructor/destructor. This will also
* mark the symbol as an export. Initializers may never be zero page symbols.
}
/* Check if the symbol was not already defined as ZP symbol */
- if ((S->Flags & SF_ZP) != 0) {
+ if (S->AddrSize == ADDR_SIZE_ZP) {
Error (ERR_SYM_REDECL_MISMATCH, Name);
}
-/* Scope identifiers */
-#define SCOPE_ANY 0
-#define SCOPE_GLOBAL 1
-#define SCOPE_LOCAL 2
-
/* A symbol table */
typedef struct SymTable SymTable;
struct SymTable {
SymTable* Right; /* Pointer to greater entry */
SymTable* Parent; /* Link to enclosing scope if any */
SymTable* Childs; /* Pointer to child scopes */
+ unsigned char AddrSize; /* Address size */
+ unsigned char Type; /* Type of the scope */
unsigned Level; /* Lexical level */
unsigned TableSlots; /* Number of hash table slots */
unsigned TableEntries; /* Number of entries in the table */
-void SymEnterLevel (const char* ScopeName);
+void SymEnterLevel (const char* ScopeName, unsigned AddrSize);
/* Enter a new lexical level */
void SymLeaveLevel (void);
/* Leave the current lexical level */
-SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags);
+SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew);
/* Find a scope in the given enclosing scope */
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
* new entry created, or - in case AllocNew is zero - return 0.
*/
-void SymImport (const char* Name);
-/* Mark the given symbol as an imported symbol */
-
-void SymImportZP (const char* Name);
-/* Mark the given symbol as a imported zeropage symbol */
-
-void SymImportForced (const char* Name);
-/* Mark the given symbol as a forced imported symbol */
-
-void SymExport (const char* Name);
-/* Mark the given symbol as an exported symbol */
-
-void SymExportZP (const char* Name);
-/* Mark the given symbol as an exported zeropage symbol */
-
-void SymGlobal (const char* Name);
-/* Mark the given symbol as a global symbol, that is, as a symbol that is
- * either imported or exported.
- */
-
-void SymGlobalZP (const char* Name);
-/* Mark the given symbol as a global zeropage symbol, that is, as a symbol
- * that is either imported or exported.
- */
-
void SymConDes (const char* Name, unsigned Type, unsigned Prio);
/* Mark the given symbol as a module constructor/destructor. This will also
* mark the symbol as an export. Initializers may never be zero page symbols.
--- /dev/null
+/*****************************************************************************/
+/* */
+/* addrsize.c */
+/* */
+/* Address size definitions */
+/* */
+/* */
+/* */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+/* common */
+#include "addrsize.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+const char* AddrSizeToStr (unsigned char AddrSize)
+/* Return the name for an address size specifier */
+{
+ switch (AddrSize) {
+ case ADDR_SIZE_DEFAULT: return "default";
+ case ADDR_SIZE_ZP: return "zeropage";
+ case ADDR_SIZE_ABS: return "absolute";
+ case ADDR_SIZE_FAR: return "far";
+ default: return "unknown";
+ }
+}
+
+
+
#define ADDR_SIZE_DEFAULT 0x00
-#define ADDR_SIZE_ZEROPAGE 0x01
-#define ADDR_SIZE_ABSOLUTE 0x02
+#define ADDR_SIZE_ZP 0x01
+#define ADDR_SIZE_ABS 0x02
#define ADDR_SIZE_FAR 0x03
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+const char* AddrSizeToStr (unsigned char AddrSize);
+/* Return the name for an address size specifier */
+
+
+
/* End of addrsize.h */
#endif
OBJS = abend.o \
+ addrsize.o \
bitops.o \
chartype.o \
check.o \
export INCLUDE = $(WATCOM)\\h
# We will use the windows compiler under linux (define as empty for windows)
-WINE = wine --
+WINE = wine --
# Programs
AR = $(WINE) WLIB
# All library OBJ files
OBJS = abend.obj \
+ addrsize.obj \
bitops.obj \
chartype.obj \
check.obj \
/* */
/* */
/* */
-/* (C) 2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2002-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
-SegDef* NewSegDef (const char* Name, unsigned Type)
+SegDef* NewSegDef (const char* Name, unsigned AddrSize)
/* Create a new segment definition and return it */
{
/* Allocate memory */
SegDef* D = xmalloc (sizeof (SegDef));
/* Initialize it */
- if (D) {
- D->Name = xstrdup (Name);
- D->Type = Type;
- }
+ D->Name = xstrdup (Name);
+ D->AddrSize = AddrSize;
/* Return the result */
return D;
SegDef* DupSegDef (const SegDef* Def)
/* Duplicate a segment definition and return it */
{
- return NewSegDef (Def->Name, Def->Type);
-}
-
-
-
-const char* SegTypeToStr (unsigned char Type)
-/* Map a segment type into a string */
-{
- switch (Type) {
- case SEGTYPE_ABS: return "abs";
- case SEGTYPE_ZP: return "zp";
- case SEGTYPE_FAR: return "far";
- default: return "unknown";
- }
+ return NewSegDef (Def->Name, Def->AddrSize);
}
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#define SEGDEFS_H
+
+/* common */
+#include "addrsize.h"
+
+
/*****************************************************************************/
/* Data */
-/* Available segment types */
-#define SEGTYPE_DEFAULT 0
-#define SEGTYPE_ABS 1
-#define SEGTYPE_ZP 2
-#define SEGTYPE_FAR 3
-
/* Segment definition */
typedef struct SegDef SegDef;
struct SegDef {
char* Name; /* Segment name */
- unsigned Type; /* Segment type, see above */
+ unsigned AddrSize; /* Default address size */
};
/* Initializer for static SegDefs */
-#define STATIC_SEGDEF_INITIALIZER(name, type) { (name), (type) }
+#define STATIC_SEGDEF_INITIALIZER(name, addrsize) { name, addrsize }
-SegDef* NewSegDef (const char* Name, unsigned Type);
+SegDef* NewSegDef (const char* Name, unsigned AddrSize);
/* Create a new segment definition and return it */
void FreeSegDef (SegDef* D);
SegDef* DupSegDef (const SegDef* D);
/* Duplicate a segment definition and return it */
-const char* SegTypeToStr (unsigned char Type);
-/* Map a segment type into a string */
-
/* End of segdefs.h */
#include <string.h>
/* common */
+#include "addrsize.h"
#include "check.h"
#include "coll.h"
#include "fragdefs.h"
static void ConDesCreateOne (ConDesDesc* CD)
/* Create one table if requested */
{
- Segment* Seg; /* Segment for table */
+ Segment* Seg; /* Segment for table */
Section* Sec; /* Section for table */
unsigned Count; /* Number of exports */
unsigned I;
CollSort (&CD->ExpList, ConDesCompare, CD);
/* Get the segment for the table, create it if needed */
- Seg = GetSegment (CD->SegName, SEGTYPE_ABS, 0);
+ Seg = GetSegment (CD->SegName, ADDR_SIZE_ABS, 0);
/* Create a new section for the table */
- Sec = NewSection (Seg, 1, SEGTYPE_ABS);
+ Sec = NewSection (Seg, 1, ADDR_SIZE_ABS);
/* Walk over the exports and create a fragment for each one. We will use
* the exported expression without copying it, since it's cheap and there
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
static Segment* HashTab [HASHTAB_SIZE];
static unsigned SegCount = 0; /* Segment count */
-static Segment* SegRoot = 0; /* List of all segments */
+static Segment* SegRoot = 0; /* List of all segments */
-static Segment* NewSegment (unsigned Name, unsigned char Type)
+static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
/* Create a new segment and initialize it */
{
unsigned Hash;
S->AlignObj = 0;
S->Align = 0;
S->FillVal = 0;
- S->Type = Type;
+ S->AddrSize = AddrSize;
S->ReadOnly = 0;
S->Relocatable = 0;
S->Dumped = 0;
-Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName)
+Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName)
/* Search for a segment and return an existing one. If the segment does not
* exist, create a new one and return that. ObjName is only used for the error
* message and may be NULL if the segment is linker generated.
*/
if (S == 0) {
/* Create a new segment */
- S = NewSegment (Name, Type);
+ S = NewSegment (Name, AddrSize);
} else {
- /* Check if the existing segment has the requested type */
- if (S->Type != Type) {
+ /* Check if the existing segment has the requested address size */
+ if (S->AddrSize != AddrSize) {
/* Allow an empty object name */
if (ObjName == 0) {
ObjName = "[linker generated]";
-Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type)
+Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize)
/* Create a new section for the given segment */
{
unsigned long V;
S->FragLast = 0;
S->Size = 0;
S->Align = Align;
- S->Type = Type;
+ S->AddrSize = AddrSize;
/* Calculate the alignment bytes needed for the section */
V = (0x01UL << S->Align) - 1;
/* Print the segment data */
fprintf (F, "segment\t\"%s\", 0x%06lX, 0x%04lX, %s, %s\n",
GetString (S->Name), S->PC, S->Size,
- SegTypeToStr (S->Type),
+ AddrSizeToStr (S->AddrSize),
S->ReadOnly? "ro" : "rw");
}
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
struct ObjData* AlignObj; /* Module that requested the alignment */
unsigned char Align; /* Alignment needed */
unsigned char FillVal; /* Value to use for fill bytes */
- unsigned char Type; /* Type of segment */
+ unsigned char AddrSize; /* Address size of segment */
unsigned char ReadOnly; /* True for readonly segments (config) */
unsigned char Relocatable; /* True if the segment is relocatable */
unsigned char Dumped; /* Did we dump this segment? */
unsigned long Size; /* Size of the section */
unsigned char Align; /* Alignment */
unsigned char Fill; /* Fill bytes for alignment */
- unsigned char Type; /* Type of segment */
+ unsigned char AddrSize; /* Address size of segment */
};
-Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName);
+Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName);
/* Search for a segment and return an existing one. If the segment does not
* exist, create a new one and return that. ObjName is only used for the error
* message and may be NULL if the segment is linker generated.
*/
-Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type);
+Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize);
/* Create a new section for the given segment */
Section* ReadSection (FILE* F, struct ObjData* O);
#include <time.h>
/* common */
+#include "addrsize.h"
#include "cddefs.h"
#include "coll.h"
#include "exprdefs.h"
unsigned Len = strlen (Name);
unsigned long Size = Read32 (F);
unsigned Align = (1U << Read8 (F));
- unsigned char Type = Read8 (F);
+ unsigned char AddrSize = Read8 (F);
unsigned long FragCount = ReadVar (F);
- /* Get the description for the type */
- const char* TypeDesc;
- switch (Type) {
- case SEGTYPE_DEFAULT: TypeDesc = "SEGTYPE_DEFAULT"; break;
- case SEGTYPE_ABS: TypeDesc = "SEGTYPE_ABS"; break;
- case SEGTYPE_ZP: TypeDesc = "SEGTYPE_ZP"; break;
- case SEGTYPE_FAR: TypeDesc = "SEGTYPE_FAR"; break;
- default: TypeDesc = "SEGTYPE_UNKNOWN"; break;
- }
-
/* Print the header */
printf (" Index:%27u\n", I);
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
printf (" Size:%26lu\n", Size);
printf (" Alignment:%21u\n", Align);
- printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
+ printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
+ AddrSizeToStr (AddrSize));
printf (" Fragment count:%16lu\n", FragCount);
/* Seek to the end of the segment data (start of next) */