Merge branch 'master' into fix-pr-2778

This commit is contained in:
Colin Leroy-Mira
2025-07-20 16:28:49 +02:00
97 changed files with 1245 additions and 561 deletions

View File

@@ -71,7 +71,7 @@ unsigned WarningCount = 0;
typedef enum { DC_NOTE, DC_WARN, DC_ERR, DC_FATAL, DC_COUNT } DiagCat;
/* Descriptions for diagnostic categories */
const char* DiagCatDesc[DC_COUNT] = {
static const char* DiagCatDesc[DC_COUNT] = {
"Note", "Warning", "Error", "Fatal error"
};

View File

@@ -504,14 +504,11 @@ static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char*
static void OptColor(const char* Opt, const char* Arg)
/* Handle the --color option */
{
if (strcmp (Arg, "off") == 0 || strcmp (Arg, "false") == 0) {
CP_SetColorMode (CM_OFF);
} else if (strcmp (Arg, "auto") == 0) {
CP_SetColorMode (CM_AUTO);
} else if (strcmp (Arg, "on") == 0 || strcmp (Arg, "true") == 0) {
CP_SetColorMode (CM_ON);
} else {
ColorMode Mode = CP_Parse (Arg);
if (Mode == CM_INVALID) {
AbEnd ("Invalid argument to %s: %s", Opt, Arg);
} else {
CP_SetColorMode (Mode);
}
}
@@ -745,6 +742,8 @@ static void OptVersion (const char* Opt attribute ((unused)),
exit (EXIT_SUCCESS);
}
static void OptSeglist (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Enable segment listing */
@@ -752,6 +751,8 @@ static void OptSeglist (const char* Opt attribute ((unused)),
SegList = 1;
}
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Generate an error if any warnings occur */
@@ -759,6 +760,8 @@ static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
WarningsAsErrors = 1;
}
static void OptExpandMacros (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Expand macros in listing
@@ -770,6 +773,8 @@ static void OptExpandMacros (const char* Opt attribute ((unused)),
ExpandMacros++;
}
static void DoPCAssign (void)
/* Start absolute code */
{

View File

@@ -642,7 +642,7 @@ static void DoCharMap (void)
/* Read the index as numerical value */
Index = ConstExpression ();
if (IsByteRange (Index)) {
if (!IsByteRange (Index)) {
/* Value out of range */
ErrorSkip ("Index must be in byte range");
return;

View File

@@ -107,15 +107,15 @@ struct OptFunc {
static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 };
static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 };
static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptAXLoad = { OptAXLoad, "OptAXLoad", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptAXLoad2 = { OptAXLoad2, "OptAXLoad2", 66, 0, 0, 0, 0, 0 };
static OptFunc DOptAXOps = { OptAXOps, "OptAXOps", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd1 = { OptAdd1, "OptAdd1", 125, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 65, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd6 = { OptAdd6, "OptAdd6", 40, 0, 0, 0, 0, 0 };
static OptFunc DOptAXLoad = { OptAXLoad, "OptAXLoad", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptAXLoad2 = { OptAXLoad2, "OptAXLoad2", 66, 0, 0, 0, 0, 0 };
static OptFunc DOptAXOps = { OptAXOps, "OptAXOps", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0, 0, 0, 0, 0 };
@@ -233,13 +233,15 @@ static OptFunc* OptFuncs[] = {
&DOpt65C02BitOps,
&DOpt65C02Ind,
&DOpt65C02Stores,
&DOptAXLoad,
&DOptAXLoad2,
&DOptAXOps,
&DOptAdd1,
&DOptAdd2,
&DOptAdd3,
&DOptAdd4,
&DOptAdd5,
&DOptAdd6,
&DOptAXOps,
&DOptBNegA1,
&DOptBNegA2,
&DOptBNegAX1,

View File

@@ -140,6 +140,7 @@ static void Usage (void)
" --target sys\t\t\tSet the target system\n"
" --verbose\t\t\tIncrease verbosity\n"
" --version\t\t\tPrint the compiler version number\n"
" --warnings-as-errors\t\tTreat warnings as errors\n"
" --writable-strings\t\tMake string literals writable\n",
ProgName);
}
@@ -968,6 +969,15 @@ static void OptWarning (const char* Opt attribute ((unused)), const char* Arg)
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Generate an error if any warnings occur */
{
IS_Set (&WarningsAreErrors, 1);
}
static void OptWritableStrings (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Make string literals writable */
@@ -1016,6 +1026,7 @@ int main (int argc, char* argv[])
{ "--target", 1, OptTarget },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
{ "--warnings-as-errors", 0, OptWarningsAsErrors },
{ "--writable-strings", 0, OptWritableStrings },
};
@@ -1089,6 +1100,14 @@ int main (int argc, char* argv[])
OptSignedChars (Arg, 0);
break;
case 'm':
if (Arg[2] == 'm') {
OptMemoryModel (Arg, GetArg (&I, 3));
} else {
UnknownOption (Arg);
}
break;
case 'o':
SetOutputName (GetArg (&I, 2));
break;

View File

@@ -70,6 +70,7 @@
/* common */
#include "attrib.h"
#include "cmdline.h"
#include "consprop.h"
#include "filetype.h"
#include "fname.h"
#include "mmodel.h"
@@ -858,6 +859,7 @@ static void Usage (void)
" --code-label name\t\tDefine and export a CODE segment label\n"
" --code-name seg\t\tSet the name of the CODE segment\n"
" --codesize x\t\t\tAccept larger code by factor x\n"
" --color [on|auto|off]\t\tColor diagnostics (default: auto)\n"
" --config name\t\t\tUse linker config file\n"
" --cpu type\t\t\tSet CPU type\n"
" --create-dep name\t\tCreate a make dependency file\n"
@@ -880,6 +882,7 @@ static void Usage (void)
" --module\t\t\tLink as a module\n"
" --module-id id\t\tSpecify a module ID for the linker\n"
" --no-target-lib\t\tDon't link the target library\n"
" --no-utf8\t\t\tDisable use of UTF-8 in diagnostics\n"
" --o65-model model\t\tOverride the o65 model\n"
" --obj file\t\t\tLink this object file\n"
" --obj-path path\t\tSpecify an object file search path\n"
@@ -895,7 +898,8 @@ static void Usage (void)
" --version\t\t\tPrint the version number\n"
" --verbose\t\t\tVerbose mode\n"
" --zeropage-label name\t\tDefine and export a ZEROPAGE segment label\n"
" --zeropage-name seg\t\tSet the name of the ZEROPAGE segment\n",
" --zeropage-name seg\t\tSet the name of the ZEROPAGE segment\n"
" --warnings-as-errors\t\tTreat warnings as errors\n",
ProgName);
}
@@ -1028,6 +1032,19 @@ static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
static void OptColor(const char* Opt, const char* Arg)
/* Handle the --color option */
{
if (CP_Parse (Arg) == CM_INVALID) {
Error ("Invalid argument to %s: %s", Opt, Arg);
} else {
CmdAddArg2 (&CA65, "--color", Arg);
CmdAddArg2 (&LD65, "--color", Arg);
}
}
static void OptCPU (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --cpu option */
{
@@ -1236,6 +1253,16 @@ static void OptNoTargetLib (const char* Opt attribute ((unused)),
static void OptNoUtf8 (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --no-utf8 option */
{
CmdAddArg (&CA65, "--no-utf8");
CmdAddArg (&LD65, "--no-utf8");
}
static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --o65-model option */
{
@@ -1409,63 +1436,77 @@ static void OptZeropageName (const char* Opt attribute ((unused)), const char* A
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --warnings-as-errors option */
{
CmdAddArg (&CA65, "--warnings-as-errors");
CmdAddArg (&CC65, "--warnings-as-errors");
CmdAddArg (&LD65, "--warnings-as-errors");
}
int main (int argc, char* argv [])
/* Utility main program */
{
/* Program long options */
static const LongOpt OptTab[] = {
{ "--add-source", 0, OptAddSource },
{ "--all-cdecl", 0, OptAllCDecl },
{ "--asm-args", 1, OptAsmArgs },
{ "--asm-define", 1, OptAsmDefine },
{ "--asm-include-dir", 1, OptAsmIncludeDir },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--bss-label", 1, OptBssLabel },
{ "--bss-name", 1, OptBssName },
{ "--cc-args", 1, OptCCArgs },
{ "--cfg-path", 1, OptCfgPath },
{ "--check-stack", 0, OptCheckStack },
{ "--code-label", 1, OptCodeLabel },
{ "--code-name", 1, OptCodeName },
{ "--codesize", 1, OptCodeSize },
{ "--config", 1, OptConfig },
{ "--cpu", 1, OptCPU },
{ "--create-dep", 1, OptCreateDep },
{ "--create-full-dep", 1, OptCreateFullDep },
{ "--data-label", 1, OptDataLabel },
{ "--data-name", 1, OptDataName },
{ "--debug", 0, OptDebug },
{ "--debug-info", 0, OptDebugInfo },
{ "--feature", 1, OptFeature },
{ "--force-import", 1, OptForceImport },
{ "--help", 0, OptHelp },
{ "--include-dir", 1, OptIncludeDir },
{ "--ld-args", 1, OptLdArgs },
{ "--lib-path", 1, OptLibPath },
{ "--list-targets", 0, OptListTargets },
{ "--listing", 1, OptListing },
{ "--list-bytes", 1, OptListBytes },
{ "--mapfile", 1, OptMapFile },
{ "--memory-model", 1, OptMemoryModel },
{ "--module", 0, OptModule },
{ "--module-id", 1, OptModuleId },
{ "--no-target-lib", 0, OptNoTargetLib },
{ "--o65-model", 1, OptO65Model },
{ "--obj", 1, OptObj },
{ "--obj-path", 1, OptObjPath },
{ "--print-target-path", 0, OptPrintTargetPath},
{ "--register-space", 1, OptRegisterSpace },
{ "--register-vars", 0, OptRegisterVars },
{ "--rodata-name", 1, OptRodataName },
{ "--signed-chars", 0, OptSignedChars },
{ "--standard", 1, OptStandard },
{ "--start-addr", 1, OptStartAddr },
{ "--static-locals", 0, OptStaticLocals },
{ "--target", 1, OptTarget },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
{ "--zeropage-label", 1, OptZeropageLabel },
{ "--zeropage-name", 1, OptZeropageName },
{ "--add-source", 0, OptAddSource },
{ "--all-cdecl", 0, OptAllCDecl },
{ "--asm-args", 1, OptAsmArgs },
{ "--asm-define", 1, OptAsmDefine },
{ "--asm-include-dir", 1, OptAsmIncludeDir },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--bss-label", 1, OptBssLabel },
{ "--bss-name", 1, OptBssName },
{ "--cc-args", 1, OptCCArgs },
{ "--cfg-path", 1, OptCfgPath },
{ "--check-stack", 0, OptCheckStack },
{ "--code-label", 1, OptCodeLabel },
{ "--code-name", 1, OptCodeName },
{ "--codesize", 1, OptCodeSize },
{ "--color", 1, OptColor },
{ "--config", 1, OptConfig },
{ "--cpu", 1, OptCPU },
{ "--create-dep", 1, OptCreateDep },
{ "--create-full-dep", 1, OptCreateFullDep },
{ "--data-label", 1, OptDataLabel },
{ "--data-name", 1, OptDataName },
{ "--debug", 0, OptDebug },
{ "--debug-info", 0, OptDebugInfo },
{ "--feature", 1, OptFeature },
{ "--force-import", 1, OptForceImport },
{ "--help", 0, OptHelp },
{ "--include-dir", 1, OptIncludeDir },
{ "--ld-args", 1, OptLdArgs },
{ "--lib-path", 1, OptLibPath },
{ "--list-targets", 0, OptListTargets },
{ "--listing", 1, OptListing },
{ "--list-bytes", 1, OptListBytes },
{ "--mapfile", 1, OptMapFile },
{ "--memory-model", 1, OptMemoryModel },
{ "--module", 0, OptModule },
{ "--module-id", 1, OptModuleId },
{ "--no-target-lib", 0, OptNoTargetLib },
{ "--no-utf8", 0, OptNoUtf8 },
{ "--o65-model", 1, OptO65Model },
{ "--obj", 1, OptObj },
{ "--obj-path", 1, OptObjPath },
{ "--print-target-path", 0, OptPrintTargetPath },
{ "--register-space", 1, OptRegisterSpace },
{ "--register-vars", 0, OptRegisterVars },
{ "--rodata-name", 1, OptRodataName },
{ "--signed-chars", 0, OptSignedChars },
{ "--standard", 1, OptStandard },
{ "--start-addr", 1, OptStartAddr },
{ "--static-locals", 0, OptStaticLocals },
{ "--target", 1, OptTarget },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
{ "--zeropage-label", 1, OptZeropageLabel },
{ "--zeropage-name", 1, OptZeropageName },
{ "--warnings-as-errors", 0, OptWarningsAsErrors },
};
char* CmdPath;

View File

@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#if !defined(_WIN32)
# include <unistd.h>
#else
@@ -153,6 +154,23 @@ void CP_Init (void)
ColorMode CP_Parse (const char* Mode)
/* Parse the given string which is assumed to be one of the color modes.
* Return the matching enum or CM_INVALID if there was no match.
*/
{
if (strcmp (Mode, "off") == 0 || strcmp (Mode, "false") == 0) {
return CM_OFF;
} else if (strcmp (Mode, "auto") == 0) {
return CM_AUTO;
} else if (strcmp (Mode, "on") == 0 || strcmp (Mode, "true") == 0) {
return CM_ON;
} else {
return CM_INVALID;
}
}
int CP_IsTTY (void)
/* Return true if console output goes to a tty */
{

View File

@@ -48,7 +48,7 @@
/* Color mode for the program */
enum ColorMode { CM_OFF, CM_AUTO, CM_ON };
enum ColorMode { CM_INVALID = -1, CM_OFF, CM_AUTO, CM_ON };
typedef enum ColorMode ColorMode;
/* Colors */
@@ -96,6 +96,11 @@ void CP_Init (void);
** data from this module.
**/
ColorMode CP_Parse (const char* Mode);
/* Parse the given string which is assumed to be one of the color modes.
** Return the matching enum or CM_INVALID if there was no match.
*/
int CP_IsTTY (void);
/* Return true if console output goes to a tty */

View File

@@ -154,13 +154,17 @@ const unsigned CPUIsets[CPU_COUNT] = {
CAP_BIT (CAP_CPU_HAS_INA) | \
CAP_BIT (CAP_CPU_HAS_PUSHXY))
#define CAP_W65C02 \
(CAP_BIT (CAP_CPU_HAS_BRA8) | \
(CAP_BIT (CAP_CPU_HAS_BITIMM) | \
CAP_BIT (CAP_CPU_HAS_BRA8) | \
CAP_BIT (CAP_CPU_HAS_INA) | \
CAP_BIT (CAP_CPU_HAS_PUSHXY))
CAP_BIT (CAP_CPU_HAS_PUSHXY) | \
CAP_BIT (CAP_CPU_HAS_ZPIND) | \
CAP_BIT (CAP_CPU_HAS_STZ))
#define CAP_65CE02 \
(CAP_BIT (CAP_CPU_HAS_BRA8) | \
CAP_BIT (CAP_CPU_HAS_INA) | \
CAP_BIT (CAP_CPU_HAS_PUSHXY))
CAP_BIT (CAP_CPU_HAS_PUSHXY) | \
CAP_BIT (CAP_CPU_HAS_STZ))
/* Table containing one capability entry per CPU */
static const uint32_t CPUCaps[CPU_COUNT] = {

View File

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

View File

@@ -301,11 +301,11 @@ void BinWriteTarget (BinDesc* D, struct File* F)
/* Open the file */
D->F = fopen (D->Filename, "wb");
if (D->F == 0) {
Error ("Cannot open '%s': %s", D->Filename, strerror (errno));
Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
}
/* Keep the user happy */
Print (stdout, 1, "Opened '%s'...\n", D->Filename);
Print (stdout, 1, "Opened `%s'...\n", D->Filename);
/* Dump all memory areas */
for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
@@ -317,7 +317,7 @@ void BinWriteTarget (BinDesc* D, struct File* F)
/* Close the file */
if (fclose (D->F) != 0) {
Error ("Cannot write to '%s': %s", D->Filename, strerror (errno));
Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
}
/* Reset the file and filename */

View File

@@ -105,11 +105,11 @@ static ExprNode* Factor (void)
/* Left parenthesis */
CfgNextTok ();
N = CfgExpr ();
CfgConsume (CFGTOK_RPAR, "')' expected");
CfgConsume (CFGTOK_RPAR, "`)' expected");
break;
default:
CfgError (&CfgErrorPos, "Invalid expression: %d", CfgTok);
PError (&CfgErrorPos, "Invalid expression: %d", CfgTok);
break;
}
@@ -213,7 +213,7 @@ long CfgConstExpr (void)
/* Check that it's const */
if (!IsConstExpr (Expr)) {
CfgError (&CfgErrorPos, "Constant expression expected");
PError (&CfgErrorPos, "Constant expression expected");
}
/* Get the value */
@@ -238,7 +238,7 @@ long CfgCheckedConstExpr (long Min, long Max)
/* Check the range */
if (Val < Min || Val > Max) {
CfgError (&CfgErrorPos, "Range error");
PError (&CfgErrorPos, "Range error");
}
/* Return the value */

View File

@@ -228,7 +228,7 @@ static MemoryArea* CfgGetMemory (unsigned Name)
{
MemoryArea* M = CfgFindMemory (Name);
if (M == 0) {
CfgError (&CfgErrorPos, "Invalid memory area '%s'", GetString (Name));
PError (&CfgErrorPos, "Invalid memory area `%s'", GetString (Name));
}
return M;
}
@@ -321,9 +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",
GetString (Name));
PError (&CfgErrorPos, "Memory area `%s' defined twice",
GetString (Name));
}
/* Create a new memory area */
@@ -345,7 +344,7 @@ static SegDesc* NewSegDesc (unsigned Name)
/* Check for duplicate names */
SegDesc* S = CfgFindSegDesc (Name);
if (S) {
CfgError (&CfgErrorPos, "Segment '%s' defined twice", GetString (Name));
PError (&CfgErrorPos, "Segment `%s' defined twice", GetString (Name));
}
/* Allocate memory */
@@ -391,7 +390,7 @@ static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
*/
{
if (*Flags & Mask) {
CfgError (&CfgErrorPos, "%s is already defined", Name);
PError (&CfgErrorPos, "Attribute `%s' is already defined", Name);
}
*Flags |= Mask;
}
@@ -402,7 +401,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);
PError (&CfgErrorPos, "Mandatory attribute `%s' is missing", Name);
}
}
@@ -440,7 +439,8 @@ static void ParseMemory (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"Memory attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -500,7 +500,7 @@ static void ParseMemory (void)
case CFGTOK_TYPE:
FlagAttr (&M->Attr, MA_TYPE, "TYPE");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "TYPE");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Memory type");
if (CfgTok == CFGTOK_RO) {
M->Flags |= MF_RO;
}
@@ -554,7 +554,7 @@ static void ParseFiles (void)
/* The MEMORY section must preceed the FILES section */
if ((SectionsEncountered & SE_MEMORY) == 0) {
CfgError (&CfgErrorPos, "MEMORY must precede FILES");
PError (&CfgErrorPos, "`MEMORY' must precede `FILES'");
}
/* Parse all files */
@@ -568,9 +568,8 @@ static void ParseFiles (void)
/* 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));
PError (&CfgErrorPos, "File `%s' not found in `MEMORY' section",
SB_GetConstBuf (&CfgSVal));
}
/* Skip the token and the following colon */
@@ -582,7 +581,8 @@ static void ParseFiles (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"File attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -595,11 +595,10 @@ static void ParseFiles (void)
case CFGTOK_FORMAT:
if (F->Format != BINFMT_DEFAULT) {
/* We've set the format already! */
CfgError (&CfgErrorPos,
"Cannot set a file format twice");
PError (&CfgErrorPos, "Cannot set a file format twice");
}
/* Read the format token */
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "File format");
switch (CfgTok) {
case CFGTOK_BIN:
@@ -667,7 +666,7 @@ static void ParseSegments (void)
/* The MEMORY section must preceed the SEGMENTS section */
if ((SectionsEncountered & SE_MEMORY) == 0) {
CfgError (&CfgErrorPos, "MEMORY must precede SEGMENTS");
PError (&CfgErrorPos, "`MEMORY' must precede `SEGMENTS'");
}
while (CfgTok == CFGTOK_IDENT) {
@@ -686,7 +685,7 @@ static void ParseSegments (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Segment attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -759,7 +758,7 @@ static void ParseSegments (void)
case CFGTOK_TYPE:
FlagAttr (&S->Attr, SA_TYPE, "TYPE");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Segment type");
switch (CfgTok) {
case CFGTOK_RO: S->Flags |= SF_RO; break;
case CFGTOK_RW: /* Default */ break;
@@ -793,9 +792,9 @@ static void ParseSegments (void)
** separate run and load memory areas.
*/
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
CfgWarning (&CfgErrorPos,
"ALIGN_LOAD attribute specified, but no separate "
"LOAD and RUN memory areas assigned");
PWarning (&CfgErrorPos,
"`ALIGN_LOAD' attribute specified, but no separate "
"`LOAD' and `RUN' memory areas assigned");
/* Remove the flag */
S->Flags &= ~SF_ALIGN_LOAD;
}
@@ -804,17 +803,17 @@ static void ParseSegments (void)
** 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 "
"memory areas assigned");
PWarning (&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));
PError (&CfgErrorPos,
"Cannot place r/w segment `%s' in r/o memory area `%s'",
GetString (S->Name), GetString (S->Run->Name));
}
}
@@ -823,8 +822,8 @@ static void ParseSegments (void)
((S->Flags & SF_OFFSET) != 0) +
((S->Flags & SF_START) != 0);
if (Count > 1) {
CfgError (&CfgErrorPos,
"Only one of ALIGN, START, OFFSET may be used");
PError (&CfgErrorPos,
"Only one of `ALIGN', `START' or `OFFSET' may be used");
}
/* Skip the semicolon */
@@ -881,7 +880,7 @@ static void ParseO65 (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "O65 attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -924,7 +923,7 @@ static void ParseO65 (void)
/* Cannot have this attribute twice */
FlagAttr (&AttrFlags, atType, "TYPE");
/* Get the type of the executable */
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "O65 type");
switch (CfgTok) {
case CFGTOK_SMALL:
@@ -936,7 +935,7 @@ static void ParseO65 (void)
break;
default:
CfgError (&CfgErrorPos, "Unexpected type token");
PError (&CfgErrorPos, "Unexpected type token");
}
/* Eat the attribute token */
CfgNextTok ();
@@ -952,13 +951,15 @@ static void ParseO65 (void)
CfgRangeCheck (O65OS_MIN, O65OS_MAX);
OS = (unsigned) CfgIVal;
} else {
CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type");
CfgSpecialToken (OperatingSystems,
ENTRY_COUNT (OperatingSystems),
"O65 OS specification");
switch (CfgTok) {
case CFGTOK_LUNIX: OS = O65OS_LUNIX; break;
case CFGTOK_OSA65: OS = O65OS_OSA65; break;
case CFGTOK_CC65: OS = O65OS_CC65; break;
case CFGTOK_OPENCBM: OS = O65OS_OPENCBM; break;
default: CfgError (&CfgErrorPos, "Unexpected OS token");
default: PError (&CfgErrorPos, "Unexpected OS token");
}
}
CfgNextTok ();
@@ -993,13 +994,13 @@ static void ParseO65 (void)
/* Check for attributes that may not be combined */
if (OS == O65OS_CC65) {
if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) {
CfgError (&CfgErrorPos,
"OS type CC65 may not have imports or exports for ids < $8000");
PError (&CfgErrorPos,
"OS type CC65 may not have imports or exports for ids < $8000");
}
} else {
if (AttrFlags & atID) {
CfgError (&CfgErrorPos,
"Operating system does not support the ID attribute");
PError (&CfgErrorPos,
"Operating system does not support the ID attribute");
}
}
@@ -1033,7 +1034,7 @@ static void ParseXex (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Xex attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -1071,7 +1072,7 @@ static void ParseXex (void)
CfgNextTok ();
/* Add to XEX */
if (XexAddInitAd (XexFmtDesc, InitMem, InitAd))
CfgError (&CfgErrorPos, "INITAD already given for memory area");
PError (&CfgErrorPos, "`INITAD' already given for memory area");
break;
default:
@@ -1104,7 +1105,7 @@ static void ParseFormats (void)
/* Map the identifier to a token */
cfgtok_t FormatTok;
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format attribute");
FormatTok = CfgTok;
/* Skip the name and the following colon */
@@ -1190,7 +1191,8 @@ static void ParseConDes (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"CONDES attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -1232,7 +1234,7 @@ static void ParseConDes (void)
case CFGTOK_ORDER:
/* Don't allow this twice */
FlagAttr (&AttrFlags, atOrder, "ORDER");
CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order");
CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "CONDES order");
switch (CfgTok) {
case CFGTOK_DECREASING: Order = cdDecreasing; break;
case CFGTOK_INCREASING: Order = cdIncreasing; break;
@@ -1257,7 +1259,7 @@ static void ParseConDes (void)
CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
Type = (int) CfgIVal;
} else {
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "CONDES type");
switch (CfgTok) {
case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
@@ -1289,10 +1291,10 @@ static void ParseConDes (void)
AttrCheck (AttrFlags, atType, "TYPE");
/* Check if the condes has already attributes defined */
if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) {
CfgError (&CfgErrorPos,
"CONDES attributes for type %d are already defined",
Type);
if (ConDesHasSegName (Type) || ConDesHasLabel (Type)) {
PError (&CfgErrorPos,
"`CONDES' attributes for type %d are already defined",
Type);
}
/* Define the attributes */
@@ -1334,7 +1336,8 @@ static void ParseStartAddress (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"Start address attribute");
AttrTok = CfgTok;
/* An optional assignment follows */
@@ -1389,7 +1392,7 @@ static void ParseFeatures (void)
/* Map the identifier to a token */
cfgtok_t FeatureTok;
CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature");
CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature attribute");
FeatureTok = CfgTok;
/* Skip the name and the following colon */
@@ -1479,7 +1482,8 @@ static void ParseSymbols (void)
/* Map the identifier to a token */
cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes),
"Symbol attribute");
AttrTok = CfgTok;
/* Skip the attribute name */
@@ -1495,7 +1499,8 @@ static void ParseSymbols (void)
/* 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),
"Address size specification");
switch (CfgTok) {
case CFGTOK_ABS: AddrSize = ADDR_SIZE_ABS; break;
case CFGTOK_FAR: AddrSize = ADDR_SIZE_FAR; break;
@@ -1511,7 +1516,8 @@ static void ParseSymbols (void)
/* 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),
"Address size type");
switch (CfgTok) {
case CFGTOK_EXPORT: Type = CfgSymExport; break;
case CFGTOK_IMPORT: Type = CfgSymImport; break;
@@ -1559,7 +1565,7 @@ static void ParseSymbols (void)
case CfgSymImport:
/* An import must not have a value */
if (AttrFlags & atValue) {
CfgError (&CfgErrorPos, "Imports must not have a value");
PError (&CfgErrorPos, "Imports must not have a value");
}
/* Generate the import */
Imp = InsertImport (GenImport (Name, AddrSize));
@@ -1606,12 +1612,13 @@ static void ParseConfig (void)
do {
/* Read the block ident */
CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier");
CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames),
"Configuration block identifier");
BlockTok = CfgTok;
CfgNextTok ();
/* Expected a curly brace */
CfgConsume (CFGTOK_LCURLY, "'{' expected");
CfgConsume (CFGTOK_LCURLY, "`{' expected");
/* Read the block */
switch (BlockTok) {
@@ -1646,7 +1653,7 @@ static void ParseConfig (void)
}
/* Skip closing brace */
CfgConsume (CFGTOK_RCURLY, "'}' expected");
CfgConsume (CFGTOK_RCURLY, "`}' expected");
} while (CfgTok != CFGTOK_EOF);
}
@@ -1702,10 +1709,20 @@ static void ProcessSegments (void)
** 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 ((S->Flags & SF_BSS) != 0 && S->Seg != 0) {
Section* Sec = GetNonBSSSection (S->Seg);
if (Sec) {
const FilePos* Pos = GetSourcePos (S->LI);
if (Sec->Obj) {
AddPNote (Pos, "Initialized data comes at least partially "
"from `%s'", GetString (Sec->Obj->Name));
} else {
AddPNote (Pos, "Initialized data is at least partially "
"linker generated");
}
PWarning (Pos, "Segment `%s' with type `bss' contains "
"initialized data", GetString (S->Name));
}
}
/* If this segment does exist in any of the object files, insert the
@@ -1732,9 +1749,8 @@ static void ProcessSegments (void)
/* Print a warning if the segment is not optional */
if ((S->Flags & SF_OPTIONAL) == 0) {
CfgWarning (&CfgErrorPos,
"Segment '%s' does not exist",
GetString (S->Name));
PWarning (&CfgErrorPos, "Segment `%s' does not exist",
GetString (S->Name));
}
/* Discard the descriptor and remove it from the collection */
@@ -1764,9 +1780,9 @@ static void ProcessSymbols (void)
case CfgSymO65Export:
/* Check if the export symbol is also defined as an import. */
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
PError (
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)
);
}
@@ -1776,9 +1792,9 @@ static void ProcessSymbols (void)
** error message when checking it here.
*/
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
PError (
GetSourcePos (Sym->LI),
"Duplicate exported o65 symbol: '%s'",
"Duplicate exported o65 symbol: `%s'",
GetString (Sym->Name)
);
}
@@ -1790,9 +1806,9 @@ static void ProcessSymbols (void)
case CfgSymO65Import:
/* Check if the import symbol is also defined as an export. */
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
PError (
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)
);
}
@@ -1802,9 +1818,9 @@ static void ProcessSymbols (void)
** error message when checking it here.
*/
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
PError (
GetSourcePos (Sym->LI),
"Duplicate imported o65 symbol: '%s'",
"Duplicate imported o65 symbol: `%s'",
GetString (Sym->Name)
);
}
@@ -1913,9 +1929,9 @@ unsigned CfgProcess (void)
** and mark the memory area as placed.
*/
if (!IsConstExpr (M->StartExpr)) {
CfgError (GetSourcePos (M->LI),
"Start address of memory area '%s' is not constant",
GetString (M->Name));
PError (GetSourcePos (M->LI),
"Start address of memory area `%s' is not constant",
GetString (M->Name));
}
Addr = M->Start = GetExprVal (M->StartExpr);
M->Flags |= MF_PLACED;
@@ -1938,15 +1954,15 @@ unsigned CfgProcess (void)
/* Resolve the size expression */
if (!IsConstExpr (M->SizeExpr)) {
CfgError (GetSourcePos (M->LI),
"Size of memory area '%s' is not constant",
GetString (M->Name));
PError (GetSourcePos (M->LI),
"Size of memory area `%s' is not constant",
GetString (M->Name));
}
M->Size = GetExprVal (M->SizeExpr);
if (M->Size >= 0x80000000) {
CfgError (GetSourcePos (M->LI),
"Size of memory area '%s' is negative: %ld",
GetString (M->Name), (long)M->Size);
PError (GetSourcePos (M->LI),
"Size of memory area `%s' is negative: %ld",
GetString (M->Name), (long)M->Size);
}
/* Walk through the segments in this memory area */
@@ -1968,17 +1984,17 @@ unsigned CfgProcess (void)
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));
PError (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));
PError (GetSourcePos (M->LI),
"Segment `%s' is preceded by at least one segment"
" of type `overwrite'",
GetString (S->Name));
}
}
@@ -2002,10 +2018,10 @@ unsigned CfgProcess (void)
/* 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));
PWarning (GetSourcePos (S->LI),
"Segment `%s' isn't aligned properly; the"
" resulting executable might not be functional.",
GetString (S->Name));
}
if (S->Flags & SF_ALIGN) {
@@ -2017,10 +2033,10 @@ unsigned CfgProcess (void)
** that is somewhat suspicious.
*/
if (M->FillLevel == 0 && NewAddr > Addr) {
CfgWarning (GetSourcePos (S->LI),
"The first segment in memory area '%s' "
"needs fill bytes for alignment.",
GetString (M->Name));
PWarning (GetSourcePos (S->LI),
"The first segment in memory area `%s' "
"needs fill bytes for alignment.",
GetString (M->Name));
}
/* Use the aligned address */
@@ -2038,9 +2054,9 @@ unsigned CfgProcess (void)
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));
PError (GetSourcePos (S->LI),
"Segment `%s' begins before memory area `%s'",
GetString (S->Name), GetString (M->Name));
} else {
Addr = NewAddr;
}
@@ -2049,15 +2065,23 @@ unsigned CfgProcess (void)
/* 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%s",
GetString (S->Name), GetString (M->Name),
Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s");
PWarning (
GetSourcePos (S->LI),
"Segment `%s' offset is too small in `%s' by %lu byte%s",
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%s",
GetString (S->Name), GetString (M->Name),
Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s");
PWarning (
GetSourcePos (S->LI),
"Segment `%s' start address is too low in `%s' by %lu byte%s",
GetString (S->Name),
GetString (M->Name),
Addr - NewAddr,
(Addr - NewAddr == 1) ? "" : "s"
);
}
} else {
Addr = NewAddr;
@@ -2101,10 +2125,14 @@ unsigned CfgProcess (void)
if (FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
++Overflows;
M->Flags |= MF_OVERFLOW;
CfgWarning (GetSourcePos (M->LI),
"Segment '%s' overflows memory area '%s' by %lu byte%s",
GetString (S->Name), GetString (M->Name),
FillLevel - M->Size, (FillLevel - M->Size == 1) ? "" : "s");
PWarning (
GetSourcePos (M->LI),
"Segment `%s' overflows memory area `%s' by %lu byte%s",
GetString (S->Name),
GetString (M->Name),
FillLevel - M->Size,
(FillLevel - M->Size == 1) ? "" : "s"
);
}
if (FillLevel > M->FillLevel) {
/* Regular segments increase FillLevel. Overwrite segments may

View File

@@ -107,7 +107,7 @@ void CreateDbgFile (void)
/* Open the debug info file */
FILE* F = fopen (DbgFileName, "w");
if (F == 0) {
Error ("Cannot create debug file '%s': %s", DbgFileName, strerror (errno));
Error ("Cannot create debug file `%s': %s", DbgFileName, strerror (errno));
}
/* Output version information */
@@ -166,6 +166,6 @@ void CreateDbgFile (void)
/* Close the file */
if (fclose (F) != 0) {
Error ("Error closing debug file '%s': %s", DbgFileName, strerror (errno));
Error ("Error closing debug file `%s': %s", DbgFileName, strerror (errno));
}
}

