X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fconfig.c;h=f8bff2ac050fa5b5008e9d5b8b4be4d359f2fd55;hb=b03ae76b54d77f435088cacf12d3cfd9873f05ed;hp=d0ad874aeca6d14bf298b65026d19d7ed621bba9;hpb=081308942c2421a8a22fd0fd856e80e066445d77;p=cc65 diff --git a/src/ld65/config.c b/src/ld65/config.c index d0ad874ae..f8bff2ac0 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1,12 +1,12 @@ /*****************************************************************************/ /* */ -/* config.c */ +/* config.c */ /* */ -/* Target configuration file for the ld65 linker */ +/* Target configuration file for the ld65 linker */ /* */ /* */ /* */ -/* (C) 1998-2011, Ullrich von Bassewitz */ +/* (c) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -47,6 +47,8 @@ #include "bitops.h" #include "check.h" #include "print.h" +#include "segdefs.h" +#include "target.h" #include "xmalloc.h" #include "xsprintf.h" @@ -66,11 +68,12 @@ #include "objdata.h" #include "scanner.h" #include "spool.h" +#include "xex.h" /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -95,27 +98,29 @@ static Collection FileList = STATIC_COLLECTION_INITIALIZER; static Collection MemoryAreas = STATIC_COLLECTION_INITIALIZER; /* Memory attributes */ -#define MA_START 0x0001 -#define MA_SIZE 0x0002 -#define MA_TYPE 0x0004 -#define MA_FILE 0x0008 -#define MA_DEFINE 0x0010 -#define MA_FILL 0x0020 -#define MA_FILLVAL 0x0040 +#define MA_START 0x0001 +#define MA_SIZE 0x0002 +#define MA_TYPE 0x0004 +#define MA_FILE 0x0008 +#define MA_DEFINE 0x0010 +#define MA_FILL 0x0020 +#define MA_FILLVAL 0x0040 +#define MA_BANK 0x0080 /* Segment list */ static Collection SegDescList = STATIC_COLLECTION_INITIALIZER; /* Segment attributes */ -#define SA_TYPE 0x0001 -#define SA_LOAD 0x0002 -#define SA_RUN 0x0004 -#define SA_ALIGN 0x0008 +#define SA_TYPE 0x0001 +#define SA_LOAD 0x0002 +#define SA_RUN 0x0004 +#define SA_ALIGN 0x0008 #define SA_ALIGN_LOAD 0x0010 -#define SA_DEFINE 0x0020 -#define SA_OFFSET 0x0040 -#define SA_START 0x0080 +#define SA_DEFINE 0x0020 +#define SA_OFFSET 0x0040 +#define SA_START 0x0080 #define SA_OPTIONAL 0x0100 +#define SA_FILLVAL 0x0200 /* Symbol types used in the CfgSymbol structure */ typedef enum { @@ -127,9 +132,9 @@ typedef enum { } CfgSymType; /* 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). - */ +** symbols from the SYMBOLS sections (symbols defined in the config file or +** forced imports). +*/ typedef struct CfgSymbol CfgSymbol; struct CfgSymbol { CfgSymType Type; /* Type of symbol */ @@ -143,13 +148,14 @@ struct CfgSymbol { static Collection CfgSymbols = STATIC_COLLECTION_INITIALIZER; /* Descriptor holding information about the binary formats */ -static BinDesc* BinFmtDesc = 0; -static O65Desc* O65FmtDesc = 0; +static BinDesc* BinFmtDesc = 0; +static O65Desc* O65FmtDesc = 0; +static XexDesc* XexFmtDesc = 0; /*****************************************************************************/ -/* Forwards */ +/* Forwards */ /*****************************************************************************/ @@ -160,7 +166,7 @@ static File* NewFile (unsigned Name); /*****************************************************************************/ -/* List management */ +/* List management */ /*****************************************************************************/ @@ -171,9 +177,9 @@ static File* FindFile (unsigned Name) unsigned I; for (I = 0; I < CollCount (&FileList); ++I) { File* F = CollAtUnchecked (&FileList, I); - if (F->Name == Name) { - return F; - } + if (F->Name == Name) { + return F; + } } return 0; } @@ -185,8 +191,8 @@ static File* GetFile (unsigned Name) { File* F = FindFile (Name); if (F == 0) { - /* Create a new one */ - F = NewFile (Name); + /* Create a new one */ + F = NewFile (Name); } return F; } @@ -208,9 +214,9 @@ static MemoryArea* CfgFindMemory (unsigned Name) unsigned I; for (I = 0; I < CollCount (&MemoryAreas); ++I) { MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); - if (M->Name == Name) { - return M; - } + if (M->Name == Name) { + return M; + } } return 0; } @@ -222,7 +228,7 @@ static MemoryArea* CfgGetMemory (unsigned Name) { MemoryArea* M = CfgFindMemory (Name); if (M == 0) { - CfgError (&CfgErrorPos, "Invalid memory area `%s'", GetString (Name)); + CfgError (&CfgErrorPos, "Invalid memory area '%s'", GetString (Name)); } return M; } @@ -235,10 +241,10 @@ static SegDesc* CfgFindSegDesc (unsigned Name) unsigned I; for (I = 0; I < CollCount (&SegDescList); ++I) { SegDesc* S = CollAtUnchecked (&SegDescList, I); - if (S->Name == Name) { - /* Found */ - return S; - } + if (S->Name == Name) { + /* Found */ + return S; + } } /* Not found */ @@ -257,16 +263,16 @@ static void MemoryInsert (MemoryArea* M, SegDesc* S) /*****************************************************************************/ -/* Constructors/Destructors */ +/* Constructors/Destructors */ /*****************************************************************************/ static CfgSymbol* NewCfgSymbol (CfgSymType Type, unsigned Name) /* Create a new CfgSymbol structure with the given type and name. The - * current config file position is recorded in the returned struct. The - * created struct is inserted into the CfgSymbols collection and returned. - */ +** current config file position is recorded in the returned struct. The +** created struct is inserted into the CfgSymbols collection and returned. +*/ { /* Allocate memory */ CfgSymbol* Sym = xmalloc (sizeof (CfgSymbol)); @@ -315,8 +321,8 @@ static MemoryArea* CreateMemoryArea (const FilePos* Pos, unsigned Name) /* Check for duplicate names */ MemoryArea* M = CfgFindMemory (Name); if (M) { - CfgError (&CfgErrorPos, - "Memory area `%s' defined twice", + CfgError (&CfgErrorPos, + "Memory area '%s' defined twice", GetString (Name)); } @@ -339,7 +345,7 @@ static SegDesc* NewSegDesc (unsigned Name) /* Check for duplicate names */ SegDesc* S = CfgFindSegDesc (Name); if (S) { - CfgError (&CfgErrorPos, "Segment `%s' defined twice", GetString (Name)); + CfgError (&CfgErrorPos, "Segment '%s' defined twice", GetString (Name)); } /* Allocate memory */ @@ -351,6 +357,7 @@ static SegDesc* NewSegDesc (unsigned Name) S->Seg = 0; S->Attr = 0; S->Flags = 0; + S->FillVal = 0; S->RunAlignment = 1; S->LoadAlignment = 1; @@ -380,11 +387,11 @@ static void FreeSegDesc (SegDesc* S) static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name) /* Check if the item is already defined. Print an error if so. If not, set - * the marker that we have a definition now. - */ +** the marker that we have a definition now. +*/ { if (*Flags & Mask) { - CfgError (&CfgErrorPos, "%s is already defined", Name); + CfgError (&CfgErrorPos, "%s is already defined", Name); } *Flags |= Mask; } @@ -395,7 +402,7 @@ static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name) /* Check that a mandatory attribute was given */ { if ((Attr & Mask) == 0) { - CfgError (&CfgErrorPos, "%s attribute is missing", Name); + CfgError (&CfgErrorPos, "%s attribute is missing", Name); } } @@ -405,118 +412,124 @@ static void ParseMemory (void) /* Parse a MEMORY section */ { static const IdentTok Attributes [] = { - { "START", CFGTOK_START }, - { "SIZE", CFGTOK_SIZE }, - { "TYPE", CFGTOK_TYPE }, - { "FILE", CFGTOK_FILE }, + { "BANK", CFGTOK_BANK }, { "DEFINE", CFGTOK_DEFINE }, - { "FILL", CFGTOK_FILL }, - { "FILLVAL", CFGTOK_FILLVAL }, + { "FILE", CFGTOK_FILE }, + { "FILL", CFGTOK_FILL }, + { "FILLVAL", CFGTOK_FILLVAL }, + { "SIZE", CFGTOK_SIZE }, + { "START", CFGTOK_START }, + { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { - { "RO", CFGTOK_RO }, - { "RW", CFGTOK_RW }, + { "RO", CFGTOK_RO }, + { "RW", CFGTOK_RW }, }; while (CfgTok == CFGTOK_IDENT) { - /* Create a new entry on the heap */ - MemoryArea* M = CreateMemoryArea (&CfgErrorPos, GetStrBufId (&CfgSVal)); + /* Create a new entry on the heap */ + MemoryArea* M = CreateMemoryArea (&CfgErrorPos, GetStrBufId (&CfgSVal)); - /* Skip the name and the following colon */ - CfgNextTok (); - CfgConsumeColon (); + /* Skip the name and the following colon */ + CfgNextTok (); + CfgConsumeColon (); - /* Read the attributes */ - while (CfgTok == CFGTOK_IDENT) { + /* Read the attributes */ + while (CfgTok == CFGTOK_IDENT) { - /* Map the identifier to a token */ - cfgtok_t AttrTok; - CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); - AttrTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; - /* An optional assignment follows */ - CfgNextTok (); - CfgOptionalAssign (); + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); - /* Check which attribute was given */ - switch (AttrTok) { + /* Check which attribute was given */ + switch (AttrTok) { - case CFGTOK_START: - FlagAttr (&M->Attr, MA_START, "START"); - M->StartExpr = CfgExpr (); - break; - - case CFGTOK_SIZE: - FlagAttr (&M->Attr, MA_SIZE, "SIZE"); - M->SizeExpr = CfgExpr (); - break; - - case CFGTOK_TYPE: - FlagAttr (&M->Attr, MA_TYPE, "TYPE"); - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - if (CfgTok == CFGTOK_RO) { - M->Flags |= MF_RO; - } - CfgNextTok (); - break; + case CFGTOK_BANK: + FlagAttr (&M->Attr, MA_BANK, "BANK"); + M->BankExpr = CfgExpr (); + break; - case CFGTOK_FILE: - FlagAttr (&M->Attr, MA_FILE, "FILE"); - CfgAssureStr (); - /* Get the file entry and insert the memory area */ - FileInsert (GetFile (GetStrBufId (&CfgSVal)), M); + case CFGTOK_DEFINE: + FlagAttr (&M->Attr, MA_DEFINE, "DEFINE"); + /* Map the token to a boolean */ + CfgBoolToken (); + if (CfgTok == CFGTOK_TRUE) { + M->Flags |= MF_DEFINE; + } CfgNextTok (); - break; - - case CFGTOK_DEFINE: - FlagAttr (&M->Attr, MA_DEFINE, "DEFINE"); - /* Map the token to a boolean */ - CfgBoolToken (); - if (CfgTok == CFGTOK_TRUE) { - M->Flags |= MF_DEFINE; - } + break; + + case CFGTOK_FILE: + FlagAttr (&M->Attr, MA_FILE, "FILE"); + CfgAssureStr (); + /* Get the file entry and insert the memory area */ + FileInsert (GetFile (GetStrBufId (&CfgSVal)), M); CfgNextTok (); - break; - - case CFGTOK_FILL: - FlagAttr (&M->Attr, MA_FILL, "FILL"); - /* Map the token to a boolean */ - CfgBoolToken (); - if (CfgTok == CFGTOK_TRUE) { - M->Flags |= MF_FILL; - } + break; + + case CFGTOK_FILL: + FlagAttr (&M->Attr, MA_FILL, "FILL"); + /* Map the token to a boolean */ + CfgBoolToken (); + if (CfgTok == CFGTOK_TRUE) { + M->Flags |= MF_FILL; + } CfgNextTok (); - break; + break; - case CFGTOK_FILLVAL: - FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL"); - M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); - break; + case CFGTOK_FILLVAL: + FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL"); + M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); + break; - default: - FAIL ("Unexpected attribute token"); + case CFGTOK_SIZE: + FlagAttr (&M->Attr, MA_SIZE, "SIZE"); + M->SizeExpr = CfgExpr (); + break; - } + case CFGTOK_START: + FlagAttr (&M->Attr, MA_START, "START"); + M->StartExpr = CfgExpr (); + break; - /* Skip an optional comma */ - CfgOptionalComma (); - } + case CFGTOK_TYPE: + FlagAttr (&M->Attr, MA_TYPE, "TYPE"); + CfgSpecialToken (Types, ENTRY_COUNT (Types), "TYPE"); + if (CfgTok == CFGTOK_RO) { + M->Flags |= MF_RO; + } + CfgNextTok (); + break; + + default: + FAIL ("Unexpected attribute token"); + + } + + /* Skip an optional comma */ + CfgOptionalComma (); + } - /* Skip the semicolon */ - CfgConsumeSemi (); + /* Skip the semicolon */ + CfgConsumeSemi (); - /* Check for mandatory parameters */ - AttrCheck (M->Attr, MA_START, "START"); - AttrCheck (M->Attr, MA_SIZE, "SIZE"); + /* Check for mandatory parameters */ + AttrCheck (M->Attr, MA_START, "START"); + AttrCheck (M->Attr, MA_SIZE, "SIZE"); - /* If we don't have a file name for output given, use the default - * file name. - */ - if ((M->Attr & MA_FILE) == 0) { - FileInsert (GetFile (GetStringId (OutputName)), M); - OutputNameUsed = 1; - } + /* If we don't have a file name for output given, use the default + ** file name. + */ + if ((M->Attr & MA_FILE) == 0) { + FileInsert (GetFile (GetStringId (OutputName)), M); + OutputNameUsed = 1; + } } /* Remember we had this section */ @@ -529,12 +542,13 @@ static void ParseFiles (void) /* Parse a FILES section */ { static const IdentTok Attributes [] = { - { "FORMAT", CFGTOK_FORMAT }, + { "FORMAT", CFGTOK_FORMAT }, }; static const IdentTok Formats [] = { - { "O65", CFGTOK_O65 }, - { "BIN", CFGTOK_BIN }, - { "BINARY", CFGTOK_BIN }, + { "ATARI", CFGTOK_ATARIEXE }, + { "O65", CFGTOK_O65 }, + { "BIN", CFGTOK_BIN }, + { "BINARY", CFGTOK_BIN }, }; @@ -546,73 +560,77 @@ static void ParseFiles (void) /* Parse all files */ while (CfgTok != CFGTOK_RCURLY) { - File* F; + File* F; - /* We expect a string value here */ - CfgAssureStr (); + /* We expect a string value here */ + CfgAssureStr (); - /* Search for the file, it must exist */ - F = FindFile (GetStrBufId (&CfgSVal)); - if (F == 0) { - CfgError (&CfgErrorPos, - "File `%s' not found in MEMORY section", + /* Search for the file, it must exist */ + F = FindFile (GetStrBufId (&CfgSVal)); + if (F == 0) { + CfgError (&CfgErrorPos, + "File '%s' not found in MEMORY section", SB_GetConstBuf (&CfgSVal)); - } + } - /* Skip the token and the following colon */ - CfgNextTok (); - CfgConsumeColon (); + /* Skip the token and the following colon */ + CfgNextTok (); + CfgConsumeColon (); - /* Read the attributes */ - while (CfgTok == CFGTOK_IDENT) { + /* Read the attributes */ + while (CfgTok == CFGTOK_IDENT) { - /* Map the identifier to a token */ - cfgtok_t AttrTok; - CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); - AttrTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; - /* An optional assignment follows */ - CfgNextTok (); - CfgOptionalAssign (); + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); - /* Check which attribute was given */ - switch (AttrTok) { + /* Check which attribute was given */ + switch (AttrTok) { - case CFGTOK_FORMAT: - if (F->Format != BINFMT_DEFAULT) { - /* We've set the format already! */ - CfgError (&CfgErrorPos, + case CFGTOK_FORMAT: + if (F->Format != BINFMT_DEFAULT) { + /* We've set the format already! */ + CfgError (&CfgErrorPos, "Cannot set a file format twice"); - } - /* Read the format token */ - CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); - switch (CfgTok) { + } + /* Read the format token */ + CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); + switch (CfgTok) { + + case CFGTOK_BIN: + F->Format = BINFMT_BINARY; + break; - case CFGTOK_BIN: - F->Format = BINFMT_BINARY; - break; + case CFGTOK_O65: + F->Format = BINFMT_O65; + break; - case CFGTOK_O65: - F->Format = BINFMT_O65; - break; + case CFGTOK_ATARIEXE: + F->Format = BINFMT_ATARIEXE; + break; - default: - Error ("Unexpected format token"); - } - break; + default: + Error ("Unexpected format token"); + } + break; - default: - FAIL ("Unexpected attribute token"); + default: + FAIL ("Unexpected attribute token"); - } + } - /* Skip the attribute value and an optional comma */ - CfgNextTok (); - CfgOptionalComma (); - } + /* Skip the attribute value and an optional comma */ + CfgNextTok (); + CfgOptionalComma (); + } - /* Skip the semicolon */ - CfgConsumeSemi (); + /* Skip the semicolon */ + CfgConsumeSemi (); } @@ -629,18 +647,20 @@ static void ParseSegments (void) { "ALIGN", CFGTOK_ALIGN }, { "ALIGN_LOAD", CFGTOK_ALIGN_LOAD }, { "DEFINE", CFGTOK_DEFINE }, - { "LOAD", CFGTOK_LOAD }, - { "OFFSET", CFGTOK_OFFSET }, + { "FILLVAL", CFGTOK_FILLVAL }, + { "LOAD", CFGTOK_LOAD }, + { "OFFSET", CFGTOK_OFFSET }, { "OPTIONAL", CFGTOK_OPTIONAL }, - { "RUN", CFGTOK_RUN }, - { "START", CFGTOK_START }, + { "RUN", CFGTOK_RUN }, + { "START", CFGTOK_START }, { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { - { "RO", CFGTOK_RO }, - { "RW", CFGTOK_RW }, - { "BSS", CFGTOK_BSS }, - { "ZP", CFGTOK_ZP }, + { "RO", CFGTOK_RO }, + { "RW", CFGTOK_RW }, + { "BSS", CFGTOK_BSS }, + { "ZP", CFGTOK_ZP }, + { "OVERWRITE", CFGTOK_OVERWRITE }, }; unsigned Count; @@ -652,121 +672,128 @@ static void ParseSegments (void) while (CfgTok == CFGTOK_IDENT) { - SegDesc* S; + SegDesc* S; - /* Create a new entry on the heap */ - S = NewSegDesc (GetStrBufId (&CfgSVal)); + /* Create a new entry on the heap */ + S = NewSegDesc (GetStrBufId (&CfgSVal)); - /* Skip the name and the following colon */ - CfgNextTok (); - CfgConsumeColon (); + /* Skip the name and the following colon */ + CfgNextTok (); + CfgConsumeColon (); - /* Read the attributes */ - while (CfgTok == CFGTOK_IDENT) { + /* Read the attributes */ + while (CfgTok == CFGTOK_IDENT) { - /* Map the identifier to a token */ - cfgtok_t AttrTok; - CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); - AttrTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; - /* An optional assignment follows */ - CfgNextTok (); - CfgOptionalAssign (); + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); - /* Check which attribute was given */ - switch (AttrTok) { + /* Check which attribute was given */ + switch (AttrTok) { - case CFGTOK_ALIGN: - FlagAttr (&S->Attr, SA_ALIGN, "ALIGN"); - S->RunAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT); - S->Flags |= SF_ALIGN; - break; + case CFGTOK_ALIGN: + FlagAttr (&S->Attr, SA_ALIGN, "ALIGN"); + S->RunAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT); + S->Flags |= SF_ALIGN; + break; case CFGTOK_ALIGN_LOAD: - FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD"); - S->LoadAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT); - S->Flags |= SF_ALIGN_LOAD; - break; - - case CFGTOK_DEFINE: - FlagAttr (&S->Attr, SA_DEFINE, "DEFINE"); - /* Map the token to a boolean */ - CfgBoolToken (); - if (CfgTok == CFGTOK_TRUE) { - S->Flags |= SF_DEFINE; - } + FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD"); + S->LoadAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT); + S->Flags |= SF_ALIGN_LOAD; + break; + + case CFGTOK_DEFINE: + FlagAttr (&S->Attr, SA_DEFINE, "DEFINE"); + /* Map the token to a boolean */ + CfgBoolToken (); + if (CfgTok == CFGTOK_TRUE) { + S->Flags |= SF_DEFINE; + } CfgNextTok (); - break; + break; + + case CFGTOK_FILLVAL: + FlagAttr (&S->Attr, SA_FILLVAL, "FILLVAL"); + S->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); + S->Flags |= SF_FILLVAL; + break; - case CFGTOK_LOAD: - FlagAttr (&S->Attr, SA_LOAD, "LOAD"); - S->Load = CfgGetMemory (GetStrBufId (&CfgSVal)); + case CFGTOK_LOAD: + FlagAttr (&S->Attr, SA_LOAD, "LOAD"); + S->Load = CfgGetMemory (GetStrBufId (&CfgSVal)); CfgNextTok (); - break; - - case CFGTOK_OFFSET: - FlagAttr (&S->Attr, SA_OFFSET, "OFFSET"); - S->Addr = CfgCheckedConstExpr (1, 0x1000000); - S->Flags |= SF_OFFSET; - break; - - case CFGTOK_OPTIONAL: - FlagAttr (&S->Attr, SA_OPTIONAL, "OPTIONAL"); - CfgBoolToken (); - if (CfgTok == CFGTOK_TRUE) { - S->Flags |= SF_OPTIONAL; - } + break; + + case CFGTOK_OFFSET: + FlagAttr (&S->Attr, SA_OFFSET, "OFFSET"); + S->Addr = CfgCheckedConstExpr (1, 0x1000000); + S->Flags |= SF_OFFSET; + break; + + case CFGTOK_OPTIONAL: + FlagAttr (&S->Attr, SA_OPTIONAL, "OPTIONAL"); + CfgBoolToken (); + if (CfgTok == CFGTOK_TRUE) { + S->Flags |= SF_OPTIONAL; + } CfgNextTok (); - break; + break; - case CFGTOK_RUN: - FlagAttr (&S->Attr, SA_RUN, "RUN"); - S->Run = CfgGetMemory (GetStrBufId (&CfgSVal)); + case CFGTOK_RUN: + FlagAttr (&S->Attr, SA_RUN, "RUN"); + S->Run = CfgGetMemory (GetStrBufId (&CfgSVal)); CfgNextTok (); - break; - - case CFGTOK_START: - FlagAttr (&S->Attr, SA_START, "START"); - S->Addr = CfgCheckedConstExpr (1, 0x1000000); - S->Flags |= SF_START; - break; - - case CFGTOK_TYPE: - FlagAttr (&S->Attr, SA_TYPE, "TYPE"); - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - switch (CfgTok) { - case CFGTOK_RO: S->Flags |= SF_RO; break; - case CFGTOK_RW: /* Default */ break; - case CFGTOK_BSS: S->Flags |= SF_BSS; break; - case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break; - default: Internal ("Unexpected token: %d", CfgTok); - } + break; + + case CFGTOK_START: + FlagAttr (&S->Attr, SA_START, "START"); + S->Addr = CfgCheckedConstExpr (1, 0x1000000); + S->Flags |= SF_START; + break; + + case CFGTOK_TYPE: + FlagAttr (&S->Attr, SA_TYPE, "TYPE"); + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + switch (CfgTok) { + case CFGTOK_RO: S->Flags |= SF_RO; break; + case CFGTOK_RW: /* Default */ break; + case CFGTOK_BSS: S->Flags |= SF_BSS; break; + case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break; + case CFGTOK_OVERWRITE: S->Flags |= (SF_OVERWRITE | SF_RO); break; + default: Internal ("Unexpected token: %d", CfgTok); + } CfgNextTok (); - break; + break; - default: - FAIL ("Unexpected attribute token"); + default: + FAIL ("Unexpected attribute token"); - } + } - /* Skip an optional comma */ - CfgOptionalComma (); - } + /* Skip an optional comma */ + CfgOptionalComma (); + } - /* Check for mandatory parameters */ - AttrCheck (S->Attr, SA_LOAD, "LOAD"); + /* Check for mandatory parameters */ + AttrCheck (S->Attr, SA_LOAD, "LOAD"); - /* Set defaults for stuff not given */ - if ((S->Attr & SA_RUN) == 0) { - S->Attr |= SA_RUN; - S->Run = S->Load; - } + /* Set defaults for stuff not given */ + if ((S->Attr & SA_RUN) == 0) { + S->Attr |= SA_RUN; + S->Run = S->Load; + } /* An attribute of ALIGN_LOAD doesn't make sense if there are no - * separate run and load memory areas. - */ + ** separate run and load memory areas. + */ if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) { - CfgWarning (&CfgErrorPos, + CfgWarning (&CfgErrorPos, "ALIGN_LOAD attribute specified, but no separate " "LOAD and RUN memory areas assigned"); /* Remove the flag */ @@ -774,34 +801,34 @@ static void ParseSegments (void) } /* If the segment is marked as BSS style, it may not have separate - * load and run memory areas, because it's is never written to disk. - */ + ** load and run memory areas, because it's is never written to disk. + */ if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) { - CfgWarning (&CfgErrorPos, - "Segment with type `bss' has both LOAD and RUN " + CfgWarning (&CfgErrorPos, + "Segment with type 'bss' has both LOAD and RUN " "memory areas assigned"); } - /* Don't allow read/write data to be put into a readonly area */ - if ((S->Flags & SF_RO) == 0) { - if (S->Run->Flags & MF_RO) { - CfgError (&CfgErrorPos, - "Cannot put r/w segment `%s' in r/o memory area `%s'", - GetString (S->Name), GetString (S->Run->Name)); - } - } - - /* Only one of ALIGN, START and OFFSET may be used */ - Count = ((S->Flags & SF_ALIGN) != 0) + - ((S->Flags & SF_OFFSET) != 0) + - ((S->Flags & SF_START) != 0); - if (Count > 1) { - CfgError (&CfgErrorPos, + /* Don't allow read/write data to be put into a readonly area */ + if ((S->Flags & SF_RO) == 0) { + if (S->Run->Flags & MF_RO) { + CfgError (&CfgErrorPos, + "Cannot put r/w segment '%s' in r/o memory area '%s'", + GetString (S->Name), GetString (S->Run->Name)); + } + } + + /* Only one of ALIGN, START and OFFSET may be used */ + Count = ((S->Flags & SF_ALIGN) != 0) + + ((S->Flags & SF_OFFSET) != 0) + + ((S->Flags & SF_START) != 0); + if (Count > 1) { + CfgError (&CfgErrorPos, "Only one of ALIGN, START, OFFSET may be used"); - } + } - /* Skip the semicolon */ - CfgConsumeSemi (); + /* Skip the semicolon */ + CfgConsumeSemi (); } /* Remember we had this section */ @@ -814,32 +841,32 @@ static void ParseO65 (void) /* Parse the o65 format section */ { static const IdentTok Attributes [] = { - { "EXPORT", CFGTOK_EXPORT }, - { "IMPORT", CFGTOK_IMPORT }, - { "TYPE", CFGTOK_TYPE }, - { "OS", CFGTOK_OS }, - { "ID", CFGTOK_ID }, - { "VERSION", CFGTOK_VERSION }, + { "EXPORT", CFGTOK_EXPORT }, + { "IMPORT", CFGTOK_IMPORT }, + { "TYPE", CFGTOK_TYPE }, + { "OS", CFGTOK_OS }, + { "ID", CFGTOK_ID }, + { "VERSION", CFGTOK_VERSION }, }; static const IdentTok Types [] = { - { "SMALL", CFGTOK_SMALL }, - { "LARGE", CFGTOK_LARGE }, + { "SMALL", CFGTOK_SMALL }, + { "LARGE", CFGTOK_LARGE }, }; static const IdentTok OperatingSystems [] = { - { "LUNIX", CFGTOK_LUNIX }, - { "OSA65", CFGTOK_OSA65 }, + { "LUNIX", CFGTOK_LUNIX }, + { "OSA65", CFGTOK_OSA65 }, { "CC65", CFGTOK_CC65 }, { "OPENCBM", CFGTOK_OPENCBM }, }; /* Bitmask to remember the attributes we got already */ enum { - atNone = 0x0000, - atOS = 0x0001, + atNone = 0x0000, + atOS = 0x0001, atOSVersion = 0x0002, - atType = 0x0004, - atImport = 0x0008, - atExport = 0x0010, + atType = 0x0004, + atImport = 0x0008, + atExport = 0x0010, atID = 0x0020, atVersion = 0x0040 }; @@ -852,72 +879,72 @@ static void ParseO65 (void) /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { - /* Map the identifier to a token */ - cfgtok_t AttrTok; - CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); - AttrTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; - /* An optional assignment follows */ - CfgNextTok (); - CfgOptionalAssign (); + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); - /* Check which attribute was given */ - switch (AttrTok) { + /* Check which attribute was given */ + switch (AttrTok) { - case CFGTOK_EXPORT: + case CFGTOK_EXPORT: /* Remember we had this token (maybe more than once) */ AttrFlags |= atExport; - /* We expect an identifier */ - CfgAssureIdent (); + /* We expect an identifier */ + CfgAssureIdent (); /* Remember it as an export for later */ NewCfgSymbol (CfgSymO65Export, GetStrBufId (&CfgSVal)); /* Eat the identifier token */ CfgNextTok (); - break; + break; - case CFGTOK_IMPORT: + case CFGTOK_IMPORT: /* Remember we had this token (maybe more than once) */ AttrFlags |= atImport; - /* We expect an identifier */ - CfgAssureIdent (); + /* We expect an identifier */ + CfgAssureIdent (); /* Remember it as an import for later */ NewCfgSymbol (CfgSymO65Import, GetStrBufId (&CfgSVal)); /* Eat the identifier token */ CfgNextTok (); - break; - - case CFGTOK_TYPE: - /* Cannot have this attribute twice */ - FlagAttr (&AttrFlags, atType, "TYPE"); - /* Get the type of the executable */ - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - switch (CfgTok) { - - case CFGTOK_SMALL: - O65SetSmallModel (O65FmtDesc); - break; - - case CFGTOK_LARGE: - O65SetLargeModel (O65FmtDesc); - break; - - default: - CfgError (&CfgErrorPos, "Unexpected type token"); - } + break; + + case CFGTOK_TYPE: + /* Cannot have this attribute twice */ + FlagAttr (&AttrFlags, atType, "TYPE"); + /* Get the type of the executable */ + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + switch (CfgTok) { + + case CFGTOK_SMALL: + O65SetSmallModel (O65FmtDesc); + break; + + case CFGTOK_LARGE: + O65SetLargeModel (O65FmtDesc); + break; + + default: + CfgError (&CfgErrorPos, "Unexpected type token"); + } /* Eat the attribute token */ CfgNextTok (); - break; - - case CFGTOK_OS: - /* Cannot use this attribute twice */ - FlagAttr (&AttrFlags, atOS, "OS"); - /* Get the operating system. It may be specified as name or - * as a number in the range 1..255. - */ - if (CfgTok == CFGTOK_INTCON) { - CfgRangeCheck (O65OS_MIN, O65OS_MAX); - OS = (unsigned) CfgIVal; - } else { + break; + + case CFGTOK_OS: + /* Cannot use this attribute twice */ + FlagAttr (&AttrFlags, atOS, "OS"); + /* Get the operating system. It may be specified as name or + ** as a number in the range 1..255. + */ + if (CfgTok == CFGTOK_INTCON) { + CfgRangeCheck (O65OS_MIN, O65OS_MAX); + OS = (unsigned) CfgIVal; + } else { CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type"); switch (CfgTok) { case CFGTOK_LUNIX: OS = O65OS_LUNIX; break; @@ -928,7 +955,7 @@ static void ParseO65 (void) } } CfgNextTok (); - break; + break; case CFGTOK_ID: /* Cannot have this attribute twice */ @@ -944,13 +971,13 @@ static void ParseO65 (void) Version = (unsigned) CfgCheckedConstExpr (0, 0xFF); break; - default: - FAIL ("Unexpected attribute token"); + default: + FAIL ("Unexpected attribute token"); - } + } - /* Skip an optional comma */ - CfgOptionalComma (); + /* Skip an optional comma */ + CfgOptionalComma (); } /* Check if we have all mandatory attributes */ @@ -975,43 +1002,129 @@ static void ParseO65 (void) +static void ParseXex (void) +/* Parse the o65 format section */ +{ + static const IdentTok Attributes [] = { + { "RUNAD", CFGTOK_RUNAD }, + { "INITAD", CFGTOK_INITAD }, + }; + + /* Remember the attributes read */ + /* Bitmask to remember the attributes we got already */ + enum { + atNone = 0x0000, + atRunAd = 0x0001, + }; + unsigned AttrFlags = atNone; + Import *RunAd = 0; + Import *InitAd; + MemoryArea *InitMem; + + /* Read the attributes */ + while (CfgTok == CFGTOK_IDENT) { + + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; + + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); + + /* Check which attribute was given */ + switch (AttrTok) { + + case CFGTOK_RUNAD: + /* Cannot have this attribute twice */ + FlagAttr (&AttrFlags, atRunAd, "RUNAD"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Generate an import for the symbol */ + RunAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS)); + /* Remember the file position */ + CollAppend (&RunAd->RefLines, GenLineInfo (&CfgErrorPos)); + /* Eat the identifier token */ + CfgNextTok (); + break; + + case CFGTOK_INITAD: + /* We expect a memory area followed by a colon and an identifier */ + CfgAssureIdent (); + InitMem = CfgGetMemory (GetStrBufId (&CfgSVal)); + CfgNextTok (); + CfgConsumeColon (); + CfgAssureIdent (); + /* Generate an import for the symbol */ + InitAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS)); + /* Remember the file position */ + CollAppend (&InitAd->RefLines, GenLineInfo (&CfgErrorPos)); + /* Eat the identifier token */ + CfgNextTok (); + /* Add to XEX */ + if (XexAddInitAd (XexFmtDesc, InitMem, InitAd)) + CfgError (&CfgErrorPos, "INITAD already given for memory area"); + break; + + default: + FAIL ("Unexpected attribute token"); + + } + + /* Skip an optional comma */ + CfgOptionalComma (); + } + + /* Set the RUNAD import if we have one */ + if ( RunAd ) + XexSetRunAd (XexFmtDesc, RunAd); +} + + + static void ParseFormats (void) /* Parse a target format section */ { static const IdentTok Formats [] = { - { "O65", CFGTOK_O65 }, - { "BIN", CFGTOK_BIN }, - { "BINARY", CFGTOK_BIN }, + { "O65", CFGTOK_O65 }, + { "BIN", CFGTOK_BIN }, + { "BINARY", CFGTOK_BIN }, + { "ATARI", CFGTOK_ATARIEXE }, }; while (CfgTok == CFGTOK_IDENT) { - /* Map the identifier to a token */ - cfgtok_t FormatTok; - CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); - FormatTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t FormatTok; + CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); + FormatTok = CfgTok; - /* Skip the name and the following colon */ - CfgNextTok (); - CfgConsumeColon (); + /* Skip the name and the following colon */ + CfgNextTok (); + CfgConsumeColon (); - /* Parse the format options */ - switch (FormatTok) { + /* Parse the format options */ + switch (FormatTok) { - case CFGTOK_O65: - ParseO65 (); - break; + case CFGTOK_O65: + ParseO65 (); + break; - case CFGTOK_BIN: - /* No attribibutes available */ - break; + case CFGTOK_ATARIEXE: + ParseXex (); + break; - default: - Error ("Unexpected format token"); - } + case CFGTOK_BIN: + /* No attribibutes available */ + break; - /* Skip the semicolon */ - CfgConsumeSemi (); + default: + Error ("Unexpected format token"); + } + + /* Skip the semicolon */ + CfgConsumeSemi (); } @@ -1025,128 +1138,142 @@ static void ParseConDes (void) /* Parse the CONDES feature */ { static const IdentTok Attributes [] = { - { "SEGMENT", CFGTOK_SEGMENT }, - { "LABEL", CFGTOK_LABEL }, - { "COUNT", CFGTOK_COUNT }, - { "TYPE", CFGTOK_TYPE }, - { "ORDER", CFGTOK_ORDER }, + { "COUNT", CFGTOK_COUNT }, + { "IMPORT", CFGTOK_IMPORT }, + { "LABEL", CFGTOK_LABEL }, + { "ORDER", CFGTOK_ORDER }, + { "SEGMENT", CFGTOK_SEGMENT }, + { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { - { "CONSTRUCTOR", CFGTOK_CONSTRUCTOR }, - { "DESTRUCTOR", CFGTOK_DESTRUCTOR }, + { "CONSTRUCTOR", CFGTOK_CONSTRUCTOR }, + { "DESTRUCTOR", CFGTOK_DESTRUCTOR }, { "INTERRUPTOR", CFGTOK_INTERRUPTOR }, }; static const IdentTok Orders [] = { - { "DECREASING", CFGTOK_DECREASING }, - { "INCREASING", CFGTOK_INCREASING }, + { "DECREASING", CFGTOK_DECREASING }, + { "INCREASING", CFGTOK_INCREASING }, }; /* Attribute values. */ - unsigned SegName = INVALID_STRING_ID; - unsigned Label = INVALID_STRING_ID; unsigned Count = INVALID_STRING_ID; + unsigned Label = INVALID_STRING_ID; + unsigned SegName = INVALID_STRING_ID; + ConDesImport Import; /* Initialize to avoid gcc warnings: */ int Type = -1; ConDesOrder Order = cdIncreasing; /* Bitmask to remember the attributes we got already */ enum { - atNone = 0x0000, - atSegName = 0x0001, - atLabel = 0x0002, - atCount = 0x0004, - atType = 0x0008, - atOrder = 0x0010 + atNone = 0x0000, + atCount = 0x0001, + atImport = 0x0002, + atLabel = 0x0004, + atOrder = 0x0008, + atSegName = 0x0010, + atType = 0x0020, }; unsigned AttrFlags = atNone; /* Parse the attributes */ while (1) { - /* Map the identifier to a token */ - cfgtok_t AttrTok; - CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); - AttrTok = CfgTok; - - /* An optional assignment follows */ - CfgNextTok (); - CfgOptionalAssign (); - - /* Check which attribute was given */ - switch (AttrTok) { - - case CFGTOK_SEGMENT: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atSegName, "SEGMENT"); - /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - SegName = GetStrBufId (&CfgSVal); - break; - - case CFGTOK_LABEL: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atLabel, "LABEL"); - /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - Label = GetStrBufId (&CfgSVal); - break; - - case CFGTOK_COUNT: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atCount, "COUNT"); - /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - Count = GetStrBufId (&CfgSVal); - break; - - case CFGTOK_TYPE: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atType, "TYPE"); - /* The type may be given as id or numerical */ - if (CfgTok == CFGTOK_INTCON) { - CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); - Type = (int) CfgIVal; - } else { - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - switch (CfgTok) { - case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; - case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; + + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); + + /* Check which attribute was given */ + switch (AttrTok) { + + case CFGTOK_COUNT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atCount, "COUNT"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + Count = GetStrBufId (&CfgSVal); + break; + + case CFGTOK_IMPORT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atImport, "IMPORT"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember value and position for later */ + Import.Name = GetStrBufId (&CfgSVal); + Import.Pos = CfgErrorPos; + Import.AddrSize = ADDR_SIZE_ABS; + break; + + case CFGTOK_LABEL: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atLabel, "LABEL"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + Label = GetStrBufId (&CfgSVal); + break; + + case CFGTOK_ORDER: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atOrder, "ORDER"); + CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order"); + switch (CfgTok) { + case CFGTOK_DECREASING: Order = cdDecreasing; break; + case CFGTOK_INCREASING: Order = cdIncreasing; break; + default: FAIL ("Unexpected order token"); + } + break; + + case CFGTOK_SEGMENT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atSegName, "SEGMENT"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + SegName = GetStrBufId (&CfgSVal); + break; + + case CFGTOK_TYPE: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atType, "TYPE"); + /* The type may be given as id or numerical */ + if (CfgTok == CFGTOK_INTCON) { + CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); + Type = (int) CfgIVal; + } else { + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + switch (CfgTok) { + case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; + case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break; - default: FAIL ("Unexpected type token"); - } - } - break; - - case CFGTOK_ORDER: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atOrder, "ORDER"); - CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order"); - switch (CfgTok) { - case CFGTOK_DECREASING: Order = cdDecreasing; break; - case CFGTOK_INCREASING: Order = cdIncreasing; break; - default: FAIL ("Unexpected order token"); - } - break; - - default: - FAIL ("Unexpected attribute token"); - - } - - /* Skip the attribute value */ - CfgNextTok (); - - /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ - if (CfgTok == CFGTOK_SEMI) { - break; - } else if (CfgTok == CFGTOK_COMMA) { - CfgNextTok (); - } + default: FAIL ("Unexpected type token"); + } + } + break; + + default: + FAIL ("Unexpected attribute token"); + + } + + /* Skip the attribute value */ + CfgNextTok (); + + /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ + if (CfgTok == CFGTOK_SEMI) { + break; + } else if (CfgTok == CFGTOK_COMMA) { + CfgNextTok (); + } } /* Check if we have all mandatory attributes */ @@ -1156,7 +1283,7 @@ static void ParseConDes (void) /* Check if the condes has already attributes defined */ if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) { - CfgError (&CfgErrorPos, + CfgError (&CfgErrorPos, "CONDES attributes for type %d are already defined", Type); } @@ -1165,10 +1292,13 @@ static void ParseConDes (void) ConDesSetSegName (Type, SegName); ConDesSetLabel (Type, Label); if (AttrFlags & atCount) { - ConDesSetCountSym (Type, Count); + ConDesSetCountSym (Type, Count); + } + if (AttrFlags & atImport) { + ConDesSetImport (Type, &Import); } if (AttrFlags & atOrder) { - ConDesSetOrder (Type, Order); + ConDesSetOrder (Type, Order); } } @@ -1178,7 +1308,7 @@ static void ParseStartAddress (void) /* Parse the STARTADDRESS feature */ { static const IdentTok Attributes [] = { - { "DEFAULT", CFGTOK_DEFAULT }, + { "DEFAULT", CFGTOK_DEFAULT }, }; @@ -1187,52 +1317,52 @@ static void ParseStartAddress (void) /* Bitmask to remember the attributes we got already */ enum { - atNone = 0x0000, - atDefault = 0x0001 + atNone = 0x0000, + atDefault = 0x0001 }; unsigned AttrFlags = atNone; /* Parse the attributes */ while (1) { - /* Map the identifier to a token */ - cfgtok_t AttrTok; - CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); - AttrTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; - /* An optional assignment follows */ - CfgNextTok (); - CfgOptionalAssign (); + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); - /* Check which attribute was given */ - switch (AttrTok) { + /* Check which attribute was given */ + switch (AttrTok) { - case CFGTOK_DEFAULT: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atDefault, "DEFAULT"); - /* We expect a numeric expression */ + case CFGTOK_DEFAULT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atDefault, "DEFAULT"); + /* We expect a numeric expression */ DefStartAddr = CfgCheckedConstExpr (0, 0xFFFFFF); - break; + break; - default: - FAIL ("Unexpected attribute token"); + default: + FAIL ("Unexpected attribute token"); - } + } - /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ - if (CfgTok == CFGTOK_SEMI) { - break; - } else if (CfgTok == CFGTOK_COMMA) { - CfgNextTok (); - } + /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ + if (CfgTok == CFGTOK_SEMI) { + break; + } else if (CfgTok == CFGTOK_COMMA) { + CfgNextTok (); + } } /* Check if we have all mandatory attributes */ AttrCheck (AttrFlags, atDefault, "DEFAULT"); /* If no start address was given on the command line, use the one given - * here - */ + ** here + */ if (!HaveStartAddr) { StartAddr = DefStartAddr; } @@ -1244,39 +1374,39 @@ static void ParseFeatures (void) /* Parse a features section */ { static const IdentTok Features [] = { - { "CONDES", CFGTOK_CONDES }, + { "CONDES", CFGTOK_CONDES }, { "STARTADDRESS", CFGTOK_STARTADDRESS }, }; while (CfgTok == CFGTOK_IDENT) { - /* Map the identifier to a token */ - cfgtok_t FeatureTok; - CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature"); - FeatureTok = CfgTok; + /* Map the identifier to a token */ + cfgtok_t FeatureTok; + CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature"); + FeatureTok = CfgTok; - /* Skip the name and the following colon */ - CfgNextTok (); - CfgConsumeColon (); + /* Skip the name and the following colon */ + CfgNextTok (); + CfgConsumeColon (); - /* Parse the format options */ - switch (FeatureTok) { + /* Parse the format options */ + switch (FeatureTok) { - case CFGTOK_CONDES: - ParseConDes (); - break; + case CFGTOK_CONDES: + ParseConDes (); + break; case CFGTOK_STARTADDRESS: ParseStartAddress (); break; - default: - FAIL ("Unexpected feature token"); - } + default: + FAIL ("Unexpected feature token"); + } - /* Skip the semicolon */ - CfgConsumeSemi (); + /* Skip the semicolon */ + CfgConsumeSemi (); } /* Remember we had this section */ @@ -1291,48 +1421,48 @@ static void ParseSymbols (void) static const IdentTok Attributes[] = { { "ADDRSIZE", CFGTOK_ADDRSIZE }, { "TYPE", CFGTOK_TYPE }, - { "VALUE", CFGTOK_VALUE }, + { "VALUE", CFGTOK_VALUE }, }; static const IdentTok AddrSizes [] = { - { "ABS", CFGTOK_ABS }, - { "ABSOLUTE", CFGTOK_ABS }, - { "DIRECT", CFGTOK_ZP }, - { "DWORD", CFGTOK_LONG }, - { "FAR", CFGTOK_FAR }, - { "LONG", CFGTOK_LONG }, - { "NEAR", CFGTOK_ABS }, - { "ZEROPAGE", CFGTOK_ZP }, - { "ZP", CFGTOK_ZP }, + { "ABS", CFGTOK_ABS }, + { "ABSOLUTE", CFGTOK_ABS }, + { "DIRECT", CFGTOK_ZP }, + { "DWORD", CFGTOK_LONG }, + { "FAR", CFGTOK_FAR }, + { "LONG", CFGTOK_LONG }, + { "NEAR", CFGTOK_ABS }, + { "ZEROPAGE", CFGTOK_ZP }, + { "ZP", CFGTOK_ZP }, }; static const IdentTok Types [] = { - { "EXPORT", CFGTOK_EXPORT }, - { "IMPORT", CFGTOK_IMPORT }, - { "WEAK", CFGTOK_WEAK }, + { "EXPORT", CFGTOK_EXPORT }, + { "IMPORT", CFGTOK_IMPORT }, + { "WEAK", CFGTOK_WEAK }, }; while (CfgTok == CFGTOK_IDENT) { /* Bitmask to remember the attributes we got already */ enum { - atNone = 0x0000, + atNone = 0x0000, atAddrSize = 0x0001, atType = 0x0002, atValue = 0x0004, }; unsigned AttrFlags = atNone; - ExprNode* Value = 0; + ExprNode* Value = 0; CfgSymType Type = CfgSymExport; unsigned char AddrSize = ADDR_SIZE_ABS; Import* Imp; Export* Exp; CfgSymbol* Sym; - /* Remember the name */ - unsigned Name = GetStrBufId (&CfgSVal); - CfgNextTok (); + /* Remember the name */ + unsigned Name = GetStrBufId (&CfgSVal); + CfgNextTok (); /* New syntax - skip the colon */ CfgNextTok (); @@ -1354,36 +1484,36 @@ static void ParseSymbols (void) /* Check which attribute was given */ switch (AttrTok) { - case CFGTOK_ADDRSIZE: + case CFGTOK_ADDRSIZE: /* Don't allow this twice */ FlagAttr (&AttrFlags, atAddrSize, "ADDRSIZE"); /* Map the type to a token */ - CfgSpecialToken (AddrSizes, ENTRY_COUNT (AddrSizes), "AddrSize"); + CfgSpecialToken (AddrSizes, ENTRY_COUNT (AddrSizes), "AddrSize"); switch (CfgTok) { case CFGTOK_ABS: AddrSize = ADDR_SIZE_ABS; break; case CFGTOK_FAR: AddrSize = ADDR_SIZE_FAR; break; case CFGTOK_LONG: AddrSize = ADDR_SIZE_LONG; break; case CFGTOK_ZP: AddrSize = ADDR_SIZE_ZP; break; - default: + default: Internal ("Unexpected token: %d", CfgTok); } CfgNextTok (); - break; + break; - case CFGTOK_TYPE: + case CFGTOK_TYPE: /* Don't allow this twice */ FlagAttr (&AttrFlags, atType, "TYPE"); /* Map the type to a token */ - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { case CFGTOK_EXPORT: Type = CfgSymExport; break; case CFGTOK_IMPORT: Type = CfgSymImport; break; case CFGTOK_WEAK: Type = CfgSymWeak; break; - default: + default: Internal ("Unexpected token: %d", CfgTok); } CfgNextTok (); - break; + break; case CFGTOK_VALUE: /* Don't allow this twice */ @@ -1413,7 +1543,7 @@ static void ParseSymbols (void) case CfgSymExport: /* We must have a value */ - AttrCheck (AttrFlags, atType, "TYPE"); + AttrCheck (AttrFlags, atValue, "VALUE"); /* Create the export */ Exp = CreateExprExport (Name, Value, AddrSize); CollAppend (&Exp->DefLines, GenLineInfo (&CfgErrorPos)); @@ -1427,12 +1557,12 @@ static void ParseSymbols (void) /* Generate the import */ Imp = InsertImport (GenImport (Name, AddrSize)); /* Remember the file position */ - CollAppend (&Imp->DefLines, GenLineInfo (&CfgErrorPos)); + CollAppend (&Imp->RefLines, GenLineInfo (&CfgErrorPos)); break; case CfgSymWeak: /* We must have a value */ - AttrCheck (AttrFlags, atType, "TYPE"); + AttrCheck (AttrFlags, atValue, "VALUE"); /* Remember the symbol for later */ Sym = NewCfgSymbol (CfgSymWeak, Name); Sym->Value = Value; @@ -1443,8 +1573,8 @@ static void ParseSymbols (void) Internal ("Unexpected symbol type %d", Type); } - /* Skip the semicolon */ - CfgConsumeSemi (); + /* Skip the semicolon */ + CfgConsumeSemi (); } /* Remember we had this section */ @@ -1457,59 +1587,59 @@ static void ParseConfig (void) /* Parse the config file */ { static const IdentTok BlockNames [] = { - { "MEMORY", CFGTOK_MEMORY }, - { "FILES", CFGTOK_FILES }, + { "MEMORY", CFGTOK_MEMORY }, + { "FILES", CFGTOK_FILES }, { "SEGMENTS", CFGTOK_SEGMENTS }, - { "FORMATS", CFGTOK_FORMATS }, - { "FEATURES", CFGTOK_FEATURES }, - { "SYMBOLS", CFGTOK_SYMBOLS }, + { "FORMATS", CFGTOK_FORMATS }, + { "FEATURES", CFGTOK_FEATURES }, + { "SYMBOLS", CFGTOK_SYMBOLS }, }; cfgtok_t BlockTok; do { - /* Read the block ident */ - CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier"); - BlockTok = CfgTok; - CfgNextTok (); + /* Read the block ident */ + CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier"); + BlockTok = CfgTok; + CfgNextTok (); - /* Expected a curly brace */ - CfgConsume (CFGTOK_LCURLY, "`{' expected"); + /* Expected a curly brace */ + CfgConsume (CFGTOK_LCURLY, "'{' expected"); - /* Read the block */ - switch (BlockTok) { + /* Read the block */ + switch (BlockTok) { - case CFGTOK_MEMORY: - ParseMemory (); - break; + case CFGTOK_MEMORY: + ParseMemory (); + break; - case CFGTOK_FILES: - ParseFiles (); - break; + case CFGTOK_FILES: + ParseFiles (); + break; - case CFGTOK_SEGMENTS: - ParseSegments (); - break; + case CFGTOK_SEGMENTS: + ParseSegments (); + break; - case CFGTOK_FORMATS: - ParseFormats (); - break; + case CFGTOK_FORMATS: + ParseFormats (); + break; - case CFGTOK_FEATURES: - ParseFeatures (); - break; + case CFGTOK_FEATURES: + ParseFeatures (); + break; - case CFGTOK_SYMBOLS: - ParseSymbols (); - break; + case CFGTOK_SYMBOLS: + ParseSymbols (); + break; - default: - FAIL ("Unexpected block token"); + default: + FAIL ("Unexpected block token"); - } + } - /* Skip closing brace */ - CfgConsume (CFGTOK_RCURLY, "`}' expected"); + /* Skip closing brace */ + CfgConsume (CFGTOK_RCURLY, "'}' expected"); } while (CfgTok != CFGTOK_EOF); } @@ -1522,10 +1652,11 @@ void CfgRead (void) /* Create the descriptors for the binary formats */ BinFmtDesc = NewBinDesc (); O65FmtDesc = NewO65Desc (); + XexFmtDesc = NewXexDesc (); /* If we have a config name given, open the file, otherwise we will read - * from a buffer. - */ + ** from a buffer. + */ CfgOpenInput (); /* Parse the file */ @@ -1553,53 +1684,56 @@ static void ProcessSegments (void) while (I < CollCount (&SegDescList)) { /* Get the next segment descriptor */ - SegDesc* S = CollAtUnchecked (&SegDescList, I); + 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. - */ + ** 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)) { - CfgWarning (GetSourcePos (S->LI), - "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); - } + /* 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)) { + CfgWarning (GetSourcePos (S->LI), + "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); + } + + /* Use the fill value from the config */ + S->Seg->FillVal = S->FillVal; /* Process the next segment descriptor in the next run */ ++I; - } else { + } else { /* Print a warning if the segment is not optional */ if ((S->Flags & SF_OPTIONAL) == 0) { CfgWarning (&CfgErrorPos, - "Segment `%s' does not exist", + "Segment '%s' does not exist", GetString (S->Name)); } - /* Discard the descriptor and remove it from the collection */ - FreeSegDesc (S); + /* Discard the descriptor and remove it from the collection */ + FreeSegDesc (S); CollDelete (&SegDescList, I); - } + } } } @@ -1625,19 +1759,19 @@ static void ProcessSymbols (void) if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), - "Exported o65 symbol `%s' cannot also be an o65 import", + "Exported o65 symbol '%s' cannot also be an o65 import", 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. - */ + ** routine will check this also, but we get a more verbose + ** error message when checking it here. + */ if (O65GetExport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), - "Duplicate exported o65 symbol: `%s'", + "Duplicate exported o65 symbol: '%s'", GetString (Sym->Name) ); } @@ -1651,19 +1785,19 @@ static void ProcessSymbols (void) if (O65GetExport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), - "Imported o65 symbol `%s' cannot also be an o65 export", + "Imported o65 symbol '%s' cannot also be an o65 export", 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. - */ + ** routine will check this also, but we get a more verbose + ** error message when checking it here. + */ if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), - "Duplicate imported o65 symbol: `%s'", + "Duplicate imported o65 symbol: '%s'", GetString (Sym->Name) ); } @@ -1731,33 +1865,33 @@ static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr) unsigned CfgProcess (void) -/* Process the config file after reading in object files and libraries. This - * includes postprocessing of the config file data but also assigning segments - * and defining segment/memory area related symbols. The function will return - * the number of memory area overflows (so zero means anything went ok). - * In case of overflows, a short mapfile can be generated later, to ease the - * task of rearranging segments for the user. - */ +/* Process the config file, after reading in object files and libraries. This +** includes postprocessing of the config file data; but also assigning segments, +** and defining segment/memory-area related symbols. The function will return +** the number of memory area overflows (so, zero means everything went OK). +** In case of overflows, a short mapfile can be generated later, to ease the +** user's task of re-arranging segments. +*/ { unsigned Overflows = 0; unsigned I; /* Postprocess symbols. We must do that first, since weak symbols are - * defined here, which may be needed later. - */ + ** defined here, which may be needed later. + */ ProcessSymbols (); /* Postprocess segments */ ProcessSegments (); - /* Walk through each of the memory sections. Add up the sizes and check - * for an overflow of the section. Assign the start addresses of the - * segments while doing this. - */ + /* Walk through each of the memory sections. Add up the sizes; and, check + ** for an overflow of the section. Assign the start addresses of the + ** segments while doing that. + */ for (I = 0; I < CollCount (&MemoryAreas); ++I) { - unsigned J; unsigned long Addr; + unsigned Overwrites = 0; /* Get the next memory area */ MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); @@ -1768,28 +1902,28 @@ unsigned CfgProcess (void) /* Remember if this is a relocatable memory area */ M->Relocatable = RelocatableBinFmt (M->F->Format); - /* Resolve the start address expression, remember the start address - * and mark the memory area as placed. - */ + /* Resolve the start address expression, remember the start address, + ** and mark the memory area as placed. + */ if (!IsConstExpr (M->StartExpr)) { CfgError (GetSourcePos (M->LI), - "Start address of memory area `%s' is not constant", + "Start address of memory area '%s' is not constant", GetString (M->Name)); } Addr = M->Start = GetExprVal (M->StartExpr); M->Flags |= MF_PLACED; /* If requested, define the symbol for the start of the memory area. - * Doing it here means that the expression for the size of the area - * may reference this symbol. - */ - if (M->Flags & MF_DEFINE) { + ** Doing it here means that the expression for the size of the area + ** may reference this symbol. + */ + if (M->Flags & MF_DEFINE) { Export* E; - StrBuf Buf = STATIC_STRBUF_INITIALIZER; + StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Define the start of the memory area */ - SB_Printf (&Buf, "__%s_START__", GetString (M->Name)); - E = CreateMemoryExport (GetStrBufId (&Buf), M, 0); + SB_Printf (&Buf, "__%s_START__", GetString (M->Name)); + E = CreateMemoryExport (GetStrBufId (&Buf), M, 0); CollAppend (&E->DefLines, M->LI); SB_Done (&Buf); @@ -1798,140 +1932,209 @@ unsigned CfgProcess (void) /* Resolve the size expression */ if (!IsConstExpr (M->SizeExpr)) { CfgError (GetSourcePos (M->LI), - "Size of memory area `%s' is not constant", + "Size of memory area '%s' is not constant", GetString (M->Name)); } M->Size = GetExprVal (M->SizeExpr); - /* Walk through the segments in this memory area */ + /* Walk through the segments in this memory area */ for (J = 0; J < CollCount (&M->SegList); ++J) { + /* Get the segment */ + SegDesc* S = CollAtUnchecked (&M->SegList, J); + + /* Remember the start address before handling this segment */ + unsigned long StartAddr = Addr; + + /* Take note of "overwrite" segments and make sure there are no + ** other segment types following them in current memory region. + */ + if (S->Flags & SF_OVERWRITE) { + if (S->Flags & (SF_OFFSET | SF_START)) { + ++Overwrites; + } else { + CfgError (GetSourcePos (M->LI), + "Segment '%s' of type 'overwrite' requires either" + " 'Start' or 'Offset' attribute to be specified", + GetString (S->Name)); + } + } else { + if (Overwrites > 0) { + CfgError (GetSourcePos (M->LI), + "Segment '%s' is preceded by at least one segment" + " of type 'overwrite'", + GetString (S->Name)); + } + } - /* Get the segment */ - SegDesc* S = CollAtUnchecked (&M->SegList, J); - - /* Some actions depend on wether this is the load or run memory - * area. - */ + /* Some actions depend on whether this is the load or run memory + ** area. + */ if (S->Run == M) { - /* This is the run (and maybe load) memory area. Handle - * alignment and explict start address and offset. - */ + ** alignment and explict start address and offset. + */ + + /* Check if the alignment for the segment from the linker + ** config is a multiple for that of the segment. + ** If START or OFFSET is provided instead of ALIGN, check + ** if its address fits alignment requirements. + */ + unsigned long AlignedBy = (S->Flags & SF_START) ? S->Addr + : (S->Flags & SF_OFFSET) ? (S->Addr + M->Start) + : S->RunAlignment; + if ((AlignedBy % S->Seg->Alignment) != 0) { + /* Segment requires another alignment than configured + ** in the linker. + */ + CfgWarning (GetSourcePos (S->LI), + "Segment '%s' isn't aligned properly; the" + " resulting executable might not be functional.", + GetString (S->Name)); + } + if (S->Flags & SF_ALIGN) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment); /* If the first segment placed in the memory area needs - * fill bytes for the alignment, emit a warning, since - * this is somewhat suspicious. - */ + ** fill bytes for the alignment, emit a warning, since + ** that is somewhat suspicious. + */ if (M->FillLevel == 0 && NewAddr > Addr) { CfgWarning (GetSourcePos (S->LI), - "First segment in memory area `%s' does " - "already need fill bytes for alignment", + "The first segment in memory area '%s' " + "needs fill bytes for alignment.", GetString (M->Name)); } /* Use the aligned address */ Addr = NewAddr; - } else if (S->Flags & (SF_OFFSET | SF_START)) { + } else if ((S->Flags & (SF_OFFSET | SF_START)) != 0 && + (M->Flags & MF_OVERFLOW) == 0) { /* Give the segment a fixed starting address */ unsigned long NewAddr = S->Addr; + if (S->Flags & SF_OFFSET) { /* An offset was given, no address, make an address */ NewAddr += M->Start; } - if (Addr > NewAddr) { - /* Offset already too large */ - if (S->Flags & SF_OFFSET) { - CfgError (GetSourcePos (M->LI), - "Offset too small in `%s', segment `%s'", - GetString (M->Name), - GetString (S->Name)); + + if (S->Flags & SF_OVERWRITE) { + if (NewAddr < M->Start) { + CfgError (GetSourcePos (S->LI), + "Segment '%s' begins before memory area '%s'", + GetString (S->Name), GetString (M->Name)); } else { - CfgError (GetSourcePos (M->LI), - "Start address too low in `%s', segment `%s'", - GetString (M->Name), - GetString (S->Name)); + Addr = NewAddr; + } + } else { + if (NewAddr < Addr) { + /* Offset already too large */ + ++Overflows; + if (S->Flags & SF_OFFSET) { + CfgWarning (GetSourcePos (S->LI), + "Segment '%s' offset is too small in '%s' by %lu byte%c", + GetString (S->Name), GetString (M->Name), + Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); + } else { + CfgWarning (GetSourcePos (S->LI), + "Segment '%s' start address is too low in '%s' by %lu byte%c", + GetString (S->Name), GetString (M->Name), + Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); + } + } else { + Addr = NewAddr; } } - Addr = NewAddr; } /* Set the start address of this segment, set the readonly flag - * in the segment and and remember if the segment is in a - * relocatable file or not. - */ + ** in the segment, and remember if the segment is in a + ** relocatable file or not. + */ S->Seg->PC = Addr; S->Seg->ReadOnly = (S->Flags & SF_RO) != 0; - S->Seg->Relocatable = M->Relocatable; - /* Remember that this segment is placed */ - S->Seg->Placed = 1; + /* Remember the run memory for this segment, which is also a + ** flag that the segment has been placed. + */ + S->Seg->MemArea = M; } else if (S->Load == M) { - - /* This is the load memory area, *and* run and load are - * different (because of the "else" above). Handle alignment. - */ + /* This is the load memory area; *and*, run and load are + ** different (because of the "else" above). Handle alignment. + */ if (S->Flags & SF_ALIGN_LOAD) { /* Align the address */ Addr = AlignAddr (Addr, S->LoadAlignment); } + } + /* If this is the load memory area, and the segment doesn't have a + ** fill value defined, use the one from the memory area. + */ + if (S->Load == M && (S->Flags & SF_FILLVAL) == 0) { + S->Seg->FillVal = M->FillVal; } - /* Increment the fill level of the memory area and check for an - * overflow. - */ - M->FillLevel = Addr + S->Seg->Size - M->Start; - if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { + /* Increment the fill level of the memory area; and, check for an + ** overflow. + */ + M->FillLevel = Addr + S->Seg->Size - M->Start; + if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { ++Overflows; M->Flags |= MF_OVERFLOW; CfgWarning (GetSourcePos (M->LI), - "Memory area overflow in `%s', segment `%s' (%lu bytes)", - GetString (M->Name), GetString (S->Name), - M->FillLevel - M->Size); - } - - /* If requested, define symbols for the start and size of the - * segment. - */ - if (S->Flags & SF_DEFINE) { + "Segment '%s' overflows memory area '%s' by %lu byte%c", + GetString (S->Name), GetString (M->Name), + M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's'); + } + + /* If requested, define symbols for the start and size of the + ** segment. + */ + if (S->Flags & SF_DEFINE) { if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) { CreateRunDefines (S, Addr); } if (S->Load == M && (S->Flags & SF_LOAD_DEF) == 0) { CreateLoadDefines (S, Addr); } - } + } - /* Calculate the new address */ - Addr += S->Seg->Size; + /* Calculate the new address */ + Addr += S->Seg->Size; - } + /* If this segment will go out to the file, or its place + ** in the file will be filled, then increase the file size. + */ + if (S->Load == M && + ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) { + M->F->Size += Addr - StartAddr; + } + } - /* If requested, define symbols for start, size and offset of the - * memory area - */ - if (M->Flags & MF_DEFINE) { + /* If requested, define symbols for start, size, and offset of the + ** memory area + */ + if (M->Flags & MF_DEFINE) { Export* E; - StrBuf Buf = STATIC_STRBUF_INITIALIZER; + StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Define the size of the memory area */ - SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name)); - E = CreateConstExport (GetStrBufId (&Buf), M->Size); + SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name)); + E = CreateConstExport (GetStrBufId (&Buf), M->Size); CollAppend (&E->DefLines, M->LI); /* Define the fill level of the memory area */ - SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name)); - E = CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel); + SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name)); + E = CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel); CollAppend (&E->DefLines, M->LI); - + /* Define the file offset of the memory area. This isn't of much - * use for relocatable output files. - */ + ** use for relocatable output files. + */ if (!M->Relocatable) { SB_Printf (&Buf, "__%s_FILEOFFS__", GetString (M->Name)); E = CreateConstExport (GetStrBufId (&Buf), M->FileOffs); @@ -1940,13 +2143,13 @@ unsigned CfgProcess (void) /* Throw away the string buffer */ SB_Done (&Buf); - } + } - /* Grow the file by the size of the memory area */ - if (M->Flags & MF_FILL) { - M->F->Size += M->Size; - } else { - M->F->Size += M->FillLevel; + /* If we didn't have an overflow, and are requested to fill the memory + ** area, account for that in the file size. + */ + if ((M->Flags & MF_OVERFLOW) == 0 && (M->Flags & MF_FILL) != 0) { + M->F->Size += (M->Size - M->FillLevel); } } @@ -1967,62 +2170,63 @@ void CfgWriteTarget (void) /* Get this entry */ File* F = CollAtUnchecked (&FileList, I); - /* We don't need to look at files with no memory areas */ - if (CollCount (&F->MemoryAreas) > 0) { + /* We don't need to look at files with no memory areas */ + if (CollCount (&F->MemoryAreas) > 0) { + + /* Is there an output file? */ + if (SB_GetLen (GetStrBuf (F->Name)) > 0) { - /* Is there an output file? */ - if (SB_GetLen (GetStrBuf (F->Name)) > 0) { + /* Assign a proper binary format */ + if (F->Format == BINFMT_DEFAULT) { + F->Format = DefaultBinFmt; + } - /* Assign a proper binary format */ - if (F->Format == BINFMT_DEFAULT) { - F->Format = DefaultBinFmt; - } + /* Call the apropriate routine for the binary format */ + switch (F->Format) { - /* Call the apropriate routine for the binary format */ - switch (F->Format) { + case BINFMT_BINARY: + BinWriteTarget (BinFmtDesc, F); + break; - case BINFMT_BINARY: - BinWriteTarget (BinFmtDesc, F); - break; + case BINFMT_O65: + O65WriteTarget (O65FmtDesc, F); + break; - case BINFMT_O65: - O65WriteTarget (O65FmtDesc, F); - break; + case BINFMT_ATARIEXE: + XexWriteTarget (XexFmtDesc, F); + break; - default: - Internal ("Invalid binary format: %u", F->Format); + default: + Internal ("Invalid binary format: %u", F->Format); - } + } - } else { + } else { - /* No output file. Walk through the list and mark all segments - * loading into these memory areas in this file as dumped. - */ + /* No output file. Walk through the list and mark all segments + ** loading into these memory areas in this file as dumped. + */ unsigned J; for (J = 0; J < CollCount (&F->MemoryAreas); ++J) { unsigned K; /* Get this entry */ - MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, J); + MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, J); - /* Debugging */ - Print (stdout, 2, "Skipping `%s'...\n", GetString (M->Name)); + /* Debugging */ + Print (stdout, 2, "Skipping '%s'...\n", GetString (M->Name)); - /* Walk throught the segments */ + /* Walk throught the segments */ for (K = 0; K < CollCount (&M->SegList); ++K) { SegDesc* S = CollAtUnchecked (&M->SegList, K); - if (S->Load == M) { - /* Load area - mark the segment as dumped */ - S->Seg->Dumped = 1; - } - } - } - } - } + if (S->Load == M) { + /* Load area - mark the segment as dumped */ + S->Seg->Dumped = 1; + } + } + } + } + } } } - - -