/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2014, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdio.h>
#include <string.h>
+#include <limits.h>
#if defined(_MSC_VER)
/* Microsoft compiler */
# include <io.h>
#endif
/* common */
+#include "cpu.h"
#include "xmalloc.h"
/* da65 */
+#include "asminc.h"
#include "attrtab.h"
+#include "comments.h"
#include "error.h"
#include "global.h"
#include "infofile.h"
+#include "labels.h"
+#include "opctable.h"
#include "scanner.h"
+#include "segment.h"
+#include "handler.h"
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
+static void AddAttr (const char* Name, unsigned* Set, unsigned Attr)
+/* Add an attribute to the set and check that it is not given twice */
+{
+ if (*Set & Attr) {
+ /* Attribute is already in the set */
+ InfoError ("%s given twice", Name);
+ }
+ *Set |= Attr;
+}
+
+
+
+static void AsmIncSection (void)
+/* Parse a asminc section */
+{
+ static const IdentTok LabelDefs[] = {
+ { "COMMENTSTART", INFOTOK_COMMENTSTART },
+ { "FILE", INFOTOK_FILE },
+ { "IGNOREUNKNOWN", INFOTOK_IGNOREUNKNOWN },
+ };
+
+ /* Locals - initialize to avoid gcc warnings */
+ char* Name = 0;
+ int CommentStart = EOF;
+ int IgnoreUnknown = -1;
+
+ /* Skip the token */
+ InfoNextTok ();
+
+ /* Expect the opening curly brace */
+ InfoConsumeLCurly ();
+
+ /* Look for section tokens */
+ while (InfoTok != INFOTOK_RCURLY) {
+
+ /* Convert to special token */
+ InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");
+
+ /* Look at the token */
+ switch (InfoTok) {
+
+ case INFOTOK_COMMENTSTART:
+ InfoNextTok ();
+ if (CommentStart != EOF) {
+ InfoError ("Commentstart already given");
+ }
+ InfoAssureChar ();
+ CommentStart = (char) InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_FILE:
+ InfoNextTok ();
+ if (Name) {
+ InfoError ("File name already given");
+ }
+ InfoAssureStr ();
+ if (InfoSVal[0] == '\0') {
+ InfoError ("File name may not be empty");
+ }
+ Name = xstrdup (InfoSVal);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_IGNOREUNKNOWN:
+ InfoNextTok ();
+ if (IgnoreUnknown != -1) {
+ InfoError ("Ignoreunknown already specified");
+ }
+ InfoBoolToken ();
+ IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
+ InfoNextTok ();
+ break;
+
+ default:
+ Internal ("Unexpected token: %u", InfoTok);
+ }
+
+ /* Directive is followed by a semicolon */
+ InfoConsumeSemi ();
+ }
+
+ /* Check for the necessary data and assume defaults */
+ if (Name == 0) {
+ InfoError ("File name is missing");
+ }
+ if (CommentStart == EOF) {
+ CommentStart = ';';
+ }
+ if (IgnoreUnknown == -1) {
+ IgnoreUnknown = 0;
+ }
+
+ /* Open the file and read the symbol definitions */
+ AsmInc (Name, CommentStart, IgnoreUnknown);
+
+ /* Delete the dynamically allocated memory for Name */
+ xfree (Name);
+
+ /* Consume the closing brace */
+ InfoConsumeRCurly ();
+}
+
+
+
static void GlobalSection (void)
/* Parse a global section */
{
static const IdentTok GlobalDefs[] = {
- { "INPUTNAME", INFOTOK_INPUTNAME },
- { "OUTPUTNAME", INFOTOK_OUTPUTNAME },
- { "PAGELENGTH", INFOTOK_PAGELENGTH },
- { "STARTADDR", INFOTOK_STARTADDR },
+ { "ARGUMENTCOL", INFOTOK_ARGUMENT_COLUMN },
+ { "ARGUMENTCOLUMN", INFOTOK_ARGUMENT_COLUMN },
+ { "COMMENTCOL", INFOTOK_COMMENT_COLUMN },
+ { "COMMENTCOLUMN", INFOTOK_COMMENT_COLUMN },
+ { "COMMENTS", INFOTOK_COMMENTS },
+ { "CPU", INFOTOK_CPU },
+ { "HEXOFFS", INFOTOK_HEXOFFS },
+ { "INPUTNAME", INFOTOK_INPUTNAME },
+ { "INPUTOFFS", INFOTOK_INPUTOFFS },
+ { "INPUTSIZE", INFOTOK_INPUTSIZE },
+ { "LABELBREAK", INFOTOK_LABELBREAK },
+ { "MNEMONICCOL", INFOTOK_MNEMONIC_COLUMN },
+ { "MNEMONICCOLUMN", INFOTOK_MNEMONIC_COLUMN },
+ { "NEWLINEAFTERJMP", INFOTOK_NL_AFTER_JMP },
+ { "NEWLINEAFTERRTS", INFOTOK_NL_AFTER_RTS },
+ { "OUTPUTNAME", INFOTOK_OUTPUTNAME },
+ { "PAGELENGTH", INFOTOK_PAGELENGTH },
+ { "STARTADDR", INFOTOK_STARTADDR },
+ { "TEXTCOL", INFOTOK_TEXT_COLUMN },
+ { "TEXTCOLUMN", INFOTOK_TEXT_COLUMN },
+ };
+
+ /* Skip the token */
+ InfoNextTok ();
+
+ /* Expect the opening curly brace */
+ InfoConsumeLCurly ();
+
+ /* Look for section tokens */
+ while (InfoTok != INFOTOK_RCURLY) {
+
+ /* Convert to special token */
+ InfoSpecialToken (GlobalDefs, ENTRY_COUNT (GlobalDefs), "Global directive");
+
+ /* Look at the token */
+ switch (InfoTok) {
+
+ case INFOTOK_ARGUMENT_COLUMN:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (MIN_ACOL, MAX_ACOL);
+ ACol = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_COMMENT_COLUMN:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (MIN_CCOL, MAX_CCOL);
+ CCol = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_COMMENTS:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (MIN_COMMENTS, MAX_COMMENTS);
+ Comments = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_CPU:
+ InfoNextTok ();
+ InfoAssureStr ();
+ if (CPU != CPU_UNKNOWN) {
+ InfoError ("CPU already specified");
+ }
+ CPU = FindCPU (InfoSVal);
+ SetOpcTable (CPU);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_HEXOFFS:
+ InfoNextTok ();
+ InfoBoolToken ();
+ switch (InfoTok) {
+ case INFOTOK_FALSE: UseHexOffs = 0; break;
+ case INFOTOK_TRUE: UseHexOffs = 1; break;
+ }
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_INPUTNAME:
+ InfoNextTok ();
+ InfoAssureStr ();
+ if (InFile) {
+ InfoError ("Input file name already given");
+ }
+ InFile = xstrdup (InfoSVal);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_INPUTOFFS:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InputOffs = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_INPUTSIZE:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (1, 0x10000);
+ InputSize = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_LABELBREAK:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (0, UCHAR_MAX);
+ LBreak = (unsigned char) InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_MNEMONIC_COLUMN:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (MIN_MCOL, MAX_MCOL);
+ MCol = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_NL_AFTER_JMP:
+ InfoNextTok ();
+ if (NewlineAfterJMP != -1) {
+ InfoError ("NLAfterJMP already specified");
+ }
+ InfoBoolToken ();
+ NewlineAfterJMP = (InfoTok != INFOTOK_FALSE);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_NL_AFTER_RTS:
+ InfoNextTok ();
+ InfoBoolToken ();
+ if (NewlineAfterRTS != -1) {
+ InfoError ("NLAfterRTS already specified");
+ }
+ NewlineAfterRTS = (InfoTok != INFOTOK_FALSE);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_OUTPUTNAME:
+ InfoNextTok ();
+ InfoAssureStr ();
+ if (OutFile) {
+ InfoError ("Output file name already given");
+ }
+ OutFile = xstrdup (InfoSVal);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_PAGELENGTH:
+ InfoNextTok ();
+ InfoAssureInt ();
+ if (InfoIVal != 0) {
+ InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
+ }
+ PageLength = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_STARTADDR:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (0x0000, 0xFFFF);
+ StartAddr = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_TEXT_COLUMN:
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (MIN_TCOL, MAX_TCOL);
+ TCol = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ default:
+ Internal ("Unexpected token: %u", InfoTok);
+
+ }
+
+ /* Directive is followed by a semicolon */
+ InfoConsumeSemi ();
+
+ }
+
+ /* Consume the closing brace */
+ InfoConsumeRCurly ();
+}
+
+
+
+static void LabelSection (void)
+/* Parse a label section */
+{
+ static const IdentTok LabelDefs[] = {
+ { "COMMENT", INFOTOK_COMMENT },
+ { "ADDR", INFOTOK_ADDR },
+ { "NAME", INFOTOK_NAME },
+ { "SIZE", INFOTOK_SIZE },
+ { "PARAMSIZE", INFOTOK_PARAMSIZE },
};
+ /* Locals - initialize to avoid gcc warnings */
+ char* Name = 0;
+ char* Comment = 0;
+ long Value = -1;
+ long Size = -1;
+ long ParamSize = -1;
+
/* Skip the token */
InfoNextTok ();
/* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) {
- /* Convert to special token */
- InfoSpecialToken (GlobalDefs, ENTRY_COUNT (GlobalDefs), "Global directive");
-
- /* Look at the token */
- switch (InfoTok) {
-
- case INFOTOK_INPUTNAME:
- InfoNextTok ();
- InfoAssureStr ();
- if (InFile) {
- InfoError ("Input file name already given");
- }
- InFile = xstrdup (InfoSVal);
- InfoNextTok ();
- break;
-
- case INFOTOK_OUTPUTNAME:
- InfoNextTok ();
- InfoAssureStr ();
- if (OutFile) {
- InfoError ("Output file name already given");
- }
- OutFile = xstrdup (InfoSVal);
- InfoNextTok ();
- break;
-
- case INFOTOK_PAGELENGTH:
- InfoNextTok ();
- InfoAssureInt ();
- if (InfoIVal != -1) {
- InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
- }
- PageLength = InfoIVal;
- InfoNextTok ();
- break;
-
- case INFOTOK_STARTADDR:
- InfoNextTok ();
- InfoAssureInt ();
- InfoRangeCheck (0x0000, 0xFFFF);
- StartAddr = InfoIVal;
- InfoNextTok ();
- break;
-
- }
-
- /* Directive is followed by a semicolon */
- InfoConsumeSemi ();
+ /* Convert to special token */
+ InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label attribute");
+
+ /* Look at the token */
+ switch (InfoTok) {
+
+ case INFOTOK_ADDR:
+ InfoNextTok ();
+ if (Value >= 0) {
+ InfoError ("Value already given");
+ }
+ InfoAssureInt ();
+ InfoRangeCheck (0, 0xFFFF);
+ Value = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_COMMENT:
+ InfoNextTok ();
+ if (Comment) {
+ InfoError ("Comment already given");
+ }
+ InfoAssureStr ();
+ if (InfoSVal[0] == '\0') {
+ InfoError ("Comment may not be empty");
+ }
+ Comment = xstrdup (InfoSVal);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_NAME:
+ InfoNextTok ();
+ if (Name) {
+ InfoError ("Name already given");
+ }
+ InfoAssureStr ();
+ Name = xstrdup (InfoSVal);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_SIZE:
+ InfoNextTok ();
+ if (Size >= 0) {
+ InfoError ("Size already given");
+ }
+ InfoAssureInt ();
+ InfoRangeCheck (1, 0x10000);
+ Size = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_PARAMSIZE:
+ InfoNextTok ();
+ if (ParamSize >= 0) {
+ InfoError ("ParamSize already given");
+ }
+ InfoAssureInt ();
+ InfoRangeCheck (1, 0x10000);
+ ParamSize = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ default:
+ Internal ("Unexpected token: %u", InfoTok);
+ }
+
+ /* Directive is followed by a semicolon */
+ InfoConsumeSemi ();
+ }
+
+ /* Did we get the necessary data */
+ if (Name == 0) {
+ InfoError ("Label name is missing");
+ }
+ if (Name[0] == '\0' && Size > 1) {
+ InfoError ("Unnamed labels must not have a size > 1");
+ }
+ if (Value < 0) {
+ InfoError ("Label value is missing");
+ }
+ if (Size < 0) {
+ /* Use default */
+ Size = 1;
+ }
+ if (Value + Size > 0x10000) {
+ InfoError ("Invalid size (address out of range)");
+ }
+ if (HaveLabel ((unsigned) Value)) {
+ InfoError ("Label for address $%04lX already defined", Value);
+ }
+
+ /* Define the label(s) */
+ if (Name[0] == '\0') {
+ /* Size has already beed checked */
+ AddUnnamedLabel (Value);
+ } else {
+ AddExtLabelRange ((unsigned) Value, Name, Size);
+ }
+ if (ParamSize >= 0) {
+ SetSubroutineParamSize ((unsigned) Value, (unsigned) ParamSize);
+ }
+ /* Define the comment */
+ if (Comment) {
+ SetComment (Value, Comment);
}
+ /* Delete the dynamically allocated memory for Name and Comment */
+ xfree (Name);
+ xfree (Comment);
+
/* Consume the closing brace */
InfoConsumeRCurly ();
}
/* Parse a range section */
{
static const IdentTok RangeDefs[] = {
- { "START", INFOTOK_START },
- { "END", INFOTOK_END },
- { "TYPE", INFOTOK_TYPE },
+ { "COMMENT", INFOTOK_COMMENT },
+ { "END", INFOTOK_END },
+ { "NAME", INFOTOK_NAME },
+ { "START", INFOTOK_START },
+ { "TYPE", INFOTOK_TYPE },
};
static const IdentTok TypeDefs[] = {
- { "CODE", INFOTOK_CODE },
- { "BYTETABLE", INFOTOK_BYTETAB },
- { "WORDTABLE", INFOTOK_WORDTAB },
- { "DWORDTABLE", INFOTOK_DWORDTAB },
- { "ADDRTABLE", INFOTOK_ADDRTAB },
- { "RTSTABLE", INFOTOK_RTSTAB },
- { "TEXTTABLE", INFOTOK_TEXTTAB },
+ { "ADDRTABLE", INFOTOK_ADDRTAB },
+ { "BYTETABLE", INFOTOK_BYTETAB },
+ { "CODE", INFOTOK_CODE },
+ { "DBYTETABLE", INFOTOK_DBYTETAB },
+ { "DWORDTABLE", INFOTOK_DWORDTAB },
+ { "RTSTABLE", INFOTOK_RTSTAB },
+ { "SKIP", INFOTOK_SKIP },
+ { "TEXTTABLE", INFOTOK_TEXTTAB },
+ { "WORDTABLE", INFOTOK_WORDTAB },
};
/* Which values did we get? */
enum {
- tNone = 0x00,
- tStart = 0x01,
- tEnd = 0x02,
- tType = 0x04,
- tAll = 0x07
- } Needed = tNone;
+ tNone = 0x00,
+ tStart = 0x01,
+ tEnd = 0x02,
+ tType = 0x04,
+ tName = 0x08,
+ tComment= 0x10,
+ tNeeded = (tStart | tEnd | tType)
+ };
+ unsigned Attributes = tNone;
/* Locals - initialize to avoid gcc warnings */
- unsigned Start = 0;
- unsigned End = 0;
- unsigned char Type = 0;
+ unsigned Start = 0;
+ unsigned End = 0;
+ unsigned char Type = 0;
+ char* Name = 0;
+ char* Comment = 0;
+ unsigned MemberSize = 0;
+
/* Skip the token */
InfoNextTok ();
/* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) {
- /* Convert to special token */
- InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive");
-
- /* Look at the token */
- switch (InfoTok) {
-
- case INFOTOK_START:
- InfoNextTok ();
- InfoAssureInt ();
- InfoRangeCheck (0x0000, 0xFFFF);
- Start = InfoIVal;
- Needed |= tStart;
- InfoNextTok ();
- break;
-
- case INFOTOK_END:
- InfoNextTok ();
- InfoAssureInt ();
- InfoRangeCheck (0x0000, 0xFFFF);
- End = InfoIVal;
- Needed |= tEnd;
- InfoNextTok ();
- break;
-
- case INFOTOK_TYPE:
- InfoNextTok ();
- InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "Type");
- switch (InfoTok) {
- case INFOTOK_CODE: Type = atCode; break;
- case INFOTOK_BYTETAB: Type = atByteTab; break;
- case INFOTOK_WORDTAB: Type = atWordTab; break;
- case INFOTOK_DWORDTAB: Type = atDWordTab; break;
- case INFOTOK_ADDRTAB: Type = atAddrTab; break;
- case INFOTOK_RTSTAB: Type = atRtsTab; break;
- case INFOTOK_TEXTTAB: Type = atTextTab; break;
- }
- Needed |= tType;
- InfoNextTok ();
- break;
- }
-
- /* Directive is followed by a semicolon */
- InfoConsumeSemi ();
+ /* Convert to special token */
+ InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute");
+
+ /* Look at the token */
+ switch (InfoTok) {
+
+ case INFOTOK_COMMENT:
+ AddAttr ("COMMENT", &Attributes, tComment);
+ InfoNextTok ();
+ InfoAssureStr ();
+ if (InfoSVal[0] == '\0') {
+ InfoError ("Comment may not be empty");
+ }
+ Comment = xstrdup (InfoSVal);
+ Attributes |= tComment;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_END:
+ AddAttr ("END", &Attributes, tEnd);
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (0x0000, 0xFFFF);
+ End = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_NAME:
+ AddAttr ("NAME", &Attributes, tName);
+ InfoNextTok ();
+ InfoAssureStr ();
+ if (InfoSVal[0] == '\0') {
+ InfoError ("Name may not be empty");
+ }
+ Name = xstrdup (InfoSVal);
+ Attributes |= tName;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_START:
+ AddAttr ("START", &Attributes, tStart);
+ InfoNextTok ();
+ InfoAssureInt ();
+ InfoRangeCheck (0x0000, 0xFFFF);
+ Start = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_TYPE:
+ AddAttr ("TYPE", &Attributes, tType);
+ InfoNextTok ();
+ InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
+ switch (InfoTok) {
+ case INFOTOK_ADDRTAB: Type = atAddrTab; MemberSize = 2; break;
+ case INFOTOK_BYTETAB: Type = atByteTab; MemberSize = 1; break;
+ case INFOTOK_CODE: Type = atCode; MemberSize = 1; break;
+ case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break;
+ case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break;
+ case INFOTOK_RTSTAB: Type = atRtsTab; MemberSize = 2; break;
+ case INFOTOK_SKIP: Type = atSkip; MemberSize = 1; break;
+ case INFOTOK_TEXTTAB: Type = atTextTab; MemberSize = 1; break;
+ case INFOTOK_WORDTAB: Type = atWordTab; MemberSize = 2; break;
+ }
+ InfoNextTok ();
+ break;
+
+ default:
+ Internal ("Unexpected token: %u", InfoTok);
+ }
+
+ /* Directive is followed by a semicolon */
+ InfoConsumeSemi ();
}
/* Did we get all required values? */
- if (Needed != tAll) {
- InfoError ("Required values missing from this section");
+ if ((Attributes & tNeeded) != tNeeded) {
+ InfoError ("Required values missing from this section");
}
/* Start must be less than end */
if (Start > End) {
- InfoError ("Start value must not be greater than end value");
+ InfoError ("Start value must not be greater than end value");
+ }
+
+ /* Check the granularity */
+ if (((End - Start + 1) % MemberSize) != 0) {
+ InfoError ("Type of range needs a granularity of %u", MemberSize);
}
/* Set the range */
MarkRange (Start, End, Type);
+ /* Do we have a label? */
+ if (Attributes & tName) {
+
+ /* Define a label for the table */
+ AddExtLabel (Start, Name);
+
+ /* Set the comment if we have one */
+ if (Comment) {
+ SetComment (Start, Comment);
+ }
+
+ /* Delete name and comment */
+ xfree (Name);
+ xfree (Comment);
+ }
+
/* Consume the closing brace */
InfoConsumeRCurly ();
}
-static void LabelSection (void)
-/* Parse a label section */
+static void SegmentSection (void)
+/* Parse a segment section */
{
static const IdentTok LabelDefs[] = {
- { "NAME", INFOTOK_NAME },
- { "ADDR", INFOTOK_ADDR },
- { "SIZE", INFOTOK_SIZE },
+ { "END", INFOTOK_END },
+ { "NAME", INFOTOK_NAME },
+ { "START", INFOTOK_START },
};
/* Locals - initialize to avoid gcc warnings */
- char* Name = 0;
- long Value = -1;
- long Size = -1;
+ long End = -1;
+ long Start = -1;
+ char* Name = 0;
/* Skip the token */
InfoNextTok ();
/* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) {
- /* Convert to special token */
- InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive");
-
- /* Look at the token */
- switch (InfoTok) {
-
- case INFOTOK_NAME:
- InfoNextTok ();
- if (Name) {
- InfoError ("Name already given");
- }
- InfoAssureStr ();
- if (InfoSVal[0] == '\0') {
- InfoError ("Name may not be empty");
- }
- Name = xstrdup (InfoSVal);
- InfoNextTok ();
- break;
-
- case INFOTOK_ADDR:
- InfoNextTok ();
- if (Value >= 0) {
- InfoError ("Value already given");
- }
- InfoAssureInt ();
- InfoRangeCheck (0, 0xFFFF);
- Value = InfoIVal;
- InfoNextTok ();
- break;
-
- case INFOTOK_SIZE:
- InfoNextTok ();
- if (Size >= 0) {
- InfoError ("Size already given");
- }
- InfoAssureInt ();
- InfoRangeCheck (1, 0x10000);
- Size = InfoIVal;
- InfoNextTok ();
- break;
-
- }
-
- /* Directive is followed by a semicolon */
- InfoConsumeSemi ();
+ /* Convert to special token */
+ InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute");
+
+ /* Look at the token */
+ switch (InfoTok) {
+
+ case INFOTOK_END:
+ InfoNextTok ();
+ if (End >= 0) {
+ InfoError ("Value already given");
+ }
+ InfoAssureInt ();
+ InfoRangeCheck (0, 0xFFFF);
+ End = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_NAME:
+ InfoNextTok ();
+ if (Name) {
+ InfoError ("Name already given");
+ }
+ InfoAssureStr ();
+ Name = xstrdup (InfoSVal);
+ InfoNextTok ();
+ break;
+
+ case INFOTOK_START:
+ InfoNextTok ();
+ if (Start >= 0) {
+ InfoError ("Value already given");
+ }
+ InfoAssureInt ();
+ InfoRangeCheck (0, 0xFFFF);
+ Start = InfoIVal;
+ InfoNextTok ();
+ break;
+
+ default:
+ Internal ("Unexpected token: %u", InfoTok);
+ }
+
+ /* Directive is followed by a semicolon */
+ InfoConsumeSemi ();
}
- /* Did we get the necessary data */
- if (Name == 0) {
- InfoError ("Label name is missing");
+ /* Did we get the necessary data, and is it correct? */
+ if (Name == 0 || Name[0] == '\0') {
+ InfoError ("Segment name is missing");
}
- if (Value < 0) {
- InfoError ("Label value is missing");
+ if (End < 0) {
+ InfoError ("End address is missing");
}
- if (Size < 0) {
- /* Use default */
- Size = 1;
+ if (Start < 0) {
+ InfoError ("Start address is missing");
}
- if (Value + Size > 0x10000) {
- InfoError ("Invalid size (address out of range)");
- }
- if (HaveLabel ((unsigned) Value)) {
- InfoError ("Label for address $%04lX already defined", Value);
+ if (Start > End) {
+ InfoError ("Start address of segment is greater than end address");
}
- /* Define the label */
- AddLabel ((unsigned) Value, atExtLabel, Name);
-
- /* Define dependent labels if necessary */
- if (Size > 1) {
- unsigned Offs;
-
- /* Allocate memory for the dependent label names */
- unsigned NameLen = strlen (Name);
- char* DepName = xmalloc (NameLen + 7);
- char* DepOffs = DepName + NameLen + 1;
-
- /* Copy the original name into the buffer */
- memcpy (DepName, Name, NameLen);
- DepName[NameLen] = '+';
-
- /* Define the labels */
- for (Offs = 1; Offs < (unsigned) Size; ++Offs) {
- sprintf (DepOffs, "%u", Offs);
- AddLabel ((unsigned) Value+Offs, atDepLabel, DepName);
- }
-
- /* Free the name buffer */
- xfree (DepName);
+ /* Check that segments do not overlap */
+ if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
+ InfoError ("Segments must not overlap");
}
+ /* Remember the segment data */
+ AddAbsSegment ((unsigned) Start, (unsigned) End, Name);
+
/* Delete the dynamically allocated memory for Name */
xfree (Name);
/* Parse the config file */
{
static const IdentTok Globals[] = {
- { "GLOBAL", INFOTOK_GLOBAL },
- { "RANGE", INFOTOK_RANGE },
- { "LABEL", INFOTOK_LABEL },
+ { "ASMINC", INFOTOK_ASMINC },
+ { "GLOBAL", INFOTOK_GLOBAL },
+ { "LABEL", INFOTOK_LABEL },
+ { "RANGE", INFOTOK_RANGE },
+ { "SEGMENT", INFOTOK_SEGMENT },
};
while (InfoTok != INFOTOK_EOF) {
- /* Convert an identifier into a token */
- InfoSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive");
+ /* Convert an identifier into a token */
+ InfoSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive");
+
+ /* Check the token */
+ switch (InfoTok) {
- /* Check the token */
- switch (InfoTok) {
+ case INFOTOK_ASMINC:
+ AsmIncSection ();
+ break;
- case INFOTOK_GLOBAL:
- GlobalSection ();
- break;
+ case INFOTOK_GLOBAL:
+ GlobalSection ();
+ break;
- case INFOTOK_RANGE:
- RangeSection ();
- break;
+ case INFOTOK_LABEL:
+ LabelSection ();
+ break;
- case INFOTOK_LABEL:
- LabelSection ();
- break;
+ case INFOTOK_RANGE:
+ RangeSection ();
+ break;
- }
+ case INFOTOK_SEGMENT:
+ SegmentSection ();
+ break;
- /* Semicolon expected */
- InfoConsumeSemi ();
+ default:
+ Internal ("Unexpected token: %u", InfoTok);
+ }
+
+ /* Semicolon expected */
+ InfoConsumeSemi ();
}
}
InfoCloseInput ();
}
}
-
-
-
-
-
-