Merge branch 'master' into fix-pr-2778

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

View File

@@ -33,7 +33,8 @@ function checkarray_quoted_name
}
find "$CHECK_DIR" -name \*.\[ch\] -print | while read N; do
FILES=$(find "$CHECK_DIR" -name \*.\[ch\] -print)
for N in $FILES; do
grep -q "BEGIN SORTED.SH" "$N" && checkarray_quoted_name "$N"
done
exit 0

View File

@@ -63,7 +63,8 @@ function checkarray
}
find "$CHECK_DIR" -name \*.\[ch\] -print | while read N; do
FILES=$(find "$CHECK_DIR" -name \*.\[ch\] -print)
for N in $FILES; do
grep -q "BEGIN DECL SORTED_CODEOPT.SH" "$N" && checkarray "$N"
done
exit 0

View File

@@ -34,7 +34,8 @@ function checkarray_quoted_name
rm -rf .a.tmp
}
find "$CHECK_DIR" -name \*.\[ch\] -print | while read N; do
FILES=$(find "$CHECK_DIR" -name \*.\[ch\] -print)
for N in $FILES; do
grep -q "BEGIN SORTED_OPCODES.SH" "$N" && checkarray_quoted_name "$N"
done
exit 0

View File

@@ -39,7 +39,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro, optional = yes;
STARTUP: load = ROMS, type = ro, define = yes;
ONCE: load = ROMS, type = ro, define = yes;

View File

@@ -23,7 +23,7 @@ FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = INIT;
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,

View File

@@ -208,6 +208,16 @@ Here is a description of all the command line options:
mortals:-)
<label id="option-D">
<tag><tt>-D</tt></tag>
This option allows you to define symbols on the command line. Without a
value, the symbol is defined with the value zero. When giving a value,
you may use the '&dollar;' prefix for hexadecimal symbols. Please note
that for some operating systems, '&dollar;' has a special meaning, so
you may have to quote the expression.
<label id="option--feature">
<tag><tt>--feature name</tt></tag>
@@ -237,6 +247,16 @@ Here is a description of all the command line options:
Print the short option summary shown above.
<label id="option-I">
<tag><tt>-I dir, --include-dir dir</tt></tag>
Name a directory which is searched for include files. The option may be
used more than once to specify more than one directory to search. The
current directory is always searched first before considering any
additional directories. See also the section about <ref id="search-paths"
name="search paths">.
<label id="option-i">
<tag><tt>-i, --ignore-case</tt></tag>
@@ -316,6 +336,12 @@ Here is a description of all the command line options:
</itemize>
<label id="option-S">
<tag><tt>-S, --segment-list</tt></tag>
Add the segment ID in front of each address in the listing file.
<label id="option-s">
<tag><tt>-s, --smart-mode</tt></tag>
@@ -345,34 +371,6 @@ Here is a description of all the command line options:
overridden by using the <tt/<ref id="option--cpu" name="--cpu">/ option.
<label id="option-v">
<tag><tt>-v, --verbose</tt></tag>
Increase the assembler verbosity. Usually only needed for debugging
purposes. You may use this option more than one time for even more
verbose output.
<label id="option-D">
<tag><tt>-D</tt></tag>
This option allows you to define symbols on the command line. Without a
value, the symbol is defined with the value zero. When giving a value,
you may use the '&dollar;' prefix for hexadecimal symbols. Please note
that for some operating systems, '&dollar;' has a special meaning, so
you may have to quote the expression.
<label id="option-I">
<tag><tt>-I dir, --include-dir dir</tt></tag>
Name a directory which is searched for include files. The option may be
used more than once to specify more than one directory to search. The
current directory is always searched first before considering any
additional directories. See also the section about <ref id="search-paths"
name="search paths">.
<label id="option-U">
<tag><tt>-U, --auto-import</tt></tag>
@@ -385,6 +383,14 @@ Here is a description of all the command line options:
which is not always true for assembler programmers.
<label id="option-v">
<tag><tt>-v, --verbose</tt></tag>
Increase the assembler verbosity. Usually only needed for debugging
purposes. You may use this option more than one time for even more
verbose output.
<label id="option-V">
<tag><tt>-V, --version</tt></tag>
@@ -407,6 +413,12 @@ Here is a description of all the command line options:
An error will be generated if any warnings were produced.
<label id="option-x">
<tag><tt>-x, --expand-macros</tt></tag>
In the listing file, show exactly how macros were expanded. Use twice for
more verbose output.
</descrip>
<p>

