Merge pull request #2802 from kugelfuhr/kugelfuhr/modernize-ld65-diags
Modernize ld65 diagnostics
This commit is contained in:
@@ -110,6 +110,7 @@ Long options:
|
|||||||
--target sys Set the target system
|
--target sys Set the target system
|
||||||
--verbose Increase verbosity
|
--verbose Increase verbosity
|
||||||
--version Print the compiler version number
|
--version Print the compiler version number
|
||||||
|
--warnings-as-errors Treat warnings as errors
|
||||||
--writable-strings Make string literals writable
|
--writable-strings Make string literals writable
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
@@ -656,6 +657,15 @@ Here is a description of all the command line options:
|
|||||||
or warnings are encountered.
|
or warnings are encountered.
|
||||||
|
|
||||||
|
|
||||||
|
<label id="option--warnings-as-errors">
|
||||||
|
<tag><tt>--warnings-as-errors</tt></tag>
|
||||||
|
|
||||||
|
Treat all warnings as error. This makes the compiler exit with an appropriate
|
||||||
|
error code in case of warnings. The effect of this switch is identical to
|
||||||
|
the command line option <tt/<ref id="option-W" name="-W error">/. It is
|
||||||
|
available for compatibility with the other tools.
|
||||||
|
|
||||||
|
|
||||||
<label id="option-writable-strings">
|
<label id="option-writable-strings">
|
||||||
<tag><tt>--writable-strings</tt></tag>
|
<tag><tt>--writable-strings</tt></tag>
|
||||||
|
|
||||||
@@ -766,7 +776,9 @@ Here is a description of all the command line options:
|
|||||||
<tag><tt/const-comparison/</tag>
|
<tag><tt/const-comparison/</tag>
|
||||||
Warn if the result of a comparison is constant.
|
Warn if the result of a comparison is constant.
|
||||||
<tag><tt/error/</tag>
|
<tag><tt/error/</tag>
|
||||||
Treat all warnings as errors.
|
Treat all warnings as errors. This has the same effect as using the
|
||||||
|
<tt/<ref id="option--warnings-as-errors" name="--warnings-as-errors">/
|
||||||
|
option.
|
||||||
<tag><tt/no-effect/</tag>
|
<tag><tt/no-effect/</tag>
|
||||||
Warn about statements that don't have an effect.
|
Warn about statements that don't have an effect.
|
||||||
<tag><tt/pointer-sign/</tag>
|
<tag><tt/pointer-sign/</tag>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ and other things.
|
|||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
Usage: cl65 [options] file [...]
|
Usage: cl65 [options] file [...]
|
||||||
Short options:
|
Short options:
|
||||||
-c Compile and assemble but don't link
|
-c Compile and assemble, but don't link
|
||||||
-d Debug mode
|
-d Debug mode
|
||||||
-g Add debug info
|
-g Add debug info
|
||||||
-h Help (this text)
|
-h Help (this text)
|
||||||
@@ -55,10 +55,10 @@ Short options:
|
|||||||
-L path Specify a library search path
|
-L path Specify a library search path
|
||||||
-Ln name Create a VICE label file
|
-Ln name Create a VICE label file
|
||||||
-O Optimize code
|
-O Optimize code
|
||||||
-Oi Optimize code, inline more code
|
-Oi Optimize code, inline runtime functions
|
||||||
-Or Optimize code, honour the register keyword
|
-Or Optimize code, honour the register keyword
|
||||||
-Os Optimize code, inline standard functions
|
-Os Optimize code, inline known C functions
|
||||||
-S Compile but don't assemble and link
|
-S Compile, but don't assemble and link
|
||||||
-T Include source as comment
|
-T Include source as comment
|
||||||
-V Print the version number
|
-V Print the version number
|
||||||
-W name[,...] Suppress compiler warnings
|
-W name[,...] Suppress compiler warnings
|
||||||
@@ -81,8 +81,9 @@ Long options:
|
|||||||
--code-label name Define and export a CODE segment label
|
--code-label name Define and export a CODE segment label
|
||||||
--code-name seg Set the name of the CODE segment
|
--code-name seg Set the name of the CODE segment
|
||||||
--codesize x Accept larger code by factor x
|
--codesize x Accept larger code by factor x
|
||||||
|
--color [on|auto|off] Color diagnostics (default: auto)
|
||||||
--config name Use linker config file
|
--config name Use linker config file
|
||||||
--cpu type Set cpu type
|
--cpu type Set CPU type
|
||||||
--create-dep name Create a make dependency file
|
--create-dep name Create a make dependency file
|
||||||
--create-full-dep name Create a full make dependency file
|
--create-full-dep name Create a full make dependency file
|
||||||
--data-label name Define and export a DATA segment label
|
--data-label name Define and export a DATA segment label
|
||||||
@@ -101,8 +102,9 @@ Long options:
|
|||||||
--mapfile name Create a map file
|
--mapfile name Create a map file
|
||||||
--memory-model model Set the memory model
|
--memory-model model Set the memory model
|
||||||
--module Link as a module
|
--module Link as a module
|
||||||
--module-id id Specify a module id for the linker
|
--module-id id Specify a module ID for the linker
|
||||||
--no-target-lib Don't link the target library
|
--no-target-lib Don't link the target library
|
||||||
|
--no-utf8 Disable use of UTF-8 in diagnostics
|
||||||
--o65-model model Override the o65 model
|
--o65-model model Override the o65 model
|
||||||
--obj file Link this object file
|
--obj file Link this object file
|
||||||
--obj-path path Specify an object file search path
|
--obj-path path Specify an object file search path
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ Short options:
|
|||||||
Long options:
|
Long options:
|
||||||
--allow-multiple-definition Allow multiple definitions
|
--allow-multiple-definition Allow multiple definitions
|
||||||
--cfg-path path Specify a config file search path
|
--cfg-path path Specify a config file search path
|
||||||
|
--color [on|auto|off] Color diagnostics (default: auto)
|
||||||
--config name Use linker config file
|
--config name Use linker config file
|
||||||
--dbgfile name Generate debug information
|
--dbgfile name Generate debug information
|
||||||
--define sym=val Define a symbol
|
--define sym=val Define a symbol
|
||||||
@@ -84,13 +85,13 @@ Long options:
|
|||||||
--lib-path path Specify a library search path
|
--lib-path path Specify a library search path
|
||||||
--mapfile name Create a map file
|
--mapfile name Create a map file
|
||||||
--module-id id Specify a module id
|
--module-id id Specify a module id
|
||||||
|
--no-utf8 Disable use of UTF-8 in diagnostics
|
||||||
--obj file Link this object file
|
--obj file Link this object file
|
||||||
--obj-path path Specify an object file search path
|
--obj-path path Specify an object file search path
|
||||||
--start-addr addr Set the default start address
|
--start-addr addr Set the default start address
|
||||||
--start-group Start a library group
|
--start-group Start a library group
|
||||||
--target sys Set the target system
|
--target sys Set the target system
|
||||||
--version Print the linker version
|
--version Print the linker version
|
||||||
--warnings-as-errors Treat warnings as errors
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
@@ -292,6 +293,14 @@ Here is a description of all of the command-line options:
|
|||||||
and in a built-in default directory.
|
and in a built-in default directory.
|
||||||
|
|
||||||
|
|
||||||
|
<label id="option--color">
|
||||||
|
<tag><tt>--color</tt></tag>
|
||||||
|
|
||||||
|
This option controls if the linker will use colors when printing
|
||||||
|
diagnostics. The default is "auto" which will enable colors if the output
|
||||||
|
goes to a terminal (not to a file).
|
||||||
|
|
||||||
|
|
||||||
<label id="option--dbgfile">
|
<label id="option--dbgfile">
|
||||||
<tag><tt>--dbgfile name</tt></tag>
|
<tag><tt>--dbgfile name</tt></tag>
|
||||||
|
|
||||||
@@ -315,6 +324,14 @@ Here is a description of all of the command-line options:
|
|||||||
type because of an unusual extension.
|
type because of an unusual extension.
|
||||||
|
|
||||||
|
|
||||||
|
<label id="option--no-utf8">
|
||||||
|
<tag><tt>--no-utf8</tt></tag>
|
||||||
|
|
||||||
|
Disable the use of UTF-8 characters in diagnostics. This might be necessary
|
||||||
|
if auto detection fails or if the output is captured for processing with a
|
||||||
|
tool that is not UTF-8 capable.
|
||||||
|
|
||||||
|
|
||||||
<tag><tt>--obj file</tt></tag>
|
<tag><tt>--obj file</tt></tag>
|
||||||
|
|
||||||
Links an object file to the output. Use this command-line option instead
|
Links an object file to the output. Use this command-line option instead
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ unsigned WarningCount = 0;
|
|||||||
typedef enum { DC_NOTE, DC_WARN, DC_ERR, DC_FATAL, DC_COUNT } DiagCat;
|
typedef enum { DC_NOTE, DC_WARN, DC_ERR, DC_FATAL, DC_COUNT } DiagCat;
|
||||||
|
|
||||||
/* Descriptions for diagnostic categories */
|
/* Descriptions for diagnostic categories */
|
||||||
const char* DiagCatDesc[DC_COUNT] = {
|
static const char* DiagCatDesc[DC_COUNT] = {
|
||||||
"Note", "Warning", "Error", "Fatal error"
|
"Note", "Warning", "Error", "Fatal error"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -504,14 +504,11 @@ static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char*
|
|||||||
static void OptColor(const char* Opt, const char* Arg)
|
static void OptColor(const char* Opt, const char* Arg)
|
||||||
/* Handle the --color option */
|
/* Handle the --color option */
|
||||||
{
|
{
|
||||||
if (strcmp (Arg, "off") == 0 || strcmp (Arg, "false") == 0) {
|
ColorMode Mode = CP_Parse (Arg);
|
||||||
CP_SetColorMode (CM_OFF);
|
if (Mode == CM_INVALID) {
|
||||||
} 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 {
|
|
||||||
AbEnd ("Invalid argument to %s: %s", Opt, Arg);
|
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);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void OptSeglist (const char* Opt attribute ((unused)),
|
static void OptSeglist (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
/* Enable segment listing */
|
/* Enable segment listing */
|
||||||
@@ -752,6 +751,8 @@ static void OptSeglist (const char* Opt attribute ((unused)),
|
|||||||
SegList = 1;
|
SegList = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
|
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
/* Generate an error if any warnings occur */
|
/* Generate an error if any warnings occur */
|
||||||
@@ -759,6 +760,8 @@ static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
|
|||||||
WarningsAsErrors = 1;
|
WarningsAsErrors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void OptExpandMacros (const char* Opt attribute ((unused)),
|
static void OptExpandMacros (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
/* Expand macros in listing
|
/* Expand macros in listing
|
||||||
@@ -770,6 +773,8 @@ static void OptExpandMacros (const char* Opt attribute ((unused)),
|
|||||||
ExpandMacros++;
|
ExpandMacros++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void DoPCAssign (void)
|
static void DoPCAssign (void)
|
||||||
/* Start absolute code */
|
/* Start absolute code */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ static void Usage (void)
|
|||||||
" --target sys\t\t\tSet the target system\n"
|
" --target sys\t\t\tSet the target system\n"
|
||||||
" --verbose\t\t\tIncrease verbosity\n"
|
" --verbose\t\t\tIncrease verbosity\n"
|
||||||
" --version\t\t\tPrint the compiler version number\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",
|
" --writable-strings\t\tMake string literals writable\n",
|
||||||
ProgName);
|
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)),
|
static void OptWritableStrings (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
/* Make string literals writable */
|
/* Make string literals writable */
|
||||||
@@ -1016,6 +1026,7 @@ int main (int argc, char* argv[])
|
|||||||
{ "--target", 1, OptTarget },
|
{ "--target", 1, OptTarget },
|
||||||
{ "--verbose", 0, OptVerbose },
|
{ "--verbose", 0, OptVerbose },
|
||||||
{ "--version", 0, OptVersion },
|
{ "--version", 0, OptVersion },
|
||||||
|
{ "--warnings-as-errors", 0, OptWarningsAsErrors },
|
||||||
{ "--writable-strings", 0, OptWritableStrings },
|
{ "--writable-strings", 0, OptWritableStrings },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
147
src/cl65/main.c
147
src/cl65/main.c
@@ -70,6 +70,7 @@
|
|||||||
/* common */
|
/* common */
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
#include "cmdline.h"
|
#include "cmdline.h"
|
||||||
|
#include "consprop.h"
|
||||||
#include "filetype.h"
|
#include "filetype.h"
|
||||||
#include "fname.h"
|
#include "fname.h"
|
||||||
#include "mmodel.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-label name\t\tDefine and export a CODE segment label\n"
|
||||||
" --code-name seg\t\tSet the name of the CODE segment\n"
|
" --code-name seg\t\tSet the name of the CODE segment\n"
|
||||||
" --codesize x\t\t\tAccept larger code by factor x\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"
|
" --config name\t\t\tUse linker config file\n"
|
||||||
" --cpu type\t\t\tSet CPU type\n"
|
" --cpu type\t\t\tSet CPU type\n"
|
||||||
" --create-dep name\t\tCreate a make dependency file\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\t\t\tLink as a module\n"
|
||||||
" --module-id id\t\tSpecify a module ID for the linker\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-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"
|
" --o65-model model\t\tOverride the o65 model\n"
|
||||||
" --obj file\t\t\tLink this object file\n"
|
" --obj file\t\t\tLink this object file\n"
|
||||||
" --obj-path path\t\tSpecify an object file search path\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"
|
" --version\t\t\tPrint the version number\n"
|
||||||
" --verbose\t\t\tVerbose mode\n"
|
" --verbose\t\t\tVerbose mode\n"
|
||||||
" --zeropage-label name\t\tDefine and export a ZEROPAGE segment label\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);
|
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)
|
static void OptCPU (const char* Opt attribute ((unused)), const char* Arg)
|
||||||
/* Handle the --cpu option */
|
/* 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)
|
static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg)
|
||||||
/* Handle the --o65-model option */
|
/* 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 [])
|
int main (int argc, char* argv [])
|
||||||
/* Utility main program */
|
/* Utility main program */
|
||||||
{
|
{
|
||||||
/* Program long options */
|
/* Program long options */
|
||||||
static const LongOpt OptTab[] = {
|
static const LongOpt OptTab[] = {
|
||||||
{ "--add-source", 0, OptAddSource },
|
{ "--add-source", 0, OptAddSource },
|
||||||
{ "--all-cdecl", 0, OptAllCDecl },
|
{ "--all-cdecl", 0, OptAllCDecl },
|
||||||
{ "--asm-args", 1, OptAsmArgs },
|
{ "--asm-args", 1, OptAsmArgs },
|
||||||
{ "--asm-define", 1, OptAsmDefine },
|
{ "--asm-define", 1, OptAsmDefine },
|
||||||
{ "--asm-include-dir", 1, OptAsmIncludeDir },
|
{ "--asm-include-dir", 1, OptAsmIncludeDir },
|
||||||
{ "--bin-include-dir", 1, OptBinIncludeDir },
|
{ "--bin-include-dir", 1, OptBinIncludeDir },
|
||||||
{ "--bss-label", 1, OptBssLabel },
|
{ "--bss-label", 1, OptBssLabel },
|
||||||
{ "--bss-name", 1, OptBssName },
|
{ "--bss-name", 1, OptBssName },
|
||||||
{ "--cc-args", 1, OptCCArgs },
|
{ "--cc-args", 1, OptCCArgs },
|
||||||
{ "--cfg-path", 1, OptCfgPath },
|
{ "--cfg-path", 1, OptCfgPath },
|
||||||
{ "--check-stack", 0, OptCheckStack },
|
{ "--check-stack", 0, OptCheckStack },
|
||||||
{ "--code-label", 1, OptCodeLabel },
|
{ "--code-label", 1, OptCodeLabel },
|
||||||
{ "--code-name", 1, OptCodeName },
|
{ "--code-name", 1, OptCodeName },
|
||||||
{ "--codesize", 1, OptCodeSize },
|
{ "--codesize", 1, OptCodeSize },
|
||||||
{ "--config", 1, OptConfig },
|
{ "--color", 1, OptColor },
|
||||||
{ "--cpu", 1, OptCPU },
|
{ "--config", 1, OptConfig },
|
||||||
{ "--create-dep", 1, OptCreateDep },
|
{ "--cpu", 1, OptCPU },
|
||||||
{ "--create-full-dep", 1, OptCreateFullDep },
|
{ "--create-dep", 1, OptCreateDep },
|
||||||
{ "--data-label", 1, OptDataLabel },
|
{ "--create-full-dep", 1, OptCreateFullDep },
|
||||||
{ "--data-name", 1, OptDataName },
|
{ "--data-label", 1, OptDataLabel },
|
||||||
{ "--debug", 0, OptDebug },
|
{ "--data-name", 1, OptDataName },
|
||||||
{ "--debug-info", 0, OptDebugInfo },
|
{ "--debug", 0, OptDebug },
|
||||||
{ "--feature", 1, OptFeature },
|
{ "--debug-info", 0, OptDebugInfo },
|
||||||
{ "--force-import", 1, OptForceImport },
|
{ "--feature", 1, OptFeature },
|
||||||
{ "--help", 0, OptHelp },
|
{ "--force-import", 1, OptForceImport },
|
||||||
{ "--include-dir", 1, OptIncludeDir },
|
{ "--help", 0, OptHelp },
|
||||||
{ "--ld-args", 1, OptLdArgs },
|
{ "--include-dir", 1, OptIncludeDir },
|
||||||
{ "--lib-path", 1, OptLibPath },
|
{ "--ld-args", 1, OptLdArgs },
|
||||||
{ "--list-targets", 0, OptListTargets },
|
{ "--lib-path", 1, OptLibPath },
|
||||||
{ "--listing", 1, OptListing },
|
{ "--list-targets", 0, OptListTargets },
|
||||||
{ "--list-bytes", 1, OptListBytes },
|
{ "--listing", 1, OptListing },
|
||||||
{ "--mapfile", 1, OptMapFile },
|
{ "--list-bytes", 1, OptListBytes },
|
||||||
{ "--memory-model", 1, OptMemoryModel },
|
{ "--mapfile", 1, OptMapFile },
|
||||||
{ "--module", 0, OptModule },
|
{ "--memory-model", 1, OptMemoryModel },
|
||||||
{ "--module-id", 1, OptModuleId },
|
{ "--module", 0, OptModule },
|
||||||
{ "--no-target-lib", 0, OptNoTargetLib },
|
{ "--module-id", 1, OptModuleId },
|
||||||
{ "--o65-model", 1, OptO65Model },
|
{ "--no-target-lib", 0, OptNoTargetLib },
|
||||||
{ "--obj", 1, OptObj },
|
{ "--no-utf8", 0, OptNoUtf8 },
|
||||||
{ "--obj-path", 1, OptObjPath },
|
{ "--o65-model", 1, OptO65Model },
|
||||||
{ "--print-target-path", 0, OptPrintTargetPath},
|
{ "--obj", 1, OptObj },
|
||||||
{ "--register-space", 1, OptRegisterSpace },
|
{ "--obj-path", 1, OptObjPath },
|
||||||
{ "--register-vars", 0, OptRegisterVars },
|
{ "--print-target-path", 0, OptPrintTargetPath },
|
||||||
{ "--rodata-name", 1, OptRodataName },
|
{ "--register-space", 1, OptRegisterSpace },
|
||||||
{ "--signed-chars", 0, OptSignedChars },
|
{ "--register-vars", 0, OptRegisterVars },
|
||||||
{ "--standard", 1, OptStandard },
|
{ "--rodata-name", 1, OptRodataName },
|
||||||
{ "--start-addr", 1, OptStartAddr },
|
{ "--signed-chars", 0, OptSignedChars },
|
||||||
{ "--static-locals", 0, OptStaticLocals },
|
{ "--standard", 1, OptStandard },
|
||||||
{ "--target", 1, OptTarget },
|
{ "--start-addr", 1, OptStartAddr },
|
||||||
{ "--verbose", 0, OptVerbose },
|
{ "--static-locals", 0, OptStaticLocals },
|
||||||
{ "--version", 0, OptVersion },
|
{ "--target", 1, OptTarget },
|
||||||
{ "--zeropage-label", 1, OptZeropageLabel },
|
{ "--verbose", 0, OptVerbose },
|
||||||
{ "--zeropage-name", 1, OptZeropageName },
|
{ "--version", 0, OptVersion },
|
||||||
|
{ "--zeropage-label", 1, OptZeropageLabel },
|
||||||
|
{ "--zeropage-name", 1, OptZeropageName },
|
||||||
|
{ "--warnings-as-errors", 0, OptWarningsAsErrors },
|
||||||
};
|
};
|
||||||
|
|
||||||
char* CmdPath;
|
char* CmdPath;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#else
|
#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)
|
int CP_IsTTY (void)
|
||||||
/* Return true if console output goes to a tty */
|
/* Return true if console output goes to a tty */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Color mode for the program */
|
/* 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;
|
typedef enum ColorMode ColorMode;
|
||||||
|
|
||||||
/* Colors */
|
/* Colors */
|
||||||
@@ -96,6 +96,11 @@ void CP_Init (void);
|
|||||||
** data from this module.
|
** 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);
|
int CP_IsTTY (void);
|
||||||
/* Return true if console output goes to a tty */
|
/* Return true if console output goes to a tty */
|
||||||
|
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ void CheckAssertions (void)
|
|||||||
for (I = 0; I < CollCount (&Assertions); ++I) {
|
for (I = 0; I < CollCount (&Assertions); ++I) {
|
||||||
|
|
||||||
const LineInfo* LI;
|
const LineInfo* LI;
|
||||||
const char* Module;
|
const FilePos* Pos;
|
||||||
unsigned Line;
|
const char* Message;
|
||||||
|
|
||||||
/* Get the assertion */
|
/* Get the assertion */
|
||||||
Assertion* A = CollAtUnchecked (&Assertions, I);
|
Assertion* A = CollAtUnchecked (&Assertions, I);
|
||||||
@@ -120,38 +120,33 @@ 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 file name and line number from the source */
|
Pos = GetSourcePos (LI);
|
||||||
Module = GetSourceName (LI);
|
|
||||||
Line = GetSourceLine (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:
|
||||||
case ASSERT_ACT_LDWARN:
|
case ASSERT_ACT_LDWARN:
|
||||||
Warning ("%s:%u: %s", Module, Line, Message);
|
PWarning (Pos, "Assertion failed: %s", Message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASSERT_ACT_ERROR:
|
case ASSERT_ACT_ERROR:
|
||||||
case ASSERT_ACT_LDERROR:
|
case ASSERT_ACT_LDERROR:
|
||||||
Error ("%s:%u: %s", Module, Line, Message);
|
PError (Pos, "Assertion failed: %s", Message);
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,11 +301,11 @@ void BinWriteTarget (BinDesc* D, struct File* F)
|
|||||||
/* Open the file */
|
/* Open the file */
|
||||||
D->F = fopen (D->Filename, "wb");
|
D->F = fopen (D->Filename, "wb");
|
||||||
if (D->F == 0) {
|
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 */
|
/* Keep the user happy */
|
||||||
Print (stdout, 1, "Opened '%s'...\n", D->Filename);
|
Print (stdout, 1, "Opened `%s'...\n", D->Filename);
|
||||||
|
|
||||||
/* Dump all memory areas */
|
/* Dump all memory areas */
|
||||||
for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
|
for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
|
||||||
@@ -317,7 +317,7 @@ void BinWriteTarget (BinDesc* D, struct File* F)
|
|||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
if (fclose (D->F) != 0) {
|
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 */
|
/* Reset the file and filename */
|
||||||
|
|||||||
@@ -105,11 +105,11 @@ static ExprNode* Factor (void)
|
|||||||
/* Left parenthesis */
|
/* Left parenthesis */
|
||||||
CfgNextTok ();
|
CfgNextTok ();
|
||||||
N = CfgExpr ();
|
N = CfgExpr ();
|
||||||
CfgConsume (CFGTOK_RPAR, "')' expected");
|
CfgConsume (CFGTOK_RPAR, "`)' expected");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CfgError (&CfgErrorPos, "Invalid expression: %d", CfgTok);
|
PError (&CfgErrorPos, "Invalid expression: %d", CfgTok);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ long CfgConstExpr (void)
|
|||||||
|
|
||||||
/* Check that it's const */
|
/* Check that it's const */
|
||||||
if (!IsConstExpr (Expr)) {
|
if (!IsConstExpr (Expr)) {
|
||||||
CfgError (&CfgErrorPos, "Constant expression expected");
|
PError (&CfgErrorPos, "Constant expression expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the value */
|
/* Get the value */
|
||||||
@@ -238,7 +238,7 @@ long CfgCheckedConstExpr (long Min, long Max)
|
|||||||
|
|
||||||
/* Check the range */
|
/* Check the range */
|
||||||
if (Val < Min || Val > Max) {
|
if (Val < Min || Val > Max) {
|
||||||
CfgError (&CfgErrorPos, "Range error");
|
PError (&CfgErrorPos, "Range error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the value */
|
/* Return the value */
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ static MemoryArea* CfgGetMemory (unsigned Name)
|
|||||||
{
|
{
|
||||||
MemoryArea* M = CfgFindMemory (Name);
|
MemoryArea* M = CfgFindMemory (Name);
|
||||||
if (M == 0) {
|
if (M == 0) {
|
||||||
CfgError (&CfgErrorPos, "Invalid memory area '%s'", GetString (Name));
|
PError (&CfgErrorPos, "Invalid memory area `%s'", GetString (Name));
|
||||||
}
|
}
|
||||||
return M;
|
return M;
|
||||||
}
|
}
|
||||||
@@ -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) {
|
||||||
CfgError (&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 */
|
||||||
@@ -345,7 +344,7 @@ static SegDesc* NewSegDesc (unsigned Name)
|
|||||||
/* Check for duplicate names */
|
/* Check for duplicate names */
|
||||||
SegDesc* S = CfgFindSegDesc (Name);
|
SegDesc* S = CfgFindSegDesc (Name);
|
||||||
if (S) {
|
if (S) {
|
||||||
CfgError (&CfgErrorPos, "Segment '%s' defined twice", GetString (Name));
|
PError (&CfgErrorPos, "Segment `%s' defined twice", GetString (Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
@@ -391,7 +390,7 @@ static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (*Flags & Mask) {
|
if (*Flags & Mask) {
|
||||||
CfgError (&CfgErrorPos, "%s is already defined", Name);
|
PError (&CfgErrorPos, "Attribute `%s' is already defined", Name);
|
||||||
}
|
}
|
||||||
*Flags |= Mask;
|
*Flags |= Mask;
|
||||||
}
|
}
|
||||||
@@ -402,7 +401,7 @@ static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
|
|||||||
/* Check that a mandatory attribute was given */
|
/* Check that a mandatory attribute was given */
|
||||||
{
|
{
|
||||||
if ((Attr & Mask) == 0) {
|
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 */
|
/* 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) {
|
||||||
CfgError (&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) {
|
||||||
CfgError (&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! */
|
||||||
CfgError (&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) {
|
||||||
CfgError (&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;
|
||||||
@@ -793,9 +792,9 @@ static void ParseSegments (void)
|
|||||||
** separate run and load memory areas.
|
** separate run and load memory areas.
|
||||||
*/
|
*/
|
||||||
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
|
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
|
||||||
CfgWarning (&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;
|
||||||
}
|
}
|
||||||
@@ -804,17 +803,17 @@ static void ParseSegments (void)
|
|||||||
** load and run memory areas, because it's is never written to disk.
|
** load and run memory areas, because it's is never written to disk.
|
||||||
*/
|
*/
|
||||||
if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
|
if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
|
||||||
CfgWarning (&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) {
|
||||||
CfgError (&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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,8 +822,8 @@ static void ParseSegments (void)
|
|||||||
((S->Flags & SF_OFFSET) != 0) +
|
((S->Flags & SF_OFFSET) != 0) +
|
||||||
((S->Flags & SF_START) != 0);
|
((S->Flags & SF_START) != 0);
|
||||||
if (Count > 1) {
|
if (Count > 1) {
|
||||||
CfgError (&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:
|
||||||
@@ -936,7 +935,7 @@ static void ParseO65 (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CfgError (&CfgErrorPos, "Unexpected type token");
|
PError (&CfgErrorPos, "Unexpected type token");
|
||||||
}
|
}
|
||||||
/* Eat the attribute token */
|
/* Eat the attribute token */
|
||||||
CfgNextTok ();
|
CfgNextTok ();
|
||||||
@@ -952,13 +951,15 @@ 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;
|
||||||
case CFGTOK_CC65: OS = O65OS_CC65; break;
|
case CFGTOK_CC65: OS = O65OS_CC65; break;
|
||||||
case CFGTOK_OPENCBM: OS = O65OS_OPENCBM; break;
|
case CFGTOK_OPENCBM: OS = O65OS_OPENCBM; break;
|
||||||
default: CfgError (&CfgErrorPos, "Unexpected OS token");
|
default: PError (&CfgErrorPos, "Unexpected OS token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CfgNextTok ();
|
CfgNextTok ();
|
||||||
@@ -993,13 +994,13 @@ static void ParseO65 (void)
|
|||||||
/* Check for attributes that may not be combined */
|
/* Check for attributes that may not be combined */
|
||||||
if (OS == O65OS_CC65) {
|
if (OS == O65OS_CC65) {
|
||||||
if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) {
|
if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) {
|
||||||
CfgError (&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) {
|
||||||
CfgError (&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))
|
||||||
CfgError (&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;
|
||||||
@@ -1289,10 +1291,10 @@ static void ParseConDes (void)
|
|||||||
AttrCheck (AttrFlags, atType, "TYPE");
|
AttrCheck (AttrFlags, atType, "TYPE");
|
||||||
|
|
||||||
/* 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)) {
|
||||||
CfgError (&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;
|
||||||
@@ -1559,7 +1565,7 @@ static void ParseSymbols (void)
|
|||||||
case CfgSymImport:
|
case CfgSymImport:
|
||||||
/* An import must not have a value */
|
/* An import must not have a value */
|
||||||
if (AttrFlags & atValue) {
|
if (AttrFlags & atValue) {
|
||||||
CfgError (&CfgErrorPos, "Imports must not have a value");
|
PError (&CfgErrorPos, "Imports must not have a value");
|
||||||
}
|
}
|
||||||
/* Generate the import */
|
/* Generate the import */
|
||||||
Imp = InsertImport (GenImport (Name, AddrSize));
|
Imp = InsertImport (GenImport (Name, AddrSize));
|
||||||
@@ -1606,12 +1612,13 @@ 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 ();
|
||||||
|
|
||||||
/* Expected a curly brace */
|
/* Expected a curly brace */
|
||||||
CfgConsume (CFGTOK_LCURLY, "'{' expected");
|
CfgConsume (CFGTOK_LCURLY, "`{' expected");
|
||||||
|
|
||||||
/* Read the block */
|
/* Read the block */
|
||||||
switch (BlockTok) {
|
switch (BlockTok) {
|
||||||
@@ -1646,7 +1653,7 @@ static void ParseConfig (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Skip closing brace */
|
/* Skip closing brace */
|
||||||
CfgConsume (CFGTOK_RCURLY, "'}' expected");
|
CfgConsume (CFGTOK_RCURLY, "`}' expected");
|
||||||
|
|
||||||
} while (CfgTok != CFGTOK_EOF);
|
} 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 any of the object file, check that there's no initialized data
|
||||||
** in the segment.
|
** in the segment.
|
||||||
*/
|
*/
|
||||||
if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
|
if ((S->Flags & SF_BSS) != 0 && S->Seg != 0) {
|
||||||
CfgWarning (GetSourcePos (S->LI),
|
Section* Sec = GetNonBSSSection (S->Seg);
|
||||||
"Segment '%s' with type 'bss' contains initialized data",
|
if (Sec) {
|
||||||
GetString (S->Name));
|
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
|
/* 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 */
|
/* Print a warning if the segment is not optional */
|
||||||
if ((S->Flags & SF_OPTIONAL) == 0) {
|
if ((S->Flags & SF_OPTIONAL) == 0) {
|
||||||
CfgWarning (&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 */
|
||||||
@@ -1764,9 +1780,9 @@ static void ProcessSymbols (void)
|
|||||||
case CfgSymO65Export:
|
case CfgSymO65Export:
|
||||||
/* Check if the export symbol is also defined as an import. */
|
/* Check if the export symbol is also defined as an import. */
|
||||||
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
|
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
|
||||||
CfgError (
|
PError (
|
||||||
GetSourcePos (Sym->LI),
|
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)
|
GetString (Sym->Name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1776,9 +1792,9 @@ static void ProcessSymbols (void)
|
|||||||
** error message when checking it here.
|
** error message when checking it here.
|
||||||
*/
|
*/
|
||||||
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
|
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
|
||||||
CfgError (
|
PError (
|
||||||
GetSourcePos (Sym->LI),
|
GetSourcePos (Sym->LI),
|
||||||
"Duplicate exported o65 symbol: '%s'",
|
"Duplicate exported o65 symbol: `%s'",
|
||||||
GetString (Sym->Name)
|
GetString (Sym->Name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1790,9 +1806,9 @@ static void ProcessSymbols (void)
|
|||||||
case CfgSymO65Import:
|
case CfgSymO65Import:
|
||||||
/* Check if the import symbol is also defined as an export. */
|
/* Check if the import symbol is also defined as an export. */
|
||||||
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
|
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
|
||||||
CfgError (
|
PError (
|
||||||
GetSourcePos (Sym->LI),
|
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)
|
GetString (Sym->Name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1802,9 +1818,9 @@ static void ProcessSymbols (void)
|
|||||||
** error message when checking it here.
|
** error message when checking it here.
|
||||||
*/
|
*/
|
||||||
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
|
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
|
||||||
CfgError (
|
PError (
|
||||||
GetSourcePos (Sym->LI),
|
GetSourcePos (Sym->LI),
|
||||||
"Duplicate imported o65 symbol: '%s'",
|
"Duplicate imported o65 symbol: `%s'",
|
||||||
GetString (Sym->Name)
|
GetString (Sym->Name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1913,9 +1929,9 @@ unsigned CfgProcess (void)
|
|||||||
** and mark the memory area as placed.
|
** and mark the memory area as placed.
|
||||||
*/
|
*/
|
||||||
if (!IsConstExpr (M->StartExpr)) {
|
if (!IsConstExpr (M->StartExpr)) {
|
||||||
CfgError (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;
|
||||||
@@ -1938,15 +1954,15 @@ unsigned CfgProcess (void)
|
|||||||
|
|
||||||
/* Resolve the size expression */
|
/* Resolve the size expression */
|
||||||
if (!IsConstExpr (M->SizeExpr)) {
|
if (!IsConstExpr (M->SizeExpr)) {
|
||||||
CfgError (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) {
|
||||||
CfgError (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 */
|
||||||
@@ -1968,17 +1984,17 @@ unsigned CfgProcess (void)
|
|||||||
if (S->Flags & (SF_OFFSET | SF_START)) {
|
if (S->Flags & (SF_OFFSET | SF_START)) {
|
||||||
++Overwrites;
|
++Overwrites;
|
||||||
} else {
|
} else {
|
||||||
CfgError (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) {
|
||||||
CfgError (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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2002,10 +2018,10 @@ unsigned CfgProcess (void)
|
|||||||
/* Segment requires another alignment than configured
|
/* Segment requires another alignment than configured
|
||||||
** in the linker.
|
** in the linker.
|
||||||
*/
|
*/
|
||||||
CfgWarning (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) {
|
||||||
@@ -2017,10 +2033,10 @@ unsigned CfgProcess (void)
|
|||||||
** that is somewhat suspicious.
|
** that is somewhat suspicious.
|
||||||
*/
|
*/
|
||||||
if (M->FillLevel == 0 && NewAddr > Addr) {
|
if (M->FillLevel == 0 && NewAddr > Addr) {
|
||||||
CfgWarning (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 */
|
||||||
@@ -2038,9 +2054,9 @@ unsigned CfgProcess (void)
|
|||||||
|
|
||||||
if (S->Flags & SF_OVERWRITE) {
|
if (S->Flags & SF_OVERWRITE) {
|
||||||
if (NewAddr < M->Start) {
|
if (NewAddr < M->Start) {
|
||||||
CfgError (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 +2065,23 @@ unsigned CfgProcess (void)
|
|||||||
/* Offset already too large */
|
/* Offset already too large */
|
||||||
++Overflows;
|
++Overflows;
|
||||||
if (S->Flags & SF_OFFSET) {
|
if (S->Flags & SF_OFFSET) {
|
||||||
CfgWarning (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 {
|
||||||
CfgWarning (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 +2125,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;
|
||||||
CfgWarning (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
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void CreateDbgFile (void)
|
|||||||
/* Open the debug info file */
|
/* Open the debug info file */
|
||||||
FILE* F = fopen (DbgFileName, "w");
|
FILE* F = fopen (DbgFileName, "w");
|
||||||
if (F == 0) {
|
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 */
|
/* Output version information */
|
||||||
@@ -166,6 +166,6 @@ void CreateDbgFile (void)
|
|||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
if (fclose (F) != 0) {
|
if (fclose (F) != 0) {
|
||||||
Error ("Error closing debug file '%s': %s", DbgFileName, strerror (errno));
|
Error ("Error closing debug file `%s': %s", DbgFileName, strerror (errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
304
src/ld65/error.c
304
src/ld65/error.c
@@ -39,10 +39,13 @@
|
|||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "cmdline.h"
|
#include "cmdline.h"
|
||||||
|
#include "coll.h"
|
||||||
|
#include "consprop.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "spool.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -55,6 +58,22 @@
|
|||||||
/* Statistics */
|
/* Statistics */
|
||||||
unsigned WarningCount = 0;
|
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, ...)
|
void Warning (const char* Format, ...)
|
||||||
/* Print a warning message */
|
/* Print a warning message */
|
||||||
{
|
{
|
||||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
/* Output the message */
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
SB_VPrintf (&S, Format, ap);
|
VPrintMsg (&NoFile, DC_WARN, Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
SB_Terminate (&S);
|
|
||||||
|
|
||||||
fprintf (stderr, "%s: Warning: %s\n", ProgName, SB_GetConstBuf (&S));
|
/* Output all stored notes */
|
||||||
|
OutputNotes ();
|
||||||
SB_Done (&S);
|
|
||||||
|
|
||||||
/* Count warnings */
|
/* Count warnings */
|
||||||
++WarningCount;
|
++WarningCount;
|
||||||
@@ -87,18 +299,16 @@ void Warning (const char* Format, ...)
|
|||||||
void Error (const char* Format, ...)
|
void Error (const char* Format, ...)
|
||||||
/* Print an error message and die */
|
/* Print an error message and die */
|
||||||
{
|
{
|
||||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
/* Output the message */
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
SB_VPrintf (&S, Format, ap);
|
VPrintMsg (&NoFile, DC_ERR, Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
SB_Terminate (&S);
|
|
||||||
|
|
||||||
fprintf (stderr, "%s: Error: %s\n", ProgName, SB_GetConstBuf (&S));
|
/* Output all stored notes */
|
||||||
|
OutputNotes ();
|
||||||
SB_Done (&S);
|
|
||||||
|
|
||||||
|
/* Terminate after errors */
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,17 +317,67 @@ void Error (const char* Format, ...)
|
|||||||
void Internal (const char* Format, ...)
|
void Internal (const char* Format, ...)
|
||||||
/* Print an internal error message and die */
|
/* Print an internal error message and die */
|
||||||
{
|
{
|
||||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
/* Output the message */
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
SB_VPrintf (&S, Format, ap);
|
VPrintMsg (&NoFile, DC_INT, Format, ap);
|
||||||
va_end (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);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "attrib.h"
|
#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)));
|
void Warning (const char* Format, ...) attribute((format(printf,1,2)));
|
||||||
/* Print a warning message */
|
/* 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)));
|
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 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 */
|
/* End of error.h */
|
||||||
|
|||||||
@@ -167,13 +167,13 @@ Import* ReadImport (FILE* F, ObjData* Obj)
|
|||||||
*/
|
*/
|
||||||
if (ObjHasFiles (I->Obj)) {
|
if (ObjHasFiles (I->Obj)) {
|
||||||
const LineInfo* LI = GetImportPos (I);
|
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),
|
GetString (I->Name),
|
||||||
GetSourceName (LI),
|
GetSourceName (LI),
|
||||||
GetSourceLine (LI),
|
GetSourceLine (LI),
|
||||||
I->AddrSize);
|
I->AddrSize);
|
||||||
} else {
|
} 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),
|
GetString (I->Name),
|
||||||
GetObjFileName (I->Obj),
|
GetObjFileName (I->Obj),
|
||||||
I->AddrSize);
|
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
|
/* We have no object file information and no line info for a new
|
||||||
** import
|
** import
|
||||||
*/
|
*/
|
||||||
Error ("Invalid import size 0x%02X for symbol '%s'",
|
Error ("Invalid import size 0x%02X for symbol `%s'",
|
||||||
I->AddrSize,
|
I->AddrSize,
|
||||||
GetString (I->Name));
|
GetString (I->Name));
|
||||||
}
|
}
|
||||||
@@ -484,7 +484,7 @@ void InsertExport (Export* E)
|
|||||||
}
|
}
|
||||||
} else if (AllowMultDef == 0) {
|
} else if (AllowMultDef == 0) {
|
||||||
/* Duplicate entry, this is fatal unless allowed by the user */
|
/* Duplicate entry, this is fatal unless allowed by the user */
|
||||||
Error ("Duplicate external identifier: '%s'",
|
Error ("Duplicate external identifier: `%s'",
|
||||||
GetString (L->Name));
|
GetString (L->Name));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -663,7 +663,7 @@ long GetExportVal (const Export* E)
|
|||||||
{
|
{
|
||||||
if (E->Expr == 0) {
|
if (E->Expr == 0) {
|
||||||
/* OOPS */
|
/* OOPS */
|
||||||
Internal ("'%s' is an undefined external", GetString (E->Name));
|
Internal ("`%s' is an undefined external", GetString (E->Name));
|
||||||
}
|
}
|
||||||
return GetExprVal (E->Expr);
|
return GetExprVal (E->Expr);
|
||||||
}
|
}
|
||||||
@@ -726,9 +726,9 @@ static void CheckSymType (const Export* E)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Output the diagnostic */
|
/* Output the diagnostic */
|
||||||
Warning ("Address size mismatch for '%s': "
|
Warning ("Address size mismatch for `%s': "
|
||||||
"Exported from %s as '%s', "
|
"Exported from %s as `%s', "
|
||||||
"import in %s as '%s'",
|
"import in %s as `%s'",
|
||||||
GetString (E->Name),
|
GetString (E->Name),
|
||||||
SB_GetConstBuf (&ExportLoc),
|
SB_GetConstBuf (&ExportLoc),
|
||||||
ExpAddrSize,
|
ExpAddrSize,
|
||||||
@@ -775,21 +775,20 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
|
|||||||
if (E->Expr == 0 && E->ImpCount > 0 && F (E->Name, Data) == 0) {
|
if (E->Expr == 0 && E->ImpCount > 0 && F (E->Name, Data) == 0) {
|
||||||
/* Unresolved external */
|
/* Unresolved external */
|
||||||
Import* Imp = E->ImpList;
|
Import* Imp = E->ImpList;
|
||||||
const char* name = GetString (E->Name);
|
const char* Name = GetString (E->Name);
|
||||||
while (Imp) {
|
while (Imp) {
|
||||||
unsigned J, count = CollCount (&Imp->RefLines);
|
unsigned J, Count = CollCount (&Imp->RefLines);
|
||||||
/* The count is 0 when the import was not added by an input file,
|
/* The count is 0 when the import was not added by an input
|
||||||
but by the compiler itself. */
|
** file, but by the compiler itself.
|
||||||
if (count == 0) {
|
*/
|
||||||
fprintf (stderr, "Error: Unresolved external '%s'\n", name);
|
if (Count == 0) {
|
||||||
|
Warning ("Unresolved external `%s'", Name);
|
||||||
} else {
|
} else {
|
||||||
for (J = 0; J < count; ++J) {
|
for (J = 0; J < Count; ++J) {
|
||||||
const LineInfo* LI = CollConstAt (&Imp->RefLines, J);
|
const LineInfo* LI = CollConstAt (&Imp->RefLines, J);
|
||||||
fprintf (stderr,
|
PWarning (GetSourcePos (LI),
|
||||||
"%s:%u: Error: Unresolved external '%s'\n",
|
"Unresolved external `%s'",
|
||||||
GetSourceName (LI),
|
Name);
|
||||||
GetSourceLine (LI),
|
|
||||||
name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Imp = Imp->Next;
|
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 */
|
/* Print an error about a circular reference using to define the given export */
|
||||||
{
|
{
|
||||||
const LineInfo* LI = GetExportPos (E);
|
const LineInfo* LI = GetExportPos (E);
|
||||||
Error ("Circular reference for symbol '%s', %s:%u",
|
Error ("Circular reference for symbol `%s', %s:%u",
|
||||||
GetString (E->Name),
|
GetString (E->Name),
|
||||||
GetSourceName (LI),
|
GetSourceName (LI),
|
||||||
GetSourceLine (LI));
|
GetSourceLine (LI));
|
||||||
|
|||||||
@@ -408,12 +408,12 @@ long GetExprVal (ExprNode* Expr)
|
|||||||
Error ("Argument of .BANK() isn't a label attached to a segment");
|
Error ("Argument of .BANK() isn't a label attached to a segment");
|
||||||
}
|
}
|
||||||
if (D.Seg->MemArea == 0) {
|
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",
|
" but not assigned to a memory area",
|
||||||
GetString (D.Seg->Name));
|
GetString (D.Seg->Name));
|
||||||
}
|
}
|
||||||
if (D.Seg->MemArea->BankExpr == 0) {
|
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",
|
" but has no BANK attribute",
|
||||||
GetString (D.Seg->MemArea->Name));
|
GetString (D.Seg->MemArea->Name));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ ExtSym* NewExtSym (ExtSymTab* Tab, unsigned Name)
|
|||||||
ExtSym* E = GetExtSym (Tab, Name);
|
ExtSym* E = GetExtSym (Tab, Name);
|
||||||
if (E != 0) {
|
if (E != 0) {
|
||||||
/* We do already have a symbol with this name */
|
/* 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 */
|
/* Allocate memory for the structure */
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ static void CloseLibrary (Library* L)
|
|||||||
{
|
{
|
||||||
/* Close the library file */
|
/* Close the library file */
|
||||||
if (fclose (L->F) != 0) {
|
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;
|
L->F = 0;
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ static void LibSeek (Library* L, unsigned long Offs)
|
|||||||
/* Do a seek in the library checking for errors */
|
/* Do a seek in the library checking for errors */
|
||||||
{
|
{
|
||||||
if (fseek (L->F, Offs, SEEK_SET) != 0) {
|
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));
|
GetString (L->Name), Offs, strerror (errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ static void LibReadHeader (Library* L)
|
|||||||
L->Header.Magic = LIB_MAGIC;
|
L->Header.Magic = LIB_MAGIC;
|
||||||
L->Header.Version = Read16 (L->F);
|
L->Header.Version = Read16 (L->F);
|
||||||
if (L->Header.Version != LIB_VERSION) {
|
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.Flags = Read16 (L->F);
|
||||||
L->Header.IndexOffs = Read32 (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);
|
O->Header.Magic = Read32 (L->F);
|
||||||
if (O->Header.Magic != OBJ_MAGIC) {
|
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));
|
GetObjFileName (O), GetString (L->Name));
|
||||||
}
|
}
|
||||||
O->Header.Version = Read16 (L->F);
|
O->Header.Version = Read16 (L->F);
|
||||||
if (O->Header.Version != OBJ_VERSION) {
|
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));
|
GetObjFileName (O), GetString (L->Name));
|
||||||
}
|
}
|
||||||
O->Header.Flags = Read16 (L->F);
|
O->Header.Flags = Read16 (L->F);
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
#include "asserts.h"
|
#include "asserts.h"
|
||||||
#include "binfmt.h"
|
#include "binfmt.h"
|
||||||
#include "condes.h"
|
#include "condes.h"
|
||||||
|
#include "consprop.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dbgfile.h"
|
#include "dbgfile.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@@ -130,6 +131,7 @@ static void Usage (void)
|
|||||||
"Long options:\n"
|
"Long options:\n"
|
||||||
" --allow-multiple-definition\tAllow multiple definitions\n"
|
" --allow-multiple-definition\tAllow multiple definitions\n"
|
||||||
" --cfg-path path\t\tSpecify a config file search path\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"
|
" --config name\t\t\tUse linker config file\n"
|
||||||
" --dbgfile name\t\tGenerate debug information\n"
|
" --dbgfile name\t\tGenerate debug information\n"
|
||||||
" --define sym=val\t\tDefine a symbol\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"
|
" --lib-path path\t\tSpecify a library search path\n"
|
||||||
" --mapfile name\t\tCreate a map file\n"
|
" --mapfile name\t\tCreate a map file\n"
|
||||||
" --module-id id\t\tSpecify a module id\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 file\t\t\tLink this object file\n"
|
||||||
" --obj-path path\t\tSpecify an object file search path\n"
|
" --obj-path path\t\tSpecify an object file search path\n"
|
||||||
" --start-addr addr\t\tSet the default start address\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 */
|
/* We must have a valid name now */
|
||||||
if (PathName == 0) {
|
if (PathName == 0) {
|
||||||
Error ("Input file '%s' not found", Name);
|
Error ("Input file `%s' not found", Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to open the file */
|
/* Try to open the file */
|
||||||
F = fopen (PathName, "rb");
|
F = fopen (PathName, "rb");
|
||||||
if (F == 0) {
|
if (F == 0) {
|
||||||
Error ("Cannot open '%s': %s", PathName, strerror (errno));
|
Error ("Cannot open `%s': %s", PathName, strerror (errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the magic word */
|
/* Read the magic word */
|
||||||
@@ -248,7 +251,7 @@ static void LinkFile (const char* Name, FILETYPE Type)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
fclose (F);
|
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)
|
static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
|
||||||
/* Define the config file */
|
/* Define the config file */
|
||||||
{
|
{
|
||||||
@@ -324,7 +340,7 @@ static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
|
|||||||
PathName = SearchFile (CfgDefaultPath, Arg);
|
PathName = SearchFile (CfgDefaultPath, Arg);
|
||||||
}
|
}
|
||||||
if (PathName == 0) {
|
if (PathName == 0) {
|
||||||
Error ("Cannot find config file '%s'", Arg);
|
Error ("Cannot find config file `%s'", Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the config */
|
/* 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 */
|
/* Get the address size and check it */
|
||||||
unsigned char AddrSize = AddrSizeFromStr (ColPos+1);
|
unsigned char AddrSize = AddrSizeFromStr (ColPos+1);
|
||||||
if (AddrSize == ADDR_SIZE_INVALID) {
|
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 */
|
/* 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)
|
static void OptObj (const char* Opt attribute ((unused)), const char* Arg)
|
||||||
/* Link an object file */
|
/* 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 */
|
/* Map the target name to a target id */
|
||||||
Target = FindTarget (Arg);
|
Target = FindTarget (Arg);
|
||||||
if (Target == TGT_UNKNOWN) {
|
if (Target == TGT_UNKNOWN) {
|
||||||
Error ("Invalid target name: '%s'", Arg);
|
Error ("Invalid target name: `%s'", Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the target binary format */
|
/* 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));
|
PathName = SearchFile (CfgDefaultPath, SB_GetBuf (&FileName));
|
||||||
}
|
}
|
||||||
if (PathName == 0) {
|
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 */
|
/* 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 */
|
/* Program long options */
|
||||||
static const LongOpt OptTab[] = {
|
static const LongOpt OptTab[] = {
|
||||||
{ "--allow-multiple-definition", 0, OptMultDef },
|
{ "--allow-multiple-definition", 0, OptMultDef },
|
||||||
{ "--cfg-path", 1, OptCfgPath },
|
{ "--cfg-path", 1, OptCfgPath },
|
||||||
|
{ "--color", 1, OptColor },
|
||||||
{ "--config", 1, CmdlOptConfig },
|
{ "--config", 1, CmdlOptConfig },
|
||||||
{ "--dbgfile", 1, OptDbgFile },
|
{ "--dbgfile", 1, OptDbgFile },
|
||||||
{ "--define", 1, OptDefine },
|
{ "--define", 1, OptDefine },
|
||||||
@@ -640,6 +666,7 @@ static void ParseCommandLine(void)
|
|||||||
{ "--lib-path", 1, OptLibPath },
|
{ "--lib-path", 1, OptLibPath },
|
||||||
{ "--mapfile", 1, OptMapFile },
|
{ "--mapfile", 1, OptMapFile },
|
||||||
{ "--module-id", 1, OptModuleId },
|
{ "--module-id", 1, OptModuleId },
|
||||||
|
{ "--no-utf8", 0, OptNoUtf8 },
|
||||||
{ "--obj", 1, OptObj },
|
{ "--obj", 1, OptObj },
|
||||||
{ "--obj-path", 1, OptObjPath },
|
{ "--obj-path", 1, OptObjPath },
|
||||||
{ "--start-addr", 1, OptStartAddr },
|
{ "--start-addr", 1, OptStartAddr },
|
||||||
@@ -800,6 +827,9 @@ int main (int argc, char* argv [])
|
|||||||
{
|
{
|
||||||
unsigned MemoryAreaOverflows;
|
unsigned MemoryAreaOverflows;
|
||||||
|
|
||||||
|
/* Initialize console output */
|
||||||
|
CP_Init ();
|
||||||
|
|
||||||
/* Initialize the cmdline module */
|
/* Initialize the cmdline module */
|
||||||
InitCmdLine (&argc, &argv, "ld65");
|
InitCmdLine (&argc, &argv, "ld65");
|
||||||
|
|
||||||
@@ -856,7 +886,7 @@ int main (int argc, char* argv [])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WarningCount > 0 && WarningsAsErrors) {
|
if (WarningCount > 0 && WarningsAsErrors) {
|
||||||
Error("Warnings as errors");
|
Error ("Warnings as errors");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the output file */
|
/* Create the output file */
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ void CreateMapFile (int ShortMap)
|
|||||||
/* Open the map file */
|
/* Open the map file */
|
||||||
FILE* F = fopen (MapFileName, "w");
|
FILE* F = fopen (MapFileName, "w");
|
||||||
if (F == 0) {
|
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 */
|
/* Write a modules list */
|
||||||
@@ -132,7 +132,7 @@ void CreateMapFile (int ShortMap)
|
|||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
if (fclose (F) != 0) {
|
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 */
|
/* Open the label file */
|
||||||
FILE* F = fopen (LabelFileName, "w");
|
FILE* F = fopen (LabelFileName, "w");
|
||||||
if (F == 0) {
|
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 */
|
/* Print the labels for the export symbols */
|
||||||
@@ -155,6 +155,6 @@ void CreateLabelFile (void)
|
|||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
if (fclose (F) != 0) {
|
if (fclose (F) != 0) {
|
||||||
Error ("Error closing label file '%s': %s", LabelFileName, strerror (errno));
|
Error ("Error closing label file `%s': %s", LabelFileName, strerror (errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -807,7 +807,7 @@ static void O65WriteSeg (O65Desc* D, SegDesc** Seg, unsigned Count, int DoWrite)
|
|||||||
|
|
||||||
/* Check the size of the segment for overflow */
|
/* Check the size of the segment for overflow */
|
||||||
if ((D->Header.Mode & MF_SIZE_MASK) == MF_SIZE_16BIT && D->SegSize > 0xFFFF) {
|
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 */
|
/* Bail out if we cannot handle the expression */
|
||||||
if (ED.TooComplex) {
|
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 */
|
/* 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
|
/* For some reason, we didn't find this segment in the list of
|
||||||
** segments written to the o65 file.
|
** 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);
|
SegmentID = O65SegType (Seg);
|
||||||
|
|
||||||
@@ -1209,7 +1209,7 @@ void O65SetExport (O65Desc* D, unsigned Ident)
|
|||||||
*/
|
*/
|
||||||
Export* E = FindExport (Ident);
|
Export* E = FindExport (Ident);
|
||||||
if (E == 0 || IsUnresolvedExport (E)) {
|
if (E == 0 || IsUnresolvedExport (E)) {
|
||||||
Error ("Unresolved export: '%s'", GetString (Ident));
|
Error ("Unresolved export: `%s'", GetString (Ident));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert the entry into the table */
|
/* Insert the entry into the table */
|
||||||
@@ -1372,7 +1372,7 @@ void O65WriteTarget (O65Desc* D, File* F)
|
|||||||
/* Open the file */
|
/* Open the file */
|
||||||
D->F = fopen (D->Filename, "wb");
|
D->F = fopen (D->Filename, "wb");
|
||||||
if (D->F == 0) {
|
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 */
|
/* Keep the user happy */
|
||||||
@@ -1430,7 +1430,7 @@ void O65WriteTarget (O65Desc* D, File* F)
|
|||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
if (fclose (D->F) != 0) {
|
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 */
|
/* Reset the file and filename */
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ unsigned MakeGlobalStringId (const ObjData* O, unsigned Index)
|
|||||||
/* Convert a local string id into a global one and return it. */
|
/* Convert a local string id into a global one and return it. */
|
||||||
{
|
{
|
||||||
if (Index >= O->StringCount) {
|
if (Index >= O->StringCount) {
|
||||||
Error ("Invalid string index (%u) in module '%s'",
|
Error ("Invalid string index (%u) in module `%s'",
|
||||||
Index, GetObjFileName (O));
|
Index, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
return O->Strings[Index];
|
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 */
|
/* Get a section from an object file checking for a valid index */
|
||||||
{
|
{
|
||||||
if (Id >= CollCount (&O->Sections)) {
|
if (Id >= CollCount (&O->Sections)) {
|
||||||
Error ("Invalid section index (%u) in module '%s'",
|
Error ("Invalid section index (%u) in module `%s'",
|
||||||
Id, GetObjFileName (O));
|
Id, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
return CollAtUnchecked (&O->Sections, Id);
|
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 */
|
/* Get an import from an object file checking for a valid index */
|
||||||
{
|
{
|
||||||
if (Id >= CollCount (&O->Imports)) {
|
if (Id >= CollCount (&O->Imports)) {
|
||||||
Error ("Invalid import index (%u) in module '%s'",
|
Error ("Invalid import index (%u) in module `%s'",
|
||||||
Id, GetObjFileName (O));
|
Id, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
return CollAtUnchecked (&O->Imports, Id);
|
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 */
|
/* Get an export from an object file checking for a valid index */
|
||||||
{
|
{
|
||||||
if (Id >= CollCount (&O->Exports)) {
|
if (Id >= CollCount (&O->Exports)) {
|
||||||
Error ("Invalid export index (%u) in module '%s'",
|
Error ("Invalid export index (%u) in module `%s'",
|
||||||
Id, GetObjFileName (O));
|
Id, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
return CollAtUnchecked (&O->Exports, Id);
|
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 */
|
/* Get a debug symbol from an object file checking for a valid index */
|
||||||
{
|
{
|
||||||
if (Id >= CollCount (&O->DbgSyms)) {
|
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));
|
Id, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
return CollAtUnchecked (&O->DbgSyms, Id);
|
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 */
|
/* Get a scope from an object file checking for a valid index */
|
||||||
{
|
{
|
||||||
if (Id >= CollCount (&O->Scopes)) {
|
if (Id >= CollCount (&O->Scopes)) {
|
||||||
Error ("Invalid scope index (%u) in module '%s'",
|
Error ("Invalid scope index (%u) in module `%s'",
|
||||||
Id, GetObjFileName (O));
|
Id, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
return CollAtUnchecked (&O->Scopes, Id);
|
return CollAtUnchecked (&O->Scopes, Id);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ static unsigned GetModule (const char* Name)
|
|||||||
/* Make a module name from the file name */
|
/* Make a module name from the file name */
|
||||||
const char* Module = FindName (Name);
|
const char* Module = FindName (Name);
|
||||||
if (*Module == 0) {
|
if (*Module == 0) {
|
||||||
Error ("Cannot make module name from '%s'", Name);
|
Error ("Cannot make module name from `%s'", Name);
|
||||||
}
|
}
|
||||||
return GetStringId (Module);
|
return GetStringId (Module);
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
|
|||||||
{
|
{
|
||||||
H->Version = Read16 (Obj);
|
H->Version = Read16 (Obj);
|
||||||
if (H->Version != OBJ_VERSION) {
|
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);
|
Name, OBJ_VERSION, H->Version);
|
||||||
}
|
}
|
||||||
H->Flags = Read16 (Obj);
|
H->Flags = Read16 (Obj);
|
||||||
|
|||||||
@@ -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 */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -170,7 +127,7 @@ static void StrVal (void)
|
|||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
case '\n':
|
case '\n':
|
||||||
CfgError (&CfgErrorPos, "Unterminated string");
|
PError (&CfgErrorPos, "Unterminated string");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
@@ -180,7 +137,7 @@ static void StrVal (void)
|
|||||||
case EOF:
|
case EOF:
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\"':
|
case '\"':
|
||||||
CfgError (&CfgErrorPos, "Unterminated '%%' escape sequence");
|
PError (&CfgErrorPos, "Unterminated `%%' escape sequence");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
@@ -198,8 +155,8 @@ static void StrVal (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CfgWarning (&CfgErrorPos,
|
PWarning (&CfgErrorPos,
|
||||||
"Unknown escape sequence '%%%c'", C);
|
"Unknown escape sequence `%%%c'", C);
|
||||||
SB_AppendChar (&CfgSVal, '%');
|
SB_AppendChar (&CfgSVal, '%');
|
||||||
SB_AppendChar (&CfgSVal, C);
|
SB_AppendChar (&CfgSVal, C);
|
||||||
NextChar ();
|
NextChar ();
|
||||||
@@ -255,7 +212,7 @@ Again:
|
|||||||
if (C == '$') {
|
if (C == '$') {
|
||||||
NextChar ();
|
NextChar ();
|
||||||
if (!isxdigit (C)) {
|
if (!isxdigit (C)) {
|
||||||
CfgError (&CfgErrorPos, "Hex digit expected");
|
PError (&CfgErrorPos, "Hex digit expected");
|
||||||
}
|
}
|
||||||
CfgIVal = 0;
|
CfgIVal = 0;
|
||||||
while (isxdigit (C)) {
|
while (isxdigit (C)) {
|
||||||
@@ -383,7 +340,7 @@ Again:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CfgError (&CfgErrorPos, "Invalid format specification");
|
PError (&CfgErrorPos, "Invalid format specification");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -392,7 +349,7 @@ Again:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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 */
|
/* Skip a token, print an error message if not found */
|
||||||
{
|
{
|
||||||
if (CfgTok != T) {
|
if (CfgTok != T) {
|
||||||
CfgError (&CfgErrorPos, "%s", Msg);
|
PError (&CfgErrorPos, "%s", Msg);
|
||||||
}
|
}
|
||||||
CfgNextTok ();
|
CfgNextTok ();
|
||||||
}
|
}
|
||||||
@@ -413,7 +370,7 @@ void CfgConsume (cfgtok_t T, const char* Msg)
|
|||||||
void CfgConsumeSemi (void)
|
void CfgConsumeSemi (void)
|
||||||
/* Consume a semicolon */
|
/* Consume a semicolon */
|
||||||
{
|
{
|
||||||
CfgConsume (CFGTOK_SEMI, "';' expected");
|
CfgConsume (CFGTOK_SEMI, "`;' expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -421,7 +378,7 @@ void CfgConsumeSemi (void)
|
|||||||
void CfgConsumeColon (void)
|
void CfgConsumeColon (void)
|
||||||
/* Consume a colon */
|
/* 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 */
|
/* Make sure the next token is an integer */
|
||||||
{
|
{
|
||||||
if (CfgTok != CFGTOK_INTCON) {
|
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 */
|
/* Make sure the next token is a string constant */
|
||||||
{
|
{
|
||||||
if (CfgTok != CFGTOK_STRCON) {
|
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 */
|
/* Make sure the next token is an identifier */
|
||||||
{
|
{
|
||||||
if (CfgTok != CFGTOK_IDENT) {
|
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 */
|
/* Check the range of CfgIVal */
|
||||||
{
|
{
|
||||||
if (CfgIVal < Lo || CfgIVal > Hi) {
|
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)
|
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 */
|
||||||
{
|
{
|
||||||
@@ -504,13 +483,22 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not found */
|
/* Not found. Add a helpful note about the possible names only if
|
||||||
CfgError (&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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No identifier */
|
/* No identifier */
|
||||||
CfgError (&CfgErrorPos, "%s expected", Name);
|
PError (&CfgErrorPos, "%s expected", Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -531,7 +519,7 @@ void CfgBoolToken (void)
|
|||||||
} else {
|
} else {
|
||||||
/* We expected an integer here */
|
/* We expected an integer here */
|
||||||
if (CfgTok != CFGTOK_INTCON) {
|
if (CfgTok != CFGTOK_INTCON) {
|
||||||
CfgError (&CfgErrorPos, "Boolean value expected");
|
PError (&CfgErrorPos, "Boolean value expected");
|
||||||
}
|
}
|
||||||
CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
|
CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
|
||||||
}
|
}
|
||||||
@@ -561,7 +549,7 @@ void CfgOpenInput (void)
|
|||||||
/* Open the file */
|
/* Open the file */
|
||||||
InputFile = fopen (CfgName, "r");
|
InputFile = fopen (CfgName, "r");
|
||||||
if (InputFile == 0) {
|
if (InputFile == 0) {
|
||||||
Error ("Cannot open '%s': %s", CfgName, strerror (errno));
|
Error ("Cannot open `%s': %s", CfgName, strerror (errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize variables */
|
/* Initialize variables */
|
||||||
|
|||||||
@@ -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);
|
void CfgNextTok (void);
|
||||||
/* Read the next token from the input stream */
|
/* Read the next token from the input stream */
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ void PrintDbgScopes (FILE* F)
|
|||||||
case SCOPE_ENUM: fputs (",type=enum", F); break;
|
case SCOPE_ENUM: fputs (",type=enum", F); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Error ("Module '%s': Unknown scope type %u",
|
Error ("Module `%s': Unknown scope type %u",
|
||||||
GetObjFileName (O), S->Type);
|
GetObjFileName (O), S->Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName)
|
|||||||
if (ObjName == 0) {
|
if (ObjName == 0) {
|
||||||
ObjName = "[linker generated]";
|
ObjName = "[linker generated]";
|
||||||
}
|
}
|
||||||
Error ("Module '%s': Type mismatch for segment '%s'", ObjName,
|
Error ("Module `%s': Type mismatch for segment `%s'", ObjName,
|
||||||
GetString (Name));
|
GetString (Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,13 +226,13 @@ Section* ReadSection (FILE* F, ObjData* O)
|
|||||||
if (Sec->Alignment > 1) {
|
if (Sec->Alignment > 1) {
|
||||||
Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment);
|
Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment);
|
||||||
if (Alignment > MAX_ALIGNMENT) {
|
if (Alignment > MAX_ALIGNMENT) {
|
||||||
Error ("Combined alignment for segment '%s' is %lu which exceeds "
|
Error ("Combined alignment for segment `%s' is %lu which exceeds "
|
||||||
"%lu. Last module requiring alignment was '%s'.",
|
"%lu. Last module requiring alignment was `%s'.",
|
||||||
GetString (Name), Alignment, MAX_ALIGNMENT,
|
GetString (Name), Alignment, MAX_ALIGNMENT,
|
||||||
GetObjFileName (O));
|
GetObjFileName (O));
|
||||||
} else if (Alignment >= LARGE_ALIGNMENT && Alignment > S->Alignment && Alignment > Sec->Alignment && !LargeAlignment) {
|
} else if (Alignment >= LARGE_ALIGNMENT && Alignment > S->Alignment && Alignment > Sec->Alignment && !LargeAlignment) {
|
||||||
Warning ("Combined alignment for segment '%s' is suspiciously "
|
Warning ("Combined alignment for segment `%s' is suspiciously "
|
||||||
"large (%lu). Last module requiring alignment was '%s'.",
|
"large (%lu). Last module requiring alignment was `%s'.",
|
||||||
GetString (Name), Alignment, GetObjFileName (O));
|
GetString (Name), Alignment, GetObjFileName (O));
|
||||||
}
|
}
|
||||||
S->Alignment = Alignment;
|
S->Alignment = Alignment;
|
||||||
@@ -270,7 +270,7 @@ Section* ReadSection (FILE* F, ObjData* O)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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);
|
GetObjFileName (O), GetString (S->Name), Type);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return 0;
|
return 0;
|
||||||
@@ -306,9 +306,11 @@ Segment* SegFind (unsigned Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int IsBSSType (Segment* S)
|
Section* GetNonBSSSection (Segment* S)
|
||||||
/* Check if the given segment is a BSS style segment, that is, it does not
|
/* Used when checking a BSS style segment for initialized data. Will walk over
|
||||||
** contain non-zero data.
|
** 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 */
|
/* Loop over all sections */
|
||||||
@@ -326,18 +328,20 @@ int IsBSSType (Segment* S)
|
|||||||
unsigned long Count = F->Size;
|
unsigned long Count = F->Size;
|
||||||
while (Count--) {
|
while (Count--) {
|
||||||
if (*Data++ != 0) {
|
if (*Data++ != 0) {
|
||||||
return 0;
|
return Sec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
|
} else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
|
||||||
if (GetExprVal (F->Expr) != 0) {
|
if (GetExprVal (F->Expr) != 0) {
|
||||||
return 0;
|
return Sec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
F = F->Next;
|
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;
|
break;
|
||||||
|
|
||||||
case SEG_EXPR_RANGE_ERROR:
|
case SEG_EXPR_RANGE_ERROR:
|
||||||
Error ("Range error in module '%s', line %u",
|
Error ("Range error in module `%s', line %u",
|
||||||
GetFragmentSourceName (Frag),
|
GetFragmentSourceName (Frag),
|
||||||
GetFragmentSourceLine (Frag));
|
GetFragmentSourceLine (Frag));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEG_EXPR_TOO_COMPLEX:
|
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),
|
GetFragmentSourceName (Frag),
|
||||||
GetFragmentSourceLine (Frag));
|
GetFragmentSourceLine (Frag));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEG_EXPR_INVALID:
|
case SEG_EXPR_INVALID:
|
||||||
Error ("Invalid expression in module '%s', line %u",
|
Error ("Invalid expression in module `%s', line %u",
|
||||||
GetFragmentSourceName (Frag),
|
GetFragmentSourceName (Frag),
|
||||||
GetFragmentSourceLine (Frag));
|
GetFragmentSourceLine (Frag));
|
||||||
break;
|
break;
|
||||||
@@ -638,11 +642,9 @@ void PrintDbgSegments (FILE* F)
|
|||||||
fprintf (F, ",oname=\"%s\",ooffs=%lu",
|
fprintf (F, ",oname=\"%s\",ooffs=%lu",
|
||||||
S->OutputName, S->OutputOffs);
|
S->OutputName, S->OutputOffs);
|
||||||
}
|
}
|
||||||
if (S->MemArea) {
|
if (S->MemArea && S->MemArea->BankExpr) {
|
||||||
if (S->MemArea->BankExpr) {
|
if (IsConstExpr (S->MemArea->BankExpr)) {
|
||||||
if (IsConstExpr (S->MemArea->BankExpr)) {
|
fprintf (F, ",bank=%lu", GetExprVal (S->MemArea->BankExpr));
|
||||||
fprintf (F, ",bank=%lu", GetExprVal(S->MemArea->BankExpr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fputc ('\n', F);
|
fputc ('\n', F);
|
||||||
@@ -664,7 +666,7 @@ void CheckSegments (void)
|
|||||||
|
|
||||||
/* Check it */
|
/* Check it */
|
||||||
if (S->Size > 0 && S->Dumped == 0) {
|
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));
|
GetString (S->Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,9 +131,11 @@ Section* ReadSection (FILE* F, struct ObjData* O);
|
|||||||
Segment* SegFind (unsigned Name);
|
Segment* SegFind (unsigned Name);
|
||||||
/* Return the given segment or NULL if not found. */
|
/* Return the given segment or NULL if not found. */
|
||||||
|
|
||||||
int IsBSSType (Segment* S);
|
Section* GetNonBSSSection (Segment* S);
|
||||||
/* Check if the given segment is a BSS style segment, that is, it does not
|
/* Used when checking a BSS style segment for initialized data. Will walk over
|
||||||
** contain non-zero data.
|
** 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);
|
void SegDump (void);
|
||||||
|
|||||||
@@ -120,7 +120,9 @@ void XexSetRunAd (XexDesc* D, Import *RunAd)
|
|||||||
D->RunAd = RunAd;
|
D->RunAd = RunAd;
|
||||||
}
|
}
|
||||||
|
|
||||||
XexInitAd* XexSearchInitMem(XexDesc* D, MemoryArea *InitMem)
|
|
||||||
|
|
||||||
|
XexInitAd* XexSearchInitMem (XexDesc* D, MemoryArea *InitMem)
|
||||||
{
|
{
|
||||||
XexInitAd* I;
|
XexInitAd* I;
|
||||||
for (I=D->InitAds; I != 0; I=I->next)
|
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)
|
int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd)
|
||||||
/* Sets and INITAD for the given memory area */
|
/* Sets and INITAD for the given memory area */
|
||||||
{
|
{
|
||||||
@@ -149,6 +152,8 @@ int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size,
|
static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
unsigned long Offs attribute ((unused)),
|
unsigned long Offs attribute ((unused)),
|
||||||
void* Data)
|
void* Data)
|
||||||
@@ -287,7 +292,7 @@ static unsigned long XexWriteMem (XexDesc* D, MemoryArea* M)
|
|||||||
if (DoWrite || (M->Flags & MF_FILL) != 0) {
|
if (DoWrite || (M->Flags & MF_FILL) != 0) {
|
||||||
/* "overwrite" segments are not supported */
|
/* "overwrite" segments are not supported */
|
||||||
if (S->Flags & SF_OVERWRITE) {
|
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));
|
GetString (S->Name));
|
||||||
} else {
|
} else {
|
||||||
XexStartSegment (D, Addr, NewAddr - Addr);
|
XexStartSegment (D, Addr, NewAddr - Addr);
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ define CPUDETECT_template
|
|||||||
|
|
||||||
$(WORKDIR)/$1-cpudetect.bin: cpudetect.s $1-cpudetect.ref $(ISEQUAL)
|
$(WORKDIR)/$1-cpudetect.bin: cpudetect.s $1-cpudetect.ref $(ISEQUAL)
|
||||||
$(if $(QUIET),echo asm/$1-cpudetect.bin)
|
$(if $(QUIET),echo asm/$1-cpudetect.bin)
|
||||||
$(CA65) -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$< $(CATERR)
|
$(CA65) --no-utf8 -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$< $(CATERR)
|
||||||
$(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib $(CATERR)
|
$(LD65) --no-utf8 -t none -o $$@ $$(@:.bin=.o) none.lib $(CATERR)
|
||||||
$(ISEQUAL) $1-cpudetect.ref $$@
|
$(ISEQUAL) $1-cpudetect.ref $$@
|
||||||
|
|
||||||
endef # CPUDETECT_template
|
endef # CPUDETECT_template
|
||||||
@@ -70,7 +70,7 @@ endef # CPUDETECT_template
|
|||||||
$(foreach cpu,$(CPUDETECT_CPUS),$(eval $(call CPUDETECT_template,$(cpu))))
|
$(foreach cpu,$(CPUDETECT_CPUS),$(eval $(call CPUDETECT_template,$(cpu))))
|
||||||
|
|
||||||
$(WORKDIR)/%.o: %.s | $(WORKDIR)
|
$(WORKDIR)/%.o: %.s | $(WORKDIR)
|
||||||
$(CA65) -l $(@:.o=.lst) -o $@ $< $(NULLOUT) $(CATERR)
|
$(CA65) --no-utf8 -l $(@:.o=.lst) -o $@ $< $(NULLOUT) $(CATERR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(call RMDIR,$(WORKDIR))
|
@$(call RMDIR,$(WORKDIR))
|
||||||
|
|||||||
11
test/asm/listing/170-ld-errormsg.cfg
Normal file
11
test/asm/listing/170-ld-errormsg.cfg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
MEMORY {
|
||||||
|
ZP: file = "", start = $80, size = $001F;
|
||||||
|
MAIN: file = %O, start = %S, size = $1000;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp;
|
||||||
|
CODE: load = MAIN, type = rw;
|
||||||
|
RODATA: load = MAIN, type = rw;
|
||||||
|
DATA: load = MAIN, type = rw;
|
||||||
|
BSS: load = MAIN, type = bss;
|
||||||
|
}
|
||||||
6
test/asm/listing/170-ld-errormsg.s
Normal file
6
test/asm/listing/170-ld-errormsg.s
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
.code
|
||||||
|
.byte 5
|
||||||
|
.bss
|
||||||
|
.byte 3
|
||||||
|
|
||||||
11
test/asm/listing/171-ld-errormsg.cfg
Normal file
11
test/asm/listing/171-ld-errormsg.cfg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
MEMORY {
|
||||||
|
ZP: file = "", start = $80, size = $001F;
|
||||||
|
MAIN: file = %O, start = %S, size = $100;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp;
|
||||||
|
CODE: load = MAIN, type = rw;
|
||||||
|
RODATA: load = MAIN, type = rw;
|
||||||
|
DATA: load = MAIN, type = rw;
|
||||||
|
BSS: load = MAIN, type = bss;
|
||||||
|
}
|
||||||
4
test/asm/listing/171-ld-errormsg.s
Normal file
4
test/asm/listing/171-ld-errormsg.s
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.code
|
||||||
|
.res 256, 3
|
||||||
|
.byte $FF
|
||||||
6
test/asm/listing/172-ld-errormsg.cfg
Normal file
6
test/asm/listing/172-ld-errormsg.cfg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
MEMORY {
|
||||||
|
MAIN: file = %O, start = %S, size = $1000;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
CODE: load = MAIN, type = rwx;
|
||||||
|
}
|
||||||
4
test/asm/listing/172-ld-errormsg.s
Normal file
4
test/asm/listing/172-ld-errormsg.s
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.bss
|
||||||
|
.byte 3
|
||||||
|
|
||||||
@@ -73,21 +73,21 @@ $(WORKDIR)/$1.bin: $1.s $(ISEQUAL)
|
|||||||
|
|
||||||
# compile without generating listing
|
# compile without generating listing
|
||||||
ifeq ($(wildcard control/$1.err),)
|
ifeq ($(wildcard control/$1.err),)
|
||||||
$(CA65) -t none --no-utf8 -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2)
|
$(CA65) --no-utf8 -t none --no-utf8 -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2)
|
||||||
ifeq ($(wildcard control/$1.no-ld65),)
|
ifeq ($(wildcard control/$1.no-ld65),)
|
||||||
ifeq ($(wildcard $1.cfg),)
|
ifeq ($(wildcard $1.cfg),)
|
||||||
$(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2)
|
$(LD65) --no-utf8 -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2)
|
||||||
else
|
else
|
||||||
$(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2)
|
$(LD65) --no-utf8 -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
$(CA65) -t none --no-utf8 -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2) || $(TRUE)
|
$(CA65) --no-utf8 -t none --no-utf8 -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2) || $(TRUE)
|
||||||
ifeq ($(wildcard control/$1.no-ld65),)
|
ifeq ($(wildcard control/$1.no-ld65),)
|
||||||
ifeq ($(wildcard $1.cfg),)
|
ifeq ($(wildcard $1.cfg),)
|
||||||
$(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE)
|
$(LD65) --no-utf8 -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE)
|
||||||
else
|
else
|
||||||
$(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE)
|
$(LD65) --no-utf8 -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@@ -144,21 +144,21 @@ endif
|
|||||||
|
|
||||||
# compile with listing file
|
# compile with listing file
|
||||||
ifeq ($(wildcard control/$1.err),)
|
ifeq ($(wildcard control/$1.err),)
|
||||||
$(CA65) -t none --no-utf8 -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2)
|
$(CA65) --no-utf8 -t none --no-utf8 -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2)
|
||||||
ifeq ($(wildcard control/$1.no-ld65),)
|
ifeq ($(wildcard control/$1.no-ld65),)
|
||||||
ifeq ($(wildcard $1.cfg),)
|
ifeq ($(wildcard $1.cfg),)
|
||||||
$(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2)
|
$(LD65) --no-utf8 -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2)
|
||||||
else
|
else
|
||||||
$(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2)
|
$(LD65) --no-utf8 -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
$(CA65) -t none --no-utf8 -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2) || $(TRUE)
|
$(CA65) --no-utf8 -t none --no-utf8 -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2) || $(TRUE)
|
||||||
ifeq ($(wildcard control/$1.no-ld65),)
|
ifeq ($(wildcard control/$1.no-ld65),)
|
||||||
ifeq ($(wildcard $1.cfg),)
|
ifeq ($(wildcard $1.cfg),)
|
||||||
$(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE)
|
$(LD65) --no-utf8 -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE)
|
||||||
else
|
else
|
||||||
$(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE)
|
$(LD65) --no-utf8 -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@@ -212,7 +212,7 @@ $(foreach listing,$(LISTING_TESTS),$(eval $(call LISTING_template,$(listing))))
|
|||||||
|
|
||||||
|
|
||||||
$(WORKDIR)/%.o: %.s | $(WORKDIR)
|
$(WORKDIR)/%.o: %.s | $(WORKDIR)
|
||||||
$(CA65) -l $(@:.o=.lst) -o $@ $<
|
$(CA65) --no-utf8 -l $(@:.o=.lst) -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(call RMDIR,$(WORKDIR))
|
@$(call RMDIR,$(WORKDIR))
|
||||||
|
|||||||
0
test/asm/listing/control/171-ld-errormsg.err
Normal file
0
test/asm/listing/control/171-ld-errormsg.err
Normal file
0
test/asm/listing/control/172-ld-errormsg.err
Normal file
0
test/asm/listing/control/172-ld-errormsg.err
Normal file
@@ -1,40 +1,40 @@
|
|||||||
ld65: Warning: 030-assert-success.s:3: Code not at $0000
|
030-assert-success.s:3: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:4: Code not at $0000
|
030-assert-success.s:4: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:6: Code not at $0001
|
030-assert-success.s:6: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:7: Code not at $0001
|
030-assert-success.s:7: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:12: Code not at $1001
|
030-assert-success.s:12: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 030-assert-success.s:13: Code not at $1001
|
030-assert-success.s:13: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 030-assert-success.s:15: Code not at $8000
|
030-assert-success.s:15: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 030-assert-success.s:16: Code not at $8000
|
030-assert-success.s:16: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 030-assert-success.s:18: Code not at $8001
|
030-assert-success.s:18: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 030-assert-success.s:19: Code not at $8001
|
030-assert-success.s:19: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 030-assert-success.s:23: Code not at $0000
|
030-assert-success.s:23: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:24: Code not at $0000
|
030-assert-success.s:24: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:26: Code not at $0001
|
030-assert-success.s:26: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:27: Code not at $0001
|
030-assert-success.s:27: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:29: Code not at $1000
|
030-assert-success.s:29: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 030-assert-success.s:30: Code not at $1000
|
030-assert-success.s:30: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 030-assert-success.s:35: Code not at $8000
|
030-assert-success.s:35: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 030-assert-success.s:36: Code not at $8000
|
030-assert-success.s:36: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 030-assert-success.s:38: Code not at $8001
|
030-assert-success.s:38: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 030-assert-success.s:39: Code not at $8001
|
030-assert-success.s:39: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 030-assert-success.s:45: Code not at $0000
|
030-assert-success.s:45: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:46: Code not at $0000
|
030-assert-success.s:46: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:48: Code not at $0001
|
030-assert-success.s:48: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:49: Code not at $0001
|
030-assert-success.s:49: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:51: Code not at $1000
|
030-assert-success.s:51: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 030-assert-success.s:52: Code not at $1000
|
030-assert-success.s:52: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 030-assert-success.s:54: Code not at $1001
|
030-assert-success.s:54: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 030-assert-success.s:55: Code not at $1001
|
030-assert-success.s:55: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 030-assert-success.s:60: Code not at $8001
|
030-assert-success.s:60: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 030-assert-success.s:61: Code not at $8001
|
030-assert-success.s:61: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 030-assert-success.s:65: Code not at $0000
|
030-assert-success.s:65: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:66: Code not at $0000
|
030-assert-success.s:66: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 030-assert-success.s:68: Code not at $0001
|
030-assert-success.s:68: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:69: Code not at $0001
|
030-assert-success.s:69: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 030-assert-success.s:71: Code not at $1000
|
030-assert-success.s:71: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 030-assert-success.s:72: Code not at $1000
|
030-assert-success.s:72: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 030-assert-success.s:74: Code not at $1001
|
030-assert-success.s:74: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 030-assert-success.s:75: Code not at $1001
|
030-assert-success.s:75: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 030-assert-success.s:77: Code not at $8000
|
030-assert-success.s:77: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 030-assert-success.s:78: Code not at $8000
|
030-assert-success.s:78: Warning: Assertion failed: Code not at $8000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 032-assert-error2.s:3: Code not at $0000
|
032-assert-error2.s:3: Error: Assertion failed: Code not at $0000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 032-assert-error3.s:3: Code not at $0000
|
032-assert-error3.s:3: Error: Assertion failed: Code not at $0000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 032-assert-error4.s:3: Code not at $0001
|
032-assert-error4.s:3: Error: Assertion failed: Code not at $0001
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 032-assert-error6.s:3: Code not at $1001
|
032-assert-error6.s:3: Error: Assertion failed: Code not at $1001
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 032-assert-error7.s:3: Code not at $8000
|
032-assert-error7.s:3: Error: Assertion failed: Code not at $8000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 032-assert-error8.s:3: Code not at $8001
|
032-assert-error8.s:3: Error: Assertion failed: Code not at $8001
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
ld65: Warning: 033-assert-ldwarning-success.s:3: Code not at $0000
|
033-assert-ldwarning-success.s:3: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:4: Code not at $0000
|
033-assert-ldwarning-success.s:4: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:6: Code not at $0001
|
033-assert-ldwarning-success.s:6: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:7: Code not at $0001
|
033-assert-ldwarning-success.s:7: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:12: Code not at $1001
|
033-assert-ldwarning-success.s:12: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:13: Code not at $1001
|
033-assert-ldwarning-success.s:13: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:15: Code not at $8000
|
033-assert-ldwarning-success.s:15: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:16: Code not at $8000
|
033-assert-ldwarning-success.s:16: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:18: Code not at $8001
|
033-assert-ldwarning-success.s:18: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:19: Code not at $8001
|
033-assert-ldwarning-success.s:19: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:23: Code not at $0000
|
033-assert-ldwarning-success.s:23: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:24: Code not at $0000
|
033-assert-ldwarning-success.s:24: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:26: Code not at $0001
|
033-assert-ldwarning-success.s:26: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:27: Code not at $0001
|
033-assert-ldwarning-success.s:27: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:29: Code not at $1000
|
033-assert-ldwarning-success.s:29: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:30: Code not at $1000
|
033-assert-ldwarning-success.s:30: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:35: Code not at $8000
|
033-assert-ldwarning-success.s:35: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:36: Code not at $8000
|
033-assert-ldwarning-success.s:36: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:38: Code not at $8001
|
033-assert-ldwarning-success.s:38: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:39: Code not at $8001
|
033-assert-ldwarning-success.s:39: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:45: Code not at $0000
|
033-assert-ldwarning-success.s:45: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:46: Code not at $0000
|
033-assert-ldwarning-success.s:46: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:48: Code not at $0001
|
033-assert-ldwarning-success.s:48: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:49: Code not at $0001
|
033-assert-ldwarning-success.s:49: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:51: Code not at $1000
|
033-assert-ldwarning-success.s:51: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:52: Code not at $1000
|
033-assert-ldwarning-success.s:52: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:54: Code not at $1001
|
033-assert-ldwarning-success.s:54: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:55: Code not at $1001
|
033-assert-ldwarning-success.s:55: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:60: Code not at $8001
|
033-assert-ldwarning-success.s:60: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:61: Code not at $8001
|
033-assert-ldwarning-success.s:61: Warning: Assertion failed: Code not at $8001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:65: Code not at $0000
|
033-assert-ldwarning-success.s:65: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:66: Code not at $0000
|
033-assert-ldwarning-success.s:66: Warning: Assertion failed: Code not at $0000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:68: Code not at $0001
|
033-assert-ldwarning-success.s:68: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:69: Code not at $0001
|
033-assert-ldwarning-success.s:69: Warning: Assertion failed: Code not at $0001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:71: Code not at $1000
|
033-assert-ldwarning-success.s:71: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:72: Code not at $1000
|
033-assert-ldwarning-success.s:72: Warning: Assertion failed: Code not at $1000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:74: Code not at $1001
|
033-assert-ldwarning-success.s:74: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:75: Code not at $1001
|
033-assert-ldwarning-success.s:75: Warning: Assertion failed: Code not at $1001
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:77: Code not at $8000
|
033-assert-ldwarning-success.s:77: Warning: Assertion failed: Code not at $8000
|
||||||
ld65: Warning: 033-assert-ldwarning-success.s:78: Code not at $8000
|
033-assert-ldwarning-success.s:78: Warning: Assertion failed: Code not at $8000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 034-assert-lderror2.s:3: Code not at $0000
|
034-assert-lderror2.s:3: Error: Assertion failed: Code not at $0000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 034-assert-lderror3.s:3: Code not at $0000
|
034-assert-lderror3.s:3: Error: Assertion failed: Code not at $0000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 034-assert-lderror4.s:3: Code not at $0001
|
034-assert-lderror4.s:3: Error: Assertion failed: Code not at $0001
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 034-assert-lderror6.s:3: Code not at $1001
|
034-assert-lderror6.s:3: Error: Assertion failed: Code not at $1001
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 034-assert-lderror7.s:3: Code not at $8000
|
034-assert-lderror7.s:3: Error: Assertion failed: Code not at $8000
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Error: 034-assert-lderror8.s:3: Code not at $8001
|
034-assert-lderror8.s:3: Error: Assertion failed: Code not at $8001
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Warning: <<<#PATH#>>>:<<<#INTEGER#>>>: Segment 'CODE' isn't aligned properly; the resulting executable might not be functional.
|
<<<#PATH#>>>:<<<#INTEGER#>>>: Warning: Segment 'CODE' isn't aligned properly; the resulting executable might not be functional.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ld65: Warning: runtime/sp-compat.s:16: Symbol 'sp' is deprecated - please use 'c_sp' instead
|
runtime/sp-compat.s:16: Warning: Assertion failed: Symbol 'sp' is deprecated - please use 'c_sp' instead
|
||||||
|
|||||||
1
test/asm/listing/ref/170-ld-errormsg.bin-ref
Normal file
1
test/asm/listing/ref/170-ld-errormsg.bin-ref
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
2
test/asm/listing/ref/170-ld-errormsg.ld65err2-ref
Normal file
2
test/asm/listing/ref/170-ld-errormsg.ld65err2-ref
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
170-ld-errormsg.cfg:10: Warning: Segment 'BSS' with type 'bss' contains initialized data
|
||||||
|
170-ld-errormsg.cfg:10: Note: Initialized data comes at least partially from '<<<#PATH#>>>'
|
||||||
2
test/asm/listing/ref/171-ld-errormsg.ld65err2-ref
Normal file
2
test/asm/listing/ref/171-ld-errormsg.ld65err2-ref
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
171-ld-errormsg.cfg:3: Warning: Segment 'CODE' overflows memory area 'MAIN' by 1 byte
|
||||||
|
ld65: Error: Cannot generate most of the files due to memory area overflow
|
||||||
2
test/asm/listing/ref/172-ld-errormsg.ld65err2-ref
Normal file
2
test/asm/listing/ref/172-ld-errormsg.ld65err2-ref
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
172-ld-errormsg.cfg:5: Error: Segment type expected but got 'RWX'
|
||||||
|
172-ld-errormsg.cfg:5: Note: You may use one of 'RO', 'RW', 'BSS', 'ZP' or 'OVERWRITE'
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
ld65: Warning: 201-overwrite-overflow.cfg:3: Segment 'AO' overflows memory area 'A' by 1 byte
|
201-overwrite-overflow.cfg:3: Warning: Segment 'AO' overflows memory area 'A' by 1 byte
|
||||||
ld65: Warning: 201-overwrite-overflow.cfg:4: Segment 'BO' overflows memory area 'B' by 1 byte
|
201-overwrite-overflow.cfg:4: Warning: Segment 'BO' overflows memory area 'B' by 1 byte
|
||||||
ld65: Error: Cannot generate most of the files due to memory area overflows
|
ld65: Error: Cannot generate most of the files due to memory area overflows
|
||||||
|
|||||||
@@ -63,15 +63,15 @@ define PRG_template
|
|||||||
# sim65 ensure 64-bit wait time does not timeout
|
# sim65 ensure 64-bit wait time does not timeout
|
||||||
$(WORKDIR)/sim65-timein.$1.prg: sim65-timein.s | $(WORKDIR)
|
$(WORKDIR)/sim65-timein.$1.prg: sim65-timein.s | $(WORKDIR)
|
||||||
$(if $(QUIET),echo misc/sim65-timein.$1.prg)
|
$(if $(QUIET),echo misc/sim65-timein.$1.prg)
|
||||||
$(CA65) -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
|
$(CA65) --no-utf8 -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
|
||||||
$(LD65) -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
|
$(LD65) --no-utf8 -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
|
||||||
$(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR)
|
$(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR)
|
||||||
|
|
||||||
# sim65 ensure 64-bit wait time does timeout
|
# sim65 ensure 64-bit wait time does timeout
|
||||||
$(WORKDIR)/sim65-timeout.$1.prg: sim65-timeout.s | $(WORKDIR)
|
$(WORKDIR)/sim65-timeout.$1.prg: sim65-timeout.s | $(WORKDIR)
|
||||||
$(if $(QUIET),echo misc/sim65-timeout.$1.prg)
|
$(if $(QUIET),echo misc/sim65-timeout.$1.prg)
|
||||||
$(CA65) -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
|
$(CA65) --no-utf8 -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
|
||||||
$(LD65) -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
|
$(LD65) --no-utf8 -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
|
||||||
$(NOT) $(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR)
|
$(NOT) $(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR)
|
||||||
|
|
||||||
endef # PRG_template
|
endef # PRG_template
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ define OPCODE_template
|
|||||||
|
|
||||||
$(WORKDIR)/$1-opcodes.bin: $1-opcodes.s $(ISEQUAL)
|
$(WORKDIR)/$1-opcodes.bin: $1-opcodes.s $(ISEQUAL)
|
||||||
$(if $(QUIET),echo asm/$1-opcodes.bin)
|
$(if $(QUIET),echo asm/$1-opcodes.bin)
|
||||||
$(CA65) -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$<
|
$(CA65) --no-utf8 -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$<
|
||||||
$(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib
|
$(LD65) --no-utf8 -t none -o $$@ $$(@:.bin=.o) none.lib
|
||||||
$(ISEQUAL) $1-opcodes.ref $$@
|
$(ISEQUAL) $1-opcodes.ref $$@
|
||||||
|
|
||||||
endef # OPCODE_template
|
endef # OPCODE_template
|
||||||
@@ -70,7 +70,7 @@ endef # OPCODE_template
|
|||||||
$(foreach cpu,$(OPCODE_CPUS),$(eval $(call OPCODE_template,$(cpu))))
|
$(foreach cpu,$(OPCODE_CPUS),$(eval $(call OPCODE_template,$(cpu))))
|
||||||
|
|
||||||
$(WORKDIR)/%.o: %.s | $(WORKDIR)
|
$(WORKDIR)/%.o: %.s | $(WORKDIR)
|
||||||
$(CA65) -l $(@:.o=.lst) -o $@ $<
|
$(CA65) --no-utf8 -l $(@:.o=.lst) -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(call RMDIR,$(WORKDIR))
|
@$(call RMDIR,$(WORKDIR))
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ define PRG_template
|
|||||||
|
|
||||||
$(WORKDIR)/%.$1.prg: %.s | $(WORKDIR)
|
$(WORKDIR)/%.$1.prg: %.s | $(WORKDIR)
|
||||||
$(if $(QUIET),echo asm/val/$$*.$1.prg)
|
$(if $(QUIET),echo asm/val/$$*.$1.prg)
|
||||||
$(CA65) -t sim$1 -o $$(@:.prg=.o) $$< $(NULLOUT) $(NULLERR)
|
$(CA65) --no-utf8 -t sim$1 -o $$(@:.prg=.o) $$< $(NULLOUT) $(NULLERR)
|
||||||
$(LD65) -C sim6502-asmtest.cfg -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLOUT) $(NULLERR)
|
$(LD65) --no-utf8 -C sim6502-asmtest.cfg -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLOUT) $(NULLERR)
|
||||||
$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT)
|
$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT)
|
||||||
|
|
||||||
endef # PRG_template
|
endef # PRG_template
|
||||||
|
|||||||
Reference in New Issue
Block a user