View File

@@ -39,10 +39,13 @@
/* common */
#include "cmdline.h"
#include "coll.h"
#include "consprop.h"
#include "strbuf.h"
/* ld65 */
#include "error.h"
#include "spool.h"
@@ -55,6 +58,22 @@
/* Statistics */
unsigned WarningCount = 0;
/* Diagnostic category. */
typedef enum { DC_NOTE, DC_WARN, DC_ERR, DC_INT, DC_COUNT } DiagCat;
/* Descriptions for diagnostic categories */
const char* DiagCatDesc[DC_COUNT] = {
"Note", "Warning", "Error", "Internal error"
};
/* An empty file position used when diagnostics aren't related to a file */
static FilePos NoFile = STATIC_FILEPOS_INITIALIZER;
/* Notifications. They are remembered here and output with the next call to
** Error() or Warning().
*/
static Collection Notes = STATIC_COLLECTION_INITIALIZER;
/*****************************************************************************/
@@ -63,20 +82,213 @@ unsigned WarningCount = 0;
static void ReplaceQuotes (StrBuf* Msg)
/* Replace opening and closing single quotes in Msg by their typographically
** correct UTF-8 counterparts for better readbility. A closing quote will
** only get replaced if an opening quote has been seen before.
** To handle some special cases, the function will also treat \xF0 as
** opening and \xF1 as closing quote. These are replaced without the need for
** correct ordering (open/close).
** The function will change the quotes in place, so after the call Msg will
** contain the changed string. If UTF-8 is not available, the function will
** replace '`' by '\'' since that was the default behavior before. It will
** also replace \xF0 and \xF1 by '\''.
*/
{
/* UTF-8 characters for single quotes */
static const char QuoteStart[] = "\xE2\x80\x98";
static const char QuoteEnd[] = "\xE2\x80\x99";
/* ANSI color sequences */
const char* ColorStart = CP_BrightGreen ();
const char* ColorEnd = CP_White ();
/* Remember a few things */
int IsUTF8 = CP_IsUTF8 ();
/* We create a new string in T and will later copy it back to Msg */
StrBuf T = AUTO_STRBUF_INITIALIZER;
/* Parse the string and create a modified copy */
SB_Reset (Msg);
int InQuote = 0;
while (1) {
char C = SB_Get (Msg);
switch (C) {
case '`':
if (!InQuote) {
InQuote = 1;
if (IsUTF8) {
SB_AppendStr (&T, QuoteStart);
} else {
/* ca65 uses \' for opening and closing quotes */
SB_AppendChar (&T, '\'');
}
SB_AppendStr (&T, ColorStart);
} else {
/* Found two ` without closing quote - don't replace */
SB_AppendChar (&T, '`');
}
break;
case '\'':
if (InQuote) {
InQuote = 0;
SB_AppendStr (&T, ColorEnd);
if (IsUTF8) {
SB_AppendStr (&T, QuoteEnd);
} else {
SB_AppendChar (&T, C);
}
} else {
SB_AppendChar (&T, C);
}
break;
case '\xF0':
if (IsUTF8) {
SB_AppendStr (&T, QuoteStart);
} else {
SB_AppendChar (&T, '\'');
}
break;
case '\xF1':
if (IsUTF8) {
SB_AppendStr (&T, QuoteEnd);
} else {
SB_AppendChar (&T, '\'');
}
break;
case '\0':
goto Done;
default:
SB_AppendChar (&T, C);
break;
}
}
Done:
/* Copy the string back, then terminate it */
SB_Move (Msg, &T);
SB_Terminate (Msg);
}
static void VPrepMsg (StrBuf* S, const FilePos* Pos, DiagCat Cat,
const char* Format, va_list ap)
/* Prepare an error/warning/notification message in S. */
{
StrBuf Msg = AUTO_STRBUF_INITIALIZER;
StrBuf Loc = AUTO_STRBUF_INITIALIZER;
/* Determine the description for the category and its color */
const char* Desc = DiagCatDesc[Cat];
const char* Color;
switch (Cat) {
case DC_NOTE: Color = CP_Cyan (); break;
case DC_WARN: Color = CP_Yellow (); break;
case DC_ERR: Color = CP_BrightRed (); break;
case DC_INT: Color = CP_BrightRed (); break;
default: FAIL ("Unexpected Cat value"); break;
}
/* Format the actual message, then replace quotes */
SB_VPrintf (&Msg, Format, ap);
ReplaceQuotes (&Msg);
/* Format the location. If the file position is valid, we use the file
** position, otherwise the program name. This allows to print fatal
** errors in the startup phase.
*/
if (Pos->Name == INVALID_STRING_ID) {
SB_CopyStr (&Loc, ProgName);
} else {
SB_Printf (&Loc, "%s:%u", GetString (Pos->Name), Pos->Line);
}
SB_Terminate (&Loc);
/* Format the full message */
SB_Printf (S, "%s%s: %s%s:%s %s%s",
CP_White (),
SB_GetConstBuf (&Loc),
Color,
Desc,
CP_White (),
SB_GetConstBuf (&Msg),
CP_Reset ());
/* Delete the formatted message and the location string */
SB_Done (&Loc);
SB_Done (&Msg);
/* Add a new line and terminate the generated full message */
SB_AppendChar (S, '\n');
SB_Terminate (S);
}
static void VPrintMsg (const FilePos* Pos, DiagCat Cat, const char* Format,
va_list ap)
/* Format and output an error/warning message. */
{
/* Format the message */
StrBuf S = AUTO_STRBUF_INITIALIZER;
VPrepMsg (&S, Pos, Cat, Format, ap);
/* Output the full message */
fputs (SB_GetConstBuf (&S), stderr);
/* Delete the buffer for the full message */
SB_Done (&S);
}
static void OutputNotes (void)
/* Output all stored notification messages, then delete them */
{
unsigned I;
for (I = 0; I < CollCount (&Notes); ++I) {
StrBuf* S = CollAtUnchecked (&Notes, I);
fputs (SB_GetConstBuf (S), stderr);
FreeStrBuf (S);
}
CollDeleteAll (&Notes);
}
void AddNote (const char* Format, ...)
/* Add a notification message that will be output after the next error or
** warning. There cannot be a Notification() function since Error() will
** always terminate.
*/
{
va_list ap;
/* Create a new string buffer and add it to the notes */
StrBuf* S = NewStrBuf ();
CollAppend (&Notes, S);
/* Create the message in the string buffer */
va_start (ap, Format);
VPrepMsg (S, &NoFile, DC_NOTE, Format, ap);
va_end (ap);
}
void Warning (const char* Format, ...)
/* Print a warning message */
{
StrBuf S = STATIC_STRBUF_INITIALIZER;
/* Output the message */
va_list ap;
va_start (ap, Format);
SB_VPrintf (&S, Format, ap);
VPrintMsg (&NoFile, DC_WARN, Format, ap);
va_end (ap);
SB_Terminate (&S);
fprintf (stderr, "%s: Warning: %s\n", ProgName, SB_GetConstBuf (&S));
SB_Done (&S);
/* Output all stored notes */
OutputNotes ();
/* Count warnings */
++WarningCount;
@@ -87,18 +299,16 @@ void Warning (const char* Format, ...)
void Error (const char* Format, ...)
/* Print an error message and die */
{
StrBuf S = STATIC_STRBUF_INITIALIZER;
/* Output the message */
va_list ap;
va_start (ap, Format);
SB_VPrintf (&S, Format, ap);
VPrintMsg (&NoFile, DC_ERR, Format, ap);
va_end (ap);
SB_Terminate (&S);
fprintf (stderr, "%s: Error: %s\n", ProgName, SB_GetConstBuf (&S));
SB_Done (&S);
/* Output all stored notes */
OutputNotes ();
/* Terminate after errors */
exit (EXIT_FAILURE);
}
@@ -107,17 +317,67 @@ void Error (const char* Format, ...)
void Internal (const char* Format, ...)
/* Print an internal error message and die */
{
StrBuf S = STATIC_STRBUF_INITIALIZER;
/* Output the message */
va_list ap;
va_start (ap, Format);
SB_VPrintf (&S, Format, ap);
VPrintMsg (&NoFile, DC_INT, Format, ap);
va_end (ap);
SB_Terminate (&S);
fprintf (stderr, "%s: Internal Error: %s\n", ProgName, SB_GetConstBuf (&S));
SB_Done (&S);
/* Terminate after errors */
exit (EXIT_FAILURE);
}
void AddPNote (const FilePos* Pos, const char* Format, ...)
/* Add a notifcation message using file name and line number of the config file.
** See comment for AddNote() above.
*/
{
va_list ap;
/* Create a new string buffer and add it to the notes */
StrBuf* S = NewStrBuf ();
CollAppend (&Notes, S);
/* Create the message in the string buffer */
va_start (ap, Format);
VPrepMsg (S, Pos, DC_NOTE, Format, ap);
va_end (ap);
}
void PWarning (const FilePos* Pos, const char* Format, ...)
/* Print a warning message adding file name and line number of a given file */
{
/* Output the message */
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, DC_WARN, Format, ap);
va_end (ap);
/* Output all stored notes */
OutputNotes ();
/* Count warnings */
++WarningCount;
}
void PError (const FilePos* Pos, const char* Format, ...)
/* Print an error message adding file name and line number of a given file */
{
/* Output the message */
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, DC_ERR, Format, ap);
va_end (ap);
/* Output all stored notes */
OutputNotes ();
/* Terminate after errors */
exit (EXIT_FAILURE);
}

