*/
typedef struct Symbol Symbol;
struct Symbol {
- const char* CfgName; /* Config file name */
- unsigned CfgLine; /* Config file position */
- unsigned CfgCol;
+ FilePos Pos; /* Config file position */
unsigned Name; /* Symbol name */
unsigned Flags; /* Symbol flags */
long Val; /* Symbol value if any */
{
MemoryArea* M = CfgFindMemory (Name);
if (M == 0) {
- CfgError ("Invalid memory area `%s'", GetString (Name));
+ CfgError (&CfgErrorPos, "Invalid memory area `%s'", GetString (Name));
}
return M;
}
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;
+ Sym->Pos = CfgErrorPos;
+ Sym->Name = Name;
+ Sym->Flags = Flags;
+ Sym->Val = Val;
/* Return the initialized struct */
return Sym;
-static MemoryArea* CreateMemoryArea (unsigned Name)
+static MemoryArea* CreateMemoryArea (const FilePos* Pos, unsigned Name)
/* Create a new memory area and insert it into the list */
{
/* Check for duplicate names */
MemoryArea* M = CfgFindMemory (Name);
if (M) {
- CfgError ("Memory area `%s' defined twice", GetString (Name));
+ CfgError (&CfgErrorPos,
+ "Memory area `%s' defined twice",
+ GetString (Name));
}
/* Create a new memory area */
- M = NewMemoryArea (Name);
+ M = NewMemoryArea (Pos, Name);
/* Insert the struct into the list ... */
CollAppend (&MemoryAreas, M);
/* Check for duplicate names */
SegDesc* S = CfgFindSegDesc (Name);
if (S) {
- CfgError ("Segment `%s' defined twice", GetString (Name));
+ CfgError (&CfgErrorPos, "Segment `%s' defined twice", GetString (Name));
}
/* Allocate memory */
*/
{
if (*Flags & Mask) {
- CfgError ("%s is already defined", Name);
+ CfgError (&CfgErrorPos, "%s is already defined", Name);
}
*Flags |= Mask;
}
/* Check that a mandatory attribute was given */
{
if ((Attr & Mask) == 0) {
- CfgError ("%s attribute is missing", Name);
+ CfgError (&CfgErrorPos, "%s attribute is missing", Name);
}
}
while (CfgTok == CFGTOK_IDENT) {
/* Create a new entry on the heap */
- MemoryArea* M = CreateMemoryArea (GetStrBufId (&CfgSVal));
+ MemoryArea* M = CreateMemoryArea (&CfgErrorPos, GetStrBufId (&CfgSVal));
/* Skip the name and the following colon */
CfgNextTok ();
{ "FORMAT", CFGTOK_FORMAT },
};
static const IdentTok Formats [] = {
- { "O65", CFGTOK_O65 },
+ { "O65", CFGTOK_O65 },
{ "BIN", CFGTOK_BIN },
{ "BINARY", CFGTOK_BIN },
};
/* The MEMORY section must preceed the FILES section */
if ((SectionsEncountered & SE_MEMORY) == 0) {
- CfgError ("MEMORY must precede FILES");
+ CfgError (&CfgErrorPos, "MEMORY must precede FILES");
}
/* Parse all files */
/* Search for the file, it must exist */
F = FindFile (GetStrBufId (&CfgSVal));
if (F == 0) {
- CfgError ("File `%s' not found in MEMORY section",
+ CfgError (&CfgErrorPos,
+ "File `%s' not found in MEMORY section",
SB_GetConstBuf (&CfgSVal));
}
case CFGTOK_FORMAT:
if (F->Format != BINFMT_DEFAULT) {
/* We've set the format already! */
- Error ("Cannot set a file format twice");
+ CfgError (&CfgErrorPos,
+ "Cannot set a file format twice");
}
/* Read the format token */
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
/* The MEMORY section must preceed the SEGMENTS section */
if ((SectionsEncountered & SE_MEMORY) == 0) {
- CfgError ("MEMORY must precede SEGMENTS");
+ CfgError (&CfgErrorPos, "MEMORY must precede SEGMENTS");
}
while (CfgTok == CFGTOK_IDENT) {
Val = CfgCheckedConstExpr (1, 0x10000);
S->Align = BitFind (Val);
if ((0x01L << S->Align) != Val) {
- CfgError ("Alignment must be a power of 2");
+ CfgError (&CfgErrorPos, "Alignment must be a power of 2");
}
S->Flags |= SF_ALIGN;
break;
Val = CfgCheckedConstExpr (1, 0x10000);
S->AlignLoad = BitFind (Val);
if ((0x01L << S->AlignLoad) != Val) {
- CfgError ("Alignment must be a power of 2");
+ CfgError (&CfgErrorPos, "Alignment must be a power of 2");
}
S->Flags |= SF_ALIGN_LOAD;
break;
* separate run and load memory areas.
*/
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
- Warning ("%s(%u): ALIGN_LOAD attribute specified, but no separate "
+ Warning ("%s(%lu): ALIGN_LOAD attribute specified, but no separate "
"LOAD and RUN memory areas assigned",
- CfgGetName (), CfgErrorLine);
+ CfgGetName (), CfgErrorPos.Line);
/* Remove the flag */
S->Flags &= ~SF_ALIGN_LOAD;
}
* load and run memory areas, because it's is never written to disk.
*/
if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
- Warning ("%s(%u): Segment with type `bss' has both LOAD and RUN "
- "memory areas assigned", CfgGetName (), CfgErrorLine);
+ Warning ("%s(%lu): Segment with type `bss' has both LOAD and RUN "
+ "memory areas assigned", CfgGetName (), CfgErrorPos.Line);
}
/* 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 ("Cannot put r/w segment `%s' in r/o memory area `%s'",
+ CfgError (&CfgErrorPos,
+ "Cannot put r/w segment `%s' in r/o memory area `%s'",
GetString (S->Name), GetString (S->Run->Name));
}
}
((S->Flags & SF_OFFSET) != 0) +
((S->Flags & SF_START) != 0);
if (Count > 1) {
- CfgError ("Only one of ALIGN, START, OFFSET may be used");
+ CfgError (&CfgErrorPos,
+ "Only one of ALIGN, START, OFFSET may be used");
}
/* Skip the semicolon */
break;
default:
- CfgError ("Unexpected type token");
+ CfgError (&CfgErrorPos, "Unexpected type token");
}
/* Eat the attribute token */
CfgNextTok ();
case CFGTOK_OSA65: OS = O65OS_OSA65; break;
case CFGTOK_CC65: OS = O65OS_CC65; break;
case CFGTOK_OPENCBM: OS = O65OS_OPENCBM; break;
- default: CfgError ("Unexpected OS token");
+ default: CfgError (&CfgErrorPos, "Unexpected OS token");
}
}
CfgNextTok ();
/* Check for attributes that may not be combined */
if (OS == O65OS_CC65) {
if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) {
- CfgError ("OS type CC65 may not have imports or exports for ids < $8000");
+ CfgError (&CfgErrorPos,
+ "OS type CC65 may not have imports or exports for ids < $8000");
}
} else {
if (AttrFlags & atID) {
- CfgError ("Operating system does not support the ID attribute");
+ CfgError (&CfgErrorPos,
+ "Operating system does not support the ID attribute");
}
}
/* Check if the condes has already attributes defined */
if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) {
- CfgError ("CONDES attributes for type %d are already defined", Type);
+ CfgError (&CfgErrorPos,
+ "CONDES attributes for type %d are already defined",
+ Type);
}
/* Define the attributes */
/* Resolve the expressions */
if (!IsConstExpr (M->StartExpr)) {
- Error ("Start address of memory area `%s' is not constant",
- GetString (M->Name));
+ CfgError (&M->Pos,
+ "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));
+ CfgError (&M->Pos,
+ "Size of memory area `%s' is not constant",
+ GetString (M->Name));
}
M->Size = GetExprVal (M->SizeExpr);
/* Print a warning if the segment is not optional */
if ((S->Flags & SF_OPTIONAL) == 0) {
- CfgWarning ("Segment `%s' does not exist", GetString (S->Name));
+ CfgWarning (&CfgErrorPos,
+ "Segment `%s' does not exist",
+ GetString (S->Name));
}
/* Discard the descriptor and remove it from the collection */
* 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));
+ CfgError (&Sym->Pos,
+ "Duplicate imported o65 symbol: `%s'",
+ GetString (Sym->Name));
}
/* Insert the symbol into the table */
/* 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));
+ CfgError (&Sym->Pos,
+ "Exported o65 symbol `%s' cannot also be an o65 import",
+ GetString (Sym->Name));
}
/* Check if we have this symbol defined already. The entry
* 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));
+ CfgError (&Sym->Pos,
+ "Duplicate exported o65 symbol: `%s'",
+ GetString (Sym->Name));
}
/* Insert the symbol into the table */
* Otherwise ignore the symbol from the config.
*/
if ((Sym->Flags & SYM_WEAK) == 0) {
- CfgError ("Symbol `%s' is already defined",
+ CfgError (&CfgErrorPos,
+ "Symbol `%s' is already defined",
GetString (Sym->Name));
}
} else {
if (Addr > NewAddr) {
/* Offset already too large */
if (S->Flags & SF_OFFSET) {
- Error ("Offset too small in `%s', segment `%s'",
- GetString (M->Name), GetString (S->Name));
+ CfgError (&M->Pos,
+ "Offset too small in `%s', segment `%s'",
+ GetString (M->Name),
+ GetString (S->Name));
} else {
- Error ("Start address too low in `%s', segment `%s'",
- GetString (M->Name), GetString (S->Name));
+ CfgError (&M->Pos,
+ "Start address too low in `%s', segment `%s'",
+ GetString (M->Name),
+ GetString (S->Name));
}
}
Addr = NewAddr;
/* */
/* */
/* */
-/* (C) 1998-2009, Ullrich von Bassewitz */
+/* (C) 1998-2010, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "global.h"
#include "error.h"
#include "scanner.h"
+#include "spool.h"
unsigned long CfgIVal;
/* Error location */
-unsigned CfgErrorLine;
-unsigned CfgErrorCol;
+FilePos CfgErrorPos;
/* Input sources for the configuration */
static const char* CfgName = 0;
/* Other input stuff */
static int C = ' ';
-static unsigned InputLine = 1;
-static unsigned InputCol = 0;
+static FilePos InputPos;
static FILE* InputFile = 0;
-void CfgWarning (const char* Format, ...)
-/* Print a warning message adding file name and line number of the config file */
+void CfgWarning (const FilePos* Pos, const char* Format, ...)
+/* Print a warning message adding file name and line number of a given file */
{
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
va_list ap;
SB_VPrintf (&Buf, Format, ap);
va_end (ap);
- Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
+ Warning ("%s(%lu): %s",
+ GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf));
SB_Done (&Buf);
}
-void CfgError (const char* Format, ...)
-/* Print an error message adding file name and line number of the config file */
+void CfgError (const FilePos* Pos, const char* Format, ...)
+/* Print an error message adding file name and line number of a given file */
{
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
va_list ap;
SB_VPrintf (&Buf, Format, ap);
va_end (ap);
- Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
+ Error ("%s(%lu): %s",
+ GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf));
SB_Done (&Buf);
}
/* Count columns */
if (C != EOF) {
- ++InputCol;
+ ++InputPos.Col;
}
/* Count lines */
if (C == '\n') {
- ++InputLine;
- InputCol = 0;
+ ++InputPos.Line;
+ InputPos.Col = 0;
}
}
case EOF:
case '\n':
- CfgError ("Unterminated string");
+ CfgError (&CfgErrorPos, "Unterminated string");
break;
case '%':
case EOF:
case '\n':
case '\"':
- CfgError ("Unterminated '%%' escape sequence");
+ CfgError (&CfgErrorPos, "Unterminated '%%' escape sequence");
break;
case '%':
break;
default:
- CfgWarning ("Unkown escape sequence `%%%c'", C);
+ CfgWarning (&CfgErrorPos,
+ "Unkown escape sequence `%%%c'", C);
SB_AppendChar (&CfgSVal, '%');
SB_AppendChar (&CfgSVal, C);
NextChar ();
}
/* Remember the current position */
- CfgErrorLine = InputLine;
- CfgErrorCol = InputCol;
+ CfgErrorPos = InputPos;
/* Identifier? */
if (C == '_' || IsAlpha (C)) {
if (C == '$') {
NextChar ();
if (!isxdigit (C)) {
- CfgError ("Hex digit expected");
+ CfgError (&CfgErrorPos, "Hex digit expected");
}
CfgIVal = 0;
while (isxdigit (C)) {
break;
default:
- CfgError ("Invalid format specification");
+ CfgError (&CfgErrorPos, "Invalid format specification");
}
break;
break;
default:
- CfgError ("Invalid character `%c'", C);
+ CfgError (&CfgErrorPos, "Invalid character `%c'", C);
}
}
/* Skip a token, print an error message if not found */
{
if (CfgTok != T) {
- CfgError ("%s", Msg);
+ CfgError (&CfgErrorPos, "%s", Msg);
}
CfgNextTok ();
}
/* Make sure the next token is an integer */
{
if (CfgTok != CFGTOK_INTCON) {
- CfgError ("Integer constant expected");
+ CfgError (&CfgErrorPos, "Integer constant expected");
}
}
/* Make sure the next token is a string constant */
{
if (CfgTok != CFGTOK_STRCON) {
- CfgError ("String constant expected");
+ CfgError (&CfgErrorPos, "String constant expected");
}
}
/* Make sure the next token is an identifier */
{
if (CfgTok != CFGTOK_IDENT) {
- CfgError ("Identifier expected");
+ CfgError (&CfgErrorPos, "Identifier expected");
}
}
/* Check the range of CfgIVal */
{
if (CfgIVal < Lo || CfgIVal > Hi) {
- CfgError ("Range error");
+ CfgError (&CfgErrorPos, "Range error");
}
}
}
/* Not found or no identifier */
- CfgError ("%s expected", Name);
+ CfgError (&CfgErrorPos, "%s expected", Name);
}
} else {
/* We expected an integer here */
if (CfgTok != CFGTOK_INTCON) {
- CfgError ("Boolean value expected");
+ CfgError (&CfgErrorPos, "Boolean value expected");
}
CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
}
/* Initialize variables */
C = ' ';
- InputLine = 1;
- InputCol = 0;
+ InputPos.Line = 1;
+ InputPos.Col = 0;
+ InputPos.Name = GetStringId (CfgBuf? "[builtin config]" : CfgName);
/* Start the ball rolling ... */
CfgNextTok ();
-