Some reformatting and improved diagnostics.

This commit is contained in:
Kugel Fuhr
2025-07-10 11:39:59 +02:00
parent 3e81cd6ae0
commit 2e3edf9b1b
5 changed files with 141 additions and 101 deletions

View File

@@ -110,8 +110,7 @@ void CheckAssertions (void)
const LineInfo* LI; const LineInfo* LI;
const FilePos* Pos; const FilePos* Pos;
const char* Module; const char* Message;
unsigned Line;
/* Get the assertion */ /* Get the assertion */
Assertion* A = CollAtUnchecked (&Assertions, I); Assertion* A = CollAtUnchecked (&Assertions, I);
@@ -121,25 +120,18 @@ void CheckAssertions (void)
continue; continue;
} }
/* Retrieve the relevant line info for this assertion */ /* Get some assertion data */
LI = CollConstAt (&A->LineInfos, 0); Message = GetString (A->Msg);
LI = CollConstAt (&A->LineInfos, 0);
/* Get the source file position of the assertion plus file and line Pos = GetSourcePos (LI);
** number.
*/
Pos = GetSourcePos (LI);
Line = GetSourceLine (LI);
Module = GetSourceName (LI);
/* If the expression is not constant, we're not able to handle it */ /* If the expression is not constant, we're not able to handle it */
if (!IsConstExpr (A->Expr)) { if (!IsConstExpr (A->Expr)) {
Warning ("Cannot evaluate assertion in module `%s', line %u", AddPNote (Pos, "The assert message is: \"%s\"", Message);
Module, Line); PWarning (Pos, "Cannot evaluate this source code assertion");
} else if (GetExprVal (A->Expr) == 0) { } else if (GetExprVal (A->Expr) == 0) {
/* Assertion failed */ /* Assertion failed */
const char* Message = GetString (A->Msg);
switch (A->Action) { switch (A->Action) {
case ASSERT_ACT_WARN: case ASSERT_ACT_WARN:
@@ -153,9 +145,8 @@ void CheckAssertions (void)
break; break;
default: default:
Internal ("Invalid assertion action (%u) in module '%s', " AddPNote (Pos, "The file might be corrupt or wrong version");
"line %u (file corrupt?)", PError (Pos, "Invalid assertion action %u", A->Action);
A->Action, Module, Line);
break; break;
} }
} }

View File