View File

@@ -110,6 +110,7 @@ Long options:
--target sys Set the target system
--verbose Increase verbosity
--version Print the compiler version number
--warnings-as-errors Treat warnings as errors
--writable-strings Make string literals writable
---------------------------------------------------------------------------
</verb></tscreen>
@@ -514,6 +515,28 @@ Here is a description of all the command line options:
name="#pragma&nbsp;local-strings"></tt> for fine grained control.
<tag><tt>-mm model, --memory-model model</tt></tag>
This option sets the code and data models for the compiler to use. Please
note that memory models are an unfinished feature and using this option
with any other memory model than <tt/near/ will cause compile errors.
Possible arguments are:
<descrip>
<tag/near/
This memory model uses 16 bit addresses for code and data. It is
currently the only supported memory model and suited for the 6502.
<tag/far/
This memory model uses 24 bit addresses for code and 16 bit addresses
for data. It is suited for the 65816 but currently unsupported.
<tag/huge/
This memory model uses 24 bit addresses for code and data. It is
suited for the 65816 but currently unsupported.
</descrip>
<tag><tt>-o name</tt></tag>
Specify the name of the output file. If you don't specify a name, the
@@ -656,6 +679,15 @@ Here is a description of all the command line options:
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">
<tag><tt>--writable-strings</tt></tag>
@@ -766,7 +798,9 @@ Here is a description of all the command line options:
<tag><tt/const-comparison/</tag>
Warn if the result of a comparison is constant.
<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>
Warn about statements that don't have an effect.
<tag><tt/pointer-sign/</tag>

View File

@@ -34,7 +34,7 @@ and other things.
---------------------------------------------------------------------------
Usage: cl65 [options] file [...]
Short options:
-c Compile and assemble but don't link
-c Compile and assemble, but don't link
-d Debug mode
-g Add debug info
-h Help (this text)
@@ -55,10 +55,10 @@ Short options:
-L path Specify a library search path
-Ln name Create a VICE label file
-O Optimize code
-Oi Optimize code, inline more code
-Oi Optimize code, inline runtime functions
-Or Optimize code, honour the register keyword
-Os Optimize code, inline standard functions
-S Compile but don't assemble and link
-Os Optimize code, inline known C functions
-S Compile, but don't assemble and link
-T Include source as comment
-V Print the version number
-W name[,...] Suppress compiler warnings
@@ -81,8 +81,9 @@ Long options:
--code-label name Define and export a CODE segment label
--code-name seg Set the name of the CODE segment
--codesize x Accept larger code by factor x
--color [on|auto|off] Color diagnostics (default: auto)
--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-full-dep name Create a full make dependency file
--data-label name Define and export a DATA segment label
@@ -101,8 +102,9 @@ Long options:
--mapfile name Create a map file
--memory-model model Set the memory model
--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-utf8 Disable use of UTF-8 in diagnostics
--o65-model model Override the o65 model
--obj file Link this object file
--obj-path path Specify an object file search path

View File

@@ -369,9 +369,14 @@ function.
<sect1><tt/dbg.h/<label id="dbg.h"><p>
<!-- <itemize> -->
<!-- <item><ref id="DbgInit" name="DbgInit"> -->
<!-- </itemize> -->
<itemize>
<item><ref id="DbgInit" name="DbgInit">
<!-- <item><ref id="BREAK" name="BREAK"> -->
<!-- <item><ref id="DbgDisAsm" name="DbgDisAsm"> -->
<!-- <item><ref id="DbgDisAsmLen" name="DbgDisAsmLen"> -->
<!-- <item><ref id="DbgIsRAM" name="DbgIsRAM"> -->
<!-- <item><ref id="DbgMemDump" name="DbgMemDump"> -->
</itemize>
(incomplete)
@@ -3472,6 +3477,24 @@ used in presence of a prototype.
</quote>
<sect1>DbgInit<label id="DbgInit"><p>
<quote>
<descrip>
<tag/Function/Initialize the debugger.
<tag/Header/<tt/<ref id="dbg.h" name="dbg.h">/
<tag/Declaration/<tt/void __fastcall__ DbgInit (unsigned unused);/
<tag/Description/<tt/DbgInit/ initializes the debugger.
<tag/Notes/<itemize>
<item>Use 0 as parameter.
<item>The debugger will popup on next brk encountered.
</itemize>
<tag/Availability/cc65
<tag/Example/None.
</descrip>
</quote>
<sect1>decompress_lz4<label id="decompress_lz4"><p>
<quote>