View File

@@ -40,6 +40,7 @@
/* common */
#include "attrib.h"
#include "filepos.h"
@@ -60,6 +61,12 @@ extern unsigned WarningCount;
void AddNote (const char* Format, ...) attribute((format(printf,1,2)));
/* Add a notification message that will be output after the next error or
** warning. There cannot be a Notification() function since Error() will
** always terminate.
*/
void Warning (const char* Format, ...) attribute((format(printf,1,2)));
/* Print a warning message */
@@ -69,6 +76,17 @@ void Error (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 */
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.
** See comment for AddNote() above.
*/
void PWarning (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3)));
/* Print a warning message adding file name and line number of the config file */
void PError (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3)));
/* Print an error message adding file name and line number of a given file */
/* End of error.h */

View File

@@ -167,13 +167,13 @@ Import* ReadImport (FILE* F, ObjData* Obj)
*/
if (ObjHasFiles (I->Obj)) {
const LineInfo* LI = GetImportPos (I);
Error ("Invalid import size in for '%s', imported from %s:%u: 0x%02X",
Error ("Invalid import size in for `%s', imported from %s:%u: 0x%02X",
GetString (I->Name),
GetSourceName (LI),
GetSourceLine (LI),
I->AddrSize);
} else {
Error ("Invalid import size in for '%s', imported from %s: 0x%02X",
Error ("Invalid import size in for `%s', imported from %s: 0x%02X",
GetString (I->Name),
GetObjFileName (I->Obj),
I->AddrSize);
@@ -200,7 +200,7 @@ Import* GenImport (unsigned Name, unsigned char AddrSize)
/* We have no object file information and no line info for a new
** import
*/
Error ("Invalid import size 0x%02X for symbol '%s'",
Error ("Invalid import size 0x%02X for symbol `%s'",
I->AddrSize,
GetString (I->Name));
}
@@ -484,7 +484,7 @@ void InsertExport (Export* E)
}
} else if (AllowMultDef == 0) {
/* Duplicate entry, this is fatal unless allowed by the user */
Error ("Duplicate external identifier: '%s'",
Error ("Duplicate external identifier: `%s'",
GetString (L->Name));
}
return;
@@ -663,7 +663,7 @@ long GetExportVal (const Export* E)
{
if (E->Expr == 0) {
/* OOPS */
Internal ("'%s' is an undefined external", GetString (E->Name));
Internal ("`%s' is an undefined external", GetString (E->Name));
}
return GetExprVal (E->Expr);
}
@@ -726,9 +726,9 @@ static void CheckSymType (const Export* E)
}
/* Output the diagnostic */
Warning ("Address size mismatch for '%s': "
"Exported from %s as '%s', "
"import in %s as '%s'",
Warning ("Address size mismatch for `%s': "
"Exported from %s as `%s', "
"import in %s as `%s'",
GetString (E->Name),
SB_GetConstBuf (&ExportLoc),
ExpAddrSize,
@@ -775,21 +775,20 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
if (E->Expr == 0 && E->ImpCount > 0 && F (E->Name, Data) == 0) {
/* Unresolved external */
Import* Imp = E->ImpList;
const char* name = GetString (E->Name);
const char* Name = GetString (E->Name);
while (Imp) {
unsigned J, count = CollCount (&Imp->RefLines);
/* The count is 0 when the import was not added by an input file,
but by the compiler itself. */
if (count == 0) {
fprintf (stderr, "Error: Unresolved external '%s'\n", name);
unsigned J, Count = CollCount (&Imp->RefLines);
/* The count is 0 when the import was not added by an input
** file, but by the compiler itself.
*/
if (Count == 0) {
Warning ("Unresolved external `%s'", Name);
} else {
for (J = 0; J < count; ++J) {
for (J = 0; J < Count; ++J) {
const LineInfo* LI = CollConstAt (&Imp->RefLines, J);
fprintf (stderr,
"%s:%u: Error: Unresolved external '%s'\n",
GetSourceName (LI),
GetSourceLine (LI),
name);
PWarning (GetSourcePos (LI),
"Unresolved external `%s'",
Name);
}
}
Imp = Imp->Next;
@@ -1080,7 +1079,7 @@ void CircularRefError (const Export* E)
/* Print an error about a circular reference using to define the given export */
{
const LineInfo* LI = GetExportPos (E);
Error ("Circular reference for symbol '%s', %s:%u",
Error ("Circular reference for symbol `%s', %s:%u",
GetString (E->Name),
GetSourceName (LI),
GetSourceLine (LI));

View File

@@ -408,12 +408,12 @@ long GetExprVal (ExprNode* Expr)
Error ("Argument of .BANK() isn't a label attached to a segment");
}
if (D.Seg->MemArea == 0) {
Error ("Segment '%s' is referenced by .BANK(),"
Error ("Segment `%s' is referenced by .BANK(),"
" but not assigned to a memory area",
GetString (D.Seg->Name));
}
if (D.Seg->MemArea->BankExpr == 0) {
Error ("Memory area '%s' is referenced by .BANK(),"
Error ("Memory area `%s' is referenced by .BANK(),"
" but has no BANK attribute",
GetString (D.Seg->MemArea->Name));
}

View File

@@ -89,7 +89,7 @@ ExtSym* NewExtSym (ExtSymTab* Tab, unsigned Name)
ExtSym* E = GetExtSym (Tab, Name);
if (E != 0) {
/* We do already have a symbol with this name */
Error ("Duplicate external symbol '%s'", GetString (Name));
Error ("Duplicate external symbol `%s'", GetString (Name));
}
/* Allocate memory for the structure */

View File

@@ -112,7 +112,7 @@ static void CloseLibrary (Library* L)
{
/* Close the library file */
if (fclose (L->F) != 0) {
Error ("Error closing '%s': %s", GetString (L->Name), strerror (errno));
Error ("Error closing `%s': %s", GetString (L->Name), strerror (errno));
}
L->F = 0;
}
@@ -144,7 +144,7 @@ static void LibSeek (Library* L, unsigned long Offs)
/* Do a seek in the library checking for errors */
{
if (fseek (L->F, Offs, SEEK_SET) != 0) {
Error ("Seek error in '%s' (%lu): %s",
Error ("Seek error in `%s' (%lu): %s",
GetString (L->Name), Offs, strerror (errno));
}
}
@@ -158,7 +158,7 @@ static void LibReadHeader (Library* L)
L->Header.Magic = LIB_MAGIC;
L->Header.Version = Read16 (L->F);
if (L->Header.Version != LIB_VERSION) {
Error ("Wrong data version in '%s'", GetString (L->Name));
Error ("Wrong data version in `%s'", GetString (L->Name));
}
L->Header.Flags = Read16 (L->F);
L->Header.IndexOffs = Read32 (L->F);
@@ -171,12 +171,12 @@ static void LibReadObjHeader (Library* L, ObjData* O)
{
O->Header.Magic = Read32 (L->F);
if (O->Header.Magic != OBJ_MAGIC) {
Error ("Object file '%s' in library '%s' is invalid",
Error ("Object file `%s' in library `%s' is invalid",
GetObjFileName (O), GetString (L->Name));
}
O->Header.Version = Read16 (L->F);
if (O->Header.Version != OBJ_VERSION) {
Error ("Object file '%s' in library '%s' has wrong version",
Error ("Object file `%s' in library `%s' has wrong version",
GetObjFileName (O), GetString (L->Name));
}
O->Header.Flags = Read16 (L->F);

View File

@@ -54,6 +54,7 @@
#include "asserts.h"
#include "binfmt.h"
#include "condes.h"
#include "consprop.h"
#include "config.h"
#include "dbgfile.h"
#include "error.h"
@@ -130,6 +131,7 @@ static void Usage (void)
"Long options:\n"
" --allow-multiple-definition\tAllow multiple definitions\n"
" --cfg-path path\t\tSpecify a config file search path\n"
" --color [on|auto|off]\t\tColor diagnostics (default: auto)\n"
" --config name\t\t\tUse linker config file\n"
" --dbgfile name\t\tGenerate debug information\n"
" --define sym=val\t\tDefine a symbol\n"
@@ -141,6 +143,7 @@ static void Usage (void)
" --lib-path path\t\tSpecify a library search path\n"
" --mapfile name\t\tCreate a map file\n"
" --module-id id\t\tSpecify a module id\n"
" --no-utf8\t\t\tDisable use of UTF-8 in diagnostics\n"
" --obj file\t\t\tLink this object file\n"
" --obj-path path\t\tSpecify an object file search path\n"
" --start-addr addr\t\tSet the default start address\n"
@@ -216,13 +219,13 @@ static void LinkFile (const char* Name, FILETYPE Type)
/* We must have a valid name now */
if (PathName == 0) {
Error ("Input file '%s' not found", Name);
Error ("Input file `%s' not found", Name);
}
/* Try to open the file */
F = fopen (PathName, "rb");
if (F == 0) {
Error ("Cannot open '%s': %s", PathName, strerror (errno));
Error ("Cannot open `%s': %s", PathName, strerror (errno));
}
/* Read the magic word */
@@ -248,7 +251,7 @@ static void LinkFile (const char* Name, FILETYPE Type)
default:
fclose (F);
Error ("File '%s' has unknown type", PathName);
Error ("File `%s' has unknown type", PathName);
}
@@ -310,6 +313,19 @@ static void OptCfgPath (const char* Opt attribute ((unused)), const char* Arg)
static void OptColor (const char* Opt, const char* Arg)
/* Handle the --color option */
{
ColorMode Mode = CP_Parse (Arg);
if (Mode == CM_INVALID) {
Error ("Invalid argument to %s: %s", Opt, Arg);
} else {
CP_SetColorMode (Mode);
}
}
static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
/* Define the config file */
{
@@ -324,7 +340,7 @@ static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
PathName = SearchFile (CfgDefaultPath, Arg);
}
if (PathName == 0) {
Error ("Cannot find config file '%s'", Arg);
Error ("Cannot find config file `%s'", Arg);
}
/* Read the config */
@@ -378,7 +394,7 @@ static void OptForceImport (const char* Opt attribute ((unused)), const char* Ar
/* Get the address size and check it */
unsigned char AddrSize = AddrSizeFromStr (ColPos+1);
if (AddrSize == ADDR_SIZE_INVALID) {
Error ("Invalid address size '%s'", ColPos+1);
Error ("Invalid address size `%s'", ColPos+1);
}
/* Create a copy of the argument */
@@ -457,6 +473,15 @@ static void OptModuleId (const char* Opt, const char* Arg)
static void OptNoUtf8 (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --no-utf8 option */
{
CP_DisableUTF8 ();
}
static void OptObj (const char* Opt attribute ((unused)), const char* Arg)
/* Link an object file */
{
@@ -519,7 +544,7 @@ static void OptTarget (const char* Opt attribute ((unused)), const char* Arg)
/* Map the target name to a target id */
Target = FindTarget (Arg);
if (Target == TGT_UNKNOWN) {
Error ("Invalid target name: '%s'", Arg);
Error ("Invalid target name: `%s'", Arg);
}
/* Set the target binary format */
@@ -536,7 +561,7 @@ static void OptTarget (const char* Opt attribute ((unused)), const char* Arg)
PathName = SearchFile (CfgDefaultPath, SB_GetBuf (&FileName));
}
if (PathName == 0) {
Error ("Cannot find config file '%s'", SB_GetBuf (&FileName));
Error ("Cannot find config file `%s'", SB_GetBuf (&FileName));
}
/* Free file name memory */
@@ -623,12 +648,13 @@ static void CmdlOptTarget (const char* Opt attribute ((unused)), const char* Arg
static void ParseCommandLine(void)
static void ParseCommandLine (void)
{
/* Program long options */
static const LongOpt OptTab[] = {
{ "--allow-multiple-definition", 0, OptMultDef },
{ "--cfg-path", 1, OptCfgPath },
{ "--color", 1, OptColor },
{ "--config", 1, CmdlOptConfig },
{ "--dbgfile", 1, OptDbgFile },
{ "--define", 1, OptDefine },
@@ -640,6 +666,7 @@ static void ParseCommandLine(void)
{ "--lib-path", 1, OptLibPath },
{ "--mapfile", 1, OptMapFile },
{ "--module-id", 1, OptModuleId },
{ "--no-utf8", 0, OptNoUtf8 },
{ "--obj", 1, OptObj },
{ "--obj-path", 1, OptObjPath },
{ "--start-addr", 1, OptStartAddr },
@@ -800,6 +827,9 @@ int main (int argc, char* argv [])
{
unsigned MemoryAreaOverflows;
/* Initialize console output */
CP_Init ();
/* Initialize the cmdline module */
InitCmdLine (&argc, &argv, "ld65");
@@ -856,7 +886,7 @@ int main (int argc, char* argv [])
}
if (WarningCount > 0 && WarningsAsErrors) {
Error("Warnings as errors");
Error ("Warnings as errors");
}
/* Create the output file */

View File

@@ -67,7 +67,7 @@ void CreateMapFile (int ShortMap)
/* Open the map file */
FILE* F = fopen (MapFileName, "w");
if (F == 0) {
Error ("Cannot create map file '%s': %s", MapFileName, strerror (errno));
Error ("Cannot create map file `%s': %s", MapFileName, strerror (errno));
}
/* Write a modules list */
@@ -132,7 +132,7 @@ void CreateMapFile (int ShortMap)
/* Close the file */
if (fclose (F) != 0) {
Error ("Error closing map file '%s': %s", MapFileName, strerror (errno));
Error ("Error closing map file `%s': %s", MapFileName, strerror (errno));
}
}
@@ -144,7 +144,7 @@ void CreateLabelFile (void)
/* Open the label file */
FILE* F = fopen (LabelFileName, "w");
if (F == 0) {
Error ("Cannot create label file '%s': %s", LabelFileName, strerror (errno));
Error ("Cannot create label file `%s': %s", LabelFileName, strerror (errno));
}
/* Print the labels for the export symbols */
@@ -155,6 +155,6 @@ void CreateLabelFile (void)
/* Close the file */
if (fclose (F) != 0) {
Error ("Error closing label file '%s': %s", LabelFileName, strerror (errno));
Error ("Error closing label file `%s': %s", LabelFileName, strerror (errno));
}
}

View File

@@ -807,7 +807,7 @@ static void O65WriteSeg (O65Desc* D, SegDesc** Seg, unsigned Count, int DoWrite)
/* Check the size of the segment for overflow */
if ((D->Header.Mode & MF_SIZE_MASK) == MF_SIZE_16BIT && D->SegSize > 0xFFFF) {
Error ("Segment overflow in file '%s'", D->Filename);
Error ("Segment overflow in file `%s'", D->Filename);
}
}
@@ -960,7 +960,7 @@ static void O65WriteExports (O65Desc* D)
/* Bail out if we cannot handle the expression */
if (ED.TooComplex) {
Error ("Expression for symbol '%s' is too complex", Name);
Error ("Expression for symbol `%s' is too complex", Name);
}
/* Determine the segment id for the expression */
@@ -979,7 +979,7 @@ static void O65WriteExports (O65Desc* D)
/* For some reason, we didn't find this segment in the list of
** segments written to the o65 file.
*/
Error ("Segment for symbol '%s' is undefined", Name);
Error ("Segment for symbol `%s' is undefined", Name);
}
SegmentID = O65SegType (Seg);
@@ -1209,7 +1209,7 @@ void O65SetExport (O65Desc* D, unsigned Ident)
*/
Export* E = FindExport (Ident);
if (E == 0 || IsUnresolvedExport (E)) {
Error ("Unresolved export: '%s'", GetString (Ident));
Error ("Unresolved export: `%s'", GetString (Ident));
}
/* Insert the entry into the table */
@@ -1372,7 +1372,7 @@ void O65WriteTarget (O65Desc* D, File* F)
/* Open the file */
D->F = fopen (D->Filename, "wb");
if (D->F == 0) {
Error ("Cannot open '%s': %s", D->Filename, strerror (errno));
Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
}
/* Keep the user happy */
@@ -1430,7 +1430,7 @@ void O65WriteTarget (O65Desc* D, File* F)
/* Close the file */
if (fclose (D->F) != 0) {
Error ("Cannot write to '%s': %s", D->Filename, strerror (errno));
Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
}
/* Reset the file and filename */

View File

@@ -184,7 +184,7 @@ unsigned MakeGlobalStringId (const ObjData* O, unsigned Index)
/* Convert a local string id into a global one and return it. */
{
if (Index >= O->StringCount) {
Error ("Invalid string index (%u) in module '%s'",
Error ("Invalid string index (%u) in module `%s'",
Index, GetObjFileName (O));
}
return O->Strings[Index];
@@ -214,7 +214,7 @@ struct Section* GetObjSection (const ObjData* O, unsigned Id)
/* Get a section from an object file checking for a valid index */
{
if (Id >= CollCount (&O->Sections)) {
Error ("Invalid section index (%u) in module '%s'",
Error ("Invalid section index (%u) in module `%s'",
Id, GetObjFileName (O));
}
return CollAtUnchecked (&O->Sections, Id);
@@ -226,7 +226,7 @@ struct Import* GetObjImport (const ObjData* O, unsigned Id)
/* Get an import from an object file checking for a valid index */
{
if (Id >= CollCount (&O->Imports)) {
Error ("Invalid import index (%u) in module '%s'",
Error ("Invalid import index (%u) in module `%s'",
Id, GetObjFileName (O));
}
return CollAtUnchecked (&O->Imports, Id);
@@ -238,7 +238,7 @@ struct Export* GetObjExport (const ObjData* O, unsigned Id)
/* Get an export from an object file checking for a valid index */
{
if (Id >= CollCount (&O->Exports)) {
Error ("Invalid export index (%u) in module '%s'",
Error ("Invalid export index (%u) in module `%s'",
Id, GetObjFileName (O));
}
return CollAtUnchecked (&O->Exports, Id);
@@ -250,7 +250,7 @@ struct DbgSym* GetObjDbgSym (const ObjData* O, unsigned Id)
/* Get a debug symbol from an object file checking for a valid index */
{
if (Id >= CollCount (&O->DbgSyms)) {
Error ("Invalid debug symbol index (%u) in module '%s'",
Error ("Invalid debug symbol index (%u) in module `%s'",
Id, GetObjFileName (O));
}
return CollAtUnchecked (&O->DbgSyms, Id);
@@ -262,7 +262,7 @@ struct Scope* GetObjScope (const ObjData* O, unsigned Id)
/* Get a scope from an object file checking for a valid index */
{
if (Id >= CollCount (&O->Scopes)) {
Error ("Invalid scope index (%u) in module '%s'",
Error ("Invalid scope index (%u) in module `%s'",
Id, GetObjFileName (O));
}
return CollAtUnchecked (&O->Scopes, Id);

View File

@@ -67,7 +67,7 @@ static unsigned GetModule (const char* Name)
/* Make a module name from the file name */
const char* Module = FindName (Name);
if (*Module == 0) {
Error ("Cannot make module name from '%s'", Name);
Error ("Cannot make module name from `%s'", Name);
}
return GetStringId (Module);
}
@@ -79,7 +79,7 @@ static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
{
H->Version = Read16 (Obj);
if (H->Version != OBJ_VERSION) {
Error ("Object file '%s' has wrong version, expected %08X, got %08X",
Error ("Object file `%s' has wrong version, expected %08X, got %08X",
Name, OBJ_VERSION, H->Version);
}
H->Flags = Read16 (Obj);

View File

@@ -76,49 +76,6 @@ static FILE* InputFile = 0;
/*****************************************************************************/
/* Error handling */
/*****************************************************************************/
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;
va_start (ap, Format);
SB_VPrintf (&Buf, Format, ap);
va_end (ap);
Warning ("%s:%u: %s",
GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf));
SB_Done (&Buf);
/* Count warnings */
++WarningCount;
}
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;
va_start (ap, Format);
SB_VPrintf (&Buf, Format, ap);
va_end (ap);
Error ("%s:%u: %s",
GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf));
SB_Done (&Buf);
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@@ -170,7 +127,7 @@ static void StrVal (void)
case EOF:
case '\n':
CfgError (&CfgErrorPos, "Unterminated string");
PError (&CfgErrorPos, "Unterminated string");
break;
case '%':
@@ -180,7 +137,7 @@ static void StrVal (void)
case EOF:
case '\n':
case '\"':
CfgError (&CfgErrorPos, "Unterminated '%%' escape sequence");
PError (&CfgErrorPos, "Unterminated `%%' escape sequence");
break;
case '%':
@@ -198,8 +155,8 @@ static void StrVal (void)
break;
default:
CfgWarning (&CfgErrorPos,
"Unknown escape sequence '%%%c'", C);
PWarning (&CfgErrorPos,
"Unknown escape sequence `%%%c'", C);
SB_AppendChar (&CfgSVal, '%');
SB_AppendChar (&CfgSVal, C);
NextChar ();
@@ -255,7 +212,7 @@ Again:
if (C == '$') {
NextChar ();
if (!isxdigit (C)) {
CfgError (&CfgErrorPos, "Hex digit expected");
PError (&CfgErrorPos, "Hex digit expected");
}
CfgIVal = 0;
while (isxdigit (C)) {
@@ -383,7 +340,7 @@ Again:
break;
default:
CfgError (&CfgErrorPos, "Invalid format specification");
PError (&CfgErrorPos, "Invalid format specification");
}
break;
@@ -392,7 +349,7 @@ Again:
break;
default:
CfgError (&CfgErrorPos, "Invalid character '%c'", C);
PError (&CfgErrorPos, "Invalid character `%c'", C);
}
}
@@ -403,7 +360,7 @@ void CfgConsume (cfgtok_t T, const char* Msg)
/* Skip a token, print an error message if not found */
{
if (CfgTok != T) {
CfgError (&CfgErrorPos, "%s", Msg);
PError (&CfgErrorPos, "%s", Msg);
}
CfgNextTok ();
}
@@ -413,7 +370,7 @@ void CfgConsume (cfgtok_t T, const char* Msg)
void CfgConsumeSemi (void)
/* Consume a semicolon */
{
CfgConsume (CFGTOK_SEMI, "';' expected");
CfgConsume (CFGTOK_SEMI, "`;' expected");
}
@@ -421,7 +378,7 @@ void CfgConsumeSemi (void)
void CfgConsumeColon (void)
/* Consume a colon */
{
CfgConsume (CFGTOK_COLON, "':' expected");
CfgConsume (CFGTOK_COLON, "`:' expected");
}
@@ -450,7 +407,7 @@ void CfgAssureInt (void)
/* Make sure the next token is an integer */
{
if (CfgTok != CFGTOK_INTCON) {
CfgError (&CfgErrorPos, "Integer constant expected");
PError (&CfgErrorPos, "Integer constant expected");
}
}
@@ -460,7 +417,7 @@ void CfgAssureStr (void)
/* Make sure the next token is a string constant */
{
if (CfgTok != CFGTOK_STRCON) {
CfgError (&CfgErrorPos, "String constant expected");
PError (&CfgErrorPos, "String constant expected");
}
}
@@ -470,7 +427,7 @@ void CfgAssureIdent (void)
/* Make sure the next token is an identifier */
{
if (CfgTok != CFGTOK_IDENT) {
CfgError (&CfgErrorPos, "Identifier expected");
PError (&CfgErrorPos, "Identifier expected");
}
}
@@ -480,12 +437,34 @@ void CfgRangeCheck (unsigned long Lo, unsigned long Hi)
/* Check the range of CfgIVal */
{
if (CfgIVal < Lo || CfgIVal > Hi) {
CfgError (&CfgErrorPos, "Range error");
PError (&CfgErrorPos, "Range error");
}
}
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)
/* Map an identifier to one of the special tokens in the table */
{
@@ -504,13 +483,22 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
}
}
/* Not found */
CfgError (&CfgErrorPos, "%s expected, got '%s'", Name, SB_GetConstBuf(&CfgSVal));
/* Not found. Add a helpful note about the possible names only if
** 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;
}
/* No identifier */
CfgError (&CfgErrorPos, "%s expected", Name);
PError (&CfgErrorPos, "%s expected", Name);
}
@@ -531,7 +519,7 @@ void CfgBoolToken (void)
} else {
/* We expected an integer here */
if (CfgTok != CFGTOK_INTCON) {
CfgError (&CfgErrorPos, "Boolean value expected");
PError (&CfgErrorPos, "Boolean value expected");
}
CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
}
@@ -561,7 +549,7 @@ void CfgOpenInput (void)
/* Open the file */
InputFile = fopen (CfgName, "r");
if (InputFile == 0) {
Error ("Cannot open '%s': %s", CfgName, strerror (errno));
Error ("Cannot open `%s': %s", CfgName, strerror (errno));
}
/* Initialize variables */

View File

@@ -186,12 +186,6 @@ extern FilePos CfgErrorPos;
void CfgWarning (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3)));
/* Print a warning message adding file name and line number of the config file */
void CfgError (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3)));
/* Print an error message adding file name and line number of a given file */
void CfgNextTok (void);
/* Read the next token from the input stream */

View File

@@ -147,7 +147,7 @@ void PrintDbgScopes (FILE* F)
case SCOPE_ENUM: fputs (",type=enum", F); break;
default:
Error ("Module '%s': Unknown scope type %u",
Error ("Module `%s': Unknown scope type %u",
GetObjFileName (O), S->Type);
}

View File

@@ -144,7 +144,7 @@ Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName)
if (ObjName == 0) {
ObjName = "[linker generated]";
}
Error ("Module '%s': Type mismatch for segment '%s'", ObjName,
Error ("Module `%s': Type mismatch for segment `%s'", ObjName,
GetString (Name));
}
}
@@ -226,13 +226,13 @@ Section* ReadSection (FILE* F, ObjData* O)
if (Sec->Alignment > 1) {
Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment);
if (Alignment > MAX_ALIGNMENT) {
Error ("Combined alignment for segment '%s' is %lu which exceeds "
"%lu. Last module requiring alignment was '%s'.",
Error ("Combined alignment for segment `%s' is %lu which exceeds "
"%lu. Last module requiring alignment was `%s'.",
GetString (Name), Alignment, MAX_ALIGNMENT,
GetObjFileName (O));
} else if (Alignment >= LARGE_ALIGNMENT && Alignment > S->Alignment && Alignment > Sec->Alignment && !LargeAlignment) {
Warning ("Combined alignment for segment '%s' is suspiciously "
"large (%lu). Last module requiring alignment was '%s'.",
Warning ("Combined alignment for segment `%s' is suspiciously "
"large (%lu). Last module requiring alignment was `%s'.",
GetString (Name), Alignment, GetObjFileName (O));
}
S->Alignment = Alignment;
@@ -270,7 +270,7 @@ Section* ReadSection (FILE* F, ObjData* O)
break;
default:
Error ("Unknown fragment type in module '%s', segment '%s': %02X",
Error ("Unknown fragment type in module `%s', segment `%s': %02X",
GetObjFileName (O), GetString (S->Name), Type);
/* NOTREACHED */
return 0;
@@ -306,9 +306,11 @@ Segment* SegFind (unsigned Name)
int IsBSSType (Segment* S)
/* Check if the given segment is a BSS style segment, that is, it does not
** contain non-zero data.
Section* GetNonBSSSection (Segment* S)
/* Used when checking a BSS style segment for initialized data. Will walk over
** all sections in S and check if any of them contains initialized data. If so,
** the first section containing initialized data is returned. Otherwise the
** function returns NULL.
*/
{
/* Loop over all sections */
@@ -326,18 +328,20 @@ int IsBSSType (Segment* S)
unsigned long Count = F->Size;
while (Count--) {
if (*Data++ != 0) {
return 0;
return Sec;
}
}
} else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
if (GetExprVal (F->Expr) != 0) {
return 0;
return Sec;
}
}
F = F->Next;
}
}
return 1;
/* No uninitialized data found */
return 0;
}
@@ -502,19 +506,19 @@ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void*
break;
case SEG_EXPR_RANGE_ERROR:
Error ("Range error in module '%s', line %u",
Error ("Range error in module `%s', line %u",
GetFragmentSourceName (Frag),
GetFragmentSourceLine (Frag));
break;
case SEG_EXPR_TOO_COMPLEX:
Error ("Expression too complex in module '%s', line %u",
Error ("Expression too complex in module `%s', line %u",
GetFragmentSourceName (Frag),
GetFragmentSourceLine (Frag));
break;
case SEG_EXPR_INVALID:
Error ("Invalid expression in module '%s', line %u",
Error ("Invalid expression in module `%s', line %u",
GetFragmentSourceName (Frag),
GetFragmentSourceLine (Frag));
break;
@@ -638,11 +642,9 @@ void PrintDbgSegments (FILE* F)
fprintf (F, ",oname=\"%s\",ooffs=%lu",
S->OutputName, S->OutputOffs);
}
if (S->MemArea) {
if (S->MemArea->BankExpr) {
if (IsConstExpr (S->MemArea->BankExpr)) {
fprintf (F, ",bank=%lu", GetExprVal(S->MemArea->BankExpr));
}
if (S->MemArea && S->MemArea->BankExpr) {
if (IsConstExpr (S->MemArea->BankExpr)) {
fprintf (F, ",bank=%lu", GetExprVal (S->MemArea->BankExpr));
}
}
fputc ('\n', F);
@@ -664,7 +666,7 @@ void CheckSegments (void)
/* Check it */
if (S->Size > 0 && S->Dumped == 0) {
Error ("Missing memory area assignment for segment '%s'",
Error ("Missing memory area assignment for segment `%s'",
GetString (S->Name));
}
}

View File

@@ -131,9 +131,11 @@ Section* ReadSection (FILE* F, struct ObjData* O);
Segment* SegFind (unsigned Name);
/* Return the given segment or NULL if not found. */
int IsBSSType (Segment* S);
/* Check if the given segment is a BSS style segment, that is, it does not
** contain non-zero data.
Section* GetNonBSSSection (Segment* S);
/* Used when checking a BSS style segment for initialized data. Will walk over
** all sections in S and check if any of them contains initialized data. If so,
** the first section containing initialized data is returned. Otherwise the
** function returns NULL.
*/
void SegDump (void);

View File

@@ -120,7 +120,9 @@ void XexSetRunAd (XexDesc* D, Import *RunAd)
D->RunAd = RunAd;
}
XexInitAd* XexSearchInitMem(XexDesc* D, MemoryArea *InitMem)
XexInitAd* XexSearchInitMem (XexDesc* D, MemoryArea *InitMem)
{
XexInitAd* I;
for (I=D->InitAds; I != 0; I=I->next)
@@ -132,6 +134,7 @@ XexInitAd* XexSearchInitMem(XexDesc* D, MemoryArea *InitMem)
}
int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd)
/* Sets and INITAD for the given memory area */
{
@@ -149,6 +152,8 @@ int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd)
return 0;
}
static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size,
unsigned long Offs attribute ((unused)),
void* Data)
@@ -287,7 +292,7 @@ static unsigned long XexWriteMem (XexDesc* D, MemoryArea* M)
if (DoWrite || (M->Flags & MF_FILL) != 0) {
/* "overwrite" segments are not supported */
if (S->Flags & SF_OVERWRITE) {
Error ("ATARI file format does not support overwrite for segment '%s'.",
Error ("ATARI file format does not support overwrite for segment `%s'.",
GetString (S->Name));
} else {
XexStartSegment (D, Addr, NewAddr - Addr);