diff --git a/src/ar65/library.c b/src/ar65/library.c index 1214f2343..8eb178788 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -126,15 +126,15 @@ static void ReadIndexEntry (void) O->Strings[I] = ReadStr (Lib); } - /* Exports */ - O->ExportSize = ReadVar (Lib); - O->Exports = xmalloc (O->ExportSize); - ReadData (Lib, O->Exports, O->ExportSize); - /* Imports */ O->ImportSize = ReadVar (Lib); O->Imports = xmalloc (O->ImportSize); ReadData (Lib, O->Imports, O->ImportSize); + + /* Exports */ + O->ExportSize = ReadVar (Lib); + O->Exports = xmalloc (O->ExportSize); + ReadData (Lib, O->Exports, O->ExportSize); } @@ -197,13 +197,13 @@ static void WriteIndexEntry (ObjData* O) WriteStr (NewLib, O->Strings[I]); } - /* Exports */ - WriteVar (NewLib, O->ExportSize); - WriteData (NewLib, O->Exports, O->ExportSize); - /* Imports */ WriteVar (NewLib, O->ImportSize); WriteData (NewLib, O->Imports, O->ImportSize); + + /* Exports */ + WriteVar (NewLib, O->ExportSize); + WriteData (NewLib, O->Exports, O->ExportSize); } diff --git a/src/common/exprdefs.h b/src/common/exprdefs.h index 354c6ba1a..d9a3970c0 100644 --- a/src/common/exprdefs.h +++ b/src/common/exprdefs.h @@ -110,8 +110,8 @@ struct ExprNode { long IVal; /* If this is a int value */ struct SymEntry* Sym; /* If this is a symbol */ unsigned SegNum; /* If this is a segment */ - unsigned ImpNum; /* If this is an import */ - struct Memory* Mem; /* If this is a memory area */ + struct Import* Imp; /* If this is an import */ + struct MemoryArea* Mem; /* If this is a memory area */ struct Segment* Seg; /* If this is a segment */ struct Section* Sec; /* If section and Obj is NULL */ } V; diff --git a/src/common/libdefs.h b/src/common/libdefs.h index e945675e1..c7086cbbe 100644 --- a/src/common/libdefs.h +++ b/src/common/libdefs.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* R�merstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2010, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -39,14 +39,14 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ /* Defines for magic and version */ #define LIB_MAGIC 0x7A55616E -#define LIB_VERSION 0x000B +#define LIB_VERSION 0x000C /* Size of an library file header */ #define LIB_HDR_SIZE 12 diff --git a/src/ld65/bin.c b/src/ld65/bin.c index 3c7c4a7a7..7c26febed 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1999-2008 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1999-2010, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -50,6 +50,7 @@ #include "global.h" #include "fileio.h" #include "lineinfo.h" +#include "memarea.h" #include "segments.h" #include "spool.h" @@ -129,7 +130,7 @@ static void PrintNumVal (const char* Name, unsigned long V) -static void BinWriteMem (BinDesc* D, Memory* M) +static void BinWriteMem (BinDesc* D, MemoryArea* M) /* Write the segments of one memory area to a file */ { /* Get the start address of this memory area */ @@ -294,9 +295,9 @@ void BinWriteTarget (BinDesc* D, struct File* F) Print (stdout, 1, "Opened `%s'...\n", D->Filename); /* Dump all memory areas */ - for (I = 0; I < CollCount (&F->MemList); ++I) { + for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ - Memory* M = CollAtUnchecked (&F->MemList, I); + MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); Print (stdout, 1, " Dumping `%s'\n", GetString (M->Name)); BinWriteMem (D, M); } diff --git a/src/ld65/cfgexpr.c b/src/ld65/cfgexpr.c index 6d06389a4..584ad0d4a 100644 --- a/src/ld65/cfgexpr.c +++ b/src/ld65/cfgexpr.c @@ -34,109 +34,47 @@ /* common */ +#include "addrsize.h" #include "strbuf.h" /* ld65 */ #include "cfgexpr.h" #include "error.h" #include "exports.h" +#include "expr.h" #include "scanner.h" #include "spool.h" -/*****************************************************************************/ -/* Data */ -/*****************************************************************************/ - - - -/* Type of a CfgExpr */ -enum { - ceEmpty, - ceInt, - ceString -}; - -typedef struct CfgExpr CfgExpr; -struct CfgExpr { - unsigned Type; /* Type of the expression */ - long IVal; /* Integer value if it's a string */ - StrBuf SVal; /* String value if it's a string */ -}; - -#define CFGEXPR_INITIALIZER { ceEmpty, 0, STATIC_STRBUF_INITIALIZER } - - - -/*****************************************************************************/ -/* Forwards */ -/*****************************************************************************/ - - - -static void Expr (CfgExpr* E); -/* Full expression */ - - - -/*****************************************************************************/ -/* struct CfgExpr */ -/*****************************************************************************/ - - - -static void CE_Done (CfgExpr* E) -/* Cleanup a CfgExpr struct */ -{ - /* If the type is a string, we must delete the string buffer */ - if (E->Type == ceString) { - SB_Done (&E->SVal); - } -} - - - -static void CE_AssureInt (const CfgExpr* E) -/* Make sure, E contains an integer */ -{ - if (E->Type != ceInt) { - CfgError ("Integer type expected"); - } -} - - - /*****************************************************************************/ /* Code */ /*****************************************************************************/ -static void Factor (CfgExpr* E) -/* Read and return a factor in E */ +static ExprNode* Factor (void) +/* Read and return a factor */ { - Export* Sym; + ExprNode* N = 0; /* Initialize to avoid compiler warnings */ + Export* E; + unsigned Name; switch (CfgTok) { case CFGTOK_IDENT: - /* An identifier - search an export with the given name */ - Sym = FindExport (GetStrBufId (&CfgSVal)); - if (Sym == 0) { - CfgError ("Unknown symbol in expression: `%s'", - SB_GetConstBuf (&CfgSVal)); - } - /* We can only handle constants */ - if (!IsConstExport (Sym)) { - CfgError ("Value for symbol `%s' is not constant", - SB_GetConstBuf (&CfgSVal)); - } + /* Get the name as an id */ + Name = GetStrBufId (&CfgSVal); - /* Use the symbol value */ - E->IVal = GetExportVal (Sym); - E->Type = ceInt; + /* Check if we know the symbol already */ + E = FindExport (Name); + if (E != 0 && IsConstExport (E)) { + N = LiteralExpr (GetExportVal (E), 0); + } else { + N = NewExprNode (0, EXPR_SYMBOL); + N->V.Imp = InsertImport (GenImport (Name, ADDR_SIZE_ABS)); + } /* Skip the symbol name */ CfgNextTok (); @@ -144,37 +82,27 @@ static void Factor (CfgExpr* E) case CFGTOK_INTCON: /* An integer constant */ - E->IVal = CfgIVal; - E->Type = ceInt; + N = LiteralExpr (CfgIVal, 0); CfgNextTok (); break; - case CFGTOK_STRCON: - /* A string constant */ - SB_Copy (&E->SVal, &CfgSVal); - E->Type = ceString; - CfgNextTok (); - break; - case CFGTOK_PLUS: /* Unary plus */ CfgNextTok (); - Factor (E); - CE_AssureInt (E); + N = Factor (); break; case CFGTOK_MINUS: /* Unary minus */ CfgNextTok (); - Factor (E); - CE_AssureInt (E); - E->IVal = -E->IVal; + N = NewExprNode (0, EXPR_UNARY_MINUS); + N->Left = Factor (); break; case CFGTOK_LPAR: /* Left parenthesis */ CfgNextTok (); - Expr (E); + N = CfgExpr (); CfgConsume (CFGTOK_RPAR, "')' expected"); break; @@ -182,139 +110,115 @@ static void Factor (CfgExpr* E) CfgError ("Invalid expression: %d", CfgTok); break; } + + /* Return the new expression node */ + return N; } -static void Term (CfgExpr* E) +static ExprNode* Term (void) /* Multiplicative operators: * and / */ { - /* Left operand */ - Factor (E); + /* Read left hand side */ + ExprNode* Root = Factor (); /* Handle multiplicative operators */ while (CfgTok == CFGTOK_MUL || CfgTok == CFGTOK_DIV) { - CfgExpr RightSide = CFGEXPR_INITIALIZER; + ExprNode* Left; + ExprNode* Right; + unsigned char Op; /* Remember the token, then skip it */ cfgtok_t Tok = CfgTok; CfgNextTok (); - /* Left side must be an int */ - CE_AssureInt (E); - - /* Get the right operand and make sure it's an int */ - Factor (&RightSide); - CE_AssureInt (&RightSide); + /* Move root to left side, then read right side */ + Left = Root; + Right = Factor (); /* Handle the operation */ switch (Tok) { - - case CFGTOK_MUL: - E->IVal *= RightSide.IVal; - break; - - case CFGTOK_DIV: - if (RightSide.IVal == 0) { - CfgError ("Division by zero"); - } - E->IVal /= RightSide.IVal; - break; - - default: - Internal ("Unhandled token in Term: %d", Tok); + case CFGTOK_MUL: Op = EXPR_MUL; break; + case CFGTOK_DIV: Op = EXPR_DIV; break; + default: Internal ("Unhandled token in Term: %d", Tok); } - - /* Cleanup RightSide (this is not really needed since it may not - * contain strings at this point, but call it anyway for clarity. - */ - CE_Done (&RightSide); + Root = NewExprNode (0, Op); + Root->Left = Left; + Root->Right = Right; } + + /* Return the expression tree we've created */ + return Root; } -static void SimpleExpr (CfgExpr* E) +static ExprNode* SimpleExpr (void) /* Additive operators: + and - */ { - /* Left operand */ - Term (E); + /* Read left hand side */ + ExprNode* Root = Term (); /* Handle additive operators */ while (CfgTok == CFGTOK_PLUS || CfgTok == CFGTOK_MINUS) { - CfgExpr RightSide = CFGEXPR_INITIALIZER; + ExprNode* Left; + ExprNode* Right; + unsigned char Op; /* Remember the token, then skip it */ cfgtok_t Tok = CfgTok; CfgNextTok (); - /* Get the right operand */ - Term (&RightSide); - - /* Make sure, left and right side are of the same type */ - if (E->Type != RightSide.Type) { - CfgError ("Incompatible types in expression"); - } + /* Move root to left side, then read right side */ + Left = Root; + Right = Term (); /* Handle the operation */ switch (Tok) { - - case CFGTOK_PLUS: - /* Plus is defined for strings and ints */ - if (E->Type == ceInt) { - E->IVal += RightSide.IVal; - } else if (E->Type == ceString) { - SB_Append (&E->SVal, &RightSide.SVal); - } else { - Internal ("Unhandled type in '+' operator: %u", E->Type); - } - break; - - case CFGTOK_MINUS: - /* Operands must be ints */ - CE_AssureInt (E); - E->IVal -= RightSide.IVal; - break; - - default: - Internal ("Unhandled token in SimpleExpr: %d", Tok); + case CFGTOK_PLUS: Op = EXPR_PLUS; break; + case CFGTOK_MINUS: Op = EXPR_MINUS; break; + default: Internal ("Unhandled token in SimpleExpr: %d", Tok); } - - /* Cleanup RightSide */ - CE_Done (&RightSide); + Root = NewExprNode (0, Op); + Root->Left = Left; + Root->Right = Right; } + + /* Return the expression tree we've created */ + return Root; } -static void Expr (CfgExpr* E) +ExprNode* CfgExpr (void) /* Full expression */ { - SimpleExpr (E); + return SimpleExpr (); } -long CfgIntExpr (void) -/* Read an expression, make sure it's an int, and return its value */ +long CfgConstExpr (void) +/* Read an integer expression, make sure its constant and return its value */ { long Val; - CfgExpr E = CFGEXPR_INITIALIZER; - /* Parse the expression */ - Expr (&E); + ExprNode* Expr = CfgExpr (); - /* Make sure it's an integer */ - CE_AssureInt (&E); + /* Check that it's const */ + if (!IsConstExpr (Expr)) { + CfgError ("Constant expression expected"); + } /* Get the value */ - Val = E.IVal; + Val = GetExprVal (Expr); - /* Cleaup E */ - CE_Done (&E); + /* Cleanup E */ + FreeExpr (Expr); /* Return the value */ return Val; @@ -322,17 +226,17 @@ long CfgIntExpr (void) -long CfgCheckedIntExpr (long Min, long Max) +long CfgCheckedConstExpr (long Min, long Max) /* Read an expression, make sure it's an int and in range, then return its * value. */ { /* Get the value */ - long Val = CfgIntExpr (); + long Val = CfgConstExpr (); /* Check the range */ if (Val < Min || Val > Max) { - CfgError ("Range error"); + CfgError ("Range error"); } /* Return the value */ diff --git a/src/ld65/cfgexpr.h b/src/ld65/cfgexpr.h index dc6b99bb4..68247ca08 100644 --- a/src/ld65/cfgexpr.h +++ b/src/ld65/cfgexpr.h @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2005, Ullrich von Bassewitz */ -/* R�merstrasse 52 */ +/* (C) 2005-2010, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -38,16 +38,24 @@ +/* common */ +#include "exprdefs.h" + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ -long CfgIntExpr (void); -/* Read an expression, make sure it's an int, and return its value */ +ExprNode* CfgExpr (void); +/* Read an integer expression and return its value */ -long CfgCheckedIntExpr (long Min, long Max); +long CfgConstExpr (void); +/* Read an integer expression, make sure its constant and return its value */ + +long CfgCheckedConstExpr (long Min, long Max); /* Read an expression, make sure it's an int and in range, then return its * value. */ diff --git a/src/ld65/config.c b/src/ld65/config.c index 0dae0bc73..3de6c9a1a 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -53,7 +53,9 @@ #include "config.h" #include "error.h" #include "exports.h" +#include "expr.h" #include "global.h" +#include "memarea.h" #include "o65.h" #include "objdata.h" #include "scanner.h" @@ -84,7 +86,7 @@ static enum { static Collection FileList = STATIC_COLLECTION_INITIALIZER; /* Memory list */ -static Collection MemoryList = STATIC_COLLECTION_INITIALIZER; +static Collection MemoryAreas = STATIC_COLLECTION_INITIALIZER; /* Memory attributes */ #define MA_START 0x0001 @@ -95,8 +97,6 @@ static Collection MemoryList = STATIC_COLLECTION_INITIALIZER; #define MA_FILL 0x0020 #define MA_FILLVAL 0x0040 - - /* Segment list */ static Collection SegDescList = STATIC_COLLECTION_INITIALIZER; @@ -111,7 +111,30 @@ static Collection SegDescList = STATIC_COLLECTION_INITIALIZER; #define SA_START 0x0080 #define SA_OPTIONAL 0x0100 +/* Symbol structure. It is used for o65 imports and exports, but also for + * symbols from the SYMBOLS sections (symbols defined in the config file or + * forced imports). + */ +typedef struct Symbol Symbol; +struct Symbol { + const char* CfgName; /* Config file name */ + unsigned CfgLine; /* Config file position */ + unsigned CfgCol; + unsigned Name; /* Symbol name */ + unsigned Flags; /* Symbol flags */ + long Val; /* Symbol value if any */ +}; +/* Collections with symbols */ +static Collection O65Imports = STATIC_COLLECTION_INITIALIZER; +static Collection O65Exports = STATIC_COLLECTION_INITIALIZER; +static Collection Symbols = STATIC_COLLECTION_INITIALIZER; + +/* Symbol flags */ +#define SYM_NONE 0x00 /* No special meaning */ +#define SYM_DEF 0x01 /* Symbol defined in the config file */ +#define SYM_WEAK 0x02 /* Defined symbol is weak */ +#define SYM_IMPORT 0x04 /* A forced import */ /* Descriptor holding information about the binary formats */ static BinDesc* BinFmtDesc = 0; @@ -164,21 +187,21 @@ static File* GetFile (unsigned Name) -static void FileInsert (File* F, Memory* M) +static void FileInsert (File* F, MemoryArea* M) /* Insert the memory area into the files list */ { M->F = F; - CollAppend (&F->MemList, M); + CollAppend (&F->MemoryAreas, M); } -static Memory* CfgFindMemory (unsigned Name) +static MemoryArea* CfgFindMemory (unsigned Name) /* Find the memory are with the given name. Return NULL if not found */ { unsigned I; - for (I = 0; I < CollCount (&MemoryList); ++I) { - Memory* M = CollAtUnchecked (&MemoryList, I); + for (I = 0; I < CollCount (&MemoryAreas); ++I) { + MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); if (M->Name == Name) { return M; } @@ -188,10 +211,10 @@ static Memory* CfgFindMemory (unsigned Name) -static Memory* CfgGetMemory (unsigned Name) +static MemoryArea* CfgGetMemory (unsigned Name) /* Find the memory are with the given name. Print an error on an invalid name */ { - Memory* M = CfgFindMemory (Name); + MemoryArea* M = CfgFindMemory (Name); if (M == 0) { CfgError ("Invalid memory area `%s'", GetString (Name)); } @@ -218,16 +241,7 @@ static SegDesc* CfgFindSegDesc (unsigned Name) -static void SegDescInsert (SegDesc* S) -/* Insert a segment descriptor into the list of segment descriptors */ -{ - /* Insert the struct into the list */ - CollAppend (&SegDescList, S); -} - - - -static void MemoryInsert (Memory* M, SegDesc* S) +static void MemoryInsert (MemoryArea* M, SegDesc* S) /* Insert the segment descriptor into the memory area list */ { /* Insert the segment into the segment list of the memory area */ @@ -242,6 +256,39 @@ static void MemoryInsert (Memory* M, SegDesc* S) +static Symbol* NewSymbol (unsigned Name, unsigned Flags, long Val) +/* Create a new Symbol structure with the given name name and flags. The + * current config file position is recorded in the returned struct. + */ +{ + /* Allocate memory */ + Symbol* Sym = xmalloc (sizeof (Symbol)); + + /* Initialize the fields */ + Sym->CfgName = CfgGetName (); + Sym->CfgLine = CfgErrorLine; + Sym->CfgCol = CfgErrorCol; + Sym->Name = Name; + Sym->Flags = Flags; + Sym->Val = Val; + + /* Return the initialized struct */ + return Sym; +} + + + +static Symbol* NewO65Symbol (void) +/* Create a new Symbol structure with the name in the current CfgSVal variable + * ready for use as an o65 symbol. The current config file position is recorded + * in the returned struct. + */ +{ + return NewSymbol (GetStrBufId (&CfgSVal), SYM_NONE, 0); +} + + + static File* NewFile (unsigned Name) /* Create a new file descriptor and insert it into the list */ { @@ -252,7 +299,7 @@ static File* NewFile (unsigned Name) F->Name = Name; F->Flags = 0; F->Format = BINFMT_DEFAULT; - InitCollection (&F->MemList); + InitCollection (&F->MemoryAreas); /* Insert the struct into the list */ CollAppend (&FileList, F); @@ -263,32 +310,20 @@ static File* NewFile (unsigned Name) -static Memory* NewMemory (unsigned Name) -/* Create a new memory section and insert it into the list */ +static MemoryArea* CreateMemoryArea (unsigned Name) +/* Create a new memory area and insert it into the list */ { /* Check for duplicate names */ - Memory* M = CfgFindMemory (Name); + MemoryArea* M = CfgFindMemory (Name); if (M) { CfgError ("Memory area `%s' defined twice", GetString (Name)); } - /* Allocate memory */ - M = xmalloc (sizeof (Memory)); + /* Create a new memory area */ + M = NewMemoryArea (Name); - /* Initialize the fields */ - M->Name = Name; - M->Attr = 0; - M->Flags = 0; - M->Start = 0; - M->Size = 0; - M->FillLevel = 0; - M->FillVal = 0; - M->Relocatable = 0; - InitCollection (&M->SegList); - M->F = 0; - - /* Insert the struct into the list */ - CollAppend (&MemoryList, M); + /* Insert the struct into the list ... */ + CollAppend (&MemoryAreas, M); /* ...and return it */ return M; @@ -297,9 +332,8 @@ static Memory* NewMemory (unsigned Name) static SegDesc* NewSegDesc (unsigned Name) -/* Create a segment descriptor */ +/* Create a segment descriptor and insert it into the list */ { - Segment* Seg; /* Check for duplicate names */ SegDesc* S = CfgFindSegDesc (Name); @@ -307,21 +341,19 @@ static SegDesc* NewSegDesc (unsigned Name) CfgError ("Segment `%s' defined twice", GetString (Name)); } - /* Search for the actual segment in the input files. The function may - * return NULL (no such segment), this is checked later. - */ - Seg = SegFind (Name); - /* Allocate memory */ S = xmalloc (sizeof (SegDesc)); /* Initialize the fields */ S->Name = Name; - S->Seg = Seg; + S->Seg = 0; S->Attr = 0; S->Flags = 0; S->Align = 0; + /* Insert the struct into the list ... */ + CollAppend (&SegDescList, S); + /* ...and return it */ return S; } @@ -337,7 +369,7 @@ static void FreeSegDesc (SegDesc* S) /*****************************************************************************/ -/* Code */ +/* Config file parsing */ /*****************************************************************************/ @@ -385,7 +417,7 @@ static void ParseMemory (void) while (CfgTok == CFGTOK_IDENT) { /* Create a new entry on the heap */ - Memory* M = NewMemory (GetStrBufId (&CfgSVal)); + MemoryArea* M = CreateMemoryArea (GetStrBufId (&CfgSVal)); /* Skip the name and the following colon */ CfgNextTok (); @@ -408,13 +440,13 @@ static void ParseMemory (void) case CFGTOK_START: FlagAttr (&M->Attr, MA_START, "START"); - M->Start = CfgIntExpr (); + M->StartExpr = CfgExpr (); break; case CFGTOK_SIZE: FlagAttr (&M->Attr, MA_SIZE, "SIZE"); - M->Size = CfgIntExpr (); - break; + M->SizeExpr = CfgExpr (); + break; case CFGTOK_TYPE: FlagAttr (&M->Attr, MA_TYPE, "TYPE"); @@ -455,7 +487,7 @@ static void ParseMemory (void) case CFGTOK_FILLVAL: FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL"); - M->FillVal = (unsigned char) CfgCheckedIntExpr (0, 0xFF); + M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); break; default: @@ -640,7 +672,7 @@ static void ParseSegments (void) case CFGTOK_ALIGN: FlagAttr (&S->Attr, SA_ALIGN, "ALIGN"); - Val = CfgCheckedIntExpr (1, 0x10000); + Val = CfgCheckedConstExpr (1, 0x10000); S->Align = BitFind (Val); if ((0x01L << S->Align) != Val) { CfgError ("Alignment must be a power of 2"); @@ -650,7 +682,7 @@ static void ParseSegments (void) case CFGTOK_ALIGN_LOAD: FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD"); - Val = CfgCheckedIntExpr (1, 0x10000); + Val = CfgCheckedConstExpr (1, 0x10000); S->AlignLoad = BitFind (Val); if ((0x01L << S->AlignLoad) != Val) { CfgError ("Alignment must be a power of 2"); @@ -676,7 +708,7 @@ static void ParseSegments (void) case CFGTOK_OFFSET: FlagAttr (&S->Attr, SA_OFFSET, "OFFSET"); - S->Addr = CfgCheckedIntExpr (1, 0x1000000); + S->Addr = CfgCheckedConstExpr (1, 0x1000000); S->Flags |= SF_OFFSET; break; @@ -697,7 +729,7 @@ static void ParseSegments (void) case CFGTOK_START: FlagAttr (&S->Attr, SA_START, "START"); - S->Addr = CfgCheckedIntExpr (1, 0x1000000); + S->Addr = CfgCheckedConstExpr (1, 0x1000000); S->Flags |= SF_START; break; @@ -732,15 +764,6 @@ static void ParseSegments (void) S->Run = S->Load; } - /* If the segment is marked as BSS style, and if the segment exists - * in any of the object file, check that there's no initialized data - * in the segment. - */ - if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) { - Warning ("%s(%u): Segment with type `bss' contains initialized data", - CfgGetName (), CfgErrorLine); - } - /* An attribute of ALIGN_LOAD doesn't make sense if there are no * separate run and load memory areas. */ @@ -776,29 +799,6 @@ static void ParseSegments (void) CfgError ("Only one of ALIGN, START, OFFSET may be used"); } - /* If this segment does exist in any of the object files, insert the - * descriptor into the list of segment descriptors. Otherwise print a - * warning and discard it, because the segment pointer in the - * descriptor is invalid. - */ - if (S->Seg != 0) { - /* Insert the descriptor into the list of all descriptors */ - SegDescInsert (S); - /* Insert the segment into the memory area list */ - MemoryInsert (S->Run, S); - if (S->Load != S->Run) { - /* We have separate RUN and LOAD areas */ - MemoryInsert (S->Load, S); - } - } else { - /* Print a warning if the segment is not optional */ - if ((S->Flags & SF_OPTIONAL) == 0) { - CfgWarning ("Segment `%s' does not exist", GetString (S->Name)); - } - /* Discard the descriptor */ - FreeSegDesc (S); - } - /* Skip the semicolon */ CfgConsumeSemi (); } @@ -845,7 +845,6 @@ static void ParseO65 (void) unsigned AttrFlags = atNone; /* Remember the attributes read */ - unsigned CfgSValId; unsigned OS = 0; /* Initialize to keep gcc happy */ unsigned Version = 0; @@ -869,23 +868,8 @@ static void ParseO65 (void) AttrFlags |= atExport; /* We expect an identifier */ CfgAssureIdent (); - /* Convert the string into a string index */ - CfgSValId = GetStrBufId (&CfgSVal); - /* Check if the export symbol is also defined as an import. */ - if (O65GetImport (O65FmtDesc, CfgSValId) != 0) { - CfgError ("Exported symbol `%s' cannot be an import", - SB_GetConstBuf (&CfgSVal)); - } - /* Check if we have this symbol defined already. The entry - * routine will check this also, but we get a more verbose - * error message when checking it here. - */ - if (O65GetExport (O65FmtDesc, CfgSValId) != 0) { - CfgError ("Duplicate exported symbol: `%s'", - SB_GetConstBuf (&CfgSVal)); - } - /* Insert the symbol into the table */ - O65SetExport (O65FmtDesc, CfgSValId); + /* Remember it as an export for later */ + CollAppend (&O65Exports, NewO65Symbol ()); /* Eat the identifier token */ CfgNextTok (); break; @@ -895,23 +879,8 @@ static void ParseO65 (void) AttrFlags |= atImport; /* We expect an identifier */ CfgAssureIdent (); - /* Convert the string into a string index */ - CfgSValId = GetStrBufId (&CfgSVal); - /* Check if the imported symbol is also defined as an export. */ - if (O65GetExport (O65FmtDesc, CfgSValId) != 0) { - CfgError ("Imported symbol `%s' cannot be an export", - SB_GetConstBuf (&CfgSVal)); - } - /* Check if we have this symbol defined already. The entry - * routine will check this also, but we get a more verbose - * error message when checking it here. - */ - if (O65GetImport (O65FmtDesc, CfgSValId) != 0) { - CfgError ("Duplicate imported symbol: `%s'", - SB_GetConstBuf (&CfgSVal)); - } - /* Insert the symbol into the table */ - O65SetImport (O65FmtDesc, CfgSValId); + /* Remember it as an import for later */ + CollAppend (&O65Imports, NewO65Symbol ()); /* Eat the identifier token */ CfgNextTok (); break; @@ -919,7 +888,7 @@ static void ParseO65 (void) case CFGTOK_TYPE: /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atType, "TYPE"); - /* Get the type of the executable */ + /* Get the type of the executable */ CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { @@ -964,14 +933,14 @@ static void ParseO65 (void) /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atID, "ID"); /* We're expecting a number in the 0..$FFFF range*/ - ModuleId = (unsigned) CfgCheckedIntExpr (0, 0xFFFF); + ModuleId = (unsigned) CfgCheckedConstExpr (0, 0xFFFF); break; case CFGTOK_VERSION: /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atVersion, "VERSION"); /* We're expecting a number in byte range */ - Version = (unsigned) CfgCheckedIntExpr (0, 0xFF); + Version = (unsigned) CfgCheckedConstExpr (0, 0xFF); break; default: @@ -1237,7 +1206,7 @@ static void ParseStartAddress (void) /* Don't allow this twice */ FlagAttr (&AttrFlags, atDefault, "DEFAULT"); /* We expect a numeric expression */ - DefStartAddr = CfgCheckedIntExpr (0, 0xFFFFFF); + DefStartAddr = CfgCheckedConstExpr (0, 0xFFFFFF); break; default: @@ -1322,8 +1291,7 @@ static void ParseSymbols (void) while (CfgTok == CFGTOK_IDENT) { long Val = 0L; - int Weak = 0; - Export* E; + unsigned Flags = SYM_NONE; /* Remember the name */ unsigned Name = GetStrBufId (&CfgSVal); @@ -1343,13 +1311,16 @@ static void ParseSymbols (void) /* Make sure the next token is an integer expression, read and * skip it. */ - Val = CfgIntExpr (); + Val = CfgConstExpr (); + + /* This is a defined symbol */ + Flags = SYM_DEF; } else { /* Bitmask to remember the attributes we got already */ enum { - atNone = 0x0000, + atNone = 0x0000, atValue = 0x0001, atWeak = 0x0002 }; @@ -1380,14 +1351,18 @@ static void ParseSymbols (void) /* Don't allow this twice */ FlagAttr (&AttrFlags, atValue, "VALUE"); /* We expect a numeric expression */ - Val = CfgIntExpr (); + Val = CfgConstExpr (); + /* Symbol is defined */ + Flags |= SYM_DEF; break; case CFGTOK_WEAK: /* Don't allow this twice */ FlagAttr (&AttrFlags, atWeak, "WEAK"); CfgBoolToken (); - Weak = (CfgTok == CFGTOK_TRUE); + if (CfgTok == CFGTOK_TRUE) { + Flags |= SYM_WEAK; + } CfgNextTok (); break; @@ -1406,26 +1381,10 @@ static void ParseSymbols (void) /* Check if we have all mandatory attributes */ AttrCheck (AttrFlags, atValue, "VALUE"); - - /* Weak is optional, the default are non weak symbols */ - if ((AttrFlags & atWeak) == 0) { - Weak = 0; - } - } - /* Check if the symbol is already defined */ - if ((E = FindExport (Name)) != 0 && !IsUnresolvedExport (E)) { - /* If the symbol is not marked as weak, this is an error. - * Otherwise ignore the symbol from the config. - */ - if (!Weak) { - CfgError ("Symbol `%s' is already defined", GetString (Name)); - } - } else { - /* The symbol is undefined, generate an export */ - CreateConstExport (Name, Val); - } + /* Remember the symbol for later */ + CollAppend (&Symbols, NewSymbol (Name, Flags, Val)); /* Skip the semicolon */ CfgConsumeSemi (); @@ -1521,6 +1480,220 @@ void CfgRead (void) +/*****************************************************************************/ +/* Config file processing */ +/*****************************************************************************/ + + + +static void ProcessMemory (void) +/* Process the MEMORY section */ +{ + /* Walk over the list with the memory areas */ + unsigned I; + for (I = 0; I < CollCount (&MemoryAreas); ++I) { + + /* Get the next memory area */ + MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); + + /* Remember if this is a relocatable memory area */ + M->Relocatable = RelocatableBinFmt (M->F->Format); + + /* Resolve the expressions */ + if (!IsConstExpr (M->StartExpr)) { + Error ("Start address of memory area `%s' is not constant", + GetString (M->Name)); + } + M->Start = GetExprVal (M->StartExpr); + + if (!IsConstExpr (M->SizeExpr)) { + Error ("Size of memory area `%s' is not constant", + GetString (M->Name)); + } + M->Size = GetExprVal (M->SizeExpr); + + /* Mark the memory area as placed */ + M->Flags |= MF_PLACED; + } +} + + + +static void ProcessSegments (void) +/* Process the SEGMENTS section */ +{ + unsigned I; + + /* Walk over the list of segment descriptors */ + I = 0; + while (I < CollCount (&SegDescList)) { + + /* Get the next segment descriptor */ + SegDesc* S = CollAtUnchecked (&SegDescList, I); + + /* Search for the actual segment in the input files. The function may + * return NULL (no such segment), this is checked later. + */ + S->Seg = SegFind (S->Name); + + /* If the segment is marked as BSS style, and if the segment exists + * in any of the object file, check that there's no initialized data + * in the segment. + */ + if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) { + Warning ("Segment `%s' with type `bss' contains initialized data", + GetString (S->Name)); + } + + /* If this segment does exist in any of the object files, insert the + * segment into the load/run memory areas. Otherwise print a warning + * and discard it, because the segment pointer in the descriptor is + * invalid. + */ + if (S->Seg != 0) { + + /* Insert the segment into the memory area list */ + MemoryInsert (S->Run, S); + if (S->Load != S->Run) { + /* We have separate RUN and LOAD areas */ + MemoryInsert (S->Load, S); + } + + /* Process the next segment descriptor in the next run */ + ++I; + + } else { + + /* Print a warning if the segment is not optional */ + if ((S->Flags & SF_OPTIONAL) == 0) { + CfgWarning ("Segment `%s' does not exist", GetString (S->Name)); + } + + /* Discard the descriptor and remove it from the collection */ + FreeSegDesc (S); + CollDelete (&SegDescList, I); + } + } +} + + + +static void ProcessO65 (void) +/* Process the o65 format section */ +{ + unsigned I; + + /* Walk over the imports, check and add them to the o65 data */ + for (I = 0; I < CollCount (&O65Imports); ++I) { + + /* Get the import */ + Symbol* Sym = CollAtUnchecked (&O65Imports, I); + + /* Check if we have this symbol defined already. The entry + * routine will check this also, but we get a more verbose + * error message when checking it here. + */ + if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { + Error ("%s(%u): Duplicate imported o65 symbol: `%s'", + Sym->CfgName, Sym->CfgLine, GetString (Sym->Name)); + } + + /* Insert the symbol into the table */ + O65SetImport (O65FmtDesc, Sym->Name); + } + + /* Walk over the exports, check and add them to the o65 data */ + for (I = 0; I < CollCount (&O65Exports); ++I) { + + /* Get the export */ + Symbol* Sym = CollAtUnchecked (&O65Exports, I); + + /* Check if the export symbol is also defined as an import. */ + if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { + Error ("%s(%u): Exported o65 symbol `%s' cannot also be an o65 import", + Sym->CfgName, Sym->CfgLine, GetString (Sym->Name)); + } + + /* Check if we have this symbol defined already. The entry + * routine will check this also, but we get a more verbose + * error message when checking it here. + */ + if (O65GetExport (O65FmtDesc, Sym->Name) != 0) { + Error ("%s(%u): Duplicate exported o65 symbol: `%s'", + Sym->CfgName, Sym->CfgLine, GetString (Sym->Name)); + } + + /* Insert the symbol into the table */ + O65SetExport (O65FmtDesc, Sym->Name); + } +} + + + +static void ProcessBin (void) +/* Process the bin format section */ +{ +} + + + +static void ProcessFormats (void) +/* Process the target format section */ +{ + ProcessO65 (); + ProcessBin (); +} + + + +static void ProcessSymbols (void) +/* Process the SYMBOLS section */ +{ + Export* E; + + /* Walk over all symbols */ + unsigned I; + for (I = 0; I < CollCount (&Symbols); ++I) { + + /* Get the next symbol */ + Symbol* Sym = CollAtUnchecked (&Symbols, I); + + /* Do we define this symbol? */ + if ((Sym->Flags & SYM_DEF) != 0) { + /* Check if the symbol is already defined somewhere else */ + if ((E = FindExport (Sym->Name)) != 0 && !IsUnresolvedExport (E)) { + /* If the symbol is not marked as weak, this is an error. + * Otherwise ignore the symbol from the config. + */ + if ((Sym->Flags & SYM_WEAK) == 0) { + CfgError ("Symbol `%s' is already defined", + GetString (Sym->Name)); + } + } else { + /* The symbol is undefined, generate an export */ + CreateConstExport (Sym->Name, Sym->Val); + } + + } else { + + + } + } +} + + + +void CfgProcess (void) +/* Process the config file after reading in object files and libraries */ +{ + ProcessSymbols (); /* ######## */ + ProcessMemory (); + ProcessSegments (); + ProcessFormats (); +} + + + static void CreateRunDefines (SegDesc* S, unsigned long SegAddr) /* Create the defines for a RUN segment */ { @@ -1563,19 +1736,16 @@ unsigned CfgAssignSegments (void) * segments while doing this. */ unsigned I; - for (I = 0; I < CollCount (&MemoryList); ++I) { + for (I = 0; I < CollCount (&MemoryAreas); ++I) { unsigned J; /* Get this entry */ - Memory* M = CollAtUnchecked (&MemoryList, I); + MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); /* Get the start address of this memory area */ unsigned long Addr = M->Start; - /* Remember if this is a relocatable memory area */ - M->Relocatable = RelocatableBinFmt (M->F->Format); - /* Walk through the segments in this memory area */ for (J = 0; J < CollCount (&M->SegList); ++J) { @@ -1622,6 +1792,9 @@ unsigned CfgAssignSegments (void) S->Seg->ReadOnly = (S->Flags & SF_RO) != 0; S->Seg->Relocatable = M->Relocatable; + /* Remember that this segment is placed */ + S->Seg->Placed = 1; + } else if (S->Load == M) { /* This is the load memory area, *and* run and load are @@ -1696,7 +1869,7 @@ void CfgWriteTarget (void) File* F = CollAtUnchecked (&FileList, I); /* We don't need to look at files with no memory areas */ - if (CollCount (&F->MemList) > 0) { + if (CollCount (&F->MemoryAreas) > 0) { /* Is there an output file? */ if (SB_GetLen (GetStrBuf (F->Name)) > 0) { @@ -1714,7 +1887,7 @@ void CfgWriteTarget (void) break; case BINFMT_O65: - O65WriteTarget (O65FmtDesc, F); + O65WriteTarget (O65FmtDesc, F); break; default: @@ -1728,12 +1901,12 @@ void CfgWriteTarget (void) * loading into these memory areas in this file as dumped. */ unsigned J; - for (J = 0; J < CollCount (&F->MemList); ++J) { + for (J = 0; J < CollCount (&F->MemoryAreas); ++J) { unsigned K; /* Get this entry */ - Memory* M = CollAtUnchecked (&F->MemList, J); + MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, J); /* Debugging */ Print (stdout, 2, "Skipping `%s'...\n", GetString (M->Name)); diff --git a/src/ld65/config.h b/src/ld65/config.h index aa455da00..4f16e6dab 100644 --- a/src/ld65/config.h +++ b/src/ld65/config.h @@ -52,28 +52,16 @@ +/* Forward for struct MemoryArea */ +struct MemoryArea; + /* File list entry */ typedef struct File File; struct File { unsigned Name; /* Name index of the file */ - unsigned Flags; - unsigned Format; /* Output format */ - Collection MemList; /* List of memory areas in this file */ -}; - -/* Memory list entry */ -typedef struct Memory Memory; -struct Memory { - unsigned Name; /* Name index of the memory section */ - unsigned Attr; /* Which values are valid? */ - unsigned Flags; /* Set of bitmapped flags */ - unsigned long Start; /* Start address */ - unsigned long Size; /* Length of memory section */ - unsigned long FillLevel; /* Actual fill level of segment */ - unsigned char FillVal; /* Value used to fill rest of seg */ - unsigned char Relocatable; /* Memory area is relocatable */ - Collection SegList; /* List of segments for this section */ - File* F; /* File that contains the entry */ + unsigned Flags; + unsigned Format; /* Output format */ + Collection MemoryAreas; /* List of memory areas in this file */ }; /* Segment descriptor entry */ @@ -83,19 +71,13 @@ struct SegDesc { Segment* Seg; /* Pointer to segment structure */ unsigned Attr; /* Attributes for segment */ unsigned Flags; /* Set of bitmapped flags */ - Memory* Load; /* Load memory section */ - Memory* Run; /* Run memory section */ + struct MemoryArea* Load; /* Load memory section */ + struct MemoryArea* Run; /* Run memory section */ unsigned long Addr; /* Start address or offset into segment */ unsigned char Align; /* Run area alignment if given */ unsigned char AlignLoad; /* Load area alignment if given */ }; -/* Memory flags */ -#define MF_DEFINE 0x0001 /* Define start and size */ -#define MF_FILL 0x0002 /* Fill segment */ -#define MF_RO 0x0004 /* Read only memory area */ -#define MF_OVERFLOW 0x0008 /* Memory area overflow */ - /* Segment flags */ #define SF_RO 0x0001 /* Read only segment */ #define SF_BSS 0x0002 /* Segment is BSS style segment */ @@ -120,6 +102,9 @@ struct SegDesc { void CfgRead (void); /* Read the configuration */ +void CfgProcess (void); +/* Process the config file after reading in object files and libraries */ + unsigned CfgAssignSegments (void); /* Assign segments, define linker symbols where requested. The function will * return the number of memory area overflows (so zero means anything went ok). diff --git a/src/ld65/exports.c b/src/ld65/exports.c index b97130899..ca44892af 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -52,6 +52,7 @@ #include "expr.h" #include "fileio.h" #include "global.h" +#include "memarea.h" #include "objdata.h" #include "spool.h" @@ -176,14 +177,14 @@ Import* ReadImport (FILE* F, ObjData* Obj) -Import* GenImport (const char* Name, unsigned char AddrSize) +Import* GenImport (unsigned Name, unsigned char AddrSize) /* Generate a new import with the given name and address size and return it */ { /* Create a new import */ Import* I = NewImport (AddrSize, 0); /* Read the name */ - I->Name = GetStringId (Name); + I->Name = Name; /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { @@ -211,8 +212,8 @@ Import* GenImport (const char* Name, unsigned char AddrSize) -void InsertImport (Import* I) -/* Insert an import into the table */ +Import* InsertImport (Import* I) +/* Insert an import into the table, return I */ { Export* E; @@ -261,6 +262,9 @@ void InsertImport (Import* I) /* Mark the import so we know it's in the list */ I->Flags |= IMP_INLIST; + + /* Return the import to allow shorter code */ + return I; } @@ -463,7 +467,7 @@ Export* CreateConstExport (unsigned Name, long Value) -Export* CreateMemoryExport (unsigned Name, Memory* Mem, unsigned long Offs) +Export* CreateMemoryExport (unsigned Name, MemoryArea* Mem, unsigned long Offs) /* Create an relative export for a memory area offset */ { /* Create a new export */ diff --git a/src/ld65/exports.h b/src/ld65/exports.h index e3c3d89a1..170f80978 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2009, Ullrich von Bassewitz */ +/* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -46,8 +46,9 @@ #include "filepos.h" /* ld65 */ -#include "objdata.h" #include "config.h" +#include "memarea.h" +#include "objdata.h" @@ -114,11 +115,11 @@ void FreeImport (Import* I); Import* ReadImport (FILE* F, ObjData* Obj); /* Read an import from a file and insert it into the table */ -Import* GenImport (const char* Name, unsigned char AddrSize); +Import* GenImport (unsigned Name, unsigned char AddrSize); /* Generate a new import with the given name and address size and return it */ -void InsertImport (Import* I); -/* Insert an import into the table */ +Import* InsertImport (Import* I); +/* Insert an import into the table, return I */ void FreeExport (Export* E); /* Free an export. NOTE: This won't remove the export from the exports table, @@ -135,7 +136,7 @@ void InsertExport (Export* E); Export* CreateConstExport (unsigned Name, long Value); /* Create an export for a literal date */ -Export* CreateMemoryExport (unsigned Name, Memory* Mem, unsigned long Offs); +Export* CreateMemoryExport (unsigned Name, MemoryArea* Mem, unsigned long Offs); /* Create an relative export for a memory area offset */ Export* CreateSegmentExport (unsigned Name, Segment* Seg, unsigned long Offs); diff --git a/src/ld65/expr.c b/src/ld65/expr.c index 94f910d7a..a5b7a3c5c 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -42,23 +42,24 @@ #include "global.h" #include "error.h" #include "fileio.h" +#include "memarea.h" #include "segments.h" #include "expr.h" /*****************************************************************************/ -/* Helpers */ +/* Code */ /*****************************************************************************/ -static ExprNode* NewExprNode (ObjData* O) +ExprNode* NewExprNode (ObjData* O, unsigned char Op) /* Create a new expression node */ { /* Allocate fresh memory */ ExprNode* N = xmalloc (sizeof (ExprNode)); - N->Op = EXPR_NULL; + N->Op = Op; N->Left = 0; N->Right = 0; N->Obj = O; @@ -78,12 +79,6 @@ static void FreeExprNode (ExprNode* E) -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ - - - void FreeExpr (ExprNode* Root) /* Free the expression, Root is pointing to. */ { @@ -130,18 +125,19 @@ int IsConstExpr (ExprNode* Root) case EXPR_SECTION: /* A section expression is const if the segment it is in is - * not relocatable. + * not relocatable and already placed. */ S = GetExprSection (Root); - return !S->Seg->Relocatable; + return !S->Seg->Relocatable && S->Seg->Placed; case EXPR_SEGMENT: - /* A segment is const if it is not relocatable */ - return !Root->V.Seg->Relocatable; + /* A segment is const if it is not relocatable and placed */ + return !Root->V.Seg->Relocatable && Root->V.Seg->Placed; case EXPR_MEMAREA: - /* A memory area is const if it is not relocatable */ - return !Root->V.Mem->Relocatable; + /* A memory area is const if it is not relocatable and placed */ + return !Root->V.Mem->Relocatable && + (Root->V.Mem->Flags & MF_PLACED); default: /* Anything else is not const */ @@ -201,7 +197,7 @@ Import* GetExprImport (ExprNode* Expr) PRECONDITION (Expr->Op == EXPR_SYMBOL); /* Return the import */ - return CollAt (&Expr->Obj->Imports, Expr->V.ImpNum); + return Expr->V.Imp; } @@ -397,26 +393,23 @@ long GetExprVal (ExprNode* Expr) ExprNode* LiteralExpr (long Val, ObjData* O) /* Return an expression tree that encodes the given literal value */ { - ExprNode* Expr = NewExprNode (O); - Expr->Op = EXPR_LITERAL; + ExprNode* Expr = NewExprNode (O, EXPR_LITERAL); Expr->V.IVal = Val; return Expr; } -ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O) +ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O) /* Return an expression tree that encodes an offset into a memory area */ { ExprNode* Root; - ExprNode* Expr = NewExprNode (O); - Expr->Op = EXPR_MEMAREA; + ExprNode* Expr = NewExprNode (O, EXPR_MEMAREA); Expr->V.Mem = Mem; if (Offs != 0) { - Root = NewExprNode (O); - Root->Op = EXPR_PLUS; + Root = NewExprNode (O, EXPR_PLUS); Root->Left = Expr; Root->Right = LiteralExpr (Offs, O); } else { @@ -433,13 +426,11 @@ ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O) { ExprNode* Root; - ExprNode* Expr = NewExprNode (O); - Expr->Op = EXPR_SEGMENT; + ExprNode* Expr = NewExprNode (O, EXPR_SEGMENT); Expr->V.Seg = Seg; if (Offs != 0) { - Root = NewExprNode (O); - Root->Op = EXPR_PLUS; + Root = NewExprNode (O, EXPR_PLUS); Root->Left = Expr; Root->Right = LiteralExpr (Offs, O); } else { @@ -456,13 +447,11 @@ ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O) { ExprNode* Root; - ExprNode* Expr = NewExprNode (O); - Expr->Op = EXPR_SECTION; + ExprNode* Expr = NewExprNode (O, EXPR_SECTION); Expr->V.Sec = Sec; if (Offs != 0) { - Root = NewExprNode (O); - Root->Op = EXPR_PLUS; + Root = NewExprNode (O, EXPR_PLUS); Root->Left = Expr; Root->Right = LiteralExpr (Offs, O); } else { @@ -478,6 +467,7 @@ ExprNode* ReadExpr (FILE* F, ObjData* O) /* Read an expression from the given file */ { ExprNode* Expr; + unsigned ImpNum; /* Read the node tag and handle NULL nodes */ unsigned char Op = Read8 (F); @@ -486,29 +476,29 @@ ExprNode* ReadExpr (FILE* F, ObjData* O) } /* Create a new node */ - Expr = NewExprNode (O); - Expr->Op = Op; + Expr = NewExprNode (O, Op); /* Check the tag and handle the different expression types */ if (EXPR_IS_LEAF (Op)) { switch (Op) { case EXPR_LITERAL: - Expr->V.IVal = Read32Signed (F); - break; + Expr->V.IVal = Read32Signed (F); + break; case EXPR_SYMBOL: - /* Read the import number */ - Expr->V.ImpNum = ReadVar (F); - break; + /* Read the import number */ + ImpNum = ReadVar (F); + Expr->V.Imp = CollAt (&O->Imports, ImpNum); + break; case EXPR_SECTION: - /* Read the segment number */ - Expr->V.SegNum = Read8 (F); - break; + /* Read the segment number */ + Expr->V.SegNum = Read8 (F); + break; default: - Error ("Invalid expression op: %02X", Op); + Error ("Invalid expression op: %02X", Op); } @@ -550,8 +540,8 @@ int EqualExpr (ExprNode* E1, ExprNode* E2) return (E1->V.IVal == E2->V.IVal); case EXPR_SYMBOL: - /* Import number must be identical */ - return (E1->V.ImpNum == E2->V.ImpNum); + /* Import must be identical */ + return (E1->V.Imp == E2->V.Imp); case EXPR_SECTION: /* Section must be identical */ @@ -563,7 +553,7 @@ int EqualExpr (ExprNode* E1, ExprNode* E2) case EXPR_MEMAREA: /* Memory area must be identical */ - return (E1->V.Mem == E2->V.Mem ); + return (E1->V.Mem == E2->V.Mem); default: /* Not a leaf node */ diff --git a/src/ld65/expr.h b/src/ld65/expr.h index 536f08c41..0e9eafecf 100644 --- a/src/ld65/expr.h +++ b/src/ld65/expr.h @@ -54,6 +54,9 @@ +ExprNode* NewExprNode (ObjData* O, unsigned char Op); +/* Create a new expression node */ + void FreeExpr (ExprNode* Root); /* Free the expression tree, Root is pointing to. */ @@ -77,7 +80,7 @@ long GetExprVal (ExprNode* Expr); ExprNode* LiteralExpr (long Val, ObjData* O); /* Return an expression tree that encodes the given literal value */ -ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O); +ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O); /* Return an expression tree that encodes an offset into the memory area */ ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O); diff --git a/src/ld65/library.c b/src/ld65/library.c index 228f6c2ee..2c45d0010 100644 --- a/src/ld65/library.c +++ b/src/ld65/library.c @@ -211,14 +211,14 @@ static ObjData* ReadIndexEntry (Library* L) /* Read the string pool */ ObjReadStrPool (L->F, FileGetPos (L->F), O); - /* Skip the export size, then read the exports */ - (void) ReadVar (L->F); - ObjReadExports (L->F, FileGetPos (L->F), O); - /* Skip the import size, then read the imports */ (void) ReadVar (L->F); ObjReadImports (L->F, FileGetPos (L->F), O); + /* Skip the export size, then read the exports */ + (void) ReadVar (L->F); + ObjReadExports (L->F, FileGetPos (L->F), O); + /* Done */ return O; } diff --git a/src/ld65/main.c b/src/ld65/main.c index 10fff402e..19356630c 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -302,6 +302,9 @@ static void OptConfig (const char* Opt attribute ((unused)), const char* Arg) } else { CfgSetName (PathName); } + + /* Read the config */ + CfgRead (); } @@ -356,7 +359,7 @@ static void OptForceImport (const char* Opt attribute ((unused)), const char* Ar /* Use default address size (which for now is always absolute * addressing) */ - InsertImport (GenImport (Arg, ADDR_SIZE_ABS)); + InsertImport (GenImport (GetStringId (Arg), ADDR_SIZE_ABS)); } else { @@ -375,7 +378,7 @@ static void OptForceImport (const char* Opt attribute ((unused)), const char* Ar A[ColPos - Arg] = '\0'; /* Generate the import */ - InsertImport (GenImport (A, AddrSize)); + InsertImport (GenImport (GetStringId (A), AddrSize)); /* Delete the copy of the argument */ xfree (A); @@ -481,6 +484,9 @@ static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target data */ DefaultBinFmt = D->BinFmt; CfgSetBuf (D->Cfg); + + /* Read the target config */ + CfgRead (); } @@ -643,12 +649,12 @@ int main (int argc, char* argv []) /* Check if we have open library groups */ LibCheckGroup (); - /* Read the config file */ - CfgRead (); - /* Create the condes tables if requested */ ConDesCreate (); + /* Process data from the config file */ + CfgProcess (); + /* Assign start addresses for the segments, define linker symbols. The * function will return the number of memory area overflows (zero on * success). diff --git a/src/ld65/make/gcc.mak b/src/ld65/make/gcc.mak index 9d5c0c996..292bd1e8b 100644 --- a/src/ld65/make/gcc.mak +++ b/src/ld65/make/gcc.mak @@ -51,6 +51,7 @@ OBJS = asserts.o \ lineinfo.o \ main.o \ mapfile.o \ + memarea.o \ o65.o \ objdata.o \ objfile.o \ diff --git a/src/ld65/make/watcom.mak b/src/ld65/make/watcom.mak index c1f6b04af..b54e1a3b0 100644 --- a/src/ld65/make/watcom.mak +++ b/src/ld65/make/watcom.mak @@ -82,6 +82,7 @@ OBJS = asserts.obj \ lineinfo.obj \ main.obj \ mapfile.obj \ + memarea.obj \ o65.obj \ objdata.obj \ objfile.obj \ diff --git a/src/ld65/memarea.c b/src/ld65/memarea.c new file mode 100644 index 000000000..a6376647f --- /dev/null +++ b/src/ld65/memarea.c @@ -0,0 +1,76 @@ +/*****************************************************************************/ +/* */ +/* memarea.c */ +/* */ +/* Memory area definition for the ld65 linker */ +/* */ +/* */ +/* */ +/* (C) 2010, Ullrich von Bassewitz */ +/* Roemerstrasse 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 "xmalloc.h" + +/* ld65 */ +#include "memarea.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +MemoryArea* NewMemoryArea (unsigned Name) +/* Create a new memory area and insert it into the list */ +{ + /* Allocate memory */ + MemoryArea* M = xmalloc (sizeof (MemoryArea)); + + /* Initialize the fields ... */ + M->Name = Name; + M->Attr = 0; + M->Flags = 0; + M->StartExpr = 0; + M->Start = 0; + M->SizeExpr = 0; + M->Size = 0; + M->FillLevel = 0; + M->FillVal = 0; + M->Relocatable = 0; + InitCollection (&M->SegList); + M->F = 0; + + /* ...and return it */ + return M; +} + + + + diff --git a/src/ld65/memarea.h b/src/ld65/memarea.h new file mode 100644 index 000000000..7306c113d --- /dev/null +++ b/src/ld65/memarea.h @@ -0,0 +1,100 @@ +/*****************************************************************************/ +/* */ +/* memarea.h */ +/* */ +/* Memory area definition for the ld65 linker */ +/* */ +/* */ +/* */ +/* (C) 2010, Ullrich von Bassewitz */ +/* Roemerstrasse 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. */ +/* */ +/*****************************************************************************/ + + + +#ifndef MEMAREA_H +#define MEMAREA_H + + + +/* common */ +#include "coll.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Forwards for structures */ +struct ExprNode; +struct File; + +/* Memory area entry */ +typedef struct MemoryArea MemoryArea; +struct MemoryArea { + unsigned Name; /* Name index of the memory section */ + unsigned Attr; /* Which values are valid? */ + unsigned Flags; /* Set of bitmapped flags */ + struct ExprNode* StartExpr; /* Expression for start address */ + unsigned long Start; /* Start address */ + struct ExprNode* SizeExpr; /* Expression for size */ + unsigned long Size; /* Length of memory section */ + unsigned long FillLevel; /* Actual fill level of segment */ + unsigned char FillVal; /* Value used to fill rest of seg */ + unsigned char Relocatable; /* Memory area is relocatable */ + Collection SegList; /* List of segments for this area */ + struct File* F; /* Output file for this area */ +}; + +/* Memory flags */ +#define MF_DEFINE 0x0001 /* Define start and size */ +#define MF_FILL 0x0002 /* Fill segment */ +#define MF_RO 0x0004 /* Read only memory area */ +#define MF_OVERFLOW 0x0008 /* Memory area overflow */ +#define MF_PLACED 0x0010 /* Memory area was placed */ + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +MemoryArea* NewMemoryArea (unsigned Name); +/* Create a new memory area and insert it into the list */ + + + +/* End of memarea.h */ + +#endif + + + + + diff --git a/src/ld65/o65.c b/src/ld65/o65.c index e583bb8c3..6845efed1 100644 --- a/src/ld65/o65.c +++ b/src/ld65/o65.c @@ -53,6 +53,7 @@ #include "fileio.h" #include "global.h" #include "lineinfo.h" +#include "memarea.h" #include "o65.h" #include "spool.h" @@ -175,7 +176,7 @@ struct ExprDesc { O65Desc* D; /* File format descriptor */ long Val; /* The offset value */ int TooComplex; /* Expression too complex */ - Memory* MemRef; /* Memory reference if any */ + MemoryArea* MemRef; /* Memory reference if any */ Segment* SegRef; /* Segment reference if any */ Section* SecRef; /* Section reference if any */ ExtSym* ExtRef; /* External reference if any */ @@ -244,7 +245,7 @@ static void CvtMemoryToSegment (ExprDesc* ED) */ { /* Get the memory area from the expression */ - Memory* M = ED->MemRef; + MemoryArea* M = ED->MemRef; /* Remember the "nearest" segment and its offset */ Segment* Nearest = 0; @@ -1227,9 +1228,9 @@ static void O65SetupSegments (O65Desc* D, File* F) D->ZPCount = 0; /* Walk over the memory list */ - for (I = 0; I < CollCount (&F->MemList); ++I) { + for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ - Memory* M = CollAtUnchecked (&F->MemList, I); + MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); /* Walk through the segment list and count the segment types */ unsigned J; @@ -1257,9 +1258,9 @@ static void O65SetupSegments (O65Desc* D, File* F) /* Walk again through the list and setup the segment arrays */ TextIdx = DataIdx = BssIdx = ZPIdx = 0; - for (I = 0; I < CollCount (&F->MemList); ++I) { + for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ - Memory* M = CollAtUnchecked (&F->MemList, I); + MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); /* Walk over the segment list and check the segment types */ unsigned J; diff --git a/src/ld65/segments.c b/src/ld65/segments.c index f9154e194..3d762cae1 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -103,6 +103,7 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize) S->AddrSize = AddrSize; S->ReadOnly = 0; S->Relocatable = 0; + S->Placed = 0; S->Dumped = 0; /* Insert the segment into the segment list and assign the segment id */ @@ -487,7 +488,7 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* /* Write the data from the given segment to a file. For expressions, F is * called (see description of SegWriteFunc above). */ -{ +{ Section* Sec; int Sign; unsigned long Offs = 0; diff --git a/src/ld65/segments.h b/src/ld65/segments.h index c61d7839e..3af9fa09e 100644 --- a/src/ld65/segments.h +++ b/src/ld65/segments.h @@ -70,6 +70,7 @@ struct 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 Placed; /* Did we place this segment already? */ unsigned char Dumped; /* Did we dump this segment? */ };