View File

@@ -73,6 +73,7 @@ Short options:
Long options:
--allow-multiple-definition Allow multiple definitions
--cfg-path path Specify a config file search path
--color [on|auto|off] Color diagnostics (default: auto)
--config name Use linker config file
--dbgfile name Generate debug information
--define sym=val Define a symbol
@@ -84,13 +85,13 @@ Long options:
--lib-path path Specify a library search path
--mapfile name Create a map file
--module-id id Specify a module id
--no-utf8 Disable use of UTF-8 in diagnostics
--obj file Link this object file
--obj-path path Specify an object file search path
--start-addr addr Set the default start address
--start-group Start a library group
--target sys Set the target system
--version Print the linker version
--warnings-as-errors Treat warnings as errors
---------------------------------------------------------------------------
</verb></tscreen>
@@ -292,6 +293,14 @@ Here is a description of all of the command-line options:
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">
<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.
<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>
Links an object file to the output. Use this command-line option instead

View File

@@ -332,7 +332,7 @@ BreakPoint DbgBreaks [MAX_USERBREAKS+2];
BreakPoint* DbgGetBreakSlot (void);
/* Search for a free breakpoint slot. Return a pointer to the slot or 0 */
BreakPoint* DbgIsBreak (unsigned Addr);
BreakPoint* __cdecl__ DbgIsBreak (unsigned Addr);
/* Check if there is a user breakpoint at the given address, if so, return
** a pointer to the slot, else return 0.
*/

View File

@@ -1,7 +1,7 @@
;
; Startup code for cc65 (Oric version)
;
; By Debrune J<EFBFBD>r<EFBFBD>me <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org>
; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org>
;
.export _exit
@@ -36,12 +36,12 @@
; Call the module destructors. This is also the exit() entry.
_exit: jsr donelib
_exit:
; Restore the system stuff.
; Save return code on stack
ldx spsave
txs
pha
jsr donelib
; Copy back the zero-page stuff.
@@ -51,6 +51,16 @@ L2: lda zpsave,x
dex
bpl L2
; Restore the return code.
; The return code is on the stack, so we can just pop it.
; This is the return code from main().
pla
; Restore the system stuff.
ldx spsave
txs
; Back to BASIC.
rts

View File