@@ -321,9 +321,8 @@ static MemoryArea* CreateMemoryArea (const FilePos* Pos, unsigned Name)
/* Check for duplicate names */ /* Check for duplicate names */
MemoryArea* M = CfgFindMemory (Name); MemoryArea* M = CfgFindMemory (Name);
if (M) { if (M) {
PError (&CfgErrorPos, PError (&CfgErrorPos, "Memory area `%s' defined twice",
"Memory area `%s' defined twice", GetString (Name));
GetString (Name));
} }
/* Create a new memory area */ /* Create a new memory area */
@@ -440,7 +439,8 @@ static void ParseMemory (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"Memory attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -500,7 +500,7 @@ static void ParseMemory (void)
case CFGTOK_TYPE: case CFGTOK_TYPE:
FlagAttr (&M->Attr, MA_TYPE, "TYPE"); FlagAttr (&M->Attr, MA_TYPE, "TYPE");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "TYPE"); CfgSpecialToken (Types, ENTRY_COUNT (Types), "Memory type");
if (CfgTok == CFGTOK_RO) { if (CfgTok == CFGTOK_RO) {
M->Flags |= MF_RO; M->Flags |= MF_RO;
} }
@@ -554,7 +554,7 @@ static void ParseFiles (void)
/* The MEMORY section must preceed the FILES section */ /* The MEMORY section must preceed the FILES section */
if ((SectionsEncountered & SE_MEMORY) == 0) { if ((SectionsEncountered & SE_MEMORY) == 0) {
PError (&CfgErrorPos, "MEMORY must precede FILES"); PError (&CfgErrorPos, "`MEMORY' must precede `FILES'");
} }
/* Parse all files */ /* Parse all files */
@@ -568,9 +568,8 @@ static void ParseFiles (void)
/* Search for the file, it must exist */ /* Search for the file, it must exist */
F = FindFile (GetStrBufId (&CfgSVal)); F = FindFile (GetStrBufId (&CfgSVal));
if (F == 0) { if (F == 0) {
PError (&CfgErrorPos, PError (&CfgErrorPos, "File `%s' not found in `MEMORY' section",
"File `%s' not found in MEMORY section", SB_GetConstBuf (&CfgSVal));
SB_GetConstBuf (&CfgSVal));
} }
/* Skip the token and the following colon */ /* Skip the token and the following colon */
@@ -582,7 +581,8 @@ static void ParseFiles (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"File attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -595,11 +595,10 @@ static void ParseFiles (void)
case CFGTOK_FORMAT: case CFGTOK_FORMAT:
if (F->Format != BINFMT_DEFAULT) { if (F->Format != BINFMT_DEFAULT) {
/* We've set the format already! */ /* We've set the format already! */
PError (&CfgErrorPos, PError (&CfgErrorPos, "Cannot set a file format twice");
"Cannot set a file format twice");
} }
/* Read the format token */ /* Read the format token */
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "File format");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_BIN: case CFGTOK_BIN:
@@ -667,7 +666,7 @@ static void ParseSegments (void)
/* The MEMORY section must preceed the SEGMENTS section */ /* The MEMORY section must preceed the SEGMENTS section */
if ((SectionsEncountered & SE_MEMORY) == 0) { if ((SectionsEncountered & SE_MEMORY) == 0) {
PError (&CfgErrorPos, "MEMORY must precede SEGMENTS"); PError (&CfgErrorPos, "`MEMORY' must precede `SEGMENTS'");
} }
while (CfgTok == CFGTOK_IDENT) { while (CfgTok == CFGTOK_IDENT) {
@@ -686,7 +685,7 @@ static void ParseSegments (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Segment attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -759,7 +758,7 @@ static void ParseSegments (void)
case CFGTOK_TYPE: case CFGTOK_TYPE:
FlagAttr (&S->Attr, SA_TYPE, "TYPE"); FlagAttr (&S->Attr, SA_TYPE, "TYPE");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); CfgSpecialToken (Types, ENTRY_COUNT (Types), "Segment type");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_RO: S->Flags |= SF_RO; break; case CFGTOK_RO: S->Flags |= SF_RO; break;
case CFGTOK_RW: /* Default */ break; case CFGTOK_RW: /* Default */ break;
@@ -794,8 +793,8 @@ static void ParseSegments (void)
*/ */
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) { if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
PWarning (&CfgErrorPos, PWarning (&CfgErrorPos,
"ALIGN_LOAD attribute specified, but no separate " "`ALIGN_LOAD' attribute specified, but no separate "
"LOAD and RUN memory areas assigned"); "`LOAD' and `RUN' memory areas assigned");
/* Remove the flag */ /* Remove the flag */
S->Flags &= ~SF_ALIGN_LOAD; S->Flags &= ~SF_ALIGN_LOAD;
} }
@@ -805,16 +804,16 @@ static void ParseSegments (void)
*/ */
if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) { if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
PWarning (&CfgErrorPos, PWarning (&CfgErrorPos,
"Segment with type `bss' has both LOAD and RUN " "Segment with type `bss' has both `LOAD' and `RUN' "
"memory areas assigned"); "memory areas assigned");
} }
/* Don't allow read/write data to be put into a readonly area */ /* Don't allow read/write data to be put into a readonly area */
if ((S->Flags & SF_RO) == 0) { if ((S->Flags & SF_RO) == 0) {
if (S->Run->Flags & MF_RO) { if (S->Run->Flags & MF_RO) {
PError (&CfgErrorPos, PError (&CfgErrorPos,
"Cannot put r/w segment `%s' in r/o memory area `%s'", "Cannot place r/w segment `%s' in r/o memory area `%s'",
GetString (S->Name), GetString (S->Run->Name)); GetString (S->Name), GetString (S->Run->Name));
} }
} }
@@ -824,7 +823,7 @@ static void ParseSegments (void)
((S->Flags & SF_START) != 0); ((S->Flags & SF_START) != 0);
if (Count > 1) { if (Count > 1) {
PError (&CfgErrorPos, PError (&CfgErrorPos,
"Only one of ALIGN, START, OFFSET may be used"); "Only one of `ALIGN', `START' or `OFFSET' may be used");
} }
/* Skip the semicolon */ /* Skip the semicolon */
@@ -881,7 +880,7 @@ static void ParseO65 (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "O65 attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -924,7 +923,7 @@ static void ParseO65 (void)
/* Cannot have this attribute twice */ /* Cannot have this attribute twice */
FlagAttr (&AttrFlags, atType, "TYPE"); FlagAttr (&AttrFlags, atType, "TYPE");
/* Get the type of the executable */ /* Get the type of the executable */
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); CfgSpecialToken (Types, ENTRY_COUNT (Types), "O65 type");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_SMALL: case CFGTOK_SMALL:
@@ -952,7 +951,9 @@ static void ParseO65 (void)
CfgRangeCheck (O65OS_MIN, O65OS_MAX); CfgRangeCheck (O65OS_MIN, O65OS_MAX);
OS = (unsigned) CfgIVal; OS = (unsigned) CfgIVal;
} else { } else {
CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type"); CfgSpecialToken (OperatingSystems,
ENTRY_COUNT (OperatingSystems),
"O65 OS specification");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_LUNIX: OS = O65OS_LUNIX; break; case CFGTOK_LUNIX: OS = O65OS_LUNIX; break;
case CFGTOK_OSA65: OS = O65OS_OSA65; break; case CFGTOK_OSA65: OS = O65OS_OSA65; break;
@@ -994,12 +995,12 @@ static void ParseO65 (void)
if (OS == O65OS_CC65) { if (OS == O65OS_CC65) {
if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) { if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) {
PError (&CfgErrorPos, PError (&CfgErrorPos,
"OS type CC65 may not have imports or exports for ids < $8000"); "OS type CC65 may not have imports or exports for ids < $8000");
} }
} else { } else {
if (AttrFlags & atID) { if (AttrFlags & atID) {
PError (&CfgErrorPos, PError (&CfgErrorPos,
"Operating system does not support the ID attribute"); "Operating system does not support the ID attribute");
} }
} }
@@ -1033,7 +1034,7 @@ static void ParseXex (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Xex attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -1071,7 +1072,7 @@ static void ParseXex (void)
CfgNextTok (); CfgNextTok ();
/* Add to XEX */ /* Add to XEX */
if (XexAddInitAd (XexFmtDesc, InitMem, InitAd)) if (XexAddInitAd (XexFmtDesc, InitMem, InitAd))
PError (&CfgErrorPos, "INITAD already given for memory area"); PError (&CfgErrorPos, "`INITAD' already given for memory area");
break; break;
default: default:
@@ -1104,7 +1105,7 @@ static void ParseFormats (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t FormatTok; cfgtok_t FormatTok;
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format attribute");
FormatTok = CfgTok; FormatTok = CfgTok;
/* Skip the name and the following colon */ /* Skip the name and the following colon */
@@ -1190,7 +1191,8 @@ static void ParseConDes (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"CONDES attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -1232,7 +1234,7 @@ static void ParseConDes (void)
case CFGTOK_ORDER: case CFGTOK_ORDER:
/* Don't allow this twice */ /* Don't allow this twice */
FlagAttr (&AttrFlags, atOrder, "ORDER"); FlagAttr (&AttrFlags, atOrder, "ORDER");
CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order"); CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "CONDES order");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_DECREASING: Order = cdDecreasing; break; case CFGTOK_DECREASING: Order = cdDecreasing; break;
case CFGTOK_INCREASING: Order = cdIncreasing; break; case CFGTOK_INCREASING: Order = cdIncreasing; break;
@@ -1257,7 +1259,7 @@ static void ParseConDes (void)
CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
Type = (int) CfgIVal; Type = (int) CfgIVal;
} else { } else {
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); CfgSpecialToken (Types, ENTRY_COUNT (Types), "CONDES type");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
@@ -1291,8 +1293,8 @@ static void ParseConDes (void)
/* Check if the condes has already attributes defined */ /* Check if the condes has already attributes defined */
if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) { if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) {
PError (&CfgErrorPos, PError (&CfgErrorPos,
"CONDES attributes for type %d are already defined", "`CONDES' attributes for type %d are already defined",
Type); Type);
} }
/* Define the attributes */ /* Define the attributes */
@@ -1334,7 +1336,8 @@ static void ParseStartAddress (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"Start address attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* An optional assignment follows */ /* An optional assignment follows */
@@ -1389,7 +1392,7 @@ static void ParseFeatures (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t FeatureTok; cfgtok_t FeatureTok;
CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature"); CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature attribute");
FeatureTok = CfgTok; FeatureTok = CfgTok;
/* Skip the name and the following colon */ /* Skip the name and the following colon */
@@ -1479,7 +1482,8 @@ static void ParseSymbols (void)
/* Map the identifier to a token */ /* Map the identifier to a token */
cfgtok_t AttrTok; cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"Symbol attribute");
AttrTok = CfgTok; AttrTok = CfgTok;
/* Skip the attribute name */ /* Skip the attribute name */
@@ -1495,7 +1499,8 @@ static void ParseSymbols (void)
/* Don't allow this twice */ /* Don't allow this twice */
FlagAttr (&AttrFlags, atAddrSize, "ADDRSIZE"); FlagAttr (&AttrFlags, atAddrSize, "ADDRSIZE");
/* Map the type to a token */ /* Map the type to a token */
CfgSpecialToken (AddrSizes, ENTRY_COUNT (AddrSizes), "AddrSize"); CfgSpecialToken (AddrSizes, ENTRY_COUNT (AddrSizes),
"Address size specification");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_ABS: AddrSize = ADDR_SIZE_ABS; break; case CFGTOK_ABS: AddrSize = ADDR_SIZE_ABS; break;
case CFGTOK_FAR: AddrSize = ADDR_SIZE_FAR; break; case CFGTOK_FAR: AddrSize = ADDR_SIZE_FAR; break;
@@ -1511,7 +1516,8 @@ static void ParseSymbols (void)
/* Don't allow this twice */ /* Don't allow this twice */
FlagAttr (&AttrFlags, atType, "TYPE"); FlagAttr (&AttrFlags, atType, "TYPE");
/* Map the type to a token */ /* Map the type to a token */
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); CfgSpecialToken (Types, ENTRY_COUNT (Types),
"Address size type");
switch (CfgTok) { switch (CfgTok) {
case CFGTOK_EXPORT: Type = CfgSymExport; break; case CFGTOK_EXPORT: Type = CfgSymExport; break;
case CFGTOK_IMPORT: Type = CfgSymImport; break; case CFGTOK_IMPORT: Type = CfgSymImport; break;
@@ -1606,7 +1612,8 @@ static void ParseConfig (void)
do { do {
/* Read the block ident */ /* Read the block ident */
CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier"); CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames),
"Configuration block identifier");
BlockTok = CfgTok; BlockTok = CfgTok;
CfgNextTok (); CfgNextTok ();
@@ -1704,8 +1711,8 @@ static void ProcessSegments (void)
*/ */
if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) { if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
PWarning (GetSourcePos (S->LI), PWarning (GetSourcePos (S->LI),
"Segment `%s' with type `bss' contains initialized data", "Segment `%s' with type `bss' contains initialized data",
GetString (S->Name)); GetString (S->Name));
} }
/* If this segment does exist in any of the object files, insert the /* If this segment does exist in any of the object files, insert the
@@ -1732,9 +1739,8 @@ static void ProcessSegments (void)
/* Print a warning if the segment is not optional */ /* Print a warning if the segment is not optional */
if ((S->Flags & SF_OPTIONAL) == 0) { if ((S->Flags & SF_OPTIONAL) == 0) {
PWarning (&CfgErrorPos, PWarning (&CfgErrorPos, "Segment `%s' does not exist",
"Segment `%s' does not exist", GetString (S->Name));
GetString (S->Name));
} }
/* Discard the descriptor and remove it from the collection */ /* Discard the descriptor and remove it from the collection */
@@ -1914,8 +1920,8 @@ unsigned CfgProcess (void)
*/ */
if (!IsConstExpr (M->StartExpr)) { if (!IsConstExpr (M->StartExpr)) {
PError (GetSourcePos (M->LI), PError (GetSourcePos (M->LI),
"Start address of memory area `%s' is not constant", "Start address of memory area `%s' is not constant",
GetString (M->Name)); GetString (M->Name));
} }
Addr = M->Start = GetExprVal (M->StartExpr); Addr = M->Start = GetExprVal (M->StartExpr);
M->Flags |= MF_PLACED; M->Flags |= MF_PLACED;
@@ -1939,14 +1945,14 @@ unsigned CfgProcess (void)
/* Resolve the size expression */ /* Resolve the size expression */
if (!IsConstExpr (M->SizeExpr)) { if (!IsConstExpr (M->SizeExpr)) {
PError (GetSourcePos (M->LI), PError (GetSourcePos (M->LI),
"Size of memory area `%s' is not constant", "Size of memory area `%s' is not constant",
GetString (M->Name)); GetString (M->Name));
} }
M->Size = GetExprVal (M->SizeExpr); M->Size = GetExprVal (M->SizeExpr);
if (M->Size >= 0x80000000) { if (M->Size >= 0x80000000) {
PError (GetSourcePos (M->LI), PError (GetSourcePos (M->LI),
"Size of memory area `%s' is negative: %ld", "Size of memory area `%s' is negative: %ld",
GetString (M->Name), (long)M->Size); GetString (M->Name), (long)M->Size);
} }
/* Walk through the segments in this memory area */ /* Walk through the segments in this memory area */
@@ -1969,16 +1975,16 @@ unsigned CfgProcess (void)
++Overwrites; ++Overwrites;
} else { } else {
PError (GetSourcePos (M->LI), PError (GetSourcePos (M->LI),
"Segment `%s' of type `overwrite' requires either" "Segment `%s' of type `overwrite' requires either"
" `START' or `OFFSET' attribute to be specified", " `START' or `OFFSET' attribute to be specified",
GetString (S->Name)); GetString (S->Name));
} }
} else { } else {
if (Overwrites > 0) { if (Overwrites > 0) {
PError (GetSourcePos (M->LI), PError (GetSourcePos (M->LI),
"Segment `%s' is preceded by at least one segment" "Segment `%s' is preceded by at least one segment"
" of type `overwrite'", " of type `overwrite'",
GetString (S->Name)); GetString (S->Name));
} }
} }
@@ -2003,9 +2009,9 @@ unsigned CfgProcess (void)
** in the linker. ** in the linker.
*/ */
PWarning (GetSourcePos (S->LI), PWarning (GetSourcePos (S->LI),
"Segment `%s' isn't aligned properly; the" "Segment `%s' isn't aligned properly; the"
" resulting executable might not be functional.", " resulting executable might not be functional.",
GetString (S->Name)); GetString (S->Name));
} }
if (S->Flags & SF_ALIGN) { if (S->Flags & SF_ALIGN) {
@@ -2018,9 +2024,9 @@ unsigned CfgProcess (void)
*/ */
if (M->FillLevel == 0 && NewAddr > Addr) { if (M->FillLevel == 0 && NewAddr > Addr) {
PWarning (GetSourcePos (S->LI), PWarning (GetSourcePos (S->LI),
"The first segment in memory area `%s' " "The first segment in memory area `%s' "
"needs fill bytes for alignment.", "needs fill bytes for alignment.",
GetString (M->Name)); GetString (M->Name));
} }
/* Use the aligned address */ /* Use the aligned address */
@@ -2039,8 +2045,8 @@ unsigned CfgProcess (void)
if (S->Flags & SF_OVERWRITE) { if (S->Flags & SF_OVERWRITE) {
if (NewAddr < M->Start) { if (NewAddr < M->Start) {
PError (GetSourcePos (S->LI), PError (GetSourcePos (S->LI),
"Segment `%s' begins before memory area `%s'", "Segment `%s' begins before memory area `%s'",
GetString (S->Name), GetString (M->Name)); GetString (S->Name), GetString (M->Name));
} else { } else {
Addr = NewAddr; Addr = NewAddr;
} }
@@ -2049,15 +2055,23 @@ unsigned CfgProcess (void)
/* Offset already too large */ /* Offset already too large */
++Overflows; ++Overflows;
if (S->Flags & SF_OFFSET) { if (S->Flags & SF_OFFSET) {
PWarning (GetSourcePos (S->LI), PWarning (
"Segment `%s' offset is too small in `%s' by %lu byte%s", GetSourcePos (S->LI),
GetString (S->Name), GetString (M->Name), "Segment `%s' offset is too small in `%s' by %lu byte%s",
Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s"); GetString (S->Name),
GetString (M->Name),
Addr - NewAddr,
(Addr - NewAddr == 1) ? "" : "s"
);
} else { } else {
PWarning (GetSourcePos (S->LI), PWarning (
"Segment `%s' start address is too low in `%s' by %lu byte%s", GetSourcePos (S->LI),
GetString (S->Name), GetString (M->Name), "Segment `%s' start address is too low in `%s' by %lu byte%s",
Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s"); GetString (S->Name),
GetString (M->Name),
Addr - NewAddr,
(Addr - NewAddr == 1) ? "" : "s"
);
} }
} else { } else {
Addr = NewAddr; Addr = NewAddr;
@@ -2101,10 +2115,14 @@ unsigned CfgProcess (void)
if (FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { if (FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
++Overflows; ++Overflows;
M->Flags |= MF_OVERFLOW; M->Flags |= MF_OVERFLOW;
PWarning (GetSourcePos (M->LI), PWarning (
"Segment `%s' overflows memory area `%s' by %lu byte%s", GetSourcePos (M->LI),
GetString (S->Name), GetString (M->Name), "Segment `%s' overflows memory area `%s' by %lu byte%s",
FillLevel - M->Size, (FillLevel - M->Size == 1) ? "" : "s"); GetString (S->Name),
GetString (M->Name),
FillLevel - M->Size,
(FillLevel - M->Size == 1) ? "" : "s"
);
} }
if (FillLevel > M->FillLevel) { if (FillLevel > M->FillLevel) {
/* Regular segments increase FillLevel. Overwrite segments may /* Regular segments increase FillLevel. Overwrite segments may

View File

@@ -329,7 +329,7 @@ void Internal (const char* Format, ...)
void AddCfgNote (const FilePos* Pos, const char* Format, ...) void AddPNote (const FilePos* Pos, const char* Format, ...)
/* Add a notifcation message using file name and line number of the config file. /* Add a notifcation message using file name and line number of the config file.
** See comment for AddNote() above. ** See comment for AddNote() above.
*/ */

View File

@@ -76,7 +76,7 @@ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
/* Print an internal error message and die */ /* Print an internal error message and die */
void AddCfgNote (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3))); void AddPNote (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3)));
/* Add a notifcation message using file name and line number of the config file. /* Add a notifcation message using file name and line number of the config file.
** See comment for AddNote() above. ** See comment for AddNote() above.
*/ */

View File

@@ -443,6 +443,28 @@ void CfgRangeCheck (unsigned long Lo, unsigned long Hi)
static void SpecialTokenHelp (const IdentTok* Table, unsigned Size, StrBuf* Msg)
/* Create a help message for errors in CfgSpecialToken. StrBuf must be
** initialized and is overwritten.
*/
{
unsigned I;
SB_AppendStr (Msg, "You may use one of `");
for (I = 0; I < Size; ++I) {
if (I == Size - 1) {
SB_AppendStr (Msg, " or `");
} else if (I > 0) {
SB_AppendStr (Msg, ", `");
}
SB_AppendStr (Msg, Table[I].Ident);
SB_AppendChar (Msg, '\'');
}
SB_Terminate (Msg); /* So we may use %s */
}
void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name) void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
/* Map an identifier to one of the special tokens in the table */ /* Map an identifier to one of the special tokens in the table */
{ {
@@ -461,8 +483,17 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
} }
} }
/* Not found */ /* Not found. Add a helpful note about the possible names only if
PError (&CfgErrorPos, "%s expected, got `%s'", Name, SB_GetConstBuf(&CfgSVal)); ** there is a not too large number of them.
*/
if (Size > 0 && Size <= 5) {
StrBuf Note = AUTO_STRBUF_INITIALIZER;
SpecialTokenHelp (Table, Size, &Note);
AddPNote (&CfgErrorPos, "%s", SB_GetConstBuf (&Note));
SB_Done (&Note);
}
PError (&CfgErrorPos, "%s expected but got `%s'", Name,
SB_GetConstBuf(&CfgSVal));
return; return;
} }