@@ -40,11 +40,13 @@ ifdef CC65_HOME
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
GRC = $(CC65_HOME)/bin/grc65
else
AS := $(if $(wildcard ../bin/ca65*),../bin/ca65,ca65)
CC := $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65)
CL := $(if $(wildcard ../bin/cl65*),../bin/cl65,cl65)
LD := $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65)
GRC := $(if $(wildcard ../bin/grc65*),../bin/grc65,grc65)
endif
ifeq ($(SILENT),s)
@@ -176,6 +178,7 @@ else
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
endif
# --------------------------------------------------------------------------
# Lists of subdirectories
@@ -193,6 +196,7 @@ EXELIST_agat = \
EXELIST_apple2 = \
ascii \
checkversion \
debug \
diodemo \
enumdevdir \
gunzip65 \
@@ -212,6 +216,7 @@ EXELIST_apple2enh = $(EXELIST_apple2)
EXELIST_atari = \
ascii \
checkversion \
debug \
gunzip65 \
hello \
mandelbrot \
@@ -250,6 +255,7 @@ EXELIST_bbc = \
EXELIST_c64 = \
ascii \
checkversion \
debug \
enumdevdir \
gunzip65 \
hello \
@@ -275,6 +281,7 @@ EXELIST_c65 = \
EXELIST_c128 = \
ascii \
checkversion \
debug \
enumdevdir \
gunzip65 \
hello \
@@ -289,6 +296,7 @@ EXELIST_c128 = \
EXELIST_c16 = \
ascii \
checkversion \
debug \
enumdevdir \
tinyshell \
hello \
@@ -297,6 +305,7 @@ EXELIST_c16 = \
EXELIST_cbm510 = \
ascii \
checkversion \
debug \
enumdevdir \
gunzip65 \
hello \
@@ -309,6 +318,7 @@ EXELIST_cbm510 = \
EXELIST_cbm610 = \
ascii \
checkversion \
debug \
enumdevdir \
gunzip65 \
hello \
@@ -323,6 +333,7 @@ EXELIST_creativision = \
EXELIST_cx16 = \
ascii \
checkversion \
debug \
enumdevdir \
gunzip65 \
hello \
@@ -337,10 +348,10 @@ EXELIST_gamate = \
hello
EXELIST_geos-cbm = \
ascii
ascii.cvt
EXELIST_geos-apple = \
ascii
ascii.cvt
EXELIST_lunix = \
notavailable
@@ -371,6 +382,7 @@ EXELIST_pce = \
EXELIST_pet = \
ascii \
checkversion \
debug \
enumdevdir \
hello \
joydemo \
@@ -380,6 +392,7 @@ EXELIST_pet = \
EXELIST_plus4 = \
ascii \
checkversion \
debug \
enumdevdir \
gunzip65 \
hello \
@@ -421,6 +434,7 @@ EXELIST_telestrat = \
EXELIST_vic20 = \
ascii \
checkversion \
debug \
enumdevdir \
hello \
joydemo \
@@ -554,6 +568,25 @@ tgidemo: tgidemo.o
$(LD) -D __HIMEM__=0x6000 $(LDFLAGS) -o $@ -C vic20-tgi.cfg -m $@.map $^ $(SYS).lib
endif
# --------------------------------------------------------------------------
# GEOS programs need a resource file linked to them
ifeq ($(SYS),geos-cbm)
asciires.o: asciires.grc
$(CL) -c -t $(SYS) $<
ascii.cvt: ascii.o asciires.o
$(if $(QUIET),echo $(SYS):$@)
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
endif
ifeq ($(SYS),geos-apple)
asciires.o: asciires.grc
$(GRC) -t $(SYS) $<
$(AS) $(<:.grc=.s)
ascii.cvt: ascii.o asciires.o
$(if $(QUIET),echo $(SYS):$@)
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
endif
# --------------------------------------------------------------------------
# some programs link against getsp.o

7
samples/asciires.grc Normal file
View File

@@ -0,0 +1,7 @@
; this is the resource file for ascii.c, a GEOS application example
HEADER APPLICATION "ascii" "ascii" "V0.1" {
dostype USR
author "cc65 team"
info "This is a cc65 sample."
}

12
samples/debug.c Normal file
View File

@@ -0,0 +1,12 @@
#include <dbg.h>
int main(void)
{
/* DbgInit has to be called once, to install the BRK handler */
DbgInit(0);
/* now to break into the debugger, use the BREAK macro */
BREAK();
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -61,8 +61,8 @@ define CPUDETECT_template
$(WORKDIR)/$1-cpudetect.bin: cpudetect.s $1-cpudetect.ref $(ISEQUAL)
$(if $(QUIET),echo asm/$1-cpudetect.bin)
$(CA65) -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$< $(CATERR)
$(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib $(CATERR)
$(CA65) --no-utf8 -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$< $(CATERR)
$(LD65) --no-utf8 -t none -o $$@ $$(@:.bin=.o) none.lib $(CATERR)
$(ISEQUAL) $1-cpudetect.ref $$@
endef # CPUDETECT_template
@@ -70,7 +70,7 @@ endef # CPUDETECT_template
$(foreach cpu,$(CPUDETECT_CPUS),$(eval $(call CPUDETECT_template,$(cpu))))
$(WORKDIR)/%.o: %.s | $(WORKDIR)
$(CA65) -l $(@:.o=.lst) -o $@ $< $(NULLOUT) $(CATERR)
$(CA65) --no-utf8 -l $(@:.o=.lst) -o $@ $< $(NULLOUT) $(CATERR)
clean:
@$(call RMDIR,$(WORKDIR))

View File

@@ -1,8 +1,4 @@
; just emit to bss for now, this way the output wont get checked, which is
; fine - we only want to see if the assembler accepts all the opcodes it
; should accept for the current CPU mode
.bss
.code
.if (.cpu .bitand CPU_ISET_6502)
.scope

View 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;
}

View File

@@ -0,0 +1,6 @@
.code
.byte 5
.bss
.byte 3

View 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;
}

View File

@@ -0,0 +1,4 @@
.code
.res 256, 3
.byte $FF

View File

@@ -0,0 +1,6 @@
MEMORY {
MAIN: file = %O, start = %S, size = $1000;
}
SEGMENTS {
CODE: load = MAIN, type = rwx;
}

View File

@@ -0,0 +1,4 @@
.bss
.byte 3

View File

@@ -0,0 +1,28 @@
; #2208 - Current ca65 generates different code for msbasic
.setcpu "6502"
ZP_START2 = $04
INPUTBUFFERX = INPUTBUFFER & $FF00
;------------------------------------------------------------------------------
;.feature org_per_seg
.zeropage
; if not present, both 2.18 and head produce a absolute,x instruction
; if present, 2.18 produces a zp,x instruction - but head uses abs,x!
.org ZP_START2
INPUTBUFFER:
;------------------------------------------------------------------------------
.segment "CODE"
.byte $f0, $f1, $f2, $f3 ; just some data to search for
; BUG: this will wrongly assembly into a 3-byte instruction
; under certain conditions
lda INPUTBUFFERX,x

View File

@@ -73,21 +73,21 @@ $(WORKDIR)/$1.bin: $1.s $(ISEQUAL)
# compile without generating listing
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 $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
$(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
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 $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
$(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
@@ -144,21 +144,21 @@ endif
# compile with listing file
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 $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
$(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
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 $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
$(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
@@ -212,7 +212,7 @@ $(foreach listing,$(LISTING_TESTS),$(eval $(call LISTING_template,$(listing))))
$(WORKDIR)/%.o: %.s | $(WORKDIR)
$(CA65) -l $(@:.o=.lst) -o $@ $<
$(CA65) --no-utf8 -l $(@:.o=.lst) -o $@ $<
clean:
@$(call RMDIR,$(WORKDIR))

View File

@@ -1,40 +1,40 @@
ld65: Warning: 030-assert-success.s:3: Code not at $0000
ld65: Warning: 030-assert-success.s:4: Code not at $0000
ld65: Warning: 030-assert-success.s:6: Code not at $0001
ld65: Warning: 030-assert-success.s:7: Code not at $0001
ld65: Warning: 030-assert-success.s:12: Code not at $1001
ld65: Warning: 030-assert-success.s:13: Code not at $1001
ld65: Warning: 030-assert-success.s:15: Code not at $8000
ld65: Warning: 030-assert-success.s:16: Code not at $8000
ld65: Warning: 030-assert-success.s:18: Code not at $8001
ld65: Warning: 030-assert-success.s:19: Code not at $8001
ld65: Warning: 030-assert-success.s:23: Code not at $0000
ld65: Warning: 030-assert-success.s:24: Code not at $0000
ld65: Warning: 030-assert-success.s:26: Code not at $0001
ld65: Warning: 030-assert-success.s:27: Code not at $0001
ld65: Warning: 030-assert-success.s:29: Code not at $1000
ld65: Warning: 030-assert-success.s:30: Code not at $1000
ld65: Warning: 030-assert-success.s:35: Code not at $8000
ld65: Warning: 030-assert-success.s:36: Code not at $8000
ld65: Warning: 030-assert-success.s:38: Code not at $8001
ld65: Warning: 030-assert-success.s:39: Code not at $8001
ld65: Warning: 030-assert-success.s:45: Code not at $0000
ld65: Warning: 030-assert-success.s:46: Code not at $0000
ld65: Warning: 030-assert-success.s:48: Code not at $0001
ld65: Warning: 030-assert-success.s:49: Code not at $0001
ld65: Warning: 030-assert-success.s:51: Code not at $1000
ld65: Warning: 030-assert-success.s:52: Code not at $1000
ld65: Warning: 030-assert-success.s:54: Code not at $1001
ld65: Warning: 030-assert-success.s:55: Code not at $1001
ld65: Warning: 030-assert-success.s:60: Code not at $8001
ld65: Warning: 030-assert-success.s:61: Code not at $8001
ld65: Warning: 030-assert-success.s:65: Code not at $0000
ld65: Warning: 030-assert-success.s:66: Code not at $0000
ld65: Warning: 030-assert-success.s:68: Code not at $0001
ld65: Warning: 030-assert-success.s:69: Code not at $0001
ld65: Warning: 030-assert-success.s:71: Code not at $1000
ld65: Warning: 030-assert-success.s:72: Code not at $1000
ld65: Warning: 030-assert-success.s:74: Code not at $1001
ld65: Warning: 030-assert-success.s:75: Code not at $1001
ld65: Warning: 030-assert-success.s:77: Code not at $8000
ld65: Warning: 030-assert-success.s:78: Code not at $8000
030-assert-success.s:3: Warning: Assertion failed: Code not at $0000
030-assert-success.s:4: Warning: Assertion failed: Code not at $0000
030-assert-success.s:6: Warning: Assertion failed: Code not at $0001
030-assert-success.s:7: Warning: Assertion failed: Code not at $0001
030-assert-success.s:12: Warning: Assertion failed: Code not at $1001
030-assert-success.s:13: Warning: Assertion failed: Code not at $1001
030-assert-success.s:15: Warning: Assertion failed: Code not at $8000
030-assert-success.s:16: Warning: Assertion failed: Code not at $8000
030-assert-success.s:18: Warning: Assertion failed: Code not at $8001
030-assert-success.s:19: Warning: Assertion failed: Code not at $8001
030-assert-success.s:23: Warning: Assertion failed: Code not at $0000
030-assert-success.s:24: Warning: Assertion failed: Code not at $0000
030-assert-success.s:26: Warning: Assertion failed: Code not at $0001
030-assert-success.s:27: Warning: Assertion failed: Code not at $0001
030-assert-success.s:29: Warning: Assertion failed: Code not at $1000
030-assert-success.s:30: Warning: Assertion failed: Code not at $1000
030-assert-success.s:35: Warning: Assertion failed: Code not at $8000
030-assert-success.s:36: Warning: Assertion failed: Code not at $8000
030-assert-success.s:38: Warning: Assertion failed: Code not at $8001
030-assert-success.s:39: Warning: Assertion failed: Code not at $8001
030-assert-success.s:45: Warning: Assertion failed: Code not at $0000
030-assert-success.s:46: Warning: Assertion failed: Code not at $0000
030-assert-success.s:48: Warning: Assertion failed: Code not at $0001
030-assert-success.s:49: Warning: Assertion failed: Code not at $0001
030-assert-success.s:51: Warning: Assertion failed: Code not at $1000
030-assert-success.s:52: Warning: Assertion failed: Code not at $1000
030-assert-success.s:54: Warning: Assertion failed: Code not at $1001
030-assert-success.s:55: Warning: Assertion failed: Code not at $1001
030-assert-success.s:60: Warning: Assertion failed: Code not at $8001
030-assert-success.s:61: Warning: Assertion failed: Code not at $8001
030-assert-success.s:65: Warning: Assertion failed: Code not at $0000
030-assert-success.s:66: Warning: Assertion failed: Code not at $0000
030-assert-success.s:68: Warning: Assertion failed: Code not at $0001
030-assert-success.s:69: Warning: Assertion failed: Code not at $0001
030-assert-success.s:71: Warning: Assertion failed: Code not at $1000
030-assert-success.s:72: Warning: Assertion failed: Code not at $1000
030-assert-success.s:74: Warning: Assertion failed: Code not at $1001
030-assert-success.s:75: Warning: Assertion failed: Code not at $1001
030-assert-success.s:77: Warning: Assertion failed: Code not at $8000
030-assert-success.s:78: Warning: Assertion failed: Code not at $8000

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,40 +1,40 @@
ld65: Warning: 033-assert-ldwarning-success.s:3: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:4: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:6: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:7: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:12: Code not at $1001
ld65: Warning: 033-assert-ldwarning-success.s:13: Code not at $1001
ld65: Warning: 033-assert-ldwarning-success.s:15: Code not at $8000
ld65: Warning: 033-assert-ldwarning-success.s:16: Code not at $8000
ld65: Warning: 033-assert-ldwarning-success.s:18: Code not at $8001
ld65: Warning: 033-assert-ldwarning-success.s:19: Code not at $8001
ld65: Warning: 033-assert-ldwarning-success.s:23: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:24: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:26: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:27: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:29: Code not at $1000
ld65: Warning: 033-assert-ldwarning-success.s:30: Code not at $1000
ld65: Warning: 033-assert-ldwarning-success.s:35: Code not at $8000
ld65: Warning: 033-assert-ldwarning-success.s:36: Code not at $8000
ld65: Warning: 033-assert-ldwarning-success.s:38: Code not at $8001
ld65: Warning: 033-assert-ldwarning-success.s:39: Code not at $8001
ld65: Warning: 033-assert-ldwarning-success.s:45: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:46: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:48: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:49: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:51: Code not at $1000
ld65: Warning: 033-assert-ldwarning-success.s:52: Code not at $1000
ld65: Warning: 033-assert-ldwarning-success.s:54: Code not at $1001
ld65: Warning: 033-assert-ldwarning-success.s:55: Code not at $1001
ld65: Warning: 033-assert-ldwarning-success.s:60: Code not at $8001
ld65: Warning: 033-assert-ldwarning-success.s:61: Code not at $8001
ld65: Warning: 033-assert-ldwarning-success.s:65: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:66: Code not at $0000
ld65: Warning: 033-assert-ldwarning-success.s:68: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:69: Code not at $0001
ld65: Warning: 033-assert-ldwarning-success.s:71: Code not at $1000
ld65: Warning: 033-assert-ldwarning-success.s:72: Code not at $1000
ld65: Warning: 033-assert-ldwarning-success.s:74: Code not at $1001
ld65: Warning: 033-assert-ldwarning-success.s:75: Code not at $1001
ld65: Warning: 033-assert-ldwarning-success.s:77: Code not at $8000
ld65: Warning: 033-assert-ldwarning-success.s:78: Code not at $8000
033-assert-ldwarning-success.s:3: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:4: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:6: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:7: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:12: Warning: Assertion failed: Code not at $1001
033-assert-ldwarning-success.s:13: Warning: Assertion failed: Code not at $1001
033-assert-ldwarning-success.s:15: Warning: Assertion failed: Code not at $8000
033-assert-ldwarning-success.s:16: Warning: Assertion failed: Code not at $8000
033-assert-ldwarning-success.s:18: Warning: Assertion failed: Code not at $8001
033-assert-ldwarning-success.s:19: Warning: Assertion failed: Code not at $8001
033-assert-ldwarning-success.s:23: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:24: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:26: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:27: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:29: Warning: Assertion failed: Code not at $1000
033-assert-ldwarning-success.s:30: Warning: Assertion failed: Code not at $1000
033-assert-ldwarning-success.s:35: Warning: Assertion failed: Code not at $8000
033-assert-ldwarning-success.s:36: Warning: Assertion failed: Code not at $8000
033-assert-ldwarning-success.s:38: Warning: Assertion failed: Code not at $8001
033-assert-ldwarning-success.s:39: Warning: Assertion failed: Code not at $8001
033-assert-ldwarning-success.s:45: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:46: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:48: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:49: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:51: Warning: Assertion failed: Code not at $1000
033-assert-ldwarning-success.s:52: Warning: Assertion failed: Code not at $1000
033-assert-ldwarning-success.s:54: Warning: Assertion failed: Code not at $1001
033-assert-ldwarning-success.s:55: Warning: Assertion failed: Code not at $1001
033-assert-ldwarning-success.s:60: Warning: Assertion failed: Code not at $8001
033-assert-ldwarning-success.s:61: Warning: Assertion failed: Code not at $8001
033-assert-ldwarning-success.s:65: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:66: Warning: Assertion failed: Code not at $0000
033-assert-ldwarning-success.s:68: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:69: Warning: Assertion failed: Code not at $0001
033-assert-ldwarning-success.s:71: Warning: Assertion failed: Code not at $1000
033-assert-ldwarning-success.s:72: Warning: Assertion failed: Code not at $1000
033-assert-ldwarning-success.s:74: Warning: Assertion failed: Code not at $1001
033-assert-ldwarning-success.s:75: Warning: Assertion failed: Code not at $1001
033-assert-ldwarning-success.s:77: Warning: Assertion failed: Code not at $8000
033-assert-ldwarning-success.s:78: Warning: Assertion failed: Code not at $8000

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -0,0 +1 @@


View 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#>>>'

View 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

View 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'

View File

@@ -1,3 +1,3 @@
ld65: Warning: 201-overwrite-overflow.cfg:3: 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:3: Warning: Segment 'AO' overflows memory area 'A' 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

Binary file not shown.

View File

@@ -63,15 +63,15 @@ define PRG_template
# sim65 ensure 64-bit wait time does not timeout
$(WORKDIR)/sim65-timein.$1.prg: sim65-timein.s | $(WORKDIR)
$(if $(QUIET),echo misc/sim65-timein.$1.prg)
$(CA65) -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
$(LD65) -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
$(CA65) --no-utf8 -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
$(LD65) --no-utf8 -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
$(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR)
# sim65 ensure 64-bit wait time does timeout
$(WORKDIR)/sim65-timeout.$1.prg: sim65-timeout.s | $(WORKDIR)
$(if $(QUIET),echo misc/sim65-timeout.$1.prg)
$(CA65) -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
$(LD65) -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
$(CA65) --no-utf8 -t sim$1 -o $$(@:.prg=.o) $$< $(NULLERR)
$(LD65) --no-utf8 -t sim$1 -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLERR)
$(NOT) $(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR)
endef # PRG_template

View File

@@ -61,8 +61,8 @@ define OPCODE_template
$(WORKDIR)/$1-opcodes.bin: $1-opcodes.s $(ISEQUAL)
$(if $(QUIET),echo asm/$1-opcodes.bin)
$(CA65) -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$<
$(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib
$(CA65) --no-utf8 -t none --cpu $1 -l $$(@:.bin=.lst) -o $$(@:.bin=.o) $$<
$(LD65) --no-utf8 -t none -o $$@ $$(@:.bin=.o) none.lib
$(ISEQUAL) $1-opcodes.ref $$@
endef # OPCODE_template
@@ -70,7 +70,7 @@ endef # OPCODE_template
$(foreach cpu,$(OPCODE_CPUS),$(eval $(call OPCODE_template,$(cpu))))
$(WORKDIR)/%.o: %.s | $(WORKDIR)
$(CA65) -l $(@:.o=.lst) -o $@ $<
$(CA65) --no-utf8 -l $(@:.o=.lst) -o $@ $<
clean:
@$(call RMDIR,$(WORKDIR))

View File

@@ -55,8 +55,8 @@ define PRG_template
$(WORKDIR)/%.$1.prg: %.s | $(WORKDIR)
$(if $(QUIET),echo asm/val/$$*.$1.prg)
$(CA65) -t sim$1 -o $$(@:.prg=.o) $$< $(NULLOUT) $(NULLERR)
$(LD65) -C sim6502-asmtest.cfg -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLOUT) $(NULLERR)
$(CA65) --no-utf8 -t sim$1 -o $$(@:.prg=.o) $$< $(NULLOUT) $(NULLERR)
$(LD65) --no-utf8 -C sim6502-asmtest.cfg -o $$@ $$(@:.prg=.o) sim$1.lib $(NULLOUT) $(NULLERR)
$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT)
endef # PRG_template

43
test/asm/val/charmap.s Normal file
View File

@@ -0,0 +1,43 @@
.setcpu "6502"
.import _exit
.export _main
.charmap $41, 0
.charmap $42, 1
.charmap $43, 2
mapped:
.byte "ABC"
.include "ascii_charmap.inc"
ascii:
.byte "ABC"
_main:
ldx #$01
lda mapped+0
cmp #0
bne error
lda mapped+1
cmp #1
bne error
lda mapped+2
cmp #2
bne error
lda ascii+0
cmp #$41
bne error
lda ascii+1
cmp #$42
bne error
lda ascii+2
cmp #$43
bne error
ldx #$00
error:
txa
jmp _exit