From 799aec23a64c9f11fa2591f5e8dc7a93ee298430 Mon Sep 17 00:00:00 2001 From: Dave Plummer Date: Sat, 4 Jun 2022 13:00:48 -0700 Subject: [PATCH 001/360] Add KIM-1 Support --- asminc/kim1.inc | 28 +++++++++++++++++ cfg/kim1.cfg | 41 ++++++++++++++++++++++++ include/kim1.h | 67 ++++++++++++++++++++++++++++++++++++++++ libsrc/Makefile | 1 + libsrc/kim1/crt0.s | 47 ++++++++++++++++++++++++++++ libsrc/kim1/ctype.s | 5 +++ libsrc/kim1/read.s | 51 ++++++++++++++++++++++++++++++ libsrc/kim1/tapeio.s | 39 +++++++++++++++++++++++ libsrc/kim1/write.s | 49 +++++++++++++++++++++++++++++ samples/Makefile | 6 +++- samples/kim1/Makefile | 56 +++++++++++++++++++++++++++++++++ samples/kim1/kimHello | Bin 0 -> 2789 bytes samples/kim1/kimHello.c | 24 ++++++++++++++ src/ca65/main.c | 4 +++ src/cc65/main.c | 4 +++ src/common/target.c | 2 ++ src/common/target.h | 1 + targettest/Makefile | 1 + 18 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 asminc/kim1.inc create mode 100644 cfg/kim1.cfg create mode 100644 include/kim1.h create mode 100644 libsrc/kim1/crt0.s create mode 100644 libsrc/kim1/ctype.s create mode 100644 libsrc/kim1/read.s create mode 100644 libsrc/kim1/tapeio.s create mode 100644 libsrc/kim1/write.s create mode 100644 samples/kim1/Makefile create mode 100644 samples/kim1/kimHello create mode 100644 samples/kim1/kimHello.c diff --git a/asminc/kim1.inc b/asminc/kim1.inc new file mode 100644 index 000000000..f0d1555a7 --- /dev/null +++ b/asminc/kim1.inc @@ -0,0 +1,28 @@ +; --------------------------------------------------------------------------- +; +; KIM-1 definitions +; +; --------------------------------------------------------------------------- + + +RAMSTART := $0200 ; Entry point + +; --------------------------------------------------------------------------- +; Monitor Functions +; --------------------------------------------------------------------------- + + +OUTCHR := $1EA0 ; Output character +INTCHR := $1E5A ; Input character without case conversion +DUMPT := $1800 ; Dump memory to tape +LOADT := $1873 ; Load memory from tape +SAL := $17F5 ; Tape load address low +SAH := $17F6 ; Tape load address high +EAL := $17F7 ; Tape address end low +EAH := $17F8 ; Tape address end high +ID := $17F9 ; Tape Identification number + +; --------------------------------------------------------------------------- +; System Memory +; --------------------------------------------------------------------------- + diff --git a/cfg/kim1.cfg b/cfg/kim1.cfg new file mode 100644 index 000000000..69636065e --- /dev/null +++ b/cfg/kim1.cfg @@ -0,0 +1,41 @@ +# kim1.cfg (4k) +# +# for unexpanded Kim-1 +# +# ld65 --config kim1.cfg -o .bin .o + +FEATURES { + STARTADDRESS: default = $0200; + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + __STACKSIZE__: type = weak, value = $0080; # 128 byte program stack + __STARTADDRESS__: type = export, value = %S; +} + +MEMORY { + ZP: file = %O, define = yes, start = $0000, size = $00EE; + CPUSTACK: file = "", define = yes, start = $0100, size = $0100; + RAM: file = %O, define = yes, start = %S, size = $1000 - %S - __STACKSIZE__; + MAINROM: file = "", define = yes, start = $E000, size = $1000; + TOP: file = "", define = yes, start = $F000, size = $1000; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + STARTUP: load = RAM, type = ro, define = yes; + CODE: load = RAM, type = ro, define = yes; + RODATA: load = RAM, type = ro, define = yes; + ONCE: load = RAM, type = ro, define = yes; + DATA: load = RAM, type = rw, define = yes; + BSS: load = RAM, type = bss, define = yes; +} + diff --git a/include/kim1.h b/include/kim1.h new file mode 100644 index 000000000..52e690c9d --- /dev/null +++ b/include/kim1.h @@ -0,0 +1,67 @@ +/*****************************************************************************/ +/* */ +/* kim1.h */ +/* */ +/* Kim-1 system-specific definitions */ +/* */ +/* */ +/* */ +/* (C) 2022 Dave Plummer */ +/* Email: davepl@davepl.com */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + +#ifndef _KIM1_H +#define _KIM1_H + +/* Check for errors */ +#if !defined(__KIM1__) +# error This module may only be used when compiling for the Kim-1! +#endif + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Hardware */ +/*****************************************************************************/ + + +// Todo (davepl) +// +// #include <_6530.h> +// #define RIOT3 (*(struct __6530*)0x1700) // U25 +// #define RIOT2 (*(struct __6530*)0x1740) // U28 + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + +/* Read from tape */ +int __fastcall__ loadt (unsigned char); + +/* Write to tape */ +int __fastcall__ dumpt (unsigned char, const void*, const void*); + +/* End of sym1.h */ +#endif diff --git a/libsrc/Makefile b/libsrc/Makefile index 2018de801..627897d9b 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -27,6 +27,7 @@ TARGETS = apple2 \ $(CBMS) \ $(GEOS) \ gamate \ + kim1 \ lynx \ nes \ none \ diff --git a/libsrc/kim1/crt0.s b/libsrc/kim1/crt0.s new file mode 100644 index 000000000..7e7dd485b --- /dev/null +++ b/libsrc/kim1/crt0.s @@ -0,0 +1,47 @@ +; +; Startup code for cc65 (kim-1 version) +; + + .export _init, _exit + .export __STARTUP__ : absolute = 1 ; Mark as startup + + .import _main + .import initlib, donelib, copydata, zerobss + .import __RAM_START__, __RAM_SIZE__ ; Linker generated + .import __STACKSIZE__ ; Linker generated + + .include "zeropage.inc" + .include "kim1.inc" + + +; Place the startup code in a special segment + +.segment "STARTUP" + + +; A little light housekeeping + +_init: cld ; Clear decimal mode + +; Set cc65 argument stack pointer + + lda #<(__RAM_START__ + __RAM_SIZE__) + sta sp + lda #>(__RAM_START__ + __RAM_SIZE__) + sta sp+1 + +; Initialize memory storage + + jsr zerobss ; Clear BSS segment + jsr copydata ; Initialize DATA segment + jsr initlib ; Run constructors + +; Call main() + + jsr _main + +; Back from main (this is also the _exit entry). There may be a more elegant way to9 +; return to the monitor on the Kim-1, but I don't know it! + +_exit: brk + diff --git a/libsrc/kim1/ctype.s b/libsrc/kim1/ctype.s new file mode 100644 index 000000000..1301965eb --- /dev/null +++ b/libsrc/kim1/ctype.s @@ -0,0 +1,5 @@ +; Character specification table. +; +; uses the "common" definition + + .include "ctype_common.inc" diff --git a/libsrc/kim1/read.s b/libsrc/kim1/read.s new file mode 100644 index 000000000..5566a9f27 --- /dev/null +++ b/libsrc/kim1/read.s @@ -0,0 +1,51 @@ +; +; int __fastcall__ read (int fd, void* buf, unsigned count); +; + +.include "kim1.inc" + +.import popax, popptr1 +.importzp ptr1, ptr2, ptr3 + +.export _read + +.proc _read + + sta ptr3 + stx ptr3+1 ; Count in ptr3 + inx + stx ptr2+1 ; Increment and store in ptr2 + tax + inx + stx ptr2 + jsr popptr1 ; Buffer address in ptr1 + jsr popax + +begin: dec ptr2 + bne getch + dec ptr2+1 + beq done ; If buffer full, return + +getch: jsr INTCHR ; Get character using Monitor ROM call + ;jsr OUTCHR ; Echo it + and #$7F ; Clear top bit + cmp #$07 ; Check for '\a' + bne chkcr ; ...if BEL character + ;jsr BEEP ; Make beep sound TODO +chkcr: cmp #$0D ; Check for '\r' + bne putch ; ...if CR character + lda #$0A ; Replace with '\n' + jsr OUTCHR ; and echo it + +putch: ldy #$00 ; Put char into return buffer + sta (ptr1),y + inc ptr1 ; Increment pointer + bne begin + inc ptr1+1 + bne begin + +done: lda ptr3 + ldx ptr3+1 + rts ; Return count + +.endproc diff --git a/libsrc/kim1/tapeio.s b/libsrc/kim1/tapeio.s new file mode 100644 index 000000000..4a16d6b9c --- /dev/null +++ b/libsrc/kim1/tapeio.s @@ -0,0 +1,39 @@ +; +; int __fastcall__ loadt (unsigned char id); +; int __fastcall__ dumpt (unsigned char id, void* start_addr, void* end_addr); +; + +.include "kim1.inc" + +.import popa, popax, return0, return1 + +.export _loadt, _dumpt + +.segment "CODE" + +.proc _loadt: near + + sta ID ; Tape record ID to P1L + jsr LOADT ; Read data from tape + bcs error + jmp return0 ; Return 0 if sucessful +error: jmp return1 ; or 1 if not + +.endproc + +.proc _dumpt: near + + sta EAL ; End address + stx EAH + jsr popax + sta SAL ; Start address + stx SAH + jsr popa + sta ID ; Tape Record ID + ldx #$00 + jsr DUMPT ; Write data to tape + bcs error + jmp return0 ; Return 0 if sucessful +error: jmp return1 ; or 1 if not + +.endproc diff --git a/libsrc/kim1/write.s b/libsrc/kim1/write.s new file mode 100644 index 000000000..216f5031c --- /dev/null +++ b/libsrc/kim1/write.s @@ -0,0 +1,49 @@ +; +; int __fastcall__ write (int fd, const void* buf, int count); +; + +.include "kim1.inc" + +.import popax, popptr1 +.importzp ptr1, ptr2, ptr3 + +.export _write + +.proc _write + + sta ptr3 + stx ptr3+1 ; Count in ptr3 + inx + stx ptr2+1 ; Increment and store in ptr2 + tax + inx + stx ptr2 + jsr popptr1 ; Buffer address in ptr1 + jsr popax + +begin: dec ptr2 + bne outch + dec ptr2+1 + beq done + +outch: ldy #0 + lda (ptr1),y + jsr OUTCHR ; Send character using Monitor call + cmp #$07 ; Check for '\a' + bne chklf ; ...if BEL character +;jsr BEEP ; Make beep sound +chklf: cmp #$0A ; Check for 'n' + bne next ; ...if LF character + lda #$0D ; Add a carriage return + jsr OUTCHR + +next: inc ptr1 + bne begin + inc ptr1+1 + jmp begin + +done: lda ptr3 + ldx ptr3+1 + rts ; Return count + +.endproc diff --git a/samples/Makefile b/samples/Makefile index 4007e3522..cec4bed89 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -154,7 +154,7 @@ endif # Lists of subdirectories # disasm depends on cpp -DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 cbm +DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 kim1 cbm # -------------------------------------------------------------------------- # Lists of executables @@ -329,6 +329,9 @@ EXELIST_supervision = \ EXELIST_sym1 = \ notavailable +EXELIST_kim1 = \ + notavailable + EXELIST_telestrat = \ ascii \ checkversion \ @@ -395,6 +398,7 @@ TARGETS := \ creativision \ cx16 \ gamate \ + kim1 \ lunix \ lynx \ nes \ diff --git a/samples/kim1/Makefile b/samples/kim1/Makefile new file mode 100644 index 000000000..89600ad5a --- /dev/null +++ b/samples/kim1/Makefile @@ -0,0 +1,56 @@ + +# Run 'make SYS='; or, set a SYS env. +# var. to build for another target system. +SYS ?= kim1 + +# Just the usual way to find out if we're +# using cmd.exe to execute make rules. +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +ifdef CMD_EXE + NULLDEV = nul: + DEL = -del /f + RMDIR = rmdir /s /q +else + NULLDEV = /dev/null + DEL = $(RM) + RMDIR = $(RM) -r +endif + +ifdef CC65_HOME + AS = $(CC65_HOME)/bin/ca65 + CC = $(CC65_HOME)/bin/cc65 + CL = $(CC65_HOME)/bin/cl65 + LD = $(CC65_HOME)/bin/ld65 +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) +endif + +EXELIST_kim1 = \ + kimHello.bin + +ifneq ($(EXELIST_$(SYS)),) +samples: $(EXELIST_$(SYS)) +else +samples: notavailable +endif + +# empty target used to skip systems that will not work with any program in this dir +notavailable: +ifeq ($(MAKELEVEL),0) + @echo "info: kim1 tests not available for" $(SYS) +else +# suppress the "nothing to be done for 'samples' message + @echo > $(NULLDEV) +endif + +kimHello.bin: kimHello.c + $(CL) -t kim1 -O -o kimHello.bin kimHello.c + +clean: + @$(DEL) kimHello.bin 2>$(NULLDEV) diff --git a/samples/kim1/kimHello b/samples/kim1/kimHello new file mode 100644 index 0000000000000000000000000000000000000000..5842567557dc9f321409d269970f08832b736d86 GIT binary patch literal 2789 zcmbVOTWl2989pPwHj|K(i1^Ur@f{@6caBR^#e^evV4CFt9Pc8bVHbVBy0T$R2rJ0ktL?4Nib zo8J=YZ<8)^P!)bIYN9})f5+@!{>KkCxqxB*K%{?2S`KParRkDPJQrCHdD} z0@!q1Hct~T-8U=R>2Yzg!)n|iY!z*Y=9&Z-6I^_pQ(G)ZbVziBX1ZQ%rU7*b56R8W zzS-W9rvhdCYxE5<>*1Q5z-yyl4%@htlkG^!b8X~$(5S~j+uJQr9m%C)In)>Rzec2U&e!Iy&9tvVtJlaZjs>yGJKl==tlO% zXy-%Q-io#@kV>@SXK-OY>rI55LlFu+v5UA_}tI20RRB<@m$XfCNhAl?vz z*O?A!QC=cGD&HgK$#}2_4)wDQE^2_eqDvcKzUV$#xl8D8#8IhNJ$09aiQy$4dPkw( zl=z_otb=D4E^yChsu-eC#o(0SAX^8=PTeG7SGHipjkp+>v<0Hw1`NNKE{b^vuV5Tv znu{uT$PBp0Kg`wzgN$(7hz7RuOMb#sIwHcIJEJ=fgQ2gno@@ial?cm!4FLHT1GeOY z!%SYuxB&&ugE=eeD@s|{Dk-h8Y)Hr00-4jb#%*%)dP*BlRCH}PrS&!D$#q?;H*OI= z3-PV*Y?p7563}_lm?KQ0-4gw(1Y*cVz%Lsb_;HnHO=UC3a>z!Ia6;a4+Lw-ui%@Ig zkOUrtWm_oNnsLM9_pKo!Oem-DMU)*zQWrOa$|I>LVuZn7Le%? z!UWJnm~h)AlO{pNp$>ErstQ_C2IlG~GW5Lci}Xqo&O<{IsGxu;$pD32=9iL}+H7^u zX5Ac5j#V=pCz8c#<{VdCbOL2z2H8-l$nMUYA0*3*P;ACapa#1FSvZb6* z&s&+D?S3H(nb42wp2(RkdQ!xtyanM{j&+s}CmhL>cq0*kl&UCStRl-ccnebss!a+S zJt%Vx8nZ>ej%(7W@t(q-^TfCu$86Q5BTRGDiQ8&bDH==WUvbG;?Qd{URcR?;zsmbC z4U@d`%(pQB_~2~nBi_H)ifg6yXN{5Aw9&#vHg|I3iVDpgfT0N4Cl1P2l~9^uOCG6d z7E8FOWUmX%~9jU$gh?>da zx+muh+bHcd_U(naBAfN}TFNrF$OU;6*YpA&(j9C*FWWjl@4yFytL@Z|2d7hZsI>$1-l@(MIr=3XX6;Y7of>)5}T24^F|l z#REB0Q0p@VWjUUc3X4su;S==xk5T8bo?iq>h60VneFaoFhFh3@+LGBvk?&8ZvrTj~ zod>kj9bD`H(c&56f^khH#8d2EOPyi2k6HY?_zEwPFiratJt9;w?x)ao*&IO5cuGx$ zbhY&;LUdG#9%~=jl4I0T;p03v)~}W7XLV1SPK{t&DoyM47A_Up69>}YE)&`trCnTRNqAu{5TWMvyKOpFlOxSER-TGIo*tPY4?Xl|Zg7xp|L(5s-+PK48p!P) z%xzQ@q-1jg0|)7=2j3jn^90wGUHRPyemKbG-lw10wD}v)Zs~jO`ES3lZTpT5&pf?( z%jUjK&u;ERNDzsv7+YU**j^a5Vv)0G$Y^e JbXnmD{{hxi-7)|G literal 0 HcmV?d00001 diff --git a/samples/kim1/kimHello.c b/samples/kim1/kimHello.c new file mode 100644 index 000000000..dcbfb4e67 --- /dev/null +++ b/samples/kim1/kimHello.c @@ -0,0 +1,24 @@ +// -------------------------------------------------------------------------- +// Hello World for Kim-1 +// +// Dave Plummer based on Sym-1 sample by Wayne Parham +// +// davepl@davepl.com +// -------------------------------------------------------------------------- + +#include +#include + +int main (void) +{ + char str[100]; + char c = 0x00; + + printf ("\nHello World!\n\n"); + printf ("Type a line and press ENTER, please.\n\n"); + + gets( str ); + + printf ("\n\nThanks: %s\n\n", str); + return 0; +} diff --git a/src/ca65/main.c b/src/ca65/main.c index b1ef3a3db..4146aaf11 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -342,6 +342,10 @@ static void SetSys (const char* Sys) NewSymbol ("__SYM1__", 1); break; + case TGT_KIM1: + NewSymbol ("__KIM1__", 1); + break; + default: AbEnd ("Invalid target name: '%s'", Sys); diff --git a/src/cc65/main.c b/src/cc65/main.c index c08616efa..f800ac43e 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -299,6 +299,10 @@ static void SetSys (const char* Sys) DefineNumericMacro ("__SYM1__", 1); break; + case TGT_KIM1: + DefineNumericMacro ("__KIM1__", 1); + break; + default: AbEnd ("Unknown target system '%s'", Sys); } diff --git a/src/common/target.c b/src/common/target.c index 4a851034a..ad62990bd 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -163,6 +163,7 @@ static const TargetEntry TargetMap[] = { { "geos", TGT_GEOS_CBM }, { "geos-apple", TGT_GEOS_APPLE }, { "geos-cbm", TGT_GEOS_CBM }, + { "kim1", TGT_KIM1 }, { "lunix", TGT_LUNIX }, { "lynx", TGT_LYNX }, { "module", TGT_MODULE }, @@ -219,6 +220,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = { { "c65", CPU_4510, BINFMT_BINARY, CTPET }, { "cx16", CPU_65C02, BINFMT_BINARY, CTPET }, { "sym1", CPU_6502, BINFMT_BINARY, CTNone }, + { "kim1", CPU_6502, BINFMT_BINARY, CTNone }, }; /* Target system */ diff --git a/src/common/target.h b/src/common/target.h index 7087048e2..7439fa621 100644 --- a/src/common/target.h +++ b/src/common/target.h @@ -87,6 +87,7 @@ typedef enum { TGT_C65, TGT_CX16, TGT_SYM1, + TGT_KIM1, // Added at end so as not to shift existing entries TGT_COUNT /* Number of target systems */ } target_t; diff --git a/targettest/Makefile b/targettest/Makefile index 0450bfd4e..23463ccd9 100644 --- a/targettest/Makefile +++ b/targettest/Makefile @@ -742,6 +742,7 @@ TARGETS := \ creativision \ cx16 \ gamate \ + kim1 \ lunix \ lynx \ nes \ From 8f9777d9e0d34b4be32ff09750980138d61e9e01 Mon Sep 17 00:00:00 2001 From: Dave Plummer Date: Mon, 6 Jun 2022 15:14:01 -0700 Subject: [PATCH 002/360] Fix ushot overflow, capitalization --- cfg/kim1-60k.cfg | 41 +++++++++++++ include/kim1.h | 4 +- libsrc/kim1/crt0.s | 2 +- samples/kim1/Makefile | 8 ++- samples/kim1/kimSieve.c | 125 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 cfg/kim1-60k.cfg create mode 100644 samples/kim1/kimSieve.c diff --git a/cfg/kim1-60k.cfg b/cfg/kim1-60k.cfg new file mode 100644 index 000000000..a6704d9dd --- /dev/null +++ b/cfg/kim1-60k.cfg @@ -0,0 +1,41 @@ +# kim1.cfg (4k) +# +# for unexpanded Kim-1 +# +# ld65 --config kim1.cfg -o .bin .o + +FEATURES { + STARTADDRESS: default = $2000; + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + __STACKSIZE__: type = weak, value = $0080; # 128 byte program stack + __STARTADDRESS__: type = export, value = %S; +} + +MEMORY { + ZP: file = %O, define = yes, start = $0000, size = $00EE; + CPUSTACK: file = "", define = yes, start = $0100, size = $0100; + RAM: file = %O, define = yes, start = %S, size = $E000 - %S - __STACKSIZE__; + MAINROM: file = "", define = yes, start = $E000, size = $1000; + TOP: file = "", define = yes, start = $F000, size = $1000; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + STARTUP: load = RAM, type = ro, define = yes; + CODE: load = RAM, type = ro, define = yes; + RODATA: load = RAM, type = ro, define = yes; + ONCE: load = RAM, type = ro, define = yes; + DATA: load = RAM, type = rw, define = yes; + BSS: load = RAM, type = bss, define = yes; +} + diff --git a/include/kim1.h b/include/kim1.h index 52e690c9d..bb616f7a0 100644 --- a/include/kim1.h +++ b/include/kim1.h @@ -2,7 +2,7 @@ /* */ /* kim1.h */ /* */ -/* Kim-1 system-specific definitions */ +/* KIM-1 system-specific definitions */ /* */ /* */ /* */ @@ -33,7 +33,7 @@ /* Check for errors */ #if !defined(__KIM1__) -# error This module may only be used when compiling for the Kim-1! +# error This module may only be used when compiling for the KIM-1! #endif diff --git a/libsrc/kim1/crt0.s b/libsrc/kim1/crt0.s index 7e7dd485b..aefdc3545 100644 --- a/libsrc/kim1/crt0.s +++ b/libsrc/kim1/crt0.s @@ -1,5 +1,5 @@ ; -; Startup code for cc65 (kim-1 version) +; Startup code for cc65 (KIM-1 version) ; .export _init, _exit diff --git a/samples/kim1/Makefile b/samples/kim1/Makefile index 89600ad5a..74c415fdc 100644 --- a/samples/kim1/Makefile +++ b/samples/kim1/Makefile @@ -32,7 +32,8 @@ else endif EXELIST_kim1 = \ - kimHello.bin + kimHello.bin \ + kimSieve.bin ifneq ($(EXELIST_$(SYS)),) samples: $(EXELIST_$(SYS)) @@ -49,8 +50,13 @@ else @echo > $(NULLDEV) endif +kimSieve.bin: kimSieve.c + $(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c + kimHello.bin: kimHello.c $(CL) -t kim1 -O -o kimHello.bin kimHello.c clean: + @$(DEL) kimSieve.bin 2>$(NULLDEV) @$(DEL) kimHello.bin 2>$(NULLDEV) + diff --git a/samples/kim1/kimSieve.c b/samples/kim1/kimSieve.c new file mode 100644 index 000000000..29cd7c7e9 --- /dev/null +++ b/samples/kim1/kimSieve.c @@ -0,0 +1,125 @@ +#include +#include + +typedef unsigned char byte; +typedef unsigned short int ushort; +typedef unsigned long int ulong; + +#define LIMIT 100000L + +// BITARRAY +// +// My bit-access macros pre-divide by two on the presumption that you'll never +// try try access both odd and even bits! + +#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7))) +#define SETBIT(array, bit) (array[bit >> 4] |= (1 << ((bit >> 1) & 7))) +#define CLRBIT(array, bit) (array[bit >> 4] &= ~(1 << ((bit >> 1) & 7))) + +// RepeatChar +// +// Outputs a given character N times + +void RepeatChar(char c, size_t count) +{ + while (count--) + putc(c, stdout); +} + +// sqrti +// +// Binary search integer square root + +ushort sqrti(ulong num) +{ + long i; + ulong ret = 0; + + for(i = 15; i >= 0; i--) + { + ulong temp = ret | (1L << (ulong)i); + if(temp * temp <= num) + { + ret = temp; + } + } + return ret; +} + +// main() +// +// CC65 main function receives no parameters + +int main(void) +{ + // CC65 cannot mix code and data so we have to declare all variables here in the function prolog + + ulong iNumber; + ushort currentFactor; + ulong numBytesAllocated, rootOfLimit; + byte *array; + ulong countOfPrimes; + + rootOfLimit = sqrti(LIMIT); + puts("\r\n\r\n"); + RepeatChar('*', 70); + puts("\r\n** Prime Number Sieve - Dave Plummer 2022 **"); + RepeatChar('*', 70); + + printf("\r\n\r\nCalculating primes to %ld using a sqrt of %ld...\r\n", LIMIT, rootOfLimit); + + // Calculate how much memory should be allocated + + numBytesAllocated = (LIMIT + 15) / 16; + array = malloc(numBytesAllocated); + if (!array) + { + printf("Unable to allocate %ld bytes for %ld bits\r\n", numBytesAllocated, LIMIT); + return 0; + } + else + { + printf("Allocated %ld bytes for %ld slots\r\n", numBytesAllocated, LIMIT); + + // Preset all the bits to true + + for (iNumber = 0; iNumber < numBytesAllocated; iNumber++) + array[iNumber] = 0xFF; + } + + // Search for next unmarked factor + + currentFactor = 3; + while (currentFactor <= rootOfLimit) + { + ulong num, n; + + for (num = currentFactor; num <= LIMIT; num += 2) + { + if (GETBIT(array, num)) + { + currentFactor = num; + break; + } + } + + for (n = (ulong) currentFactor * currentFactor; n <= LIMIT; n += currentFactor * 2) + CLRBIT(array, n); + + currentFactor += 2; + } + + // Display results + // + // printf("The following primes were found at or below %ld:\r\n2, ", LIMIT); + + countOfPrimes = 1; + for (iNumber = 3; iNumber <= LIMIT; iNumber += 2) + if (GETBIT(array, iNumber)) + countOfPrimes++; + + printf("[END: Count = %ld]\r\n", countOfPrimes); + + free(array); + return 1; +} From 46541237e0d238ad635a53b09f39764c3b4fd173 Mon Sep 17 00:00:00 2001 From: David W Plummer Date: Mon, 6 Jun 2022 15:17:19 -0700 Subject: [PATCH 003/360] Add to contributor list for KIM-1 target --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e917a13e0..f011af83c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ External contributors: * [karrika](https://github.com/karrika): Atari 7800 target * [Stephan Mühlstrasser](https://github.com/smuehlst): osic1p target * [Wayne Parham](https://github.com/WayneParham): Sym-1 target +* [Dave Plummeer](https://github.com/davepl): KIM-1 target *(The above list is incomplete, if you feel left out - please speak up or add yourself in a PR)* From db44d59f7c99e602ff9619893bcaa6c0f319c216 Mon Sep 17 00:00:00 2001 From: David W Plummer Date: Mon, 6 Jun 2022 15:17:39 -0700 Subject: [PATCH 004/360] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f011af83c..287520320 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ External contributors: * [karrika](https://github.com/karrika): Atari 7800 target * [Stephan Mühlstrasser](https://github.com/smuehlst): osic1p target * [Wayne Parham](https://github.com/WayneParham): Sym-1 target -* [Dave Plummeer](https://github.com/davepl): KIM-1 target +* [Dave Plummer](https://github.com/davepl): KIM-1 target *(The above list is incomplete, if you feel left out - please speak up or add yourself in a PR)* From 95e5471cd6a4ac49ecb188562c3d02023ade3798 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Aug 2022 14:34:50 +0800 Subject: [PATCH 005/360] Better preprocess macro expansion. --- src/cc65/input.c | 91 ++- src/cc65/input.h | 10 + src/cc65/macrotab.c | 68 +- src/cc65/macrotab.h | 16 +- src/cc65/preproc.c | 1561 ++++++++++++++++++++++++++++++++++++------- 5 files changed, 1414 insertions(+), 332 deletions(-) diff --git a/src/cc65/input.c b/src/cc65/input.c index 0e8fc3276..5754b1054 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -103,8 +103,8 @@ static Collection IFiles = STATIC_COLLECTION_INITIALIZER; /* List of all active files */ static Collection AFiles = STATIC_COLLECTION_INITIALIZER; -/* Input stack used when preprocessing. */ -static Collection InputStack = STATIC_COLLECTION_INITIALIZER; +/* Input stack used when preprocessing */ +static Collection* CurrentInputStack; /* Counter for the __COUNTER__ macro */ static unsigned MainFileCounter; @@ -394,34 +394,37 @@ static void GetInputChar (void) ** are read by this function. */ { - /* Drop all pushed fragments that don't have data left */ - while (SB_GetIndex (Line) >= SB_GetLen (Line)) { - /* Cannot read more from this line, check next line on stack if any */ - if (CollCount (&InputStack) == 0) { - /* This is THE line */ - break; - } - FreeStrBuf (Line); - Line = CollPop (&InputStack); - } - - /* Now get the next characters from the line */ - if (SB_GetIndex (Line) >= SB_GetLen (Line)) { - CurC = NextC = '\0'; + /* Get the next-next character from the line */ + if (SB_GetIndex (Line) + 1 < SB_GetLen (Line)) { + /* CurC and NextC come from this fragment */ + CurC = SB_AtUnchecked (Line, SB_GetIndex (Line)); + NextC = SB_AtUnchecked (Line, SB_GetIndex (Line) + 1); } else { - CurC = SB_AtUnchecked (Line, SB_GetIndex (Line)); - if (SB_GetIndex (Line) + 1 < SB_GetLen (Line)) { - /* NextC comes from this fragment */ - NextC = SB_AtUnchecked (Line, SB_GetIndex (Line) + 1); - } else { + /* NextC is '\0' by default */ + NextC = '\0'; + + /* Drop all pushed fragments that don't have data left */ + if (CurrentInputStack != 0) { + while (SB_GetIndex (Line) >= SB_GetLen (Line)) { + /* Cannot read more from this line, check next line on stack if any */ + if (CollCount (CurrentInputStack) == 0) { + /* This is THE line */ + break; + } + FreeStrBuf (Line); + Line = CollPop (CurrentInputStack); + } + /* NextC comes from next fragment */ - if (CollCount (&InputStack) > 0) { + if (CollCount (CurrentInputStack) > 0) { NextC = ' '; - } else { - NextC = '\0'; } } + + /* Get CurC from the line */ + CurC = SB_LookAt (Line, SB_GetIndex (Line)); } + } @@ -441,16 +444,46 @@ void NextChar (void) +Collection* UseInputStack (Collection* InputStack) +/* Use the provided input stack for incoming input. Return the previously used +** InputStack. +*/ +{ + Collection* OldInputStack = CurrentInputStack; + + CurrentInputStack = InputStack; + return OldInputStack; +} + + + +void PushLine (StrBuf* L) +/* Save the current input line and use a new one */ +{ + PRECONDITION (CurrentInputStack != 0); + if (SB_GetIndex (L) < SB_GetLen (L)) { + CollAppend (CurrentInputStack, Line); + Line = L; + GetInputChar (); + } else { + FreeStrBuf (L); + } +} + + + void ClearLine (void) /* Clear the current input line */ { - unsigned I; + if (CurrentInputStack != 0) { + unsigned I; - /* Remove all pushed fragments from the input stack */ - for (I = 0; I < CollCount (&InputStack); ++I) { - FreeStrBuf (CollAtUnchecked (&InputStack, I)); + /* Remove all pushed fragments from the input stack */ + for (I = 0; I < CollCount (CurrentInputStack); ++I) { + FreeStrBuf (Line); + Line = CollPop (CurrentInputStack); + } } - CollDeleteAll (&InputStack); /* Clear the contents of Line */ SB_Clear (Line); diff --git a/src/cc65/input.h b/src/cc65/input.h index fb24bbaa8..f9565229b 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -70,6 +70,8 @@ extern StrBuf* Line; extern char CurC; extern char NextC; +typedef struct Collection Collection; + /*****************************************************************************/ @@ -95,6 +97,14 @@ void NextChar (void); ** are read by this function. */ +Collection* UseInputStack (Collection* InputStack); +/* Use the provided input stack for incoming input. Return the previously used +** InputStack. +*/ + +void PushLine (StrBuf* L); +/* Save the current input line and use a new one */ + void ClearLine (void); /* Clear the current input line */ diff --git a/src/cc65/macrotab.c b/src/cc65/macrotab.c index 0e80cd638..3bfae0811 100644 --- a/src/cc65/macrotab.c +++ b/src/cc65/macrotab.c @@ -74,19 +74,17 @@ Macro* NewMacro (const char* Name) */ { /* Get the length of the macro name */ - unsigned Len = strlen(Name); + unsigned Len = strlen (Name); /* Allocate the structure */ Macro* M = (Macro*) xmalloc (sizeof(Macro) + Len); /* Initialize the data */ - M->Next = 0; - M->Expanding = 0; - M->ArgCount = -1; /* Flag: Not a function like macro */ - M->MaxArgs = 0; - InitCollection (&M->FormalArgs); + M->Next = 0; + M->ParamCount = -1; /* Flag: Not a function-like macro */ + InitCollection (&M->Params); SB_Init (&M->Replacement); - M->Variadic = 0; + M->Variadic = 0; memcpy (M->Name, Name, Len+1); /* Return the new macro */ @@ -102,10 +100,10 @@ void FreeMacro (Macro* M) { unsigned I; - for (I = 0; I < CollCount (&M->FormalArgs); ++I) { - xfree (CollAtUnchecked (&M->FormalArgs, I)); + for (I = 0; I < CollCount (&M->Params); ++I) { + xfree (CollAtUnchecked (&M->Params, I)); } - DoneCollection (&M->FormalArgs); + DoneCollection (&M->Params); SB_Done (&M->Replacement); xfree (M); } @@ -121,12 +119,12 @@ Macro* CloneMacro (const Macro* M) Macro* New = NewMacro (M->Name); unsigned I; - for (I = 0; I < CollCount (&M->FormalArgs); ++I) { - /* Copy the argument */ - const char* Arg = CollAtUnchecked (&M->FormalArgs, I); - CollAppend (&New->FormalArgs, xstrdup (Arg)); + for (I = 0; I < CollCount (&M->Params); ++I) { + /* Copy the parameter */ + const char* Param = CollAtUnchecked (&M->Params, I); + CollAppend (&New->Params, xstrdup (Param)); } - New->ArgCount = M->ArgCount; + New->ParamCount = M->ParamCount; New->Variadic = M->Variadic; SB_Copy (&New->Replacement, &M->Replacement); @@ -265,14 +263,14 @@ Macro* FindMacro (const char* Name) -int FindMacroArg (Macro* M, const char* Arg) -/* Search for a formal macro argument. If found, return the index of the -** argument. If the argument was not found, return -1. +int FindMacroParam (const Macro* M, const char* Param) +/* Search for a macro parameter. If found, return the index of the parameter. +** If the parameter was not found, return -1. */ { unsigned I; - for (I = 0; I < CollCount (&M->FormalArgs); ++I) { - if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) { + for (I = 0; I < CollCount (&M->Params); ++I) { + if (strcmp (CollAtUnchecked (&M->Params, I), Param) == 0) { /* Found */ return I; } @@ -284,25 +282,25 @@ int FindMacroArg (Macro* M, const char* Arg) -void AddMacroArg (Macro* M, const char* Arg) -/* Add a formal macro argument. */ +void AddMacroParam (Macro* M, const char* Param) +/* Add a macro parameter. */ { - /* Check if we have a duplicate macro argument, but add it anyway. - ** Beware: Don't use FindMacroArg here, since the actual argument array + /* Check if we have a duplicate macro parameter, but add it anyway. + ** Beware: Don't use FindMacroParam here, since the actual argument array ** may not be initialized. */ unsigned I; - for (I = 0; I < CollCount (&M->FormalArgs); ++I) { - if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) { + for (I = 0; I < CollCount (&M->Params); ++I) { + if (strcmp (CollAtUnchecked (&M->Params, I), Param) == 0) { /* Found */ - PPError ("Duplicate macro parameter: '%s'", Arg); + PPError ("Duplicate macro parameter: '%s'", Param); break; } } - /* Add the new argument */ - CollAppend (&M->FormalArgs, xstrdup (Arg)); - ++M->ArgCount; + /* Add the new parameter */ + CollAppend (&M->Params, xstrdup (Param)); + ++M->ParamCount; } @@ -313,14 +311,14 @@ int MacroCmp (const Macro* M1, const Macro* M2) int I; /* Argument count must be identical */ - if (M1->ArgCount != M2->ArgCount) { + if (M1->ParamCount != M2->ParamCount) { return 1; } - /* Compare the arguments */ - for (I = 0; I < M1->ArgCount; ++I) { - if (strcmp (CollConstAt (&M1->FormalArgs, I), - CollConstAt (&M2->FormalArgs, I)) != 0) { + /* Compare the parameters */ + for (I = 0; I < M1->ParamCount; ++I) { + if (strcmp (CollConstAt (&M1->Params, I), + CollConstAt (&M2->Params, I)) != 0) { return 1; } } diff --git a/src/cc65/macrotab.h b/src/cc65/macrotab.h index 6a09d7281..52b812b2f 100644 --- a/src/cc65/macrotab.h +++ b/src/cc65/macrotab.h @@ -55,10 +55,8 @@ typedef struct Macro Macro; struct Macro { Macro* Next; /* Next macro with same hash value */ - int Expanding; /* Are we currently expanding this macro? */ - int ArgCount; /* Number of parameters, -1 = no parens */ - unsigned MaxArgs; /* Size of formal argument list */ - Collection FormalArgs; /* Formal argument list (char*) */ + int ParamCount; /* Number of parameters, -1 = no parens */ + Collection Params; /* Parameter list (char*) */ StrBuf Replacement; /* Replacement text */ unsigned char Variadic; /* C99 variadic macro */ char Name[1]; /* Name, dynamically allocated */ @@ -120,13 +118,13 @@ INLINE int IsMacro (const char* Name) # define IsMacro(Name) (FindMacro (Name) != 0) #endif -int FindMacroArg (Macro* M, const char* Arg); -/* Search for a formal macro argument. If found, return the index of the -** argument. If the argument was not found, return -1. +int FindMacroParam (const Macro* M, const char* Param); +/* Search for a macro parameter. If found, return the index of the parameter. +** If the parameter was not found, return -1. */ -void AddMacroArg (Macro* M, const char* Arg); -/* Add a formal macro argument. */ +void AddMacroParam (Macro* M, const char* Param); +/* Add a macro parameter. */ int MacroCmp (const Macro* M1, const Macro* M2); /* Compare two macros and return zero if both are identical. */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 020df011a..8b3d43d7f 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -74,11 +74,20 @@ #define MSM_IN_DIRECTIVE 0x02U /* In PP directives scan */ #define MSM_IN_ARG_LIST 0x04U /* In macro argument scan */ #define MSM_IN_ARG_EXPANSION 0x08U /* In expansion on arguments */ -#define MSM_OP_DEFINED 0x10U /* Handle the defined operator */ -#define MSM_OP_HAS_INCLUDE 0x20U /* Handle the __has_include operator */ -#define MSM_OP_HAS_C_ATTRIBUTE 0x40U /* Handle the __has_c_attribute operator */ +#define MSM_OP_DEFINED 0x10U /* Handle the "defined" operator */ +#define MSM_OP_HAS_INCLUDE 0x20U /* Handle the "__has_include" operator */ +#define MSM_OP_HAS_C_ATTRIBUTE 0x40U /* Handle the "__has_c_attribute" operator */ #define MSM_TOK_HEADER 0x80U /* Support header tokens */ +/* Macro expansion state flags */ +#define MES_NONE 0x00U /* Nothing */ +#define MES_FIRST_TOKEN 0x01U /* Mark for detecting pp-token count in the sequence */ +#define MES_MULTIPLE_TOKEN 0x02U /* Multiple pp-tokens are detected in the sequence */ +#define MES_BEGIN_WITH_IDENT 0x04U /* The first pp-token of the sequence is an identifier */ +#define MES_HAS_REPLACEMENT 0x10U /* Macro argument has cached replacement result */ +#define MES_NO_VA_COMMA 0x20U /* Variadic macro called w/o the ',' in front of variable argument */ +#define MES_ERROR 0x80U /* Error has occurred in macro expansion */ + /* Management data for #if */ #define IFCOND_NONE 0x00U #define IFCOND_SKIP 0x01U @@ -88,6 +97,9 @@ /* Current PP if stack */ static PPIfStack* PPStack; +/* Input backup for rescan */ +static Collection* CurRescanStack; + /* Intermediate input buffers */ static StrBuf* PLine; /* Buffer for macro expansion */ static StrBuf* MLine; /* Buffer for macro expansion in #pragma */ @@ -100,8 +112,28 @@ static int FileChanged; /* Structure used when expanding macros */ typedef struct MacroExp MacroExp; struct MacroExp { - Collection ActualArgs; /* Actual arguments */ - StrBuf Replacement; /* Replacement with arguments substituted */ + Collection Args; /* Actual arguments (for function-like) */ + Collection HideSets; /* Macros hidden from expansion */ + StrBuf Tokens; /* Originally read sequence */ + unsigned IdentCount; /* Count of identifiers in the pp-token sequence */ + unsigned Flags; /* Macro argument flags */ + MacroExp* Replaced; /* Macro-replaced version of this pp-token sequence */ + unsigned FirstTokLen; /* Length of the first pp-token */ + unsigned LastTokLen; /* Length of the last pp-token */ +}; + +typedef struct HideRange HideRange; +struct HideRange +{ + HideRange* Next; + unsigned Start; + unsigned End; +}; + +typedef struct HiddenMacro HiddenMacro; +struct HiddenMacro { + const Macro* M; + HideRange* HS; }; @@ -125,8 +157,16 @@ static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFl static int ParseDirectives (unsigned ModeFlags); /* Handle directives. Return 1 if any whitespace or newlines are parsed. */ -static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags); -/* Scan for and perform macro replacement */ +static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags); +/* Scan for and perform macro replacement. Return the count of identifiers in +** the replacement result. +*/ + +static MacroExp* InitMacroExp (MacroExp* E); +/* Initialize a MacroExp structure */ + +static void DoneMacroExp (MacroExp* E); +/* Cleanup after use of a MacroExp structure */ @@ -201,17 +241,417 @@ static ppdirective_t FindPPDirectiveType (const char* Ident) +/*****************************************************************************/ +/* MacroExp helpers */ +/*****************************************************************************/ + + + +static HideRange* NewHideRange (unsigned Start, unsigned Len) +/* Create a hide range */ +{ + HideRange* HS = xmalloc (sizeof (HideRange)); + + HS->Next = 0; + HS->Start = Start; + HS->End = Start + Len; + + return HS; +} + + + +static void FreeHideRange (HideRange* HS) +/* Free a hide range */ +{ + xfree (HS); +} + + + +static HiddenMacro* NewHiddenMacro (const Macro* M) +/* Create a new struct for the hidden macro */ +{ + HiddenMacro* MHS = xmalloc (sizeof (HiddenMacro)); + + MHS->M = M; + MHS->HS = 0; + + return MHS; +} + + + +static void FreeHiddenMacro (HiddenMacro* MHS) +/* Free the struct and all ranges of the hidden macro */ +{ + HideRange* This; + HideRange* Next; + + if (MHS == 0) { + return; + } + + for (This = MHS->HS; This != 0; This = Next) { + Next = This->Next; + FreeHideRange (This); + } + + xfree (MHS); +} + + + /*****************************************************************************/ /* struct MacroExp */ /*****************************************************************************/ +static HiddenMacro* ME_FindHiddenMacro (const MacroExp* E, const Macro* M) +/* Find the macro hide set */ +{ + unsigned I; + + for (I = 0; I < CollCount (&E->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I); + if (MHS->M == M) { + return MHS; + } + } + + return 0; +} + + + +static void ME_HideMacro (unsigned Idx, unsigned Count, MacroExp* E, const Macro* M) +/* Hide the macro from the Idx'th identifier */ +{ + if (Count > 0) { + /* Find the macro hideset */ + HiddenMacro* MHS = ME_FindHiddenMacro (E, M); + HideRange** This; + + /* New hidden section */ + HideRange* NewHS = NewHideRange (Idx, Count); + + /* New macro to hide */ + if (MHS == 0) { + MHS = NewHiddenMacro (M); + CollAppend (&E->HideSets, MHS); + } + This = &MHS->HS; + + if (*This == 0) { + *This = NewHS; + } else { + /* Insert */ + while (1) { + if (*This == 0 || NewHS->Start <= (*This)->Start) { + /* Insert before */ + NewHS->Next = *This; + *This = NewHS; + break; + } else if (NewHS->Start <= (*This)->End) { + /* Insert after */ + NewHS->Next = (*This)->Next; + (*This)->Next = NewHS; + break; + } + /* Advance */ + This = &(*This)->Next; + } + + /* Merge */ + while (*This != 0) { + HideRange* Next = (*This)->Next; + + if (Next != 0 && (*This)->End >= Next->Start) { + /* Expand this to the next */ + if ((*This)->End < Next->End) { + (*This)->End = Next->End; + } + + /* Remove next */ + (*This)->Next = Next->Next; + FreeHideRange (Next); + + /* Advance */ + This = &(*This)->Next; + } else { + /* No more */ + break; + } + } + } + } +} + + + +static int ME_CanExpand (unsigned Idx, const MacroExp* E, const Macro* M) +/* Return 1 if the macro can be expanded with the Idx'th identifier */ +{ + if (E != 0) { + /* Find the macro hideset */ + HiddenMacro* MHS = ME_FindHiddenMacro (E, M); + if (MHS != 0) { + /* Check if the macro is hidden from this identifier */ + HideRange* HS = MHS->HS; + while (HS != 0) { + /* If the macro name overlaps with the range where the macro is hidden, + ** the macro cannot be expanded. + */ + if (Idx >= HS->Start && Idx < HS->End) { + return 0; + } + HS = HS->Next; + } + } + } + + return 1; +} + + + +static void ME_OffsetHideSets (unsigned Idx, unsigned Offs, MacroExp* E) +/* Adjust all macro hide set ranges for the macro expansion when the identifier +** at Idx is replaced with a count of Offs + 1 (if Offs > 0) of identifiers. +*/ +{ + if (Offs != 0) { + unsigned I; + + for (I = 0; I < CollCount (&E->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I); + HideRange* This; + + for (This = MHS->HS; This != 0; This = This->Next) { + if (Idx < This->Start) { + This->Start += Offs; + This->End += Offs; + } else if (Idx < This->End) { + This->End += Offs; + } + } + } + } +} + + + +static void ME_RemoveToken (unsigned Idx, unsigned Count, MacroExp* E) +/* Remove the Idx'th identifier token from tracking and offset all hidden +** ranges accordingly. +*/ +{ + unsigned I; + + for (I = 0; I < CollCount (&E->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I); + HideRange* This; + HideRange** Prev; + + for (Prev = &MHS->HS, This = *Prev; This != 0; This = *Prev) { + if (Idx < This->Start) { + if (This->Start - Idx >= Count) { + This->Start -= Count; + This->End -= Count; + } else { + if (This->End - Idx > Count) { + This->Start = Idx; + This->End -= Count; + } else { + /* Remove */ + (*Prev) = This->Next; + FreeHideRange (This); + continue; + } + } + } else if (Idx < This->End) { + if (This->End - Idx > Count) { + This->End -= Count; + } else { + This->End = Idx; + } + + if (This->End == This->Start) { + /* Remove */ + (*Prev) = This->Next; + FreeHideRange (This); + continue; + } + } + + Prev = &This->Next; + } + } +} + + + +static void ME_AddArgHideSets (unsigned Idx, const MacroExp* A, MacroExp* Parent) +/* Propagate the macro hide sets of the substituted argument starting as the +** Idx'th identifier of the result. +*/ +{ + unsigned I; + + /* Move the hide set generated with in the argument as it will be freed later */ + for (I = 0; I < CollCount (&A->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&A->HideSets, I); + HideRange* HS; + + for (HS = MHS->HS; HS != 0; HS = HS->Next) { + ME_HideMacro (Idx + HS->Start, HS->End - HS->Start, Parent, MHS->M); + } + } +} + + + +static void ME_DoneHideSets (MacroExp* E) +/* Free all of hidden macros for the macro expansion */ +{ + unsigned I; + + for (I = 0; I < CollCount (&E->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I); + FreeHiddenMacro (MHS); + } + DoneCollection (&E->HideSets); +} + + + +static void ME_SetTokLens (MacroExp* E, unsigned TokLen) +/* Set token lengths and flags for macro expansion struct */ +{ + E->LastTokLen = TokLen; + if ((E->Flags & MES_FIRST_TOKEN) != 0) { + E->Flags &= ~MES_FIRST_TOKEN; + E->FirstTokLen = E->LastTokLen; + } else { + E->Flags |= MES_MULTIPLE_TOKEN; + } +} + + + +static MacroExp* ME_MakeReplaced (MacroExp* A) +/* Make a replaced version of the argument */ +{ + /* Replace the parameter with actual argument tokens */ + if ((A->Flags & MES_HAS_REPLACEMENT) == 0) { + A->Replaced = xmalloc (sizeof (MacroExp)); + + InitMacroExp (A->Replaced); + SB_Reset (&A->Tokens); + + /* Propagate the hide sets */ + ME_AddArgHideSets (0, A, A->Replaced); + + /* Do macro expansion on the argument */ + A->Replaced->IdentCount = ReplaceMacros (&A->Tokens, + &A->Replaced->Tokens, + A->Replaced, + MSM_IN_ARG_EXPANSION); + + A->Flags |= MES_HAS_REPLACEMENT; + } + + return A->Replaced != 0 ? A->Replaced : A; +} + + + +static MacroExp* ME_GetOriginalArg (const MacroExp* E, unsigned Index) +/* Return an actual macro argument with the given index */ +{ + return CollAt (&E->Args, Index); +} + + + +static MacroExp* ME_GetReplacedArg (const MacroExp* E, unsigned Index) +/* Return a replaced macro argument with the given index */ +{ + return ME_MakeReplaced (CollAt (&E->Args, Index)); +} + + + +static MacroExp* ME_AppendArg (MacroExp* E, MacroExp* Arg) +/* Add a copy of Arg to the list of actual macro arguments. +** NOTE: This function will clear the token sequence of Arg! +*/ +{ + MacroExp* A = xmalloc (sizeof (MacroExp)); + + /* Initialize our MacroExp structure */ + InitMacroExp (A); + + /* Copy info about the original strings */ + A->IdentCount = Arg->IdentCount; + A->Flags = Arg->Flags; + A->FirstTokLen = Arg->FirstTokLen; + A->LastTokLen = Arg->LastTokLen; + + /* Move the contents of Arg to A */ + SB_Move (&A->Tokens, &Arg->Tokens); + + /* Add A to the list of actual arguments */ + CollAppend (&E->Args, A); + + return A; +} + + + +static void ME_ClearArgs (MacroExp* E) +/* Clear all read arguments for macro expansion */ +{ + unsigned I; + + /* Delete the list with actual arguments */ + for (I = 0; I < CollCount (&E->Args); ++I) { + MacroExp* A = CollAtUnchecked (&E->Args, I); + + /* Destroy the macro expansion structure and then free memory allocated + ** for it. + */ + DoneMacroExp (A); + xfree (A); + } + + DoneCollection (&E->Args); + InitCollection (&E->Args); +} + + + +static int ME_IsNextArgVariadic (const MacroExp* E, const Macro* M) +/* Return true if the next actual argument we will add is a variadic one */ +{ + return (M->Variadic && + M->ParamCount == (int) CollCount (&E->Args) + 1); +} + + + static MacroExp* InitMacroExp (MacroExp* E) /* Initialize a MacroExp structure */ { - InitCollection (&E->ActualArgs); - SB_Init (&E->Replacement); + InitCollection (&E->Args); + InitCollection (&E->HideSets); + SB_Init (&E->Tokens); + E->IdentCount = 0; + E->Flags = MES_FIRST_TOKEN; + E->Replaced = 0; + E->FirstTokLen = 0; + E->LastTokLen = 0; return E; } @@ -220,48 +660,12 @@ static MacroExp* InitMacroExp (MacroExp* E) static void DoneMacroExp (MacroExp* E) /* Cleanup after use of a MacroExp structure */ { - unsigned I; - - /* Delete the list with actual arguments */ - for (I = 0; I < CollCount (&E->ActualArgs); ++I) { - FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I)); + ME_ClearArgs (E); + ME_DoneHideSets (E); + SB_Done (&E->Tokens); + if (E->Replaced != 0) { + DoneMacroExp (E->Replaced); } - DoneCollection (&E->ActualArgs); - SB_Done (&E->Replacement); -} - - - -static void ME_AppendActual (MacroExp* E, StrBuf* Arg) -/* Add a copy of Arg to the list of actual macro arguments. -** NOTE: This function will clear Arg! -*/ -{ - /* Create a new string buffer */ - StrBuf* A = NewStrBuf (); - - /* Move the contents of Arg to A */ - SB_Move (A, Arg); - - /* Add A to the actual arguments */ - CollAppend (&E->ActualArgs, A); -} - - - -static StrBuf* ME_GetActual (MacroExp* E, unsigned Index) -/* Return an actual macro argument with the given index */ -{ - return CollAt (&E->ActualArgs, Index); -} - - - -static int ME_ArgIsVariadic (const MacroExp* E, const Macro* M) -/* Return true if the next actual argument we will add is a variadic one */ -{ - return (M->Variadic && - M->ArgCount == (int) CollCount (&E->ActualArgs) + 1); } @@ -272,6 +676,17 @@ static int ME_ArgIsVariadic (const MacroExp* E, const Macro* M) +static void PopRescanLine (void) +/* Pop and free a rescan input line if it reaches the end */ +{ + if (CurC == '\0' && CollCount (CurRescanStack) > 1) { + FreeStrBuf (CollPop (CurRescanStack)); + InitLine (CollLast (CurRescanStack)); + } +} + + + static int MacName (char* Ident) /* Get a macro symbol name into Ident. If we have an error, print a ** diagnostic message and clear the line. @@ -431,6 +846,32 @@ static int SkipWhitespace (int SkipLines) { int Skipped = 0; int NewLine = 0; + + if (CurRescanStack != 0 && + CollCount (CurRescanStack) > 1 && + Line == CollConstLast (CurRescanStack)) { + /* Rescanning */ + while (1) { + if (IsSpace (CurC)) { + NextChar (); + Skipped = 1; + } else if (CurC == '/' && NextC == '*') { + OldStyleComment (); + Skipped = 1; + } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { + NewStyleComment (); + Skipped = 1; + } else if (CurC == '\0') { + /* End of line, switch back input */ + PopRescanLine (); + break; + } else { + /* No more white space */ + break; + } + } + } + while (1) { if (IsSpace (CurC)) { NextChar (); @@ -521,6 +962,235 @@ static void CopyQuotedString (StrBuf* Target) +static int GetPunc (char* S) +/* Parse a punctuator token. Return 1 and store the parsed token string into S +** on success, otherwise just return 0. +*/ +{ + char C; + switch (CurC) { + + case '[': + case ']': + case '(': + case ')': + case '{': + case '}': + case '~': + case '?': + case ':': + case ';': + case ',': + /* C */ + *S++ = CurC; + NextChar (); + break; + + case '=': + case '#': + /* C or CC */ + C = *S++ = CurC; + NextChar (); + if (CurC == C) { + *S++ = C; + NextChar (); + } + break; + + case '*': + case '/': + case '%': + case '^': + case '!': + /* C or C= */ + *S++ = CurC; + NextChar (); + if (CurC == '=') { + *S++ = CurC; + NextChar (); + } + break; + + case '+': + case '&': + case '|': + /* C, CC or C= */ + C = *S++ = CurC; + NextChar (); + if (CurC == C || CurC == '=') { + *S++ = CurC; + NextChar (); + } + break; + + case '<': + case '>': + /* C, CC, C= or CC= */ + C = *S++ = CurC; + NextChar (); + if (CurC == C) { + *S++ = CurC; + if (NextC == '=') { + *S++ = NextC; + NextChar (); + } + NextChar (); + } else if (CurC == '=') { + *S++ = CurC; + NextChar (); + } + break; + + case '-': + /* C, CC, C= or C> */ + *S++ = CurC; + NextChar (); + switch (CurC) { + case '-': + case '=': + case '>': + *S++ = CurC; + NextChar (); + break; + default: + break; + } + break; + + case '.': + /* C or CCC */ + *S++ = CurC; + NextChar (); + if (CurC == '.' && NextC == '.') { + *S++ = CurC; + *S++ = NextC; + NextChar (); + NextChar (); + } + break; + + default: + return 0; + + } + + *S = '\0'; + return 1; +} + + + +static int TryPastePPTok (StrBuf* Target, + StrBuf* Appended, + unsigned FirstTokLen, + unsigned SecondTokLen) +/* Paste the whole appened pp-token sequence onto the end of the target +** pp-token sequence. Diagnose if it fails to form a valid pp-token with the +** two pp-tokens pasted together. Return 1 if succeeds. +*/ +{ + unsigned TokLen; + StrBuf* OldSource; + StrBuf Src = AUTO_STRBUF_INITIALIZER; + StrBuf Buf = AUTO_STRBUF_INITIALIZER; + + if (FirstTokLen == 0 || SecondTokLen == 0) { + SB_Append (Target, Appended); + return 1; + } + + PRECONDITION (SB_GetLen (Target) >= FirstTokLen && + SB_GetLen (Appended) >= SecondTokLen); + + /* Special casing "..", "//" and "/*" */ + if (FirstTokLen == 1) { + char C = SB_LookAt (Target, SB_GetLen (Target) - FirstTokLen); + char N = SB_LookAt (Appended, 0); + /* Avoid forming a comment introducer or an ellipsis. Note that an + ** ellipsis pp-token cannot be formed with macros anyway. + */ + if ((C == '.' && N == '.') || (C == '/' && (N == '/' || N == '*'))) { + SB_AppendChar (Target, ' '); + SB_Append (Target, Appended); + PPWarning ("Pasting formed '%c%c', an invalid preprocessing token", C, N); + + return 0; + } + } + + SB_CopyBuf (&Src, SB_GetConstBuf (Target) + SB_GetLen (Target) - FirstTokLen, FirstTokLen); + if (SecondTokLen == SB_GetLen (Appended) || IsSpace (SB_LookAt (Appended, SecondTokLen))) { + SB_AppendBuf (&Src, SB_GetConstBuf (Appended), SecondTokLen); + } else { + SB_AppendBuf (&Src, SB_GetConstBuf (Appended), SecondTokLen + 1); + } + + SB_Reset (&Src); + OldSource = InitLine (&Src); + + if (IsPPNumber (CurC, NextC)) { + /* PP-number */ + CopyPPNumber (&Buf); + } else if (IsQuote (CurC)) { + /* Quoted string */ + CopyQuotedString (&Buf); + } else { + ident Ident; + if (GetPunc (Ident)) { + /* Punctuator */ + SB_CopyStr (&Buf, Ident); + } else if (IsSym (Ident)) { + /* Identifier */ + SB_CopyStr (&Buf, Ident); + } else { + /* Unknown */ + } + } + + TokLen = SB_GetLen (&Buf); + if (TokLen < FirstTokLen + SecondTokLen) { + /* The pasting doesn't form a valid pp-token */ + while (SB_GetLen (&Buf) < FirstTokLen + SecondTokLen) { + SB_AppendChar (&Buf, CurC); + NextChar (); + } + SB_Terminate (&Buf); + PPWarning ("Pasting formed '%s', an invalid preprocessing token", + SB_GetConstBuf (&Buf)); + + /* Add a space between the tokens to avoid problems in rescanning */ + if (TokLen > FirstTokLen) { + SB_AppendChar (Target, ' '); + } + /* Append all remaining tokens */ + SB_Append (Target, Appended); + + /* No concatenation */ + TokLen = FirstTokLen; + } else { + /* Add a space after the merged token if necessary */ + SB_AppendBuf (Target, SB_GetConstBuf (Appended), SecondTokLen); + if (TokLen > FirstTokLen + SecondTokLen) { + SB_AppendChar (Target, ' '); + } + /* Append all remaining tokens */ + SB_AppendBuf (Target, + SB_GetConstBuf (Appended) + SecondTokLen, + SB_GetLen (Appended) - SecondTokLen); + } + + SB_Done (&Buf); + SB_Done (&Src); + + /* Restore old source */ + InitLine (OldSource); + + /* Return if concatenation succeeded */ + return TokLen != FirstTokLen; +} + + + static int CheckExtraTokens (const char* Name) /* Check for extra tokens at the end of the directive. Return 1 if there are ** extra tokens, otherwise 0. @@ -542,181 +1212,298 @@ static int CheckExtraTokens (const char* Name) -static void ReadMacroArgs (MacroExp* E, const Macro* M, int MultiLine) -/* Identify the arguments to a macro call as-is */ +static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, int MultiLine) +/* Identify the arguments to a macro call as-is. Return the total count of +** identifiers in the read argument list. +*/ { - int MissingParen = 0; - unsigned Parens; /* Number of open parenthesis */ - StrBuf Arg = AUTO_STRBUF_INITIALIZER; + unsigned Idx = 0; + unsigned CountInArg = 0; + unsigned Parens = 0; /* Number of open parenthesis */ + ident Ident; + MacroExp Arg; + + InitMacroExp (&Arg); /* Eat the left paren */ NextChar (); /* Read the actual macro arguments */ - Parens = 0; while (1) { /* Squeeze runs of blanks within an arg */ int OldPendingNewLines = PendingNewLines; int Skipped = SkipWhitespace (MultiLine); - if (MultiLine && CurC == '#') { + + /* Directives can only be found in an argument list that spans + ** multiple lines. + */ + if (MultiLine && OldPendingNewLines < PendingNewLines && CurC == '#') { int Newlines = 0; - while (CurC == '#') { + while (OldPendingNewLines < PendingNewLines && CurC == '#') { Newlines += PendingNewLines - OldPendingNewLines; PendingNewLines = OldPendingNewLines; OldPendingNewLines = 0; Skipped = ParseDirectives (MSM_IN_ARG_LIST) || Skipped; - Skipped = SkipWhitespace (MultiLine) || Skipped; } PendingNewLines += Newlines; } - if (Skipped && SB_NotEmpty (&Arg)) { - SB_AppendChar (&Arg, ' '); + + /* Append a space as a separator */ + if (Skipped && SB_NotEmpty (&Arg.Tokens)) { + SB_AppendChar (&Arg.Tokens, ' '); + Skipped = 1; + } else { + Skipped = 0; } - if (CurC == '(') { - /* Nested parenthesis */ - SB_AppendChar (&Arg, CurC); - NextChar (); - ++Parens; + /* Finish reading the current argument if we are not inside nested + ** parentheses or a variadic macro argument. + */ + if (Parens == 0 && + ((CurC == ',' && !ME_IsNextArgVariadic (E, M)) || CurC == ')')) { - } else if (IsQuote (CurC)) { - - /* Quoted string - just copy */ - CopyQuotedString (&Arg); - - } else if (CurC == ',' || CurC == ')') { - - if (Parens) { - /* Comma or right paren inside nested parenthesis */ - if (CurC == ')') { - --Parens; - } - SB_AppendChar (&Arg, CurC); - NextChar (); - } else if (CurC == ',' && ME_ArgIsVariadic (E, M)) { - /* It's a comma, but we're inside a variadic macro argument, so - ** just copy it and proceed. - */ - SB_AppendChar (&Arg, CurC); - NextChar (); - } else { - /* End of actual argument. Remove whitespace from the end. */ - while (IsSpace (SB_LookAtLast (&Arg))) { - SB_Drop (&Arg, 1); - } - - /* If this is not the single empty argument for a macro with - ** an empty argument list, remember it. - */ - if (CurC != ')' || SB_NotEmpty (&Arg) || M->ArgCount > 0) { - ME_AppendActual (E, &Arg); - } - - /* Check for end of macro param list */ - if (CurC == ')') { - NextChar (); - break; - } - - /* Start the next param */ - NextChar (); - SB_Clear (&Arg); + /* End of actual argument. Remove whitespace from the end. */ + while (IsSpace (SB_LookAtLast (&Arg.Tokens))) { + SB_Drop (&Arg.Tokens, 1); } + + /* If this is not the single empty argument for a macro with an + ** empty argument list, remember it. + */ + if (CurC != ')' || SB_NotEmpty (&Arg.Tokens) || M->ParamCount > 0) { + MacroExp* A = ME_AppendArg (E, &Arg); + unsigned I; + + /* Copy the hide sets from the argument list */ + for (I = 0; I < CollCount (&E->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I); + HideRange* HS; + + for (HS = MHS->HS; HS != 0; HS = HS->Next) { + /* Get the correct hide range */ + unsigned Start = NameIdx + 1 + Idx; + unsigned Len; + if (HS->Start < Start) { + if (HS->End > Start) { + Len = HS->End - Start; + } else { + /* Out of the range */ + continue; + } + Start = 0; + } else { + Len = HS->End - HS->Start; + Start = HS->Start - Start; + } + if (Start + Len > Idx + CountInArg) { + if (Idx + CountInArg > Start) { + Len = Idx + CountInArg - Start; + } else { + /* Out of the range */ + break; + } + } + ME_HideMacro (Start, Len, A, MHS->M); + } + } + + /* More argument info */ + A->IdentCount = CountInArg; + } + + Idx += CountInArg; + + /* Check for end of macro param list */ + if (CurC == ')') { + NextChar (); + break; + } + + /* Start the next param */ + NextChar (); + DoneMacroExp (&Arg); + InitMacroExp (&Arg); + CountInArg = 0; + + continue; + } else if (CurC == '\0') { + /* End of input inside macro argument list */ PPError ("Unterminated argument list invoking macro '%s'", M->Name); - MissingParen = 1; + Parens = -1; ClearLine (); + E->Flags |= MES_ERROR; + Idx = 0; break; + } else { - /* Just copy the character */ - SB_AppendChar (&Arg, CurC); - NextChar (); + unsigned LastLen = SB_GetLen (&Arg.Tokens); + + if (IsSym (Ident)) { + /* Just copy the identifier */ + SB_AppendStr (&Arg.Tokens, Ident); + + /* Count identifiers */ + ++CountInArg; + + /* Used for concatentation check */ + if ((Arg.Flags & MES_FIRST_TOKEN) != 0) { + Arg.Flags |= MES_BEGIN_WITH_IDENT; + } + } else if (IsPPNumber (CurC, NextC)) { + /* Copy a pp-number */ + CopyPPNumber (&Arg.Tokens); + } else if (IsQuote (CurC)) { + /* Quoted string - just copy */ + CopyQuotedString (&Arg.Tokens); + } else if (GetPunc (Ident)) { + /* Check nested parentheses */ + if (Ident[0] == '(') { + /* Opening nested parenthesis */ + ++Parens; + } else if (Ident[0] == ')') { + /* Closing nested parenthesis */ + --Parens; + } + /* Just copy the punctuator */ + SB_AppendStr (&Arg.Tokens, Ident); + } else { + /* Just copy the character */ + SB_AppendChar (&Arg.Tokens, CurC); + NextChar (); + + /* But don't count it */ + ++LastLen; + } + + /* Used for concatentation check */ + ME_SetTokLens (&Arg, SB_GetLen (&Arg.Tokens) - LastLen - Skipped); } } /* Compare formal and actual argument count */ - if (CollCount (&E->ActualArgs) != (unsigned) M->ArgCount) { + if (CollCount (&E->Args) != (unsigned) M->ParamCount) { - if (!MissingParen) { + if (Parens == 0) { /* Argument count mismatch */ PPError ("Macro argument count mismatch"); } /* Be sure to make enough empty arguments available */ - SB_Clear (&Arg); - while (CollCount (&E->ActualArgs) < (unsigned) M->ArgCount) { - ME_AppendActual (E, &Arg); + DoneMacroExp (&Arg); + InitMacroExp (&Arg); + Arg.Flags |= MES_HAS_REPLACEMENT; + while (CollCount (&E->Args) < (unsigned) M->ParamCount) { + ME_AppendArg (E, &Arg); } } - /* Deallocate string buf resources */ - SB_Done (&Arg); + /* Deallocate argument resources */ + DoneMacroExp (&Arg); + + /* Return the total count of identifiers in the argument list */ + return Idx; } -static void SubstMacroArgs (MacroExp* E, Macro* M) -/* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */ +static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, Macro* M, unsigned IdentCount) +/* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff. +** Return the count of identifiers found in the result. +*/ { + unsigned Idx = NameIdx; ident Ident; - int ArgIdx; + unsigned TokLen = 0; + int ParamIdx; StrBuf* OldSource; - StrBuf* Arg; - int HaveSpace; + int HaveSpace = 0; + StrBuf Buf = AUTO_STRBUF_INITIALIZER; /* Temporary buffer */ + /* Remember the current input stack and disable it for now */ + Collection* OldInputStack = UseInputStack (0); + + /* Remember the current input and switch to the macro replacement */ + unsigned OldIndex = SB_GetIndex (&M->Replacement); - /* Remember the current input and switch to the macro replacement. */ - int OldIndex = SB_GetIndex (&M->Replacement); SB_Reset (&M->Replacement); OldSource = InitLine (&M->Replacement); - /* Argument handling loop */ + /* Substitution loop */ while (CurC != '\0') { + int NeedPaste = 0; /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { - /* Check if it's a macro argument */ - if ((ArgIdx = FindMacroArg (M, Ident)) >= 0) { + /* Remember and skip any following whitespace */ + HaveSpace = SkipWhitespace (0); - /* A macro argument. Get the corresponding actual argument. */ - Arg = ME_GetActual (E, ArgIdx); - - /* Copy any following whitespace */ - HaveSpace = SkipWhitespace (0); + /* Check if it's a macro parameter */ + if ((ParamIdx = FindMacroParam (M, Ident)) >= 0) { /* If a ## operator follows, we have to insert the actual - ** argument as is, otherwise it must be macro replaced. + ** argument as-is, otherwise it must be macro-replaced. */ if (CurC == '#' && NextC == '#') { - /* ### Add placemarker if necessary */ - SB_Append (&E->Replacement, Arg); + /* Get the corresponding actual argument */ + const MacroExp* A = ME_GetOriginalArg (E, ParamIdx); + + /* For now we need no placemarkers */ + SB_Append (Target, &A->Tokens); + + /* Adjust tracking */ + ME_OffsetHideSets (Idx, A->IdentCount, E); + Idx += A->IdentCount; + + /* This will be used for concatenation */ + TokLen = A->LastTokLen; } else { - /* Replace the formal argument by a macro replaced copy - ** of the actual. - */ - SB_Reset (Arg); - MacroReplacement (Arg, &E->Replacement, 0); + /* Get the corresponding macro-replaced argument */ + const MacroExp* A = ME_GetReplacedArg (E, ParamIdx); - /* If we skipped whitespace before, re-add it now */ - if (HaveSpace) { - SB_AppendChar (&E->Replacement, ' '); - } + /* Append the replaced string */ + SB_Append (Target, &A->Tokens); + + /* Insert the range of identifiers to parent preceding this argument */ + ME_OffsetHideSets (Idx, A->IdentCount, E); + + /* Add hide range */ + ME_AddArgHideSets (Idx, A, E); + + /* Adjust tracking */ + Idx += A->IdentCount; + + /* May be used for later pp-token merge check */ + TokLen = A->LastTokLen; } - } else { /* An identifier, keep it */ - SB_AppendStr (&E->Replacement, Ident); + SB_AppendStr (Target, Ident); + /* Adjust tracking */ + ME_OffsetHideSets (Idx, 1, E); + ++Idx; + + /* May be used for later concatenation */ + TokLen = strlen (Ident); } + /* Squeeze and add the skipped whitespace back for consistency */ + if (HaveSpace) { + SB_AppendChar (Target, ' '); + } + + /* Done with this substituted argument */ + continue; + } else if (CurC == '#' && NextC == '#') { /* ## operator. */ @@ -724,127 +1511,257 @@ static void SubstMacroArgs (MacroExp* E, Macro* M) NextChar (); SkipWhitespace (0); - /* Since we need to concatenate the token sequences, remove - ** any whitespace that was added to target, since it must come + /* Since we need to concatenate the token sequences, remove the + ** last whitespace that was added to target, since it must come ** from the input. */ - while (IsSpace (SB_LookAtLast (&E->Replacement))) { - SB_Drop (&E->Replacement, 1); + if (IsBlank (SB_LookAtLast (Target))) { + SB_Drop (Target, 1); + HaveSpace = 0; } /* If the next token is an identifier which is a macro argument, - ** replace it, otherwise do nothing. + ** replace it, otherwise just add it. */ if (IsSym (Ident)) { + unsigned NewCount = 1; - /* Check if it's a macro argument */ - if ((ArgIdx = FindMacroArg (M, Ident)) >= 0) { + /* Check if it's a macro parameter */ + if ((ParamIdx = FindMacroParam (M, Ident)) >= 0) { - /* Get the corresponding actual argument and add it. */ - SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx)); + /* Get the corresponding actual argument */ + MacroExp* A = ME_GetOriginalArg (E, ParamIdx); + + /* Insert the range of identifiers to parent preceding this argument */ + ME_OffsetHideSets (Idx, A->IdentCount, E); + + /* Add hide range */ + ME_AddArgHideSets (Idx, A, E); + + /* Adjust tracking */ + NewCount = A->IdentCount; + + /* If the preceding pp-token is not a placemarker and is + ** concatenated to with an identifier, the count of tracked + ** identifiers is then one less. + */ + if (TryPastePPTok (Target, &A->Tokens, TokLen, A->FirstTokLen)) { + if (TokLen > 0 && (A->Flags & MES_BEGIN_WITH_IDENT) != 0) { + --NewCount; + ME_RemoveToken (Idx, 1, E); + } + if ((A->Flags & MES_MULTIPLE_TOKEN) == 0) { + TokLen += A->FirstTokLen; + } else { + TokLen = A->LastTokLen; + } + } else { + TokLen = A->LastTokLen; + } } else { - /* Just an ordinary identifier - add as is */ - SB_AppendStr (&E->Replacement, Ident); + unsigned Len; + + /* Just an ordinary identifier - add as-is */ + SB_CopyStr (&Buf, Ident); + + /* If the preceding pp-token is not a placemarker and is + ** concatenated to with an identifier, the count of tracked + ** identifiers is then one less. + */ + Len = SB_GetLen (&Buf); + if (TryPastePPTok (Target, &Buf, TokLen, Len)) { + if (TokLen > 0) { + --NewCount; + } + TokLen += Len; + } else { + TokLen = Len; + } + + /* Adjust tracking */ + ME_OffsetHideSets (Idx, NewCount, E); } + + /* Adjust tracking */ + Idx += NewCount; + + /* Keep the whitespace for consistency */ + HaveSpace = SkipWhitespace (0); + if (HaveSpace) { + SB_AppendChar (Target, ' '); + } + + /* Done with this concatenated identifier */ + continue; } - } else if (CurC == '#' && M->ArgCount >= 0) { + if (CurC != '\0') { + /* Non-identifiers may still be pasted together */ + NeedPaste = 1; + } - /* A # operator within a macro expansion of a function like + } else if (CurC == '#' && M->ParamCount >= 0) { + + /* A # operator within a macro expansion of a function-like ** macro. Read the following identifier and check if it's a ** macro parameter. */ + unsigned LastLen = SB_GetLen (Target); + NextChar (); SkipWhitespace (0); - if (!IsSym (Ident) || (ArgIdx = FindMacroArg (M, Ident)) < 0) { + if (!IsSym (Ident) || (ParamIdx = FindMacroParam (M, Ident)) < 0) { PPError ("'#' is not followed by a macro parameter"); } else { /* Make a valid string from Replacement */ - Arg = ME_GetActual (E, ArgIdx); - SB_Reset (Arg); - Stringize (Arg, &E->Replacement); + MacroExp* A = ME_GetOriginalArg (E, ParamIdx); + SB_Reset (&A->Tokens); + Stringize (&A->Tokens, Target); } - } else if (IsQuote (CurC)) { - CopyQuotedString (&E->Replacement); - } else { - SB_AppendChar (&E->Replacement, CurC); - NextChar (); + TokLen = SB_GetLen (Target) - LastLen; + + /* Done with this stringized argument */ + continue; + } + + /* Use the temporary buffer */ + SB_Clear (&Buf); + if (IsPPNumber (CurC, NextC)) { + CopyPPNumber (&Buf); + } else if (IsQuote (CurC)) { + CopyQuotedString (&Buf); + } else { + if (GetPunc (Ident)) { + SB_AppendStr (&Buf, Ident); + } else if (CurC != '\0') { + SB_AppendChar (&Buf, CurC); + NextChar (); + } + } + + /* Squeeze any whitespace for consistency. Especially, comments must + ** be consumed before fed to the punctuator parser, or their leading + ** '/' characters would be parsed wrongly as division operators. + */ + HaveSpace = SkipWhitespace (0); + if (HaveSpace) { + SB_AppendChar (&Buf, ' '); + } + + if (NeedPaste) { + unsigned Len = SB_GetLen (&Buf); + + /* Concatenate pp-tokens */ + if (TryPastePPTok (Target, &Buf, TokLen, Len)) { + TokLen += Len - HaveSpace; + } else { + TokLen = Len - HaveSpace; + } + } else { + /* Just append the token */ + SB_Append (Target, &Buf); + TokLen = SB_GetLen (&Buf) - HaveSpace; + } + } -#if 0 - /* Remove whitespace from the end of the line */ - while (IsSpace (SB_LookAtLast (&E->Replacement))) { - SB_Drop (&E->Replacement, 1); - } -#endif + /* Done with the temporary buffer */ + SB_Done (&Buf); + + /* Remove the macro name itself together with the arguments (if any) */ + ME_RemoveToken (Idx, 1 + IdentCount, E); /* Switch back the input */ + UseInputStack (OldInputStack); InitLine (OldSource); SB_SetIndex (&M->Replacement, OldIndex); + + /* Return the count of substituted identifiers */ + return Idx - NameIdx; } -static void ExpandMacro (StrBuf* Target, Macro* M, int MultiLine) -/* Expand a macro into Target */ +static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M, int MultiLine) +/* Expand a macro into Target. Return the count of identifiers in the result +** of the expansion. +*/ { - MacroExp E; + /* Count of identifiers */ + unsigned Count = 0; -#if 0 +#if DEV_CC65_DEBUG static unsigned V = 0; - printf ("Expanding %s(%u)\n", M->Name, ++V); + printf ("Expanding (%u) %s\n", ++V, M->Name); #endif - /* Initialize our MacroExp structure */ - InitMacroExp (&E); - /* Check if this is a function like macro */ - if (M->ArgCount >= 0) { - + if (M->ParamCount >= 0) { /* Read the actual macro arguments (with the enclosing parentheses) */ - ReadMacroArgs (&E, M, MultiLine); - + Count = ReadMacroArgs (Idx, E, M, MultiLine); } - /* Replace macro arguments handling the # and ## operators */ - SubstMacroArgs (&E, M); + if ((E->Flags & MES_ERROR) == 0) { + /* Replace macro parameters with arguments handling the # and ## operators */ + Count = SubstMacroArgs (Idx, Target, E, M, Count); + } else { + SB_CopyStr (Target, M->Name); + } - /* Forbide repeated expansion of the same macro in use */ - M->Expanding = 1; - MacroReplacement (&E.Replacement, Target, 0); - M->Expanding = 0; + if (CollCount (&E->Args) > 0) { + /* Clear all arguments */ + ME_ClearArgs (E); + } -#if 0 - printf ("Done with %s(%u)\n", E.M->Name, V--); + /* Hide this macro for the whole result of this expansion */ + ME_HideMacro (Idx, Count, E, M); + +#if DEV_CC65_DEBUG + printf ("Expanded (%u) %s to %d ident(s) at %u: %s\n", + V--, M->Name, Count, Idx, SB_GetConstBuf (Target)); #endif - /* Free memory allocated for the macro expansion structure */ - DoneMacroExp (&E); + return Count; } -static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags) -/* Scan for and perform macro replacement */ +static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags) +/* Scan for and perform macro replacement. Return the count of identifiers in +** the replacement result. +*/ { - ident Ident; + unsigned Count = 0; + StrBuf* TmpTarget = NewStrBuf (); /* Remember the current input and switch to Source */ - StrBuf* OldSource = InitLine (Source); + StrBuf* OldSource = InitLine (Source); + Collection RescanStack = AUTO_COLLECTION_INITIALIZER; + Collection* OldRescanStack = CurRescanStack; + + + CurRescanStack = &RescanStack; + CollAppend (CurRescanStack, Line); /* Loop substituting macros */ while (CurC != '\0') { + int Skipped = 0; + ident Ident; + /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { if ((ModeFlags & MSM_OP_DEFINED) != 0 && strcmp (Ident, "defined") == 0) { /* Handle the "defined" operator */ int HaveParen = 0; + /* Eat the "defined" operator */ + ME_RemoveToken (Count, 1, E); + SkipWhitespace (0); if (CurC == '(') { HaveParen = 1; @@ -853,6 +1770,7 @@ static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags } if (IsSym (Ident)) { /* Eat the identifier */ + ME_RemoveToken (Count, 1, E); SB_AppendChar (Target, IsMacro (Ident) ? '1' : '0'); if (HaveParen) { SkipWhitespace (0); @@ -869,25 +1787,46 @@ static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags SB_AppendChar (Target, '0'); } } else { - /* Check if it's an expandable macro */ Macro* M = FindMacro (Ident); - if (M != 0 && !M->Expanding) { + + /* Check if it's an expandable macro */ + if (M != 0 && ME_CanExpand (Count, E, M)) { + int MultiLine = (ModeFlags & MSM_MULTILINE) != 0; + /* Check if this is a function-like macro */ - if (M->ArgCount >= 0) { - int MultiLine = (ModeFlags & MSM_MULTILINE) != 0; - int Whitespace = SkipWhitespace (MultiLine); + if (M->ParamCount >= 0) { + int OldPendingNewLines = PendingNewLines; + int HaveSpace = SkipWhitespace (MultiLine) > 0; + + /* A function-like macro name without an immediately + ** following argument list is not subject to expansion. + */ if (CurC != '(') { - /* Function-like macro without an argument list is not replaced */ + /* No expansion */ + ++Count; + + /* Just keep the macro name */ SB_AppendStr (Target, M->Name); - if (Whitespace > 0) { + + /* Keep tracking pp-token lengths */ + if ((ModeFlags & MSM_IN_ARG_EXPANSION) != 0) { + /* Used for concatentation check */ + if ((E->Flags & MES_FIRST_TOKEN) != 0) { + E->Flags |= MES_BEGIN_WITH_IDENT; + } + ME_SetTokLens (E, strlen (M->Name)); + } + + /* Append back the whitespace */ + if (HaveSpace) { SB_AppendChar (Target, ' '); } - /* Directives can only be found in an argument list - ** that spans multiple lines. + /* Since we have already got on hold of the next + ** line, we have to go on preprocessing them. */ if (MultiLine) { - if (CurC == '#') { + if (OldPendingNewLines < PendingNewLines && CurC == '#') { /* If we were going to support #pragma in ** macro argument list, it would be output ** to OLine. @@ -903,49 +1842,143 @@ static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags /* Add the source info to preprocessor output if needed */ AddPreLine (Target); } - } else { - /* Function-like macro */ - if (OLine == 0) { - OLine = Target; - ExpandMacro (Target, M, MultiLine); - OLine = 0; - } else { - ExpandMacro (Target, M, MultiLine); - } + + /* Loop */ + goto Loop; } - } else { - /* Object-like macro */ - ExpandMacro (Target, M, 0); } - } else { - /* An identifier, keep it */ - SB_AppendStr (Target, Ident); + + /* Either an object-like or function-like macro */ + MultiLine = MultiLine && M->ParamCount >= 0; + + /* If we were going to support #pragma in macro argument + ** list, it would be output to OLine. + */ + if (MultiLine && OLine == 0) { + OLine = TmpTarget; + ExpandMacro (Count, TmpTarget, E, M, MultiLine); + OLine = 0; + } else { + ExpandMacro (Count, TmpTarget, E, M, MultiLine); + } + + /* Check for errors in expansion */ + if ((E->Flags & MES_ERROR) != 0) { + break; + } + + /* Pop the current line if it is at the end */ + PopRescanLine (); + + if (SB_GetLen (TmpTarget) > 0) { + /* Start rescanning from the temporary result */ + SB_Reset (TmpTarget); + InitLine (TmpTarget); + CollAppend (CurRescanStack, TmpTarget); + + /* Switch the buffers */ + TmpTarget = NewStrBuf (); + } + + /* Since we are rescanning, we needn't add the + ** count of just replaced identifiers right now. + */ + continue; + } + + /* An unexpandable identifier. Keep it. */ + ++Count; + SB_AppendStr (Target, Ident); + + /* Keep tracking pp-token lengths */ + if ((ModeFlags & MSM_IN_ARG_EXPANSION) != 0) { + /* Used for concatentation check */ + if ((E->Flags & MES_FIRST_TOKEN) != 0) { + E->Flags |= MES_BEGIN_WITH_IDENT; + } + ME_SetTokLens (E, strlen (Ident)); } } } else { + unsigned LastLen = SB_GetLen (Target); + if ((ModeFlags & MSM_TOK_HEADER) != 0 && (CurC == '<' || CurC == '\"')) { CopyHeaderNameToken (Target); + } else if (IsPPNumber (CurC, NextC)) { + CopyPPNumber (Target); } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else { - int Whitespace = SkipWhitespace (0); - if (Whitespace) { - SB_AppendChar (Target, ' '); - } else { - SB_AppendChar (Target, CurC); - NextChar (); + Skipped = SkipWhitespace (0); + + /* Punctuators must be checked after whitespace since comments + ** introducers may be misinterpreted as division operators. + */ + if (!Skipped) { + if (GetPunc (Ident)) { + SB_AppendStr (Target, Ident); + } else { + SB_AppendChar (Target, CurC); + NextChar (); + + /* Don't count this character */ + ++LastLen; + } } } + + /* Keep tracking pp-token lengths */ + if ((ModeFlags & MSM_IN_ARG_EXPANSION) != 0) { + ME_SetTokLens (E, SB_GetLen (Target) - LastLen); + } + } + +Loop: + /* Switch back to the previous input stream if we have finished + ** rescanning the current one. + */ + if (CurC == '\0' && CollCount (CurRescanStack) > 1) { + /* Check for rescan sequence end and pp-token pasting */ + Skipped = SkipWhitespace (0) || Skipped; + } + + /* Append a space if there hasn't been one */ + if (Skipped && !IsSpace (SB_LookAtLast (Target))) { + SB_AppendChar (Target, ' '); } } + /* Append the remaining result */ + SB_Append (Target, TmpTarget); + + /* Done with the temporary buffer */ + SB_Done (TmpTarget); + /* Drop whitespace at the end */ if (IsBlank (SB_LookAtLast (Target))) { SB_Drop (Target, 1); } + /* Sanity check */ + if ((E->Flags & MES_ERROR) == 0) { + CHECK (CollCount (CurRescanStack) == 1); + } + + /* Switch back to the old input stack */ + while (CollCount (CurRescanStack) > 1) { + FreeStrBuf (CollPop (CurRescanStack)); + } + CurRescanStack = OldRescanStack; + + /* Done with the current input stack */ + CHECK (CollCount (&RescanStack) == 1); + DoneCollection (&RescanStack); + /* Switch back the input */ InitLine (OldSource); + + /* Return the count of identifiers */ + return Count; } @@ -960,7 +1993,7 @@ static void DoDefine (void) /* Process #define directive */ { ident Ident; - Macro* M; + Macro* M = 0; Macro* Existing; int C89; unsigned Len; @@ -968,7 +2001,7 @@ static void DoDefine (void) /* Read the macro name */ SkipWhitespace (0); if (!MacName (Ident)) { - return; + goto Error_Handler; } /* Remember if we're in C89 mode */ @@ -977,20 +2010,20 @@ static void DoDefine (void) /* Check for forbidden macro names */ if (strcmp (Ident, "defined") == 0) { PPError ("'%s' cannot be used as a macro name", Ident); - return; + goto Error_Handler; } /* Create a new macro definition */ M = NewMacro (Ident); - /* Check if this is a function like macro */ + /* Check if this is a function-like macro */ if (CurC == '(') { /* Skip the left paren */ NextChar (); - /* Set the marker that this is a function like macro */ - M->ArgCount = 0; + /* Set the marker that this is a function-like macro */ + M->ParamCount = 0; /* Read the formal parameter list */ while (1) { @@ -1009,23 +2042,21 @@ static void DoDefine (void) NextChar (); if (CurC != '.' || NextC != '.') { PPError ("'...' expected"); - ClearLine (); - FreeMacro (M); - return; + goto Error_Handler; } NextChar (); NextChar (); /* Remember that the macro is variadic and use __VA_ARGS__ as - ** the argument name. + ** the parameter name. */ - AddMacroArg (M, "__VA_ARGS__"); + AddMacroParam (M, "__VA_ARGS__"); M->Variadic = 1; } else { - /* Must be macro argument name */ + /* Must be macro parameter name */ if (MacName (Ident) == 0) { - return; + goto Error_Handler; } /* __VA_ARGS__ is only allowed in post-C89 mode */ @@ -1034,12 +2065,12 @@ static void DoDefine (void) "of a C99 variadic macro"); } - /* Add the macro argument */ - AddMacroArg (M, Ident); + /* Add the macro parameter */ + AddMacroParam (M, Ident); } /* If we had an ellipsis, or the next char is not a comma, we've - ** reached the end of the macro argument list. + ** reached the end of the macro parameter list. */ SkipWhitespace (0); if (M->Variadic || CurC != ',') { @@ -1051,9 +2082,7 @@ static void DoDefine (void) /* Check for a right paren and eat it if we find one */ if (CurC != ')') { PPError ("')' expected for macro definition"); - ClearLine (); - FreeMacro (M); - return; + goto Error_Handler; } NextChar (); } @@ -1081,14 +2110,12 @@ static void DoDefine (void) SB_LookAt (&M->Replacement, 1) == '#') { /* Diagnose and bail out */ PPError ("'##' cannot appear at start of macro expansion"); - FreeMacro (M); - return; + goto Error_Handler; } else if (SB_LookAt (&M->Replacement, Len - 1) == '#' && SB_LookAt (&M->Replacement, Len - 2) == '#') { /* Diagnose and bail out */ PPError ("'##' cannot appear at end of macro expansion"); - FreeMacro (M); - return; + goto Error_Handler; } } @@ -1108,6 +2135,18 @@ static void DoDefine (void) /* Insert the new macro into the macro table */ InsertMacro (M); + + /* Success */ + return; + +Error_Handler: + + /* Cleanup */ + ClearLine (); + + if (M != 0) { + FreeMacro (M); + } } @@ -1624,7 +2663,7 @@ static int ParseDirectives (unsigned ModeFlags) Whitespace = SkipWhitespace (0) || Whitespace; } - return Whitespace != 0; + return Whitespace; } @@ -1715,7 +2754,7 @@ static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFl SkipWhitespace (0); InitMacroExp (&E); - MacroReplacement (Source, Target, ModeFlags | MSM_IN_DIRECTIVE); + ReplaceMacros (Source, Target, &E, ModeFlags | MSM_IN_DIRECTIVE); DoneMacroExp (&E); /* Restore the source input index */ @@ -1727,6 +2766,8 @@ static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFl void Preprocess (void) /* Preprocess lines count of which is affected by directives */ { + MacroExp E; + SB_Clear (PLine); /* Add the source info to preprocessor output if needed */ @@ -1744,7 +2785,9 @@ void Preprocess (void) AppendIndent (PLine, SB_GetIndex (Line)); /* Expand macros if any */ - MacroReplacement (Line, PLine, MSM_MULTILINE); + InitMacroExp (&E); + ReplaceMacros (Line, PLine, &E, MSM_MULTILINE); + DoneMacroExp (&E); /* Add the source info to preprocessor output if needed */ AddPreLine (PLine); From 2f6b5621cc97fb7719a93df2c8630fe90e375e0e Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Aug 2022 14:34:50 +0800 Subject: [PATCH 006/360] Changed handling on nested macro replacement to match up with the behavior of other major C compilers, which is unspecified by the C standard. --- src/cc65/preproc.c | 87 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 8b3d43d7f..b3404230a 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -158,8 +158,8 @@ static int ParseDirectives (unsigned ModeFlags); /* Handle directives. Return 1 if any whitespace or newlines are parsed. */ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags); -/* Scan for and perform macro replacement. Return the count of identifiers in -** the replacement result. +/* Scan for and perform macro replacement. Return the count of identifiers and +** right parentheses in the replacement result. */ static MacroExp* InitMacroExp (MacroExp* E); @@ -492,6 +492,40 @@ static void ME_RemoveToken (unsigned Idx, unsigned Count, MacroExp* E) +static void ME_HandleSemiNestedMacro (unsigned NameIdx, unsigned LastIdx, MacroExp* E) +/* Unhide the macro name from all hidesets if it was expanded with an unhidden +** right parenthesis. This is unspecified but allowed behavior according to +** ISO/IEC 9899:2018, 6.10.3.4ff. +*/ +{ + unsigned I; + + for (I = 0; I < CollCount (&E->HideSets); ++I) { + HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I); + HideRange* This; + HideRange** Prev; + + for (Prev = &MHS->HS, This = *Prev; This != 0; This = *Prev) { + if (NameIdx < This->End) { + if (NameIdx >= This->Start && LastIdx >= This->End) { + This->End = NameIdx; + if (This->End == This->Start) { + /* Remove */ + (*Prev) = This->Next; + FreeHideRange (This); + continue; + } + } + Prev = &This->Next; + } else { + break; + } + } + } +} + + + static void ME_AddArgHideSets (unsigned Idx, const MacroExp* A, MacroExp* Parent) /* Propagate the macro hide sets of the substituted argument starting as the ** Idx'th identifier of the result. @@ -1214,7 +1248,7 @@ static int CheckExtraTokens (const char* Name) static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, int MultiLine) /* Identify the arguments to a macro call as-is. Return the total count of -** identifiers in the read argument list. +** identifiers and right parentheses in the read argument list. */ { unsigned Idx = 0; @@ -1316,6 +1350,8 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in /* Check for end of macro param list */ if (CurC == ')') { + /* Count right parens */ + ++Idx; NextChar (); break; } @@ -1366,6 +1402,9 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in } else if (Ident[0] == ')') { /* Closing nested parenthesis */ --Parens; + + /* Count right parens */ + ++CountInArg; } /* Just copy the punctuator */ SB_AppendStr (&Arg.Tokens, Ident); @@ -1403,7 +1442,9 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in /* Deallocate argument resources */ DoneMacroExp (&Arg); - /* Return the total count of identifiers in the argument list */ + /* Return the total count of identifiers and right parentheses in the + ** argument list. + */ return Idx; } @@ -1411,7 +1452,7 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, Macro* M, unsigned IdentCount) /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff. -** Return the count of identifiers found in the result. +** Return the count of identifiers and right parentheses in the result. */ { unsigned Idx = NameIdx; @@ -1431,6 +1472,14 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M SB_Reset (&M->Replacement); OldSource = InitLine (&M->Replacement); + /* If the macro expansion replaces an function-like macro with an argument + ** list containing a right parenthesis outside the hidesets of previously + ** replaced macros, stop those hidesets from this replacement. This is not + ** required by the standard but just to match up with other major C + ** compilers. + */ + ME_HandleSemiNestedMacro (NameIdx, NameIdx + IdentCount, E); + /* Substitution loop */ while (CurC != '\0') { int NeedPaste = 0; @@ -1637,6 +1686,14 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M CopyQuotedString (&Buf); } else { if (GetPunc (Ident)) { + /* Count right parens. This is OK since they cannot be pasted + ** to form different punctuators with others. + */ + if (Ident[0] == ')') { + /* Adjust tracking */ + ME_OffsetHideSets (Idx, 1, E); + ++Idx; + } SB_AppendStr (&Buf, Ident); } else if (CurC != '\0') { SB_AppendChar (&Buf, CurC); @@ -1681,18 +1738,18 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M InitLine (OldSource); SB_SetIndex (&M->Replacement, OldIndex); - /* Return the count of substituted identifiers */ + /* Return the count of substituted identifiers and right parentheses */ return Idx - NameIdx; } static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M, int MultiLine) -/* Expand a macro into Target. Return the count of identifiers in the result -** of the expansion. +/* Expand a macro into Target. Return the count of identifiers and right +** parentheses in the result of the expansion. */ { - /* Count of identifiers */ + /* Count of identifiers and right parentheses */ unsigned Count = 0; #if DEV_CC65_DEBUG @@ -1732,8 +1789,8 @@ static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags) -/* Scan for and perform macro replacement. Return the count of identifiers in -** the replacement result. +/* Scan for and perform macro replacement. Return the count of identifiers and +** right parentheses in the replacement result. */ { unsigned Count = 0; @@ -1778,6 +1835,8 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi PPError ("')' expected"); ClearLine (); } else { + /* Eat the right parenthesis */ + ME_RemoveToken (Count, 1, E); NextChar (); } } @@ -1916,6 +1975,10 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi */ if (!Skipped) { if (GetPunc (Ident)) { + if (Ident[0] == ')') { + /* Count right parens */ + ++Count; + } SB_AppendStr (Target, Ident); } else { SB_AppendChar (Target, CurC); @@ -1977,7 +2040,7 @@ Loop: /* Switch back the input */ InitLine (OldSource); - /* Return the count of identifiers */ + /* Return the count of identifiers and right parentheses */ return Count; } From 6260414136e053ac6d3db2efccfca5a52216cb8c Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Aug 2022 14:34:50 +0800 Subject: [PATCH 007/360] The '#' operator in macro replacement is now checked at macro definition instead of macro expansion. --- src/cc65/preproc.c | 121 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 26 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index b3404230a..e0788ad0c 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -1663,7 +1663,8 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M NextChar (); SkipWhitespace (0); if (!IsSym (Ident) || (ParamIdx = FindMacroParam (M, Ident)) < 0) { - PPError ("'#' is not followed by a macro parameter"); + /* Should not happen, but still */ + Internal ("'#' is not followed by a macro parameter"); } else { /* Make a valid string from Replacement */ MacroExp* A = ME_GetOriginalArg (E, ParamIdx); @@ -2052,6 +2053,96 @@ Loop: +static int ParseMacroReplacement (StrBuf* Source, Macro* M) +/* Check correctness of macro definition while squeezing old and new style +** comments and other non-newline whitespace sequences. Return 1 on success +** or 0 on failure. +*/ +{ + /* Switch to the new input source */ + StrBuf* OldSource = InitLine (Source); + int HasWhiteSpace = 0; + unsigned Len; + ident Ident; + + /* Skip whitespace before the macro replacement */ + SkipWhitespace (0); + + /* Check for ## at start */ + if (CurC == '#' && NextC == '#') { + /* Diagnose and bail out */ + PPError ("'##' cannot appear at start of macro expansion"); + goto Error_Handler; + } + + /* Loop removing ws and comments */ + while (CurC != '\0') { + if (HasWhiteSpace) { + SB_AppendChar (&M->Replacement, ' '); + } else if (IsQuote (CurC)) { + CopyQuotedString (&M->Replacement); + } else { + if (M->ParamCount >= 0 && GetPunc (Ident)) { + Len = strlen (Ident); + /* Check for # */ + if (Len == 1 && Ident[0] == '#') { + HasWhiteSpace = SkipWhitespace (0); + + /* Check next pp-token */ + if (!IsSym (Ident) || FindMacroParam (M, Ident) < 0) { + PPError ("'#' is not followed by a macro parameter"); + goto Error_Handler; + } + + /* Make the replacement */ + SB_AppendChar (&M->Replacement, '#'); + if (HasWhiteSpace) { + SB_AppendChar (&M->Replacement, ' '); + } + SB_AppendStr (&M->Replacement, Ident); + } else { + SB_AppendBuf (&M->Replacement, Ident, Len); + } + } else { + SB_AppendChar (&M->Replacement, CurC); + NextChar (); + } + } + + HasWhiteSpace = SkipWhitespace (0); + } + + /* Check for ## at end */ + Len = SB_GetLen (&M->Replacement); + if (Len >= 2) { + if (SB_LookAt (&M->Replacement, Len - 1) == '#' && + SB_LookAt (&M->Replacement, Len - 2) == '#') { + /* Diagnose and bail out */ + PPError ("'##' cannot appear at end of macro expansion"); + goto Error_Handler; + } + } + + /* Terminate the new input line */ + SB_Terminate (&M->Replacement); + + /* Switch back to the old source */ + InitLine (OldSource); + + /* Success */ + return 1; + +Error_Handler: + + /* Switch back to the old source */ + InitLine (OldSource); + + /* Failure */ + return 0; +} + + + static void DoDefine (void) /* Process #define directive */ { @@ -2059,7 +2150,6 @@ static void DoDefine (void) Macro* M = 0; Macro* Existing; int C89; - unsigned Len; /* Read the macro name */ SkipWhitespace (0); @@ -2150,38 +2240,17 @@ static void DoDefine (void) NextChar (); } - /* Skip whitespace before the macro replacement */ - SkipWhitespace (0); - /* Remove whitespace and comments from the line, store the preprocessed ** line into the macro replacement buffer. */ - TranslationPhase3 (Line, &M->Replacement); - - /* Remove whitespace from the end of the line */ - while (IsSpace (SB_LookAtLast (&M->Replacement))) { - SB_Drop (&M->Replacement, 1); + if (ParseMacroReplacement (Line, M) == 0) { + goto Error_Handler; } + #if 0 printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement)); #endif - /* Check for ## at start or end */ - Len = SB_GetLen (&M->Replacement); - if (Len >= 2) { - if (SB_LookAt (&M->Replacement, 0) == '#' && - SB_LookAt (&M->Replacement, 1) == '#') { - /* Diagnose and bail out */ - PPError ("'##' cannot appear at start of macro expansion"); - goto Error_Handler; - } else if (SB_LookAt (&M->Replacement, Len - 1) == '#' && - SB_LookAt (&M->Replacement, Len - 2) == '#') { - /* Diagnose and bail out */ - PPError ("'##' cannot appear at end of macro expansion"); - goto Error_Handler; - } - } - /* Get an existing macro definition with this name */ Existing = FindMacro (M->Name); From be95cb8f58e36a8b3129607424b45d861073fea3 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Aug 2022 14:34:50 +0800 Subject: [PATCH 008/360] Fixed stringized macro argument concatenation. Example: #define s(a) L## #a. --- src/cc65/preproc.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index e0788ad0c..88ece4b36 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -1652,31 +1652,6 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M NeedPaste = 1; } - } else if (CurC == '#' && M->ParamCount >= 0) { - - /* A # operator within a macro expansion of a function-like - ** macro. Read the following identifier and check if it's a - ** macro parameter. - */ - unsigned LastLen = SB_GetLen (Target); - - NextChar (); - SkipWhitespace (0); - if (!IsSym (Ident) || (ParamIdx = FindMacroParam (M, Ident)) < 0) { - /* Should not happen, but still */ - Internal ("'#' is not followed by a macro parameter"); - } else { - /* Make a valid string from Replacement */ - MacroExp* A = ME_GetOriginalArg (E, ParamIdx); - SB_Reset (&A->Tokens); - Stringize (&A->Tokens, Target); - } - - TokLen = SB_GetLen (Target) - LastLen; - - /* Done with this stringized argument */ - continue; - } /* Use the temporary buffer */ @@ -1686,7 +1661,23 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M } else if (IsQuote (CurC)) { CopyQuotedString (&Buf); } else { - if (GetPunc (Ident)) { + if (CurC == '#' && M->ParamCount >= 0) { + /* A # operator within a macro expansion of a function-like + ** macro. Read the following identifier and check if it's a + ** macro parameter. + */ + NextChar (); + SkipWhitespace (0); + if (!IsSym (Ident) || (ParamIdx = FindMacroParam (M, Ident)) < 0) { + /* Should not happen, but still */ + Internal ("'#' is not followed by a macro parameter"); + } else { + /* Make a valid string from Replacement */ + MacroExp* A = ME_GetOriginalArg (E, ParamIdx); + SB_Reset (&A->Tokens); + Stringize (&A->Tokens, &Buf); + } + } else if (GetPunc (Ident)) { /* Count right parens. This is OK since they cannot be pasted ** to form different punctuators with others. */ From c7ff416ce99a09f06f27bf010739a4ae79cc4a80 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Aug 2022 14:34:50 +0800 Subject: [PATCH 009/360] Fixed wide strings for preprocessor. --- src/cc65/preproc.c | 36 +++++++++++++++++++++++++++++------- src/cc65/scanner.c | 12 +++++++++++- src/cc65/scanner.h | 5 +++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 88ece4b36..38b818b7d 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -965,11 +965,28 @@ static void CopyHeaderNameToken (StrBuf* Target) +static int IsQuotedString (void) +/* Retrun 1 if the incoming characters indicate a string literal or character +** constant, otherwise return 0. +*/ +{ + return IsQuote (CurC) || IsWideQuoted (CurC, NextC); +} + + + static void CopyQuotedString (StrBuf* Target) /* Copy a single or double quoted string from the input to Target. */ { /* Remember the quote character, copy it to the target buffer and skip it */ - char Quote = CurC; + char Quote; + + if (CurC == 'L') { + SB_AppendChar (Target, CurC); + NextChar (); + } + + Quote = CurC; SB_AppendChar (Target, CurC); NextChar (); @@ -1165,7 +1182,7 @@ static int TryPastePPTok (StrBuf* Target, if (IsPPNumber (CurC, NextC)) { /* PP-number */ CopyPPNumber (&Buf); - } else if (IsQuote (CurC)) { + } else if (IsQuotedString ()) { /* Quoted string */ CopyQuotedString (&Buf); } else { @@ -1391,7 +1408,7 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in } else if (IsPPNumber (CurC, NextC)) { /* Copy a pp-number */ CopyPPNumber (&Arg.Tokens); - } else if (IsQuote (CurC)) { + } else if (IsQuotedString ()) { /* Quoted string - just copy */ CopyQuotedString (&Arg.Tokens); } else if (GetPunc (Ident)) { @@ -1545,6 +1562,11 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M TokLen = strlen (Ident); } + /* Special casing for 'L' prefixing '#' */ + if (TokLen == 1 && SB_LookAtLast (Target) == 'L' && CurC == '#') { + HaveSpace = 1; + } + /* Squeeze and add the skipped whitespace back for consistency */ if (HaveSpace) { SB_AppendChar (Target, ' '); @@ -1658,7 +1680,7 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M SB_Clear (&Buf); if (IsPPNumber (CurC, NextC)) { CopyPPNumber (&Buf); - } else if (IsQuote (CurC)) { + } else if (IsQuotedString ()) { CopyQuotedString (&Buf); } else { if (CurC == '#' && M->ParamCount >= 0) { @@ -1957,7 +1979,7 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi CopyHeaderNameToken (Target); } else if (IsPPNumber (CurC, NextC)) { CopyPPNumber (Target); - } else if (IsQuote (CurC)) { + } else if (IsQuotedString ()) { CopyQuotedString (Target); } else { Skipped = SkipWhitespace (0); @@ -2070,7 +2092,7 @@ static int ParseMacroReplacement (StrBuf* Source, Macro* M) while (CurC != '\0') { if (HasWhiteSpace) { SB_AppendChar (&M->Replacement, ' '); - } else if (IsQuote (CurC)) { + } else if (IsQuotedString ()) { CopyQuotedString (&M->Replacement); } else { if (M->ParamCount >= 0 && GetPunc (Ident)) { @@ -2850,7 +2872,7 @@ static void TranslationPhase3 (StrBuf* Source, StrBuf* Target) } if (HasWhiteSpace) { SB_AppendChar (Target, ' '); - } else if (IsQuote (CurC)) { + } else if (IsQuotedString ()) { CopyQuotedString (Target); } else { SB_AppendChar (Target, CurC); diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 09dd8fef8..66ce6906e 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -235,10 +235,20 @@ void SymName (char* S) +int IsWideQuoted (char First, char Second) +/* Return 1 if the two successive characters indicate a wide string literal or +** a wide char constant, otherwise return 0. +*/ +{ + return First == 'L' && IsQuote(Second); +} + + + int IsSym (char* S) /* If a symbol follows, read it and return 1, otherwise return 0 */ { - if (IsIdent (CurC)) { + if (IsIdent (CurC) && !IsWideQuoted (CurC, NextC)) { SymName (S); return 1; } else { diff --git a/src/cc65/scanner.h b/src/cc65/scanner.h index 7a67b10ed..338ad6a65 100644 --- a/src/cc65/scanner.h +++ b/src/cc65/scanner.h @@ -282,6 +282,11 @@ void SymName (char* S); ** least of size MAX_IDENTLEN+1. */ +int IsWideQuoted (char First, char Second); +/* Return 1 if the two successive characters indicate a wide string literal or +** a wide char constant, otherwise return 0. +*/ + int IsSym (char* S); /* If a symbol follows, read it and return 1, otherwise return 0 */ From 9f8bfb859cca1667ee7df8c0124c476430481c0c Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 22 Aug 2022 14:34:50 +0800 Subject: [PATCH 010/360] Fixed handling adjacent macro expansions that should not concatenate. Example: F()G /* expansion results of F() shall not be concatenated with G */ --- src/cc65/preproc.c | 449 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 354 insertions(+), 95 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 38b818b7d..0835bac1e 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -97,8 +97,16 @@ /* Current PP if stack */ static PPIfStack* PPStack; +/* Struct for rescan */ +typedef struct RescanInputStack RescanInputStack; +struct RescanInputStack { + Collection Lines; + Collection LastTokLens; + StrBuf* PrevTok; +}; + /* Input backup for rescan */ -static Collection* CurRescanStack; +static RescanInputStack* CurRescanStack; /* Intermediate input buffers */ static StrBuf* PLine; /* Buffer for macro expansion */ @@ -168,6 +176,16 @@ static MacroExp* InitMacroExp (MacroExp* E); static void DoneMacroExp (MacroExp* E); /* Cleanup after use of a MacroExp structure */ +static int CheckPastePPTok (StrBuf* Target, unsigned TokLen, char Next); +/* Return 1 if the last pp-tokens from Source could be concatenated with any +** characters from Appended to form a new valid one. +*/ + +static void LazyCheckNextPPTok (const StrBuf* Prev, unsigned LastTokLen); +/* Memorize the previous pp-token(s) to later check for potential pp-token +** concatenation. +*/ + /*****************************************************************************/ @@ -705,22 +723,69 @@ static void DoneMacroExp (MacroExp* E) /*****************************************************************************/ -/* Code */ +/* Rescan input stack */ /*****************************************************************************/ +static void PushRescanLine (RescanInputStack* RIS, StrBuf* L, unsigned LastTokLen) +/* Push an input line to the rescan input stack */ +{ + CollAppend (&RIS->Lines, L); + /* Abuse the pointer to store an unsigned */ + CollAppend (&RIS->LastTokLens, (void*)(uintptr_t)LastTokLen); +} + + + static void PopRescanLine (void) /* Pop and free a rescan input line if it reaches the end */ { - if (CurC == '\0' && CollCount (CurRescanStack) > 1) { - FreeStrBuf (CollPop (CurRescanStack)); - InitLine (CollLast (CurRescanStack)); + if (CurC == '\0' && CollCount (&CurRescanStack->Lines) > 1) { + FreeStrBuf (CollPop (&CurRescanStack->Lines)); + InitLine (CollLast (&CurRescanStack->Lines)); + CollPop (&CurRescanStack->LastTokLens); } } +static void InitRescanInputStack (RescanInputStack* RIS) +/* Init a RescanInputStack struct */ +{ + InitCollection (&RIS->Lines); + InitCollection (&RIS->LastTokLens); + RIS->PrevTok = 0; +} + + + +static void DoneRescanInputStack (RescanInputStack* RIS) +/* Free a RescanInputStack struct. RIS must be non-NULL. */ +{ + /* Free pushed input lines */ + while (CollCount (&RIS->Lines) > 1) { + FreeStrBuf (CollPop (&RIS->Lines)); + } + /* Switch back to the old input stack */ + InitLine (CollPop (&RIS->Lines)); + + /* Free any remaining pp-tokens used for concatenation check */ + FreeStrBuf (RIS->PrevTok); + + /* Done */ + DoneCollection (&RIS->Lines); + DoneCollection (&RIS->LastTokLens); +} + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + static int MacName (char* Ident) /* Get a macro symbol name into Ident. If we have an error, print a ** diagnostic message and clear the line. @@ -881,31 +946,7 @@ static int SkipWhitespace (int SkipLines) int Skipped = 0; int NewLine = 0; - if (CurRescanStack != 0 && - CollCount (CurRescanStack) > 1 && - Line == CollConstLast (CurRescanStack)) { - /* Rescanning */ - while (1) { - if (IsSpace (CurC)) { - NextChar (); - Skipped = 1; - } else if (CurC == '/' && NextC == '*') { - OldStyleComment (); - Skipped = 1; - } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { - NewStyleComment (); - Skipped = 1; - } else if (CurC == '\0') { - /* End of line, switch back input */ - PopRescanLine (); - break; - } else { - /* No more white space */ - break; - } - } - } - + /* Rescanning */ while (1) { if (IsSpace (CurC)) { NextChar (); @@ -916,14 +957,51 @@ static int SkipWhitespace (int SkipLines) } else if (CurC == '/' && NextC == '/') { NewStyleComment (); Skipped = 1; - } else if (CurC == '\0' && SkipLines) { - /* End of line, read next */ - if (NextLine () != 0) { - ++PendingNewLines; - NewLine = 1; - Skipped = 0; + } else if (CurC == '\0') { + /* End of line */ + if (CurRescanStack != 0 && + CollCount (&CurRescanStack->Lines) > 1 && + Line == CollLast (&CurRescanStack->Lines)) { + + unsigned LastTokLen = (unsigned)(uintptr_t)CollLast (&CurRescanStack->LastTokLens); + + /* Check for potentially merged tokens */ + if (Skipped == 0 && LastTokLen != 0) { + /* Get the following input */ + StrBuf* Next = CollAtUnchecked (&CurRescanStack->Lines, + CollCount (&CurRescanStack->Lines) - 2); + char C = SB_Peek (Next); + + /* We cannot check right now if the next pp-token may be a + ** macro. + */ + if (IsIdent (C)) { + /* Memorize the previous pp-token and check it later */ + LazyCheckNextPPTok (Line, LastTokLen); + } else if (C != '\0' && !IsSpace (C)) { + /* If the two adjacent pp-tokens could be put together + ** to form a new one, we have to separate them with an + ** additional space. + */ + Skipped = CheckPastePPTok (Line, LastTokLen, SB_Peek (Next)); + } + + } + + /* switch back to previous input */ + PopRescanLine (); + + } else if (SkipLines) { + /* Read next line */ + if (NextLine () != 0) { + ++PendingNewLines; + NewLine = 1; + Skipped = 0; + } else { + /* End of input */ + break; + } } else { - /* End of input */ break; } } else { @@ -931,6 +1009,7 @@ static int SkipWhitespace (int SkipLines) break; } } + return Skipped != 0 ? Skipped : -(NewLine != 0); } @@ -1131,6 +1210,68 @@ static int GetPunc (char* S) +static int CheckPastePPTok (StrBuf* Source, unsigned TokLen, char Next) +/* Return 1 if the last pp-tokens from Source could be concatenated with any +** characters from Appended to form a new valid one. +*/ +{ + char C; + unsigned NewTokLen; + StrBuf* OldSource; + StrBuf Src = AUTO_STRBUF_INITIALIZER; + StrBuf Buf = AUTO_STRBUF_INITIALIZER; + + if (TokLen == 0 || IsBlank (SB_LookAtLast (Source))) { + return 0; + } + + PRECONDITION (SB_GetLen (Source) >= TokLen); + + /* Special casing "..", "/ /" and "/ *" that are not pp-tokens but still + ** need be separated. + */ + C = SB_LookAt (Source, SB_GetLen (Source) - TokLen); + if ((C == '.' && Next == '.') || (C == '/' && (Next == '/' || Next == '*'))) { + return 1; + } + + SB_CopyBuf (&Src, SB_GetConstBuf (Source) + SB_GetLen (Source) - TokLen, TokLen); + SB_AppendChar (&Src, Next); + + SB_Reset (&Src); + OldSource = InitLine (&Src); + + if (IsPPNumber (CurC, NextC)) { + /* PP-number */ + CopyPPNumber (&Buf); + } else if (IsQuotedString ()) { + /* Quoted string */ + CopyQuotedString (&Buf); + } else { + ident Ident; + if (GetPunc (Ident)) { + /* Punctuator */ + SB_CopyStr (&Buf, Ident); + } else if (IsSym (Ident)) { + /* Identifier */ + SB_CopyStr (&Buf, Ident); + } + } + + NewTokLen = SB_GetLen (&Buf); + + SB_Done (&Buf); + SB_Done (&Src); + + /* Restore old source */ + InitLine (OldSource); + + /* Return if concatenation succeeded */ + return NewTokLen != TokLen; +} + + + static int TryPastePPTok (StrBuf* Target, StrBuf* Appended, unsigned FirstTokLen, @@ -1150,10 +1291,18 @@ static int TryPastePPTok (StrBuf* Target, return 1; } + /* Since we need to concatenate the token sequences, remove the + ** last whitespace that was added to target, since it must come + ** from the input. + */ + if (IsBlank (SB_LookAtLast (Target))) { + SB_Drop (Target, 1); + } + PRECONDITION (SB_GetLen (Target) >= FirstTokLen && SB_GetLen (Appended) >= SecondTokLen); - /* Special casing "..", "//" and "/*" */ + /* Special casing "..", "/ /" and "/ *" */ if (FirstTokLen == 1) { char C = SB_LookAt (Target, SB_GetLen (Target) - FirstTokLen); char N = SB_LookAt (Appended, 0); @@ -1163,7 +1312,7 @@ static int TryPastePPTok (StrBuf* Target, if ((C == '.' && N == '.') || (C == '/' && (N == '/' || N == '*'))) { SB_AppendChar (Target, ' '); SB_Append (Target, Appended); - PPWarning ("Pasting formed '%c%c', an invalid preprocessing token", C, N); + PPWarning ("Pasting formed \"%c%c\", an invalid preprocessing token", C, N); return 0; } @@ -1206,7 +1355,7 @@ static int TryPastePPTok (StrBuf* Target, NextChar (); } SB_Terminate (&Buf); - PPWarning ("Pasting formed '%s', an invalid preprocessing token", + PPWarning ("Pasting formed \"%s\", an invalid preprocessing token", SB_GetConstBuf (&Buf)); /* Add a space between the tokens to avoid problems in rescanning */ @@ -1242,6 +1391,85 @@ static int TryPastePPTok (StrBuf* Target, +static void SeparatePPTok (StrBuf* Target, char Next) +/* Add a space to target if the previous pp-token could be concatenated with +** the following character. +*/ +{ + if (CurRescanStack->PrevTok != 0) { + unsigned Len = SB_GetLen (CurRescanStack->PrevTok) - SB_GetIndex (CurRescanStack->PrevTok); + + /* Check for pp-token pasting */ + if (CheckPastePPTok (CurRescanStack->PrevTok, Len, Next)) { + SB_AppendChar (Target, ' '); + } + FreeStrBuf (CurRescanStack->PrevTok); + CurRescanStack->PrevTok = 0; + } +} + + + +static void LazyCheckNextPPTok (const StrBuf* Prev, unsigned LastTokLen) +/* Memorize the previous pp-token(s) to later check for potential pp-token +** concatenation. +*/ +{ + char C; + int CheckEllipsis = 0; + unsigned NewIndex = SB_GetLen (Prev) - LastTokLen; + + PRECONDITION (SB_GetLen (Prev) >= LastTokLen); + + /* Check for some special cases */ + C = SB_AtUnchecked (Prev, NewIndex); + + /* We may exclude certain punctuators for speedups. As newer C standards + ** could add more punctuators such as "[[", "]]", "::" and so on, this + ** check might need changes accordingly. + */ + if (C == '[' || C == ']' || C == '(' || C == ')' || + C == '{' || C == '}' || C == '~' || C == '?' || + C == ':' || C == ';' || C == ',') { + /* These punctuators cannot be concatenated */ + return; + } + + /* Special check for .. */ + if (NewIndex > 0 && + C == '.' && + SB_AtUnchecked (Prev, NewIndex - 1) == '.') { + /* Save the preceding '.' as well */ + CheckEllipsis = 1; + } + + if (CurRescanStack->PrevTok != 0) { + unsigned OldIndex = SB_GetIndex (CurRescanStack->PrevTok); + unsigned OldLen = SB_GetLen (CurRescanStack->PrevTok) - OldIndex; + unsigned NewLen = SB_GetLen (Prev) - NewIndex; + if (OldLen == NewLen && + strncmp (SB_GetConstBuf (CurRescanStack->PrevTok) + OldIndex - CheckEllipsis, + SB_GetConstBuf (Prev) + NewIndex - CheckEllipsis, + OldLen + CheckEllipsis) == 0) { + /* Same pp-token, keep using the old one */ + } else { + /* Logic error */ + SB_Terminate (CurRescanStack->PrevTok); + Internal ("Unchecked pp-token concatenation: \"%s\"", + SB_GetConstBuf (CurRescanStack->PrevTok) + SB_GetIndex (CurRescanStack->PrevTok)); + } + } else { + /* Memorize the current line */ + CurRescanStack->PrevTok = NewStrBuf (); + SB_CopyBuf (CurRescanStack->PrevTok, + SB_GetConstBuf (Prev) + NewIndex - CheckEllipsis, + LastTokLen + CheckEllipsis); + SB_Reset (CurRescanStack->PrevTok); + } +} + + + static int CheckExtraTokens (const char* Name) /* Check for extra tokens at the end of the directive. Return 1 if there are ** extra tokens, otherwise 0. @@ -1315,7 +1543,7 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in ((CurC == ',' && !ME_IsNextArgVariadic (E, M)) || CurC == ')')) { /* End of actual argument. Remove whitespace from the end. */ - while (IsSpace (SB_LookAtLast (&Arg.Tokens))) { + while (IsBlank (SB_LookAtLast (&Arg.Tokens))) { SB_Drop (&Arg.Tokens, 1); } @@ -1467,9 +1695,10 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in -static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, Macro* M, unsigned IdentCount) +static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, Macro* M, unsigned* IdentCount) /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff. -** Return the count of identifiers and right parentheses in the result. +** Return the length of the last pp-token in the result and output the count +** of identifiers and right parentheses in the result to *IdentCount. */ { unsigned Idx = NameIdx; @@ -1495,7 +1724,7 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M ** required by the standard but just to match up with other major C ** compilers. */ - ME_HandleSemiNestedMacro (NameIdx, NameIdx + IdentCount, E); + ME_HandleSemiNestedMacro (NameIdx, NameIdx + *IdentCount, E); /* Substitution loop */ while (CurC != '\0') { @@ -1518,6 +1747,11 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M /* Get the corresponding actual argument */ const MacroExp* A = ME_GetOriginalArg (E, ParamIdx); + /* Separate with a white space if necessary */ + if (CheckPastePPTok (Target, TokLen, SB_Peek (&A->Tokens))) { + SB_AppendChar (Target, ' '); + } + /* For now we need no placemarkers */ SB_Append (Target, &A->Tokens); @@ -1533,6 +1767,11 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M /* Get the corresponding macro-replaced argument */ const MacroExp* A = ME_GetReplacedArg (E, ParamIdx); + /* Separate with a white space if necessary */ + if (CheckPastePPTok (Target, TokLen, SB_Peek (&A->Tokens))) { + SB_AppendChar (Target, ' '); + } + /* Append the replaced string */ SB_Append (Target, &A->Tokens); @@ -1568,7 +1807,7 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M } /* Squeeze and add the skipped whitespace back for consistency */ - if (HaveSpace) { + if (HaveSpace && !IsBlank (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } @@ -1577,20 +1816,11 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M } else if (CurC == '#' && NextC == '#') { - /* ## operator. */ + /* ## operator */ NextChar (); NextChar (); SkipWhitespace (0); - /* Since we need to concatenate the token sequences, remove the - ** last whitespace that was added to target, since it must come - ** from the input. - */ - if (IsBlank (SB_LookAtLast (Target))) { - SB_Drop (Target, 1); - HaveSpace = 0; - } - /* If the next token is an identifier which is a macro argument, ** replace it, otherwise just add it. */ @@ -1661,7 +1891,7 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M /* Keep the whitespace for consistency */ HaveSpace = SkipWhitespace (0); - if (HaveSpace) { + if (HaveSpace && !IsBlank (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } @@ -1720,23 +1950,24 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M ** '/' characters would be parsed wrongly as division operators. */ HaveSpace = SkipWhitespace (0); - if (HaveSpace) { - SB_AppendChar (&Buf, ' '); - } if (NeedPaste) { unsigned Len = SB_GetLen (&Buf); /* Concatenate pp-tokens */ if (TryPastePPTok (Target, &Buf, TokLen, Len)) { - TokLen += Len - HaveSpace; + TokLen += Len; } else { - TokLen = Len - HaveSpace; + TokLen = Len; } } else { /* Just append the token */ SB_Append (Target, &Buf); - TokLen = SB_GetLen (&Buf) - HaveSpace; + TokLen = SB_GetLen (&Buf); + } + + if (HaveSpace && !IsBlank (SB_LookAtLast (Target))) { + SB_AppendChar (Target, ' '); } } @@ -1745,26 +1976,36 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M SB_Done (&Buf); /* Remove the macro name itself together with the arguments (if any) */ - ME_RemoveToken (Idx, 1 + IdentCount, E); + ME_RemoveToken (Idx, 1 + *IdentCount, E); + + /* Hide this macro for the whole result of this expansion */ + ME_HideMacro (NameIdx, Idx - NameIdx, E, M); /* Switch back the input */ UseInputStack (OldInputStack); InitLine (OldSource); SB_SetIndex (&M->Replacement, OldIndex); - /* Return the count of substituted identifiers and right parentheses */ - return Idx - NameIdx; + /* Set the count of identifiers and right parentheses in the result */ + *IdentCount = Idx - NameIdx; + + /* Return the length of the last pp-token */ + return TokLen; } static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M, int MultiLine) -/* Expand a macro into Target. Return the count of identifiers and right -** parentheses in the result of the expansion. +/* Expand a macro into Target. Return the length of the last pp-token in the +** result of the expansion. */ { - /* Count of identifiers and right parentheses */ - unsigned Count = 0; + unsigned Count = 0; /* Count of identifiers and right parentheses */ + unsigned Len = 0; /* Length of the last pp-token in the result */ + + /* Disable previous pp-token spacing checking */ + StrBuf* PrevTok = CurRescanStack->PrevTok; + CurRescanStack->PrevTok = 0; #if DEV_CC65_DEBUG static unsigned V = 0; @@ -1779,7 +2020,7 @@ static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M if ((E->Flags & MES_ERROR) == 0) { /* Replace macro parameters with arguments handling the # and ## operators */ - Count = SubstMacroArgs (Idx, Target, E, M, Count); + Len = SubstMacroArgs (Idx, Target, E, M, &Count); } else { SB_CopyStr (Target, M->Name); } @@ -1789,15 +2030,17 @@ static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M ME_ClearArgs (E); } - /* Hide this macro for the whole result of this expansion */ - ME_HideMacro (Idx, Count, E, M); - #if DEV_CC65_DEBUG printf ("Expanded (%u) %s to %d ident(s) at %u: %s\n", V--, M->Name, Count, Idx, SB_GetConstBuf (Target)); #endif - return Count; + /* Reenable previous pp-token concatenation checking */ + FreeStrBuf (CurRescanStack->PrevTok); + CurRescanStack->PrevTok = PrevTok; + + /* Return the length of the last pp-token in the expansion result */ + return Len; } @@ -1811,13 +2054,13 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi StrBuf* TmpTarget = NewStrBuf (); /* Remember the current input and switch to Source */ - StrBuf* OldSource = InitLine (Source); - Collection RescanStack = AUTO_COLLECTION_INITIALIZER; - Collection* OldRescanStack = CurRescanStack; - + StrBuf* OldSource = InitLine (Source); + RescanInputStack RescanStack; + RescanInputStack* OldRescanStack = CurRescanStack; + InitRescanInputStack (&RescanStack); + PushRescanLine (&RescanStack, Line, 0); CurRescanStack = &RescanStack; - CollAppend (CurRescanStack, Line); /* Loop substituting macros */ while (CurC != '\0') { @@ -1839,6 +2082,10 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi NextChar (); SkipWhitespace (0); } + + /* Add a space to separate the result if necessary */ + SeparatePPTok (Target, '0'); + if (IsSym (Ident)) { /* Eat the identifier */ ME_RemoveToken (Count, 1, E); @@ -1864,7 +2111,8 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* Check if it's an expandable macro */ if (M != 0 && ME_CanExpand (Count, E, M)) { - int MultiLine = (ModeFlags & MSM_MULTILINE) != 0; + int MultiLine = (ModeFlags & MSM_MULTILINE) != 0; + unsigned LastTokLen; /* Check if this is a function-like macro */ if (M->ParamCount >= 0) { @@ -1878,7 +2126,8 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* No expansion */ ++Count; - /* Just keep the macro name */ + /* Add a space to separate the macro name if necessary */ + SeparatePPTok (Target, M->Name[0]); SB_AppendStr (Target, M->Name); /* Keep tracking pp-token lengths */ @@ -1929,10 +2178,10 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi */ if (MultiLine && OLine == 0) { OLine = TmpTarget; - ExpandMacro (Count, TmpTarget, E, M, MultiLine); + LastTokLen = ExpandMacro (Count, TmpTarget, E, M, MultiLine); OLine = 0; } else { - ExpandMacro (Count, TmpTarget, E, M, MultiLine); + LastTokLen = ExpandMacro (Count, TmpTarget, E, M, MultiLine); } /* Check for errors in expansion */ @@ -1947,7 +2196,7 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* Start rescanning from the temporary result */ SB_Reset (TmpTarget); InitLine (TmpTarget); - CollAppend (CurRescanStack, TmpTarget); + PushRescanLine (CurRescanStack, TmpTarget, LastTokLen); /* Switch the buffers */ TmpTarget = NewStrBuf (); @@ -1961,6 +2210,9 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* An unexpandable identifier. Keep it. */ ++Count; + + /* Add a space to separate the macro name if necessary */ + SeparatePPTok (Target, Ident[0]); SB_AppendStr (Target, Ident); /* Keep tracking pp-token lengths */ @@ -1973,7 +2225,12 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi } } } else { - unsigned LastLen = SB_GetLen (Target); + unsigned LastLen; + + /* Add a space to separate the macro name if necessary */ + SeparatePPTok (Target, CurC); + + LastLen = SB_GetLen (Target); if ((ModeFlags & MSM_TOK_HEADER) != 0 && (CurC == '<' || CurC == '\"')) { CopyHeaderNameToken (Target); @@ -1994,6 +2251,14 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi ++Count; } SB_AppendStr (Target, Ident); + + /* If an identifier follows immediately, it could be a macro + ** expanded later that occasionally need a space to separate. + */ + if (IsIdent (CurC)) { + /* Memorize the previous pp-token and check it later */ + LazyCheckNextPPTok (Target, strlen (Ident)); + } } else { SB_AppendChar (Target, CurC); NextChar (); @@ -2014,7 +2279,7 @@ Loop: /* Switch back to the previous input stream if we have finished ** rescanning the current one. */ - if (CurC == '\0' && CollCount (CurRescanStack) > 1) { + if (CurC == '\0' && CollCount (&CurRescanStack->Lines) > 1) { /* Check for rescan sequence end and pp-token pasting */ Skipped = SkipWhitespace (0) || Skipped; } @@ -2038,18 +2303,12 @@ Loop: /* Sanity check */ if ((E->Flags & MES_ERROR) == 0) { - CHECK (CollCount (CurRescanStack) == 1); + CHECK (CollCount (&CurRescanStack->Lines) == 1); } - /* Switch back to the old input stack */ - while (CollCount (CurRescanStack) > 1) { - FreeStrBuf (CollPop (CurRescanStack)); - } - CurRescanStack = OldRescanStack; - /* Done with the current input stack */ - CHECK (CollCount (&RescanStack) == 1); - DoneCollection (&RescanStack); + DoneRescanInputStack (CurRescanStack); + CurRescanStack = OldRescanStack; /* Switch back the input */ InitLine (OldSource); From 6096a24f1dea135e0d435d72df0c714ff5b0b828 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 03:41:48 +0200 Subject: [PATCH 011/360] dont add whitespace after a label to the actual label, this fixes the root cause of #1252 --- src/cc65/codeseg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index e621147ab..5949c0c6f 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -399,7 +399,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) default: /* Absolute, maybe indexed */ - L = ReadToken (L, ",", Arg, sizeof (Arg)); + L = ReadToken (L, ", ", Arg, sizeof (Arg)); + if (*L == ' ') { + L = SkipSpace (L+1); + } if (*L == '\0') { /* Absolute, zeropage or branch */ if ((OPC->Info & OF_BRA) != 0) { From d371046ae4c95643c69bbe26e8e0f02dce43716c Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 03:43:02 +0200 Subject: [PATCH 012/360] Despite not technically needed, it seems to be desirable to remove all trailing whitespace from inline assembly --- src/cc65/codegen.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 326d751b6..e521fff73 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -4921,5 +4921,25 @@ void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth) void g_asmcode (struct StrBuf* B) /* Output one line of assembler code. */ { - AddCodeLine ("%.*s", (int) SB_GetLen (B), SB_GetConstBuf (B)); + int len = (int) SB_GetLen(B); + const char *buf = SB_GetConstBuf(B); + + /* remove whitespace at end of line */ + /* NOTE: This masks problems in ParseInsn(), which in some cases seems to + rely on no whitespace being present at the end of a line in generated + code (see issue #1252). However, it generally seems to be a good + idea to remove trailing whitespace from (inline) assembly, so we + do it anyway. */ + while (len) { + switch (buf[len - 1]) { + case '\n': + case ' ': + case '\t': + --len; + continue; + } + break; + } + + AddCodeLine ("%.*s", len, buf); } From ce6ee1b8919e40a25cd4dddad4eacbc9256160ce Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 03:43:54 +0200 Subject: [PATCH 013/360] test some more possible cases and move test into test/val --- test/misc/Makefile | 8 -------- test/misc/bug1252.c | 19 ------------------- test/val/bug1252.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 27 deletions(-) delete mode 100644 test/misc/bug1252.c create mode 100644 test/val/bug1252.c diff --git a/test/misc/Makefile b/test/misc/Makefile index e761b1e3e..e77d37b29 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -58,14 +58,6 @@ $(ISEQUAL): ../isequal.c | $(WORKDIR) define PRG_template -# should compile, but gives an error -$(WORKDIR)/bug1252.$1.$2.prg: bug1252.c | $(WORKDIR) - @echo "FIXME: " $$@ "currently does not compile." - $(if $(QUIET),echo misc/bug1252.$1.$2.prg) - $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) - $(NOT) $(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR) -# $(NOT) $(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR) - # should compile, but gives an error $(WORKDIR)/bug1768.$1.$2.prg: bug1768.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." diff --git a/test/misc/bug1252.c b/test/misc/bug1252.c deleted file mode 100644 index 599aa064b..000000000 --- a/test/misc/bug1252.c +++ /dev/null @@ -1,19 +0,0 @@ - -#include - -int main(void) -{ -// this works -c_label: - asm("inx\n" - "bne %g\n", - c_label); - -// this does not work -c_label2: - asm("inx\n" - "bne %g \n", - c_label2); - - return EXIT_SUCCESS; -} diff --git a/test/val/bug1252.c b/test/val/bug1252.c new file mode 100644 index 000000000..ab4fd21fc --- /dev/null +++ b/test/val/bug1252.c @@ -0,0 +1,45 @@ + +// bug #1252 - inline asm: cc65 chokes on label ref if space/tab follows + +#include + +int main(void) +{ +// first test the recommended way to use labels in inline assembly: + +// this works +c_label: + asm("inx\n" + "bne %g\n", + c_label); + +// this does not work +c_label2: + asm("inx\n" + "bne %g \n", + c_label2); + +// now the following is from the original bug report. note that using labels +// this way only works by chance - the name of the label may clash with +// generated labels + +// this works + asm("label1: inx\n" + "bne label1\n"); + +// this does not work + asm("label2: inx\n" + "bne label2 \n"); + +// a variant of the above using local labels. + +// this works + asm("@label1: inx\n" + "bne @label1\n"); + +// this does not work + asm("@label2: inx\n" + "bne @label2 \n"); + + return EXIT_SUCCESS; +} From 8e5f6b822d7b5ff3a0d4b601188ebaa68399a4dc Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 20:05:11 +0200 Subject: [PATCH 014/360] fix setjmp.h --- include/setjmp.h | 4 ++-- libsrc/common/setjmp.s | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/setjmp.h b/include/setjmp.h index 460829e38..5fac25634 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -42,8 +42,8 @@ typedef char jmp_buf [5]; -int __fastcall__ _setjmp (jmp_buf buf); -#define setjmp _setjmp /* ISO insists on a macro */ +int __fastcall__ __setjmp (jmp_buf buf); +#define setjmp __setjmp /* ISO insists on a macro */ void __fastcall__ longjmp (jmp_buf buf, int retval) __attribute__((noreturn)); diff --git a/libsrc/common/setjmp.s b/libsrc/common/setjmp.s index a763ac3ec..886853368 100644 --- a/libsrc/common/setjmp.s +++ b/libsrc/common/setjmp.s @@ -2,15 +2,15 @@ ; 1998-06-06, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; int __fastcall__ setjmp (jmp_buf buf); +; int __fastcall__ __setjmp (jmp_buf buf); ; - .export __setjmp + .export ___setjmp .import return0 .importzp sp, ptr1 -__setjmp: +___setjmp: sta ptr1 ; Save buf stx ptr1+1 ldy #0 From 9246775ebee5aa5790d09883cb6b52277df24e6e Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 20:08:13 +0200 Subject: [PATCH 015/360] use __afailed instead of _afailed --- include/assert.h | 4 ++-- libsrc/common/_afailed.c | 2 +- libsrc/geos-common/common/_afailed.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/assert.h b/include/assert.h index a4dcd5d7f..ca8d4acc1 100644 --- a/include/assert.h +++ b/include/assert.h @@ -42,8 +42,8 @@ #ifdef NDEBUG # define assert(expr) #else -extern void __fastcall__ _afailed (const char*, unsigned); -# define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__)) +extern void __fastcall__ __afailed (const char*, unsigned); +# define assert(expr) ((expr)? (void)0 : __afailed(__FILE__, __LINE__)) #endif /* TODO: Guard with #if __CC65_STD__ >= __CC65_STD_C11__ if there diff --git a/libsrc/common/_afailed.c b/libsrc/common/_afailed.c index ab8b94ca6..01e8d5397 100644 --- a/libsrc/common/_afailed.c +++ b/libsrc/common/_afailed.c @@ -12,7 +12,7 @@ #include -void __fastcall__ _afailed (char* file, unsigned line) +void __fastcall__ __afailed (char* file, unsigned line) { raise (SIGABRT); fprintf (stderr, "ASSERTION FAILED IN %s:%u\n", file, line); diff --git a/libsrc/geos-common/common/_afailed.c b/libsrc/geos-common/common/_afailed.c index 97727d605..acc437fb0 100644 --- a/libsrc/geos-common/common/_afailed.c +++ b/libsrc/geos-common/common/_afailed.c @@ -8,7 +8,7 @@ #include #include -void _afailed (char* file, unsigned line) +void __afailed (char* file, unsigned line) { ExitTurbo(); From f70020a2b8b5bf03ddad690191a02eab4697d758 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 20:18:34 +0200 Subject: [PATCH 016/360] use __sig_ign and __sig_dft instead of _sig_ign and _sig_dft --- asminc/signal.inc | 4 ++-- include/signal.h | 8 ++++---- libsrc/common/raise.s | 4 ++-- libsrc/common/signal.s | 4 ++-- libsrc/common/sigtable.s | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/asminc/signal.inc b/asminc/signal.inc index ebde07e42..597cad413 100644 --- a/asminc/signal.inc +++ b/asminc/signal.inc @@ -49,8 +49,8 @@ SIGCOUNT = 6 ; Number of signals .global sigtable ; Function declarations -.global __sig_ign -.global __sig_dfl +.global ___sig_ign +.global ___sig_dfl .global _signal .global _raise diff --git a/include/signal.h b/include/signal.h index 0d5f6ad09..d67cebf7c 100644 --- a/include/signal.h +++ b/include/signal.h @@ -45,12 +45,12 @@ typedef unsigned char sig_atomic_t; typedef void __fastcall__ (*__sigfunc) (int); /* Functions that implement SIG_IGN and SIG_DFL */ -void __fastcall__ _sig_ign (int); -void __fastcall__ _sig_dfl (int); +void __fastcall__ __sig_ign (int); +void __fastcall__ __sig_dfl (int); /* Standard signal handling functions */ -#define SIG_DFL _sig_dfl -#define SIG_IGN _sig_ign +#define SIG_DFL __sig_dfl +#define SIG_IGN __sig_ign #define SIG_ERR ((__sigfunc) 0x0000) /* Signal numbers */ diff --git a/libsrc/common/raise.s b/libsrc/common/raise.s index 07898ef90..205bbd471 100644 --- a/libsrc/common/raise.s +++ b/libsrc/common/raise.s @@ -33,9 +33,9 @@ _raise: ; introduce race conditions, but it's the simplest way to satisfy the ; standard). - lda #<__sig_dfl + lda #<___sig_dfl sta sigtable,x - lda #>__sig_dfl + lda #>___sig_dfl sta sigtable+1,x ; Restore the signal number and call the function diff --git a/libsrc/common/signal.s b/libsrc/common/signal.s index 333072801..40262c457 100644 --- a/libsrc/common/signal.s +++ b/libsrc/common/signal.s @@ -54,7 +54,7 @@ _signal: pla tax pla -__sig_ign: +___sig_ign: rts ; Error entry: We use our knowledge that SIG_ERR is zero here to save a byte @@ -63,6 +63,6 @@ invalidsig: lda # Date: Sun, 28 Aug 2022 20:22:25 +0200 Subject: [PATCH 017/360] use __clocks_per_sec instead of _clocks_per_sec --- include/time.h | 4 ++-- libsrc/atari/clock.s | 6 +++--- libsrc/atari7800/clocks_per_sec.s | 6 +++--- libsrc/lynx/clock.s | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/time.h b/include/time.h index 99bb1c8e3..642d68c4e 100644 --- a/include/time.h +++ b/include/time.h @@ -89,8 +89,8 @@ struct tm { # define CLOCKS_PER_SEC 10 #elif defined(__ATARI__) || defined (__LYNX__) /* Read the clock rate at runtime */ -clock_t _clocks_per_sec (void); -# define CLOCKS_PER_SEC _clocks_per_sec() +clock_t __clocks_per_sec (void); +# define CLOCKS_PER_SEC __clocks_per_sec() #endif #define CLOCK_REALTIME 0 diff --git a/libsrc/atari/clock.s b/libsrc/atari/clock.s index 853870520..42809c4a4 100644 --- a/libsrc/atari/clock.s +++ b/libsrc/atari/clock.s @@ -3,10 +3,10 @@ ; originally by Ullrich von Bassewitz and Sidney Cadot ; ; clock_t clock (void); -; clock_t _clocks_per_sec (void); +; clock_t __clocks_per_sec (void); ; - .export _clock, __clocks_per_sec + .export _clock, ___clocks_per_sec .importzp sreg .include "atari.inc" @@ -28,7 +28,7 @@ .endproc -.proc __clocks_per_sec +.proc ___clocks_per_sec ldx #$00 ; Clear byte 1 of return value stx sreg ; Clear byte 2 of return value diff --git a/libsrc/atari7800/clocks_per_sec.s b/libsrc/atari7800/clocks_per_sec.s index e2c7d9d8d..d9179448f 100644 --- a/libsrc/atari7800/clocks_per_sec.s +++ b/libsrc/atari7800/clocks_per_sec.s @@ -1,10 +1,10 @@ ; ; 2022-03-15, Karri Kaksonen ; -; clock_t _clocks_per_sec (void); +; clock_t __clocks_per_sec (void); ; - .export __clocks_per_sec + .export ___clocks_per_sec .import sreg: zp .import _paldetected @@ -17,7 +17,7 @@ ;----------------------------------------------------------------------------- ; Return the number of clock ticks in one second. ; - .proc __clocks_per_sec + .proc ___clocks_per_sec lda #0 tax diff --git a/libsrc/lynx/clock.s b/libsrc/lynx/clock.s index e29799df6..d881e5a67 100644 --- a/libsrc/lynx/clock.s +++ b/libsrc/lynx/clock.s @@ -3,13 +3,13 @@ ; 2012-02-06, Greg King ; ; clock_t clock (void); -; clock_t _clocks_per_sec (void); +; clock_t __clocks_per_sec (void); ; ; clocks_per_sec()'s test-values are based on the numbers in "set_tv.s". ; If you change the numbers there, then change them here, too. ; - .export _clock, __clocks_per_sec, clock_count + .export _clock, ___clocks_per_sec, clock_count .interruptor update_clock, 2 ; (low priority) .constructor init_clock @@ -38,7 +38,7 @@ ;----------------------------------------------------------------------------- ; Return the number of clock ticks in one second. ; -__clocks_per_sec: +___clocks_per_sec: ldx #$00 ; >50, >60, >75 ldy PBKUP lda #<75 From 5d390489a8f754abfd032af858b6ed5686553187 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 21:36:22 +0200 Subject: [PATCH 018/360] fix underscores in errno (and related) headers --- asminc/errno.inc | 8 ++++---- include/cbm.h | 8 ++++---- include/dio.h | 6 +++--- include/errno.h | 30 ++++++++++++++++++++---------- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/asminc/errno.inc b/asminc/errno.inc index 1efe88cda..2e876c7ac 100644 --- a/asminc/errno.inc +++ b/asminc/errno.inc @@ -4,10 +4,10 @@ ; Variables and functions - .global __errno, __oserror - .global __osmaperrno - .global __seterrno - .global __directerrno, __mappederrno + .global ___errno, ___oserror + .global ___osmaperrno + .global ___seterrno + .global ___directerrno, ___mappederrno ; Error codes, must match the values in the C headers .enum diff --git a/include/cbm.h b/include/cbm.h index cceb76b1b..0679b2d65 100644 --- a/include/cbm.h +++ b/include/cbm.h @@ -225,7 +225,7 @@ void cbm_k_untlk (void); -/* The cbm_* I/O functions below set _oserror (see errno.h), +/* The cbm_* I/O functions below set __oserror (see errno.h), ** in case of an error. ** ** error-code BASIC error @@ -251,7 +251,7 @@ unsigned int __fastcall__ cbm_load (const char* name, unsigned char device, void ** address of the file if "data" is the null pointer (like load"name",8,1 ** in BASIC). ** Returns number of bytes that were loaded if loading was successful; -** otherwise 0, "_oserror" contains an error-code, then (see table above). +** otherwise 0, "__oserror" contains an error-code, then (see table above). */ unsigned char __fastcall__ cbm_save (const char* name, unsigned char device, @@ -274,7 +274,7 @@ void __fastcall__ cbm_close (unsigned char lfn); int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size); /* Reads up to "size" bytes from a file into "buffer". ** Returns the number of actually-read bytes, 0 if there are no bytes left. -** -1 in case of an error; then, _oserror contains an error-code (see table +** -1 in case of an error; then, __oserror contains an error-code (see table ** above). (Remember: 0 means end-of-file; -1 means error.) */ @@ -282,7 +282,7 @@ int __fastcall__ cbm_write (unsigned char lfn, const void* buffer, unsigned int size); /* Writes up to "size" bytes from "buffer" to a file. ** Returns the number of actually-written bytes, or -1 in case of an error; -** _oserror contains an error-code, then (see above table). +** __oserror contains an error-code, then (see above table). */ unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...); diff --git a/include/dio.h b/include/dio.h index 4201728cc..2521a90ff 100644 --- a/include/dio.h +++ b/include/dio.h @@ -35,9 +35,9 @@ -/* Please note: All functions in this file will set _oserror *and* return its -** value. The only exception is dio_open, which will return NULL, but _oserror -** will be set. All function will also set _oserror in case of successful +/* Please note: All functions in this file will set __oserror *and* return its +** value. The only exception is dio_open, which will return NULL, but __oserror +** will be set. All function will also set __oserror in case of successful ** execution, effectively clearing it. */ diff --git a/include/errno.h b/include/errno.h index 92d304938..c762e8b1c 100644 --- a/include/errno.h +++ b/include/errno.h @@ -45,12 +45,17 @@ /* Operating system specific error code */ -extern unsigned char _oserror; +extern unsigned char __oserror; -extern int _errno; +#if __CC65_STD__ >= __CC65_STD_CC65__ +/* define the name with just one underscore for backwards compatibility */ +#define _oserror __oserror +#endif + +extern int __errno; /* System errors go here */ -#define errno _errno +#define errno __errno /* errno must be a macro */ @@ -83,21 +88,26 @@ extern int _errno; -int __fastcall__ _osmaperrno (unsigned char oserror); -/* Map an operating system specific error code (for example from _oserror) +int __fastcall__ __osmaperrno (unsigned char oserror); +/* Map an operating system specific error code (for example from __oserror) ** into one of the E... codes above. It is user callable. */ -unsigned char __fastcall__ _seterrno (unsigned char code); +#if __CC65_STD__ >= __CC65_STD_CC65__ +/* define the name with just one underscore for backwards compatibility */ +#define _osmaperrno __osmaperrno +#endif + +unsigned char __fastcall__ __seterrno (unsigned char code); /* Set errno to a specific error code and return zero. Used by the library */ -int __fastcall__ _directerrno (unsigned char code); -/* Set errno to a specific error code, clear _oserror and return -1. Used +int __fastcall__ __directerrno (unsigned char code); +/* Set errno to a specific error code, clear __oserror and return -1. Used ** by the library. */ -int __fastcall__ _mappederrno (unsigned char code); -/* Set _oserror to the given platform specific error code. If it is a real +int __fastcall__ __mappederrno (unsigned char code); +/* Set __oserror to the given platform specific error code. If it is a real ** error code (not zero) set errno to the corresponding system error code ** and return -1. Otherwise return zero. ** Used by the library. From 2dabb65ee06cc9875b367dc0cf89f858acee3e59 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 21:52:53 +0200 Subject: [PATCH 019/360] fix errno related underscores in all libsrc/*.s files --- libsrc/apple2/close.s | 6 +++--- libsrc/apple2/devicedir.s | 6 +++--- libsrc/apple2/diocommon.s | 2 +- libsrc/apple2/dioopen.s | 4 ++-- libsrc/apple2/diosectcount.s | 6 +++--- libsrc/apple2/diosectsize.s | 2 +- libsrc/apple2/exec.s | 4 ++-- libsrc/apple2/getres.s | 2 +- libsrc/apple2/gettime.s | 6 +++--- libsrc/apple2/lseek.s | 6 +++--- libsrc/apple2/open.s | 8 ++++---- libsrc/apple2/oserror.s | 6 +++--- libsrc/apple2/read.s | 4 ++-- libsrc/apple2/rwcommon.s | 6 +++--- libsrc/apple2/settime.s | 2 +- libsrc/apple2/write.s | 6 +++--- libsrc/atari/close.s | 4 ++-- libsrc/atari/dio_cts.s | 4 ++-- libsrc/atari/dio_stc.s | 4 ++-- libsrc/atari/diopncls.s | 8 ++++---- libsrc/atari/dioqsize.s | 4 ++-- libsrc/atari/do_oserr.s | 4 ++-- libsrc/atari/exec.s | 4 ++-- libsrc/atari/getres.s | 2 +- libsrc/atari/gettime.s | 2 +- libsrc/atari/graphics.s | 8 ++++---- libsrc/atari/inviocb.s | 2 +- libsrc/atari/lseek.s | 6 +++--- libsrc/atari/open.s | 8 ++++---- libsrc/atari/oserror.s | 6 +++--- libsrc/atari/posixdirent.s | 8 ++++---- libsrc/atari/read.s | 4 ++-- libsrc/atari/settime.s | 2 +- libsrc/atari/siocall.s | 4 ++-- libsrc/atari/write.s | 4 ++-- libsrc/atmos/oserror.s | 6 +++--- libsrc/cbm/c_load.s | 4 ++-- libsrc/cbm/cbm_open.s | 6 +++--- libsrc/cbm/cbm_read.s | 8 ++++---- libsrc/cbm/cbm_write.s | 8 ++++---- libsrc/cbm/close.s | 4 ++-- libsrc/cbm/devicedir.s | 6 +++--- libsrc/cbm/open.s | 8 ++++---- libsrc/cbm/oserror.s | 4 ++-- libsrc/cbm/read.s | 8 ++++---- libsrc/cbm/write.s | 8 ++++---- libsrc/common/_directerrno.s | 10 ++++----- libsrc/common/_fopen.s | 4 ++-- libsrc/common/_mappederrno.s | 12 +++++------ libsrc/common/_oserror.s | 6 +++--- libsrc/common/_seterrno.s | 4 ++-- libsrc/common/atexit.s | 2 +- libsrc/common/chdir.s | 4 ++-- libsrc/common/fclose.s | 2 +- libsrc/common/fmisc.s | 2 +- libsrc/common/fopen.s | 2 +- libsrc/common/fread.s | 2 +- libsrc/common/fwrite.s | 2 +- libsrc/common/getcwd.s | 2 +- libsrc/common/mkdir.s | 4 ++-- libsrc/common/putenv.s | 2 +- libsrc/common/remove.s | 4 ++-- libsrc/common/rename.s | 4 ++-- libsrc/common/rmdir.s | 4 ++-- libsrc/common/signal.s | 2 +- libsrc/common/uname.s | 4 ++-- libsrc/common/ungetc.s | 2 +- libsrc/common/vsnprintf.s | 2 +- libsrc/geos-cbm/disk/dio_cts.s | 4 ++-- libsrc/geos-cbm/disk/dio_openclose.s | 6 +++--- libsrc/geos-cbm/disk/dio_qcount.s | 4 ++-- libsrc/geos-cbm/disk/dio_qsize.s | 4 ++-- libsrc/geos-cbm/disk/dio_read.s | 4 ++-- libsrc/geos-cbm/disk/dio_stc.s | 4 ++-- libsrc/geos-cbm/disk/dio_writev.s | 4 ++-- libsrc/geos-common/disk/calcblksfree.s | 4 ++-- libsrc/geos-common/disk/getptrcurdknm.s | 4 ++-- libsrc/geos-common/disk/setnextfree.s | 4 ++-- libsrc/geos-common/drivers/fio_module.s | 26 ++++++++++++------------ libsrc/geos-common/file/get1stdirentry.s | 4 ++-- libsrc/geos-common/file/getnxtdirentry.s | 4 ++-- libsrc/geos-common/file/readbyte.s | 4 ++-- libsrc/geos-common/system/oserror.s | 6 +++--- libsrc/geos-common/system/setoserror.s | 4 ++-- libsrc/lynx/open.s | 4 ++-- libsrc/lynx/oserror.s | 4 ++-- libsrc/osic1p/oserror.s | 6 +++--- libsrc/telestrat/oserror.s | 6 +++--- 88 files changed, 213 insertions(+), 213 deletions(-) diff --git a/libsrc/apple2/close.s b/libsrc/apple2/close.s index cef42b6f8..0002d081d 100644 --- a/libsrc/apple2/close.s +++ b/libsrc/apple2/close.s @@ -33,8 +33,8 @@ zerofd: lda #$00 ; Return success lda #$00 - ; Set __oserror -oserr: jmp __mappederrno + ; Set ___oserror +oserr: jmp ___mappederrno ; Set __errno -errno: jmp __directerrno +errno: jmp ___directerrno diff --git a/libsrc/apple2/devicedir.s b/libsrc/apple2/devicedir.s index 79f4c60de..abe900be1 100644 --- a/libsrc/apple2/devicedir.s +++ b/libsrc/apple2/devicedir.s @@ -45,9 +45,9 @@ _getdevicedir: ; Handle errors erange: lda #buf sta ICBAH,x ; set buffer address diff --git a/libsrc/atari/getres.s b/libsrc/atari/getres.s index f2e4874f9..9716040d8 100644 --- a/libsrc/atari/getres.s +++ b/libsrc/atari/getres.s @@ -41,7 +41,7 @@ _clock_getres: enosys: lda #ENOSYS ; Set __errno - jmp __directerrno + jmp ___directerrno ;---------------------------------------------------------------------------- ; timespec struct with tv_sec set to 1 second diff --git a/libsrc/atari/gettime.s b/libsrc/atari/gettime.s index 093d34843..df6e24021 100644 --- a/libsrc/atari/gettime.s +++ b/libsrc/atari/gettime.s @@ -105,7 +105,7 @@ errexit:jsr incsp3 ; Preserves A ; set __errno - jmp __directerrno + jmp ___directerrno ; ------- diff --git a/libsrc/atari/graphics.s b/libsrc/atari/graphics.s index ab26ed0da..f35087aea 100644 --- a/libsrc/atari/graphics.s +++ b/libsrc/atari/graphics.s @@ -10,7 +10,7 @@ .export __graphics .import findfreeiocb - .import __oserror + .import ___oserror .import fddecusage .import clriocb .import fdtoiocb @@ -45,7 +45,7 @@ parmok: jsr findfreeiocb beq iocbok ; we found one lda #EINVAL @@ -94,7 +94,7 @@ doopen: txa lda tmp2 ; get fd ldx #0 - stx __oserror + stx ___oserror rts cioerr: sty tmp3 ; remember error code @@ -103,6 +103,6 @@ cioerr: sty tmp3 ; remember error code jsr CIOV ; close IOCB again since open failed jsr fddecusage ; and decrement usage counter of fd lda tmp3 ; put error code into A - jmp __mappederrno + jmp ___mappederrno .endproc ; __graphics diff --git a/libsrc/atari/inviocb.s b/libsrc/atari/inviocb.s index c1c27ee03..2ceb385b1 100644 --- a/libsrc/atari/inviocb.s +++ b/libsrc/atari/inviocb.s @@ -7,4 +7,4 @@ __inviocb: lda #EUNKNOWN diff --git a/libsrc/cbm/c_load.s b/libsrc/cbm/c_load.s index d81430a03..7f2a054bd 100644 --- a/libsrc/cbm/c_load.s +++ b/libsrc/cbm/c_load.s @@ -7,7 +7,7 @@ .include "cbm.inc" .export _cbm_k_load - .import __oserror + .import ___oserror .import popa .importzp ptr1 @@ -19,7 +19,7 @@ _cbm_k_load: ldy ptr1+1 jsr LOAD bcc @Ok - sta __oserror + sta ___oserror ldx ptr1 ldy ptr1+1 @Ok: txa diff --git a/libsrc/cbm/cbm_open.s b/libsrc/cbm/cbm_open.s index db4179db8..c7590af2a 100644 --- a/libsrc/cbm/cbm_open.s +++ b/libsrc/cbm/cbm_open.s @@ -15,7 +15,7 @@ ; { ; cbm_k_setlfs(lfn, device, sec_addr); ; cbm_k_setnam(name); -; return _oserror = cbm_k_open(); +; return __oserror = cbm_k_open(); ; } ; @@ -23,7 +23,7 @@ .import popa .import _cbm_k_setlfs, _cbm_k_setnam, _cbm_k_open - .import __oserror + .import ___oserror _cbm_open: jsr _cbm_k_setnam @@ -32,5 +32,5 @@ _cbm_open: jsr _cbm_k_setlfs ; Call SETLFS, pop all args jsr _cbm_k_open - sta __oserror + sta ___oserror rts diff --git a/libsrc/cbm/cbm_read.s b/libsrc/cbm/cbm_read.s index 29e0e1f19..8a9939eca 100644 --- a/libsrc/cbm/cbm_read.s +++ b/libsrc/cbm/cbm_read.s @@ -6,7 +6,7 @@ ; int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size) ; /* Reads up to "size" bytes from a file to "buffer". ; ** Returns the number of actually read bytes, 0 if there are no bytes left -; ** (EOF) or -1 in case of an error. _oserror contains an errorcode then (see +; ** (EOF) or -1 in case of an error. __oserror contains an errorcode then (see ; ** table below). ; */ ; { @@ -14,7 +14,7 @@ ; static unsigned char tmp; ; ; /* if we can't change to the inputchannel #lfn then return an error */ -; if (_oserror = cbm_k_chkin(lfn)) return -1; +; if (__oserror = cbm_k_chkin(lfn)) return -1; ; ; bytesread = 0; ; @@ -41,7 +41,7 @@ .export _cbm_read .importzp ptr1, ptr2, ptr3, tmp1 .import popax, popa - .import __oserror + .import ___oserror _cbm_read: @@ -106,7 +106,7 @@ _cbm_read: ; CHKIN failed -@E1: sta __oserror +@E1: sta ___oserror lda #$FF tax rts ; return -1 diff --git a/libsrc/cbm/cbm_write.s b/libsrc/cbm/cbm_write.s index 5ac07209c..18c6f4684 100644 --- a/libsrc/cbm/cbm_write.s +++ b/libsrc/cbm/cbm_write.s @@ -9,7 +9,7 @@ ; static unsigned int byteswritten; ; ; /* if we can't change to the outputchannel #lfn then return an error */ -; if (_oserror = cbm_k_ckout(lfn)) return -1; +; if (__oserror = cbm_k_ckout(lfn)) return -1; ; ; byteswritten = 0; ; @@ -18,7 +18,7 @@ ; } ; ; if (cbm_k_readst()) { -; _oserror = 5; /* device not present */ +; __oserror = 5; /* device not present */ ; byteswritten = -1; ; } ; @@ -33,7 +33,7 @@ .export _cbm_write .importzp ptr1, ptr2, ptr3 .import popax, popa - .import __oserror + .import ___oserror _cbm_write: @@ -87,7 +87,7 @@ _cbm_write: ; Error entry, error code is in A -@E2: sta __oserror +@E2: sta ___oserror lda #$FF tax rts ; return -1 diff --git a/libsrc/cbm/close.s b/libsrc/cbm/close.s index 7fc600e87..0cd425cf4 100644 --- a/libsrc/cbm/close.s +++ b/libsrc/cbm/close.s @@ -54,12 +54,12 @@ ldx unittab,y jsr closecmdchannel ; Close the disk command channel pla ; Get the error code from the disk - jmp __mappederrno ; Set _oserror and _errno, return 0/-1 + jmp ___mappederrno ; Set __oserror and _errno, return 0/-1 ; Error entry: The given file descriptor is not valid or not open invalidfd: lda #EBADF - jmp __directerrno ; Set _errno, clear _oserror, return -1 + jmp ___directerrno ; Set _errno, clear __oserror, return -1 .endproc diff --git a/libsrc/cbm/devicedir.s b/libsrc/cbm/devicedir.s index 3a4e6d774..25aad556b 100644 --- a/libsrc/cbm/devicedir.s +++ b/libsrc/cbm/devicedir.s @@ -32,7 +32,7 @@ jsr popa jsr diskinit beq size - jsr __mappederrno + jsr ___mappederrno bne fail ; Branch always ; Check for sufficient buf size @@ -43,7 +43,7 @@ size: lda ptr3+1 cmp #3 bcs okay ; Buf >= 3 lda #683 rts diff --git a/libsrc/geos-cbm/disk/dio_qsize.s b/libsrc/geos-cbm/disk/dio_qsize.s index bf9178035..14c8a460a 100644 --- a/libsrc/geos-cbm/disk/dio_qsize.s +++ b/libsrc/geos-cbm/disk/dio_qsize.s @@ -5,10 +5,10 @@ ; .export _dio_query_sectsize - .import __oserror + .import ___oserror _dio_query_sectsize: lda #<256 ldx #>256 - sta __oserror + sta ___oserror rts diff --git a/libsrc/geos-cbm/disk/dio_read.s b/libsrc/geos-cbm/disk/dio_read.s index ac19f9afa..4c9297e65 100644 --- a/libsrc/geos-cbm/disk/dio_read.s +++ b/libsrc/geos-cbm/disk/dio_read.s @@ -8,7 +8,7 @@ ; .export _dio_read - .import dio_params, __oserror + .import dio_params, ___oserror .include "geossym.inc" .include "jumptab.inc" @@ -18,6 +18,6 @@ _dio_read: tay bne err jsr ReadBlock - stx __oserror + stx ___oserror txa err: rts diff --git a/libsrc/geos-cbm/disk/dio_stc.s b/libsrc/geos-cbm/disk/dio_stc.s index 469df93ca..3c3c9108f 100644 --- a/libsrc/geos-cbm/disk/dio_stc.s +++ b/libsrc/geos-cbm/disk/dio_stc.s @@ -9,7 +9,7 @@ .export _dio_log_to_phys .importzp ptr1,ptr2,ptr3,tmp1,tmp2 - .import popax,__oserror + .import popax,___oserror .import sectab_1541_l, sectab_1541_h .include "dio.inc" @@ -78,7 +78,7 @@ dio_stcend: ldx #0 txa _ret: - sta __oserror + sta ___oserror rts ; return success ; errors diff --git a/libsrc/geos-cbm/disk/dio_writev.s b/libsrc/geos-cbm/disk/dio_writev.s index 9b36ed096..962d7e77f 100644 --- a/libsrc/geos-cbm/disk/dio_writev.s +++ b/libsrc/geos-cbm/disk/dio_writev.s @@ -8,7 +8,7 @@ ; .export _dio_write_verify - .import dio_params, __oserror + .import dio_params, ___oserror .include "geossym.inc" .include "jumptab.inc" @@ -18,6 +18,6 @@ _dio_write_verify: tay bne err jsr VerWriteBlock - stx __oserror + stx ___oserror txa err: rts diff --git a/libsrc/geos-common/disk/calcblksfree.s b/libsrc/geos-common/disk/calcblksfree.s index 7e1bb4f52..fec6d6690 100644 --- a/libsrc/geos-common/disk/calcblksfree.s +++ b/libsrc/geos-common/disk/calcblksfree.s @@ -5,7 +5,7 @@ ; int CalcBlksFree (void); - .import __oserror + .import ___oserror .export _CalcBlksFree .include "jumptab.inc" @@ -18,7 +18,7 @@ _CalcBlksFree: sta r5L stx r5H jsr CalcBlksFree - stx __oserror + stx ___oserror lda r4L ldx r4H rts diff --git a/libsrc/geos-common/disk/getptrcurdknm.s b/libsrc/geos-common/disk/getptrcurdknm.s index d92e5d91e..9112c9f99 100644 --- a/libsrc/geos-common/disk/getptrcurdknm.s +++ b/libsrc/geos-common/disk/getptrcurdknm.s @@ -7,7 +7,7 @@ ; (fills curName[17] with current disk's name) .importzp ptr4, ptr3 - .import __oserror + .import ___oserror .export _GetPtrCurDkNm .include "jumptab.inc" @@ -34,5 +34,5 @@ namelp: lda (ptr4),y bne namelp fin: lda #0 sta (ptr3),y - stx __oserror + stx ___oserror rts diff --git a/libsrc/geos-common/disk/setnextfree.s b/libsrc/geos-common/disk/setnextfree.s index b24f16f6f..2d43c1e36 100644 --- a/libsrc/geos-common/disk/setnextfree.s +++ b/libsrc/geos-common/disk/setnextfree.s @@ -5,7 +5,7 @@ ; struct tr_se SetNextFree (struct tr_se *startTS); - .import __oserror + .import ___oserror .import gettrse .export _SetNextFree @@ -18,7 +18,7 @@ _SetNextFree: sta r3L stx r3H jsr SetNextFree - stx __oserror + stx ___oserror lda r3L ldx r3H rts diff --git a/libsrc/geos-common/drivers/fio_module.s b/libsrc/geos-common/drivers/fio_module.s index 1314fc4c5..d4549b4ab 100644 --- a/libsrc/geos-common/drivers/fio_module.s +++ b/libsrc/geos-common/drivers/fio_module.s @@ -14,7 +14,7 @@ FILEDES = 3 ; first free to use file descriptor .importzp ptr1, ptr2, ptr3, tmp1 .import addysp, popax, popptr1 - .import __oserror + .import ___oserror .import _FindFile, _ReadByte .export _open, _close, _read @@ -65,8 +65,8 @@ _open: stx f_offset stx f_offset+1 lda #0 ; clear errors - sta __oserror - jsr __seterrno + sta ___oserror + jsr ___seterrno lda #FILEDES ; return fd sta filedesc rts @@ -75,14 +75,14 @@ _open: .byte $2c ; skip @alreadyopen: lda #EMFILE ; too many opened files (there can be only one) - jmp __directerrno ; set errno, clear oserror, return -1 + jmp ___directerrno ; set errno, clear oserror, return -1 @oserror: - jmp __mappederrno ; set platform error code, return -1 + jmp ___mappederrno ; set platform error code, return -1 _close: lda #0 - sta __oserror - jsr __seterrno ; clear errors + sta ___oserror + jsr ___seterrno ; clear errors lda #0 ; clear fd sta filedesc tax @@ -92,7 +92,7 @@ _read: ; a/x - number of bytes ; popax - buffer ptr ; popax - fd, must be == to the above one - ; return -1+__oserror or number of bytes read + ; return -1+___oserror or number of bytes read inx stx ptr1+1 @@ -111,14 +111,14 @@ _read: @filenotopen: lda #EBADF - jmp __directerrno ; Sets _errno, clears _oserror, returns -1 + jmp ___directerrno ; Sets _errno, clears __oserror, returns -1 @fileok: lda #0 sta ptr3 sta ptr3+1 ; put 0 into ptr3 (number of bytes read) - sta __oserror ; clear error flags - jsr __seterrno + sta ___oserror ; clear error flags + jsr ___seterrno lda f_track ; restore stuff for ReadByte ldx f_sector @@ -147,11 +147,11 @@ _read: bne @L2 inc ptr3+1 -@L2: lda __oserror ; was there error ? +@L2: lda ___oserror ; was there error ? beq @L3 cmp #BFR_OVERFLOW ; EOF? beq @done ; yes, we're done - jmp __mappederrno ; no, we're screwed + jmp ___mappederrno ; no, we're screwed @L3: dec ptr1 ; decrement the count bne @L0 diff --git a/libsrc/geos-common/file/get1stdirentry.s b/libsrc/geos-common/file/get1stdirentry.s index f0ad59388..2217718ea 100644 --- a/libsrc/geos-common/file/get1stdirentry.s +++ b/libsrc/geos-common/file/get1stdirentry.s @@ -5,7 +5,7 @@ ; struct filehandle* Get1stDirEntry (void); - .import __oserror, return0 + .import ___oserror, return0 .export _Get1stDirEntry .include "diskdrv.inc" @@ -13,7 +13,7 @@ _Get1stDirEntry: jsr Get1stDirEntry - stx __oserror + stx ___oserror txa bne L1 ; jump if disk error lda r5L diff --git a/libsrc/geos-common/file/getnxtdirentry.s b/libsrc/geos-common/file/getnxtdirentry.s index e8ccbf3a2..0f74a0ed8 100644 --- a/libsrc/geos-common/file/getnxtdirentry.s +++ b/libsrc/geos-common/file/getnxtdirentry.s @@ -5,7 +5,7 @@ ; struct filehandle* GetNxtDirEntry (void); - .import __oserror, return0 + .import ___oserror, return0 .export _GetNxtDirEntry .include "diskdrv.inc" @@ -13,7 +13,7 @@ _GetNxtDirEntry: jsr GetNxtDirEntry - stx __oserror + stx ___oserror txa bne L1 ; jump if disk error tya diff --git a/libsrc/geos-common/file/readbyte.s b/libsrc/geos-common/file/readbyte.s index 9a24e68df..90616a426 100644 --- a/libsrc/geos-common/file/readbyte.s +++ b/libsrc/geos-common/file/readbyte.s @@ -5,13 +5,13 @@ ; char ReadByte (void); - .import __oserror + .import ___oserror .export _ReadByte .include "jumptab.inc" _ReadByte: jsr ReadByte - stx __oserror + stx ___oserror ldx #0 rts diff --git a/libsrc/geos-common/system/oserror.s b/libsrc/geos-common/system/oserror.s index f0915fd5b..fa45f3e14 100644 --- a/libsrc/geos-common/system/oserror.s +++ b/libsrc/geos-common/system/oserror.s @@ -3,16 +3,16 @@ ; GEOS port: Maciej 'YTM/Elysium' Witkowiak ; 2.7.2001 ; -; int __fastcall__ _osmaperrno (unsigned char oserror); +; int __fastcall__ __osmaperrno (unsigned char oserror); ; /* Map a system specific error into a system independent code */ ; - .export __osmaperrno + .export ___osmaperrno .include "errno.inc" .include "const.inc" -__osmaperrno: +___osmaperrno: ldx #ErrTabSize @L1: cmp ErrTab-2,x ; Search for the error code beq @L2 ; Jump if found diff --git a/libsrc/geos-common/system/setoserror.s b/libsrc/geos-common/system/setoserror.s index adc6ad017..6fb89e96e 100644 --- a/libsrc/geos-common/system/setoserror.s +++ b/libsrc/geos-common/system/setoserror.s @@ -5,10 +5,10 @@ ; .export setoserror - .import __oserror + .import ___oserror setoserror: - stx __oserror + stx ___oserror txa ldx #0 ; X is cleared (high byte for promoting char to int) tay ; Y register is used just to save flags state diff --git a/libsrc/lynx/open.s b/libsrc/lynx/open.s index c48b8eb95..032f55a99 100644 --- a/libsrc/lynx/open.s +++ b/libsrc/lynx/open.s @@ -66,7 +66,7 @@ parmok: jsr popax beq flagsok jsr popax lda #EINVAL - jmp __directerrno + jmp ___directerrno flagsok: jsr popax @@ -74,7 +74,7 @@ flagsok: jsr _openn ldx #$00 lda #$01 - stx __oserror + stx ___oserror rts .endproc diff --git a/libsrc/lynx/oserror.s b/libsrc/lynx/oserror.s index 5570a3bb7..b2ccbf4f0 100644 --- a/libsrc/lynx/oserror.s +++ b/libsrc/lynx/oserror.s @@ -1,7 +1,7 @@ ; ; Karri Kaksonen, 2010 ; -; int __fastcall__ _osmaperrno (unsigned char oserror); +; int __fastcall__ __osmaperrno (unsigned char oserror); ; /* Map a system specific error into a system independent code */ ; @@ -9,6 +9,6 @@ .code -__osmaperrno: +___osmaperrno: rts diff --git a/libsrc/osic1p/oserror.s b/libsrc/osic1p/oserror.s index 073691a06..380c5ebb9 100644 --- a/libsrc/osic1p/oserror.s +++ b/libsrc/osic1p/oserror.s @@ -4,14 +4,14 @@ ; original by ; Stefan Haubenthal, 2011-04-18 ; -; int __fastcall__ _osmaperrno (unsigned char oserror); +; int __fastcall__ __osmaperrno (unsigned char oserror); ; /* Map a system specific error into a system independent code */ ; .include "errno.inc" - .export __osmaperrno + .export ___osmaperrno -.proc __osmaperrno +.proc ___osmaperrno lda #EUNKNOWN diff --git a/libsrc/telestrat/oserror.s b/libsrc/telestrat/oserror.s index e3b9e619a..8fe255656 100644 --- a/libsrc/telestrat/oserror.s +++ b/libsrc/telestrat/oserror.s @@ -1,14 +1,14 @@ ; ; Jede, 2017-10-27 ; -; int __fastcall__ _osmaperrno (unsigned char oserror); +; int __fastcall__ __osmaperrno (unsigned char oserror); ; /* Map a system specific error into a system independent code */ ; .include "errno.inc" - .export __osmaperrno + .export ___osmaperrno -.proc __osmaperrno +.proc ___osmaperrno lda #EUNKNOWN From 54aff47513eb19bc115880fc32f14b1d55026f31 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 22:09:44 +0200 Subject: [PATCH 020/360] fix some errno related stuff, "make all" works again --- include/errno.h | 15 ++++++++++++++- libsrc/cbm/dir.s | 4 ++-- libsrc/cbm/readdir.c | 2 +- libsrc/common/_seterrno.s | 6 +++--- libsrc/common/errno.s | 4 ++-- libsrc/common/perror.c | 2 +- libsrc/common/strerror.s | 4 ++-- 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/include/errno.h b/include/errno.h index c762e8b1c..8f329e3cc 100644 --- a/include/errno.h +++ b/include/errno.h @@ -101,11 +101,21 @@ int __fastcall__ __osmaperrno (unsigned char oserror); unsigned char __fastcall__ __seterrno (unsigned char code); /* Set errno to a specific error code and return zero. Used by the library */ +#if __CC65_STD__ >= __CC65_STD_CC65__ +/* define the name with just one underscore for backwards compatibility */ +#define _seterrno __seterrno +#endif + int __fastcall__ __directerrno (unsigned char code); /* Set errno to a specific error code, clear __oserror and return -1. Used ** by the library. */ +#if __CC65_STD__ >= __CC65_STD_CC65__ +/* define the name with just one underscore for backwards compatibility */ +#define _directerrno __directerrno +#endif + int __fastcall__ __mappederrno (unsigned char code); /* Set __oserror to the given platform specific error code. If it is a real ** error code (not zero) set errno to the corresponding system error code @@ -113,7 +123,10 @@ int __fastcall__ __mappederrno (unsigned char code); ** Used by the library. */ - +#if __CC65_STD__ >= __CC65_STD_CC65__ +/* define the name with just one underscore for backwards compatibility */ +#define _mappederrno __mappederrno +#endif /* End of errno.h */ #endif diff --git a/libsrc/cbm/dir.s b/libsrc/cbm/dir.s index 808fcf982..734485aaf 100644 --- a/libsrc/cbm/dir.s +++ b/libsrc/cbm/dir.s @@ -92,8 +92,8 @@ L3: sta tmp1 ; Save returned count ; Didn't read enough bytes. This is an error for us, but errno is not set lda #EINVAL ; = 0 - sta __errno+1 + sta ___errno+1 ; lda #$00 ; A contains zero: "Unknown error" ; Load the pointer to the error message and return From df4b6f9d144a27ce1aeb1e4ef091f5c4a9548047 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sun, 28 Aug 2022 22:37:33 +0200 Subject: [PATCH 021/360] remove extra spaces --- libsrc/apple2/devicedir.s | 2 +- libsrc/apple2/diosectsize.s | 2 +- libsrc/apple2/lseek.s | 4 ++-- libsrc/apple2/rwcommon.s | 2 +- libsrc/atari/close.s | 2 +- libsrc/atari/diopncls.s | 4 ++-- libsrc/atari/exec.s | 2 +- libsrc/atari/graphics.s | 2 +- libsrc/atari/lseek.s | 4 ++-- libsrc/atari/read.s | 2 +- libsrc/atari/write.s | 2 +- libsrc/cbm/close.s | 4 ++-- libsrc/cbm/devicedir.s | 2 +- libsrc/cbm/open.s | 2 +- libsrc/cbm/read.s | 4 ++-- libsrc/cbm/write.s | 4 ++-- libsrc/common/_directerrno.s | 4 ++-- libsrc/common/_fopen.s | 2 +- libsrc/common/_mappederrno.s | 6 +++--- libsrc/common/chdir.s | 2 +- libsrc/common/fopen.s | 2 +- libsrc/common/fwrite.s | 2 +- libsrc/common/mkdir.s | 2 +- libsrc/common/remove.s | 2 +- libsrc/common/rmdir.s | 2 +- libsrc/common/signal.s | 2 +- libsrc/common/sigtable.s | 12 ++++++------ libsrc/common/uname.s | 2 +- libsrc/common/vsnprintf.s | 2 +- libsrc/geos-cbm/disk/dio_openclose.s | 2 +- libsrc/geos-common/drivers/fio_module.s | 14 +++++++------- 31 files changed, 51 insertions(+), 51 deletions(-) diff --git a/libsrc/apple2/devicedir.s b/libsrc/apple2/devicedir.s index abe900be1..21cabf59e 100644 --- a/libsrc/apple2/devicedir.s +++ b/libsrc/apple2/devicedir.s @@ -73,7 +73,7 @@ oserr: jsr ___mappederrno iny lda #$00 sta (ptr1),y - sta ___oserror ; Clear __oserror + sta ___oserror ; Clear __oserror ; Success, return buf lda ptr1 diff --git a/libsrc/apple2/diosectsize.s b/libsrc/apple2/diosectsize.s index 4730bd611..7d2e27a09 100644 --- a/libsrc/apple2/diosectsize.s +++ b/libsrc/apple2/diosectsize.s @@ -10,7 +10,7 @@ _dio_query_sectsize: ; Clear error - stx ___oserror ; X = 0 + stx ___oserror ; X = 0 ; Return ProDOS 8 block size txa ; X = 0 diff --git a/libsrc/apple2/lseek.s b/libsrc/apple2/lseek.s index cc6241558..be0078c1b 100644 --- a/libsrc/apple2/lseek.s +++ b/libsrc/apple2/lseek.s @@ -107,13 +107,13 @@ seek_common: einval: lda #EINVAL ; Set __errno -errno: jsr ___directerrno ; leaves -1 in AX +errno: jsr ___directerrno ; leaves -1 in AX stx sreg ; extend return value to 32 bits stx sreg+1 rts ; Set ___oserror -oserr: jsr ___mappederrno ; leaves -1 in AX +oserr: jsr ___mappederrno ; leaves -1 in AX stx sreg ; extend return value to 32 bits stx sreg+1 rts diff --git a/libsrc/apple2/rwcommon.s b/libsrc/apple2/rwcommon.s index 302b46457..769247e63 100644 --- a/libsrc/apple2/rwcommon.s +++ b/libsrc/apple2/rwcommon.s @@ -49,7 +49,7 @@ rwcommon: rwepilog: ; Return success - sta ___oserror ; A = 0 + sta ___oserror ; A = 0 lda mliparam + MLI::RW::TRANS_COUNT ldx mliparam + MLI::RW::TRANS_COUNT+1 rts diff --git a/libsrc/atari/close.s b/libsrc/atari/close.s index 63b2948f3..b5bff4173 100644 --- a/libsrc/atari/close.s +++ b/libsrc/atari/close.s @@ -18,7 +18,7 @@ jsr CIOV bmi closerr ok: ldx #0 - stx ___oserror ; clear system specific error code + stx ___oserror ; clear system specific error code txa rts diff --git a/libsrc/atari/diopncls.s b/libsrc/atari/diopncls.s index 37f25049b..f40d6bba4 100644 --- a/libsrc/atari/diopncls.s +++ b/libsrc/atari/diopncls.s @@ -49,7 +49,7 @@ _dio_open: sta sectsizetab+sst_flag,x ; set flag that drive is "open" lda #0 sta sectsizetab+sst_sectsize+1,x - sta ___oserror ; success + sta ___oserror ; success tya sta sectsizetab+sst_driveno,x stx ptr2 @@ -156,7 +156,7 @@ s128: lda #128 lda #0 ldy #sst_flag sta (ptr2),y - sta ___oserror ; success + sta ___oserror ; success tax rts ; return no error diff --git a/libsrc/atari/exec.s b/libsrc/atari/exec.s index 88430e9f7..145b28e0d 100644 --- a/libsrc/atari/exec.s +++ b/libsrc/atari/exec.s @@ -148,7 +148,7 @@ copycd: lda #ATEOL pha ; remember error code jsr close ; close the IOCB (required even if open failed) pla ; put error code back into A -setmerr:jmp ___mappederrno ; update errno from OS specific error code in A +setmerr:jmp ___mappederrno ; update errno from OS specific error code in A openok: lda #>buf sta ICBAH,x ; set buffer address diff --git a/libsrc/atari/graphics.s b/libsrc/atari/graphics.s index f35087aea..1f7844c39 100644 --- a/libsrc/atari/graphics.s +++ b/libsrc/atari/graphics.s @@ -45,7 +45,7 @@ parmok: jsr findfreeiocb beq iocbok ; we found one lda #EINVAL diff --git a/libsrc/atari/lseek.s b/libsrc/atari/lseek.s index 915ec24cf..991a86569 100644 --- a/libsrc/atari/lseek.s +++ b/libsrc/atari/lseek.s @@ -21,7 +21,7 @@ ; seeking not supported, return -1 and ENOSYS errno value no_supp:jsr incsp6 lda # Date: Mon, 29 Aug 2022 19:55:48 +0200 Subject: [PATCH 022/360] add extra underscore to heap stuff --- asminc/_heap.inc | 10 +++--- include/_heap.h | 10 +++--- include/stdlib.h | 24 +++++++++++--- libsrc/common/_heap.s | 14 ++++---- libsrc/common/_heapadd.s | 4 +-- libsrc/common/_heapblocksize.s | 4 +-- libsrc/common/_heapmaxavail.s | 16 ++++----- libsrc/common/_heapmemavail.s | 16 ++++----- libsrc/common/free.s | 60 +++++++++++++++++----------------- libsrc/common/malloc.s | 28 ++++++++-------- libsrc/common/realloc.c | 8 ++--- 11 files changed, 105 insertions(+), 89 deletions(-) diff --git a/asminc/_heap.inc b/asminc/_heap.inc index a7d6acea2..1bf80ac82 100644 --- a/asminc/_heap.inc +++ b/asminc/_heap.inc @@ -28,8 +28,8 @@ HEAP_MIN_BLOCKSIZE = .sizeof (freeblock) ; Minimum size of an allocated block HEAP_ADMIN_SPACE = .sizeof (usedblock) ; Additional space for used bock ; Variables -.global __heaporg -.global __heapptr -.global __heapend -.global __heapfirst -.global __heaplast +.global ___heaporg +.global ___heapptr +.global ___heapend +.global ___heapfirst +.global ___heaplast diff --git a/include/_heap.h b/include/_heap.h index c054cfa34..c51f864ac 100644 --- a/include/_heap.h +++ b/include/_heap.h @@ -37,11 +37,11 @@ struct freeblock { /* Variables that describe the heap */ -extern unsigned* _heaporg; /* Bottom of heap */ -extern unsigned* _heapptr; /* Current top */ -extern unsigned* _heapend; /* Upper limit */ -extern struct freeblock* _heapfirst; /* First free block in list */ -extern struct freeblock* _heaplast; /* Last free block in list */ +extern unsigned* __heaporg; /* Bottom of heap */ +extern unsigned* __heapptr; /* Current top */ +extern unsigned* __heapend; /* Upper limit */ +extern struct freeblock* __heapfirst; /* First free block in list */ +extern struct freeblock* __heaplast; /* Last free block in list */ diff --git a/include/stdlib.h b/include/stdlib.h index 99151317f..53d73bb8d 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -92,17 +92,33 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size); */ #endif -void __fastcall__ _heapadd (void* mem, size_t size); +void __fastcall__ __heapadd (void* mem, size_t size); /* Add a block to the heap */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _heapadd __heapadd +#endif -size_t __fastcall__ _heapblocksize (const void* block); +size_t __fastcall__ __heapblocksize (const void* block); /* Return the size of an allocated block */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _heapblocksize __heapblocksize +#endif -size_t _heapmemavail (void); +size_t __heapmemavail (void); /* Return the total free heap space */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _heapmemavail __heapmemavail +#endif -size_t _heapmaxavail (void); +size_t __heapmaxavail (void); /* Return the size of the largest free block on the heap */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _heapmaxavail __heapmaxavail +#endif /* Random numbers */ diff --git a/libsrc/common/_heap.s b/libsrc/common/_heap.s index 4ec8c80cd..eb680fa20 100644 --- a/libsrc/common/_heap.s +++ b/libsrc/common/_heap.s @@ -13,15 +13,15 @@ .data -__heaporg: +___heaporg: .word __BSS_RUN__+__BSS_SIZE__ ; Linker calculates this symbol -__heapptr: +___heapptr: .word __BSS_RUN__+__BSS_SIZE__ ; Dito -__heapend: +___heapend: .word __BSS_RUN__+__BSS_SIZE__ -__heapfirst: +___heapfirst: .word 0 -__heaplast: +___heaplast: .word 0 @@ -33,10 +33,10 @@ initheap: sec lda sp sbc #<__STACKSIZE__ - sta __heapend + sta ___heapend lda sp+1 sbc #>__STACKSIZE__ - sta __heapend+1 + sta ___heapend+1 rts diff --git a/libsrc/common/_heapadd.s b/libsrc/common/_heapadd.s index 14080cb5e..7695a732d 100644 --- a/libsrc/common/_heapadd.s +++ b/libsrc/common/_heapadd.s @@ -10,7 +10,7 @@ .importzp ptr1, ptr2 .import popax .import heapadd - .export __heapadd + .export ___heapadd .include "_heap.inc" @@ -19,7 +19,7 @@ ;----------------------------------------------------------------------------- ; Code -__heapadd: +___heapadd: sta ptr1 ; Store size in ptr1 stx ptr1+1 jsr popax ; Get the block pointer diff --git a/libsrc/common/_heapblocksize.s b/libsrc/common/_heapblocksize.s index db33f594c..e9b0cdad9 100644 --- a/libsrc/common/_heapblocksize.s +++ b/libsrc/common/_heapblocksize.s @@ -7,7 +7,7 @@ ; .importzp ptr1, ptr2 - .export __heapblocksize + .export ___heapblocksize .include "_heap.inc" @@ -17,7 +17,7 @@ ;----------------------------------------------------------------------------- ; Code -__heapblocksize: +___heapblocksize: ; Below the user data is a pointer that points to the start of the real ; (raw) memory block. The first word of this block is the size. To access diff --git a/libsrc/common/_heapmaxavail.s b/libsrc/common/_heapmaxavail.s index 19ae18b8d..b4e72f2d4 100644 --- a/libsrc/common/_heapmaxavail.s +++ b/libsrc/common/_heapmaxavail.s @@ -8,7 +8,7 @@ ; .importzp ptr1, ptr2 - .export __heapmaxavail + .export ___heapmaxavail .include "_heap.inc" @@ -17,22 +17,22 @@ ;----------------------------------------------------------------------------- ; Code -__heapmaxavail: +___heapmaxavail: ; size_t Size = (_heapend - _heapptr) * sizeof (*_heapend); - lda __heapend - sub __heapptr + lda ___heapend + sub ___heapptr sta ptr2 - lda __heapend+1 - sbc __heapptr+1 + lda ___heapend+1 + sbc ___heapptr+1 sta ptr2+1 ; struct freeblock* F = _heapfirst; - lda __heapfirst + lda ___heapfirst sta ptr1 - lda __heapfirst+1 + lda ___heapfirst+1 @L1: sta ptr1+1 ; while (F) { diff --git a/libsrc/common/_heapmemavail.s b/libsrc/common/_heapmemavail.s index 69aa75f8a..14ecc853a 100644 --- a/libsrc/common/_heapmemavail.s +++ b/libsrc/common/_heapmemavail.s @@ -8,7 +8,7 @@ ; .importzp ptr1, ptr2 - .export __heapmemavail + .export ___heapmemavail .include "_heap.inc" @@ -17,7 +17,7 @@ ;----------------------------------------------------------------------------- ; Code -__heapmemavail: +___heapmemavail: ; size_t Size = 0; @@ -27,9 +27,9 @@ __heapmemavail: ; struct freeblock* F = _heapfirst; - lda __heapfirst + lda ___heapfirst sta ptr1 - lda __heapfirst+1 + lda ___heapfirst+1 @L1: sta ptr1+1 ; while (F) { @@ -61,17 +61,17 @@ __heapmemavail: ; return Size + (_heapend - _heapptr) * sizeof (*_heapend); @L2: lda ptr2 - add __heapend + add ___heapend sta ptr2 lda ptr2+1 - adc __heapend+1 + adc ___heapend+1 tax lda ptr2 - sub __heapptr + sub ___heapptr sta ptr2 txa - sbc __heapptr+1 + sbc ___heapptr+1 tax lda ptr2 diff --git a/libsrc/common/free.s b/libsrc/common/free.s index 53796303c..709460ff9 100644 --- a/libsrc/common/free.s +++ b/libsrc/common/free.s @@ -105,27 +105,27 @@ _free: sta ptr2 tay lda ptr2+1 adc ptr1+1 - cpy __heapptr + cpy ___heapptr bne heapadd ; Add to free list - cmp __heapptr+1 + cmp ___heapptr+1 bne heapadd ; The pointer is located at the heap top. Lower the heap top pointer to ; release the block. @L3: lda ptr2 - sta __heapptr + sta ___heapptr lda ptr2+1 - sta __heapptr+1 + sta ___heapptr+1 ; Check if the last block in the freelist is now at heap top. If so, remove ; this block from the freelist. - lda __heaplast + lda ___heaplast sta ptr1 - ora __heaplast+1 + ora ___heaplast+1 beq @L9 ; Jump if free list empty - lda __heaplast+1 + lda ___heaplast+1 sta ptr1+1 ; Pointer to last block now in ptr1 ldy #freeblock::size @@ -136,35 +136,35 @@ _free: sta ptr2 lda (ptr1),y adc ptr1+1 - cmp __heapptr+1 + cmp ___heapptr+1 bne @L9 ; Jump if last block not on top of heap - cpx __heapptr + cpx ___heapptr bne @L9 ; Jump if last block not on top of heap ; Remove the last block lda ptr1 - sta __heapptr + sta ___heapptr lda ptr1+1 - sta __heapptr+1 + sta ___heapptr+1 ; Correct the next pointer of the now last block ldy #freeblock::prev+1 ; Offset of ->prev field lda (ptr1),y sta ptr2+1 ; Remember f->prev in ptr2 - sta __heaplast+1 + sta ___heaplast+1 dey lda (ptr1),y sta ptr2 ; Remember f->prev in ptr2 - sta __heaplast - ora __heaplast+1 ; -> prev == 0? + sta ___heaplast + ora ___heaplast+1 ; -> prev == 0? bne @L8 ; Jump if free list not empty ; Free list is now empty (A = 0) - sta __heapfirst - sta __heapfirst+1 + sta ___heapfirst + sta ___heapfirst+1 ; Done @@ -283,9 +283,9 @@ _free: sta ptr2 ; Check if the free list is empty, storing _hfirst into ptr3 for later heapadd: - lda __heapfirst + lda ___heapfirst sta ptr3 - lda __heapfirst+1 + lda ___heapfirst+1 sta ptr3+1 ora ptr3 bne SearchFreeList @@ -301,10 +301,10 @@ heapadd: lda ptr2 ldx ptr2+1 - sta __heapfirst - stx __heapfirst+1 ; _heapfirst = f; - sta __heaplast - stx __heaplast+1 ; _heaplast = f; + sta ___heapfirst + stx ___heapfirst+1 ; _heapfirst = f; + sta ___heaplast + stx ___heaplast+1 ; _heaplast = f; rts ; Done @@ -351,9 +351,9 @@ SearchFreeList: sta (ptr2),y ; Clear low byte of f->next lda ptr2 ; _heaplast = f; - sta __heaplast + sta ___heaplast lda ptr2+1 - sta __heaplast+1 + sta ___heaplast+1 ; Since we have checked the case that the freelist is empty before, if the ; right pointer is NULL, the left *cannot* be NULL here. So skip the @@ -414,9 +414,9 @@ CheckRightMerge: ; f->next is zero, this is now the last block @L1: lda ptr2 ; _heaplast = f; - sta __heaplast + sta ___heaplast lda ptr2+1 - sta __heaplast+1 + sta ___heaplast+1 jmp CheckLeftMerge ; No right merge, just set the link. @@ -451,9 +451,9 @@ CheckLeftMerge: sta (ptr2),y lda ptr2 ; _heapfirst = f; - sta __heapfirst + sta ___heapfirst lda ptr2+1 - sta __heapfirst+1 + sta ___heapfirst+1 rts ; Done @@ -510,9 +510,9 @@ CheckLeftMerge2: ; This is now the last block, do _heaplast = left @L1: lda ptr4 - sta __heaplast + sta ___heaplast lda ptr4+1 - sta __heaplast+1 + sta ___heaplast+1 rts ; Done ; No merge of the left block, just set the link. Y points to size+1 if diff --git a/libsrc/common/malloc.s b/libsrc/common/malloc.s index 3118e2e56..6872f1f2e 100644 --- a/libsrc/common/malloc.s +++ b/libsrc/common/malloc.s @@ -140,9 +140,9 @@ _malloc: ; Load a pointer to the freelist into ptr2 -@L2: lda __heapfirst +@L2: lda ___heapfirst sta ptr2 - lda __heapfirst+1 + lda ___heapfirst+1 sta ptr2+1 ; Search the freelist for a block that is big enough. We will calculate @@ -173,16 +173,16 @@ _malloc: ; We did not find a block big enough. Try to use new space from the heap top. - lda __heapptr + lda ___heapptr add ptr1 ; _heapptr + size tay - lda __heapptr+1 + lda ___heapptr+1 adc ptr1+1 bcs OutOfHeapSpace ; On overflow, we're surely out of space - cmp __heapend+1 + cmp ___heapend+1 bne @L5 - cpy __heapend + cpy ___heapend @L5: bcc TakeFromTop beq TakeFromTop @@ -196,13 +196,13 @@ Done: rts ; There is enough space left, take it from the heap top TakeFromTop: - ldx __heapptr ; p = _heapptr; + ldx ___heapptr ; p = _heapptr; stx ptr2 - ldx __heapptr+1 + ldx ___heapptr+1 stx ptr2+1 - sty __heapptr ; _heapptr += size; - sta __heapptr+1 + sty ___heapptr ; _heapptr += size; + sta ___heapptr+1 jmp FillSizeAndRet ; Done ; We found a block big enough. If the block can hold just the @@ -245,10 +245,10 @@ BlockFound: ; Do _hfirst = f->next @L1: lda (ptr2),y ; Load high byte of f->next - sta __heapfirst+1 + sta ___heapfirst+1 dey ; Points to next lda (ptr2),y ; Load low byte of f->next - sta __heapfirst + sta ___heapfirst ; Check f->next. Y points always to next if we come here @@ -275,10 +275,10 @@ BlockFound: ; Do _hlast = f->prev @L3: lda (ptr2),y ; Load low byte of f->prev - sta __heaplast + sta ___heaplast iny ; Points to prev+1 lda (ptr2),y ; Load high byte of f->prev - sta __heaplast+1 + sta ___heaplast+1 jmp RetUserPtr ; Done ; We must slice the block found. Cut off space from the upper end, so we diff --git a/libsrc/common/realloc.c b/libsrc/common/realloc.c index c47dbbb98..eeb1eeea5 100644 --- a/libsrc/common/realloc.c +++ b/libsrc/common/realloc.c @@ -74,12 +74,12 @@ void* __fastcall__ realloc (void* block, register size_t size) oldsize = b->size; /* Is the block at the current heap top? */ - if (((unsigned) b) + oldsize == ((unsigned) _heapptr)) { + if (((unsigned) b) + oldsize == ((unsigned) __heapptr)) { /* Check if we've enough memory at the heap top */ - newhptr = ((unsigned) _heapptr) - oldsize + size; - if (newhptr <= ((unsigned) _heapend)) { + newhptr = ((unsigned) __heapptr) - oldsize + size; + if (newhptr <= ((unsigned) __heapend)) { /* Ok, there's space enough */ - _heapptr = (unsigned*) newhptr; + __heapptr = (unsigned*) newhptr; b->size = size; b->start = b; return block; From 145adf61eaf482c290f36ed4df190a4f0de2031b Mon Sep 17 00:00:00 2001 From: mrdudz Date: Mon, 29 Aug 2022 20:10:21 +0200 Subject: [PATCH 023/360] define old names also for heap stuff --- include/_heap.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/_heap.h b/include/_heap.h index c51f864ac..62a7f4bed 100644 --- a/include/_heap.h +++ b/include/_heap.h @@ -43,7 +43,14 @@ extern unsigned* __heapend; /* Upper limit */ extern struct freeblock* __heapfirst; /* First free block in list */ extern struct freeblock* __heaplast; /* Last free block in list */ - +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _heaporg __heaporg +#define _heapptr __heapptr +#define _heapend __heapend +#define _heapfirst __heapfirst +#define _heaplast __heaplast +#endif /* End of _heap.h */ From 89c08dc6d438d8fa304b887533589f89595b4542 Mon Sep 17 00:00:00 2001 From: mrdudz Date: Mon, 29 Aug 2022 20:52:35 +0200 Subject: [PATCH 024/360] extra underscores for _randomize and _swap --- include/stdlib.h | 12 ++++++++++-- include/string.h | 6 +++++- libsrc/apple2/randomize.s | 6 +++--- libsrc/atari/randomize.s | 6 +++--- libsrc/atari5200/randomize.s | 6 +++--- libsrc/c128/randomize.s | 6 +++--- libsrc/c16/randomize.s | 6 +++--- libsrc/c64/randomize.s | 6 +++--- libsrc/cbm510/randomize.s | 6 +++--- libsrc/cbm610/randomize.s | 6 +++--- libsrc/common/_swap.s | 6 +++--- libsrc/common/qsort.c | 4 ++-- libsrc/cx16/randomize.s | 6 +++--- libsrc/geos-common/system/randomize.s | 6 +++--- libsrc/nes/randomize.s | 6 +++--- libsrc/pet/randomize.s | 6 +++--- libsrc/plus4/randomize.s | 6 +++--- libsrc/vic20/randomize.s | 6 +++--- 18 files changed, 62 insertions(+), 50 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index 53d73bb8d..4e7ffbd6a 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -125,7 +125,11 @@ size_t __heapmaxavail (void); #define RAND_MAX 0x7FFF int rand (void); void __fastcall__ srand (unsigned seed); -void _randomize (void); /* Non-standard */ +void __randomize (void); /* Non-standard */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _randomize __randomize +#endif /* Other standard stuff */ void abort (void) __attribute__ ((noreturn)); @@ -146,7 +150,11 @@ unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base); int __fastcall__ system (const char* s); /* Non-ANSI functions */ -void __fastcall__ _swap (void* p, void* q, size_t size); +void __fastcall__ __swap (void* p, void* q, size_t size); +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _swap __swap +#endif #if __CC65_STD__ == __CC65_STD_CC65__ char* __fastcall__ itoa (int val, char* buf, int radix); char* __fastcall__ utoa (unsigned val, char* buf, int radix); diff --git a/include/string.h b/include/string.h index 1bd83b385..bda960173 100644 --- a/include/string.h +++ b/include/string.h @@ -92,8 +92,12 @@ char* __fastcall__ strupper (char* s); char* __fastcall__ strqtok (char* s1, const char* s2); #endif -const char* __fastcall__ _stroserror (unsigned char errcode); +const char* __fastcall__ __stroserror (unsigned char errcode); /* Map an operating system error number to an error message. */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _stroserror __stroserror +#endif /* End of string.h */ diff --git a/libsrc/apple2/randomize.s b/libsrc/apple2/randomize.s index 1558d85a7..e9cd063b8 100644 --- a/libsrc/apple2/randomize.s +++ b/libsrc/apple2/randomize.s @@ -1,16 +1,16 @@ ; ; Ullrich von Bassewitz, 07.11.2002 ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "apple2.inc" -__randomize: +___randomize: ldx RNDH ; Use random value supplied by ROM lda RNDL jmp _srand ; Initialize generator diff --git a/libsrc/atari/randomize.s b/libsrc/atari/randomize.s index 915fee3bd..d004a7c19 100644 --- a/libsrc/atari/randomize.s +++ b/libsrc/atari/randomize.s @@ -1,16 +1,16 @@ ; ; Christian Groessler, 06.11.2002 ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "atari.inc" -__randomize: +___randomize: ldx VCOUNT ; Use vertical line counter as high byte lda RTCLOK+2 ; Use clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/atari5200/randomize.s b/libsrc/atari5200/randomize.s index 978ccf3f3..5c554b5f8 100644 --- a/libsrc/atari5200/randomize.s +++ b/libsrc/atari5200/randomize.s @@ -1,16 +1,16 @@ ; ; Christian Groessler, 01-Mar-2014 ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "atari5200.inc" -__randomize: +___randomize: ldx VCOUNT ; Use vertical line counter as high byte lda RTCLOK+1 ; Use clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/c128/randomize.s b/libsrc/c128/randomize.s index ae63184a4..2b7754e86 100644 --- a/libsrc/c128/randomize.s +++ b/libsrc/c128/randomize.s @@ -2,16 +2,16 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "c128.inc" -__randomize: +___randomize: ldx VIC_HLINE ; Use VIC rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/c16/randomize.s b/libsrc/c16/randomize.s index 796ad118b..0d1ccaf03 100644 --- a/libsrc/c16/randomize.s +++ b/libsrc/c16/randomize.s @@ -2,16 +2,16 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "plus4.inc" -__randomize: +___randomize: ldx TED_VLINELO ; Use TED rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/c64/randomize.s b/libsrc/c64/randomize.s index a875203af..da32dfc28 100644 --- a/libsrc/c64/randomize.s +++ b/libsrc/c64/randomize.s @@ -2,16 +2,16 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "c64.inc" -__randomize: +___randomize: ldx VIC_HLINE ; Use VIC rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/cbm510/randomize.s b/libsrc/cbm510/randomize.s index 75c419ccb..8d21cde15 100644 --- a/libsrc/cbm510/randomize.s +++ b/libsrc/cbm510/randomize.s @@ -2,15 +2,15 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .importzp time -__randomize: +___randomize: ldx time+2 ; Use 50/60HZ clock lda time+1 jmp _srand ; Initialize generator diff --git a/libsrc/cbm610/randomize.s b/libsrc/cbm610/randomize.s index 75c419ccb..8d21cde15 100644 --- a/libsrc/cbm610/randomize.s +++ b/libsrc/cbm610/randomize.s @@ -2,15 +2,15 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .importzp time -__randomize: +___randomize: ldx time+2 ; Use 50/60HZ clock lda time+1 jmp _srand ; Initialize generator diff --git a/libsrc/common/_swap.s b/libsrc/common/_swap.s index 9ad771de1..ba3e5922d 100644 --- a/libsrc/common/_swap.s +++ b/libsrc/common/_swap.s @@ -1,15 +1,15 @@ ; ; Ullrich von Bassewitz, 1998-12-09, 2004-11-30 ; -; void __fastcall__ _swap (void* p, void* q, size_t size); +; void __fastcall__ __swap (void* p, void* q, size_t size); ; - .export __swap + .export ___swap .import popax, popptr1 .importzp ptr1, ptr2, ptr3 -__swap: eor #$FF +___swap: eor #$FF sta ptr3 txa eor #$FF diff --git a/libsrc/common/qsort.c b/libsrc/common/qsort.c index 991db3ba1..913165814 100644 --- a/libsrc/common/qsort.c +++ b/libsrc/common/qsort.c @@ -32,13 +32,13 @@ static void QuickSort (register unsigned char* Base, int Lo, int Hi, J -= Size; } if (I <= J) { - _swap (Base + I, Base + J, Size); + __swap (Base + I, Base + J, Size); I += Size; J -= Size; } } if (J != Lo) { - _swap (Base + J, Base + Lo, Size); + __swap (Base + J, Base + Lo, Size); } if (((unsigned) J) * 2 > (Hi + Lo)) { QuickSort (Base, J + Size, Hi, Size, Compare); diff --git a/libsrc/cx16/randomize.s b/libsrc/cx16/randomize.s index 3d965c82a..49051e012 100644 --- a/libsrc/cx16/randomize.s +++ b/libsrc/cx16/randomize.s @@ -1,14 +1,14 @@ ; ; 2020-05-02, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import ENTROPY_GET, _srand -__randomize: +___randomize: jsr ENTROPY_GET jmp _srand ; Initialize generator diff --git a/libsrc/geos-common/system/randomize.s b/libsrc/geos-common/system/randomize.s index 67c217d80..d8f821356 100644 --- a/libsrc/geos-common/system/randomize.s +++ b/libsrc/geos-common/system/randomize.s @@ -1,16 +1,16 @@ ; ; Ullrich von Bassewitz, 05.11.2002 ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "geossym.inc" -__randomize: +___randomize: lda random ; get random value from internal generator ldx random+1 jmp _srand ; and use it as seed diff --git a/libsrc/nes/randomize.s b/libsrc/nes/randomize.s index 8df4fb88a..a146fef1b 100644 --- a/libsrc/nes/randomize.s +++ b/libsrc/nes/randomize.s @@ -1,16 +1,16 @@ ; ; Ullrich von Bassewitz, 2003-05-02 ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "nes.inc" -__randomize: +___randomize: ldx tickcount ; Use tick clock lda tickcount+1 jmp _srand ; Initialize generator diff --git a/libsrc/pet/randomize.s b/libsrc/pet/randomize.s index 44bf4c38e..a173cf076 100644 --- a/libsrc/pet/randomize.s +++ b/libsrc/pet/randomize.s @@ -2,16 +2,16 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "pet.inc" -__randomize: +___randomize: ldx TIME+2 lda TIME+1 ; Use 60HZ clock jmp _srand ; Initialize generator diff --git a/libsrc/plus4/randomize.s b/libsrc/plus4/randomize.s index 796ad118b..0d1ccaf03 100644 --- a/libsrc/plus4/randomize.s +++ b/libsrc/plus4/randomize.s @@ -2,16 +2,16 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "plus4.inc" -__randomize: +___randomize: ldx TED_VLINELO ; Use TED rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/vic20/randomize.s b/libsrc/vic20/randomize.s index 69cf07bb3..ac2c09a7d 100644 --- a/libsrc/vic20/randomize.s +++ b/libsrc/vic20/randomize.s @@ -2,16 +2,16 @@ ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; -; void _randomize (void); +; void __randomize (void); ; /* Initialize the random number generator */ ; - .export __randomize + .export ___randomize .import _srand .include "vic20.inc" -__randomize: +___randomize: lda VIC_LINES ; Get overflow bit asl a ; Shift bit 7 into carry lda VIC_HLINE ; Get bit 1-8 of rasterline From 3b03a963754d0edb7782d3ca30bbab3e9322a09c Mon Sep 17 00:00:00 2001 From: mrdudz Date: Mon, 29 Aug 2022 21:06:48 +0200 Subject: [PATCH 025/360] add underscores to _poserror and _stroserror --- include/stdio.h | 6 +++++- libsrc/common/_poserror.c | 4 ++-- libsrc/common/stroserr.s | 6 +++--- libsrc/geos-common/common/_poserror.c | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/stdio.h b/include/stdio.h index 84a991a98..858dd5059 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -147,7 +147,11 @@ int __fastcall__ vfscanf (FILE* f, const char* format, __va_list ap); FILE* __fastcall__ fdopen (int fd, const char* mode); /* Unix */ int __fastcall__ fileno (FILE* f); /* Unix */ #endif -void __fastcall__ _poserror (const char* msg); /* cc65 */ +void __fastcall__ __poserror (const char* msg); /* cc65 */ +#if __CC65_STD__ == __CC65_STD_CC65__ +/* define old name with one underscore for backwards compatibility */ +#define _poserror __poserror +#endif /* Masking macros for some functions */ #define getc(f) fgetc (f) /* ANSI */ diff --git a/libsrc/common/_poserror.c b/libsrc/common/_poserror.c index 2777fee98..a2a67dd3e 100644 --- a/libsrc/common/_poserror.c +++ b/libsrc/common/_poserror.c @@ -39,10 +39,10 @@ -void __fastcall__ _poserror (const char* msg) +void __fastcall__ __poserror (const char* msg) { /* Fetch the message that corresponds to _oserror */ - const char* errormsg = _stroserror (_oserror); + const char* errormsg = __stroserror (_oserror); /* Different output depending on msg */ if (msg) { diff --git a/libsrc/common/stroserr.s b/libsrc/common/stroserr.s index 25ca30daf..ae8e117f1 100644 --- a/libsrc/common/stroserr.s +++ b/libsrc/common/stroserr.s @@ -1,11 +1,11 @@ ; ; Ullrich von Bassewitz, 17.07.2002 ; -; const char* __fastcall__ _stroserror (unsigned char errcode); +; const char* __fastcall__ __stroserror (unsigned char errcode); ; /* Map an operating system error number to an error message. */ ; - .export __stroserror + .export ___stroserror .import __sys_oserrlist .importzp ptr1, tmp1 @@ -21,7 +21,7 @@ ; and terminated by an entry with length zero that is returned if the ; error code could not be found. -__stroserror: +___stroserror: sta tmp1 ; Save the error code ldy #<__sys_oserrlist diff --git a/libsrc/geos-common/common/_poserror.c b/libsrc/geos-common/common/_poserror.c index eeb3f368e..b47f0a7d9 100644 --- a/libsrc/geos-common/common/_poserror.c +++ b/libsrc/geos-common/common/_poserror.c @@ -9,9 +9,9 @@ #include #include -void __fastcall__ _poserror (const char* msg) +void __fastcall__ __poserror (const char* msg) { - const char *errmsg = _stroserror(_oserror); + const char *errmsg = __stroserror(_oserror); ExitTurbo(); if (msg && *msg) { From 5bda57de87da864e17bce5e5aec79c79420cff9d Mon Sep 17 00:00:00 2001 From: mrdudz Date: Mon, 29 Aug 2022 23:20:48 +0200 Subject: [PATCH 026/360] add extra underscore to _bzero, add a test for bzero/memset --- include/string.h | 2 +- libsrc/atari7800/clrscr.s | 4 +-- libsrc/atari7800/mono_clrscr.s | 4 +-- libsrc/common/calloc.s | 4 +-- libsrc/common/memset.s | 12 +++---- libsrc/geos-common/common/memset.s | 6 ++-- libsrc/pce/memset.s | 10 +++--- src/cc65/coptstop.c | 2 +- src/cc65/stdfunc.c | 2 +- src/cc65/stdnames.c | 12 +++---- src/cc65/stdnames.h | 12 +++---- test/val/bzero.c | 51 ++++++++++++++++++++++++++++++ 12 files changed, 86 insertions(+), 35 deletions(-) create mode 100644 test/val/bzero.c diff --git a/include/string.h b/include/string.h index bda960173..854359dad 100644 --- a/include/string.h +++ b/include/string.h @@ -74,7 +74,7 @@ void* __fastcall__ memset (void* s, int c, size_t count); /* The following is an internal function, the compiler will replace memset ** with it if the fill value is zero. Never use this one directly! */ -void* __fastcall__ _bzero (void* ptr, size_t n); +void* __fastcall__ __bzero (void* ptr, size_t n); /* Non standard: */ #if __CC65_STD__ == __CC65_STD_CC65__ diff --git a/libsrc/atari7800/clrscr.s b/libsrc/atari7800/clrscr.s index f9d4938b0..a1f663ba7 100644 --- a/libsrc/atari7800/clrscr.s +++ b/libsrc/atari7800/clrscr.s @@ -4,7 +4,7 @@ .export _clrscr .import _screen - .import pushax, __bzero + .import pushax, ___bzero .include "extzp.inc" .code @@ -16,7 +16,7 @@ jsr pushax ldx #>(charsperline * screenrows) lda #<(charsperline * screenrows) - jmp __bzero + jmp ___bzero .endproc diff --git a/libsrc/atari7800/mono_clrscr.s b/libsrc/atari7800/mono_clrscr.s index 19f1fdfd6..f6f6735cb 100644 --- a/libsrc/atari7800/mono_clrscr.s +++ b/libsrc/atari7800/mono_clrscr.s @@ -4,7 +4,7 @@ .export _mono_clrscr .import _mono_screen - .import pushax, __bzero + .import pushax, ___bzero .include "extzp.inc" .code @@ -16,7 +16,7 @@ jsr pushax ldx #>(mono_charsperline * screenrows) lda #<(mono_charsperline * screenrows) - jmp __bzero + jmp ___bzero .endproc diff --git a/libsrc/common/calloc.s b/libsrc/common/calloc.s index 6e3e1bd3f..4cb701146 100644 --- a/libsrc/common/calloc.s +++ b/libsrc/common/calloc.s @@ -7,7 +7,7 @@ ; .export _calloc - .import _malloc, __bzero + .import _malloc, ___bzero .import tosumulax, pushax @@ -48,7 +48,7 @@ ClearBlock: jsr pushax ; ptr lda Size ldx Size+1 ; Size - jmp __bzero + jmp ___bzero .endproc diff --git a/libsrc/common/memset.s b/libsrc/common/memset.s index a57a90e5c..be78fc30d 100644 --- a/libsrc/common/memset.s +++ b/libsrc/common/memset.s @@ -1,6 +1,6 @@ ; ; void* __fastcall__ memset (void* ptr, int c, size_t n); -; void* __fastcall__ _bzero (void* ptr, size_t n); +; void* __fastcall__ __bzero (void* ptr, size_t n); ; void __fastcall__ bzero (void* ptr, size_t n); ; ; Ullrich von Bassewitz, 29.05.1998 @@ -8,19 +8,19 @@ ; Christian Krueger, 12.09.2009, slightly improved 12.01.2011 ; ; NOTE: bzero will return it's first argument as memset does. It is no problem -; to declare the return value as void, since it may be ignored. _bzero -; (note the leading underscore) is declared with the proper return type, -; because the compiler will replace memset by _bzero if the fill value +; to declare the return value as void, since it may be ignored. __bzero +; (note the leading underscores) is declared with the proper return type, +; because the compiler will replace memset by __bzero if the fill value ; is zero, and the optimizer looks at the return type to see if the value ; in a/x is of any use. ; - .export _memset, _bzero, __bzero + .export _memset, _bzero, ___bzero .import popax .importzp sp, ptr1, ptr2, ptr3 _bzero: -__bzero: +___bzero: sta ptr3 stx ptr3+1 ; Save n ldx #0 ; Fill with zeros diff --git a/libsrc/geos-common/common/memset.s b/libsrc/geos-common/common/memset.s index 2cb6732d1..82b7f4a87 100644 --- a/libsrc/geos-common/common/memset.s +++ b/libsrc/geos-common/common/memset.s @@ -1,14 +1,14 @@ ; ; void* memset (void* ptr, int c, size_t n); -; void* _bzero (void* ptr, size_t n); +; void* __bzero (void* ptr, size_t n); ; void bzero (void* ptr, size_t n); ; ; Maciej 'YTM/Elysium' Witkowiak, 20.08.2003 ; - .export _memset, _bzero, __bzero + .export _memset, _bzero, ___bzero .import _ClearRam, _FillRam _bzero = _ClearRam -__bzero = _ClearRam +___bzero = _ClearRam _memset = _FillRam diff --git a/libsrc/pce/memset.s b/libsrc/pce/memset.s index 45a78d533..1148e00c8 100644 --- a/libsrc/pce/memset.s +++ b/libsrc/pce/memset.s @@ -6,21 +6,21 @@ ; 1998-05-29, Ullrich von Bassewitz ; 2015-11-06, Greg King ; -; void* __fastcall__ _bzero (void* ptr, size_t n); +; void* __fastcall__ __bzero (void* ptr, size_t n); ; void __fastcall__ bzero (void* ptr, size_t n); ; void* __fastcall__ memset (void* ptr, int c, size_t n); ; ; NOTE: bzero() will return its first argument, as memset() does. It is no ; problem to declare the return value as void, because it can be ignored. -; _bzero() (note the leading underscore) is declared with the proper -; return type because the compiler will replace memset() by _bzero() if +; __bzero() (note the leading underscores) is declared with the proper +; return type because the compiler will replace memset() by __bzero() if ; the fill value is zero; and, the optimizer looks at the return type ; to see if the value in .XA is of any use. ; ; NOTE: This function uses entry points from "pce/memcpy.s"! ; - .export __bzero, _bzero, _memset + .export ___bzero, _bzero, _memset .import memcpy_getparams, memcpy_increment .import pushax, popax @@ -30,7 +30,7 @@ ; ---------------------------------------------------------------------- -__bzero: +___bzero: _bzero: pha cla ; fill with zeros jsr pushax ; (high byte isn't important) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 08f6c820e..4d0151c55 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1329,7 +1329,7 @@ static unsigned Opt_a_tosult (StackOpData* D) /* The first column of these two tables must be sorted in lexical order */ static const OptFuncDesc FuncTable[] = { - { "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN }, + { "___bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN }, { "staspidx", Opt_staspidx, REG_NONE, OP_NONE }, { "staxspidx", Opt_staxspidx, REG_AX, OP_NONE }, { "tosaddax", Opt_tosaddax, REG_NONE, OP_NONE }, diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index 5ed5ce671..fc19ce7f0 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -604,7 +604,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) DoDeferred (SQP_KEEP_EAX, &Arg3.Expr); /* Emit the actual function call. This will also cleanup the stack. */ - g_call (CF_FIXARGC, MemSet? Func_memset : Func__bzero, ParamSize); + g_call (CF_FIXARGC, MemSet? Func_memset : Func___bzero, ParamSize); if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal == 0) { diff --git a/src/cc65/stdnames.c b/src/cc65/stdnames.c index 687b53894..cdecd61a1 100644 --- a/src/cc65/stdnames.c +++ b/src/cc65/stdnames.c @@ -44,9 +44,9 @@ -const char Func__bzero[] = "_bzero"; /* Asm name of "_bzero" */ -const char Func_memcpy[] = "memcpy"; /* Asm name of "memcpy" */ -const char Func_memset[] = "memset"; /* Asm name of "memset" */ -const char Func_strcmp[] = "strcmp"; /* Asm name of "strcmp" */ -const char Func_strcpy[] = "strcpy"; /* Asm name of "strcpy" */ -const char Func_strlen[] = "strlen"; /* Asm name of "strlen" */ +const char Func___bzero[] = "__bzero"; /* C name of "__bzero" */ +const char Func_memcpy[] = "memcpy"; /* C name of "memcpy" */ +const char Func_memset[] = "memset"; /* C name of "memset" */ +const char Func_strcmp[] = "strcmp"; /* C name of "strcmp" */ +const char Func_strcpy[] = "strcpy"; /* C name of "strcpy" */ +const char Func_strlen[] = "strlen"; /* C name of "strlen" */ diff --git a/src/cc65/stdnames.h b/src/cc65/stdnames.h index dcb323924..e6497e4c3 100644 --- a/src/cc65/stdnames.h +++ b/src/cc65/stdnames.h @@ -44,12 +44,12 @@ -extern const char Func__bzero[]; /* Asm name of "_bzero" */ -extern const char Func_memcpy[]; /* Asm name of "memcpy" */ -extern const char Func_memset[]; /* Asm name of "memset" */ -extern const char Func_strcmp[]; /* Asm name of "strcmp" */ -extern const char Func_strcpy[]; /* Asm name of "strcpy" */ -extern const char Func_strlen[]; /* Asm name of "strlen" */ +extern const char Func___bzero[]; /* C name of "__bzero" */ +extern const char Func_memcpy[]; /* C name of "memcpy" */ +extern const char Func_memset[]; /* C name of "memset" */ +extern const char Func_strcmp[]; /* C name of "strcmp" */ +extern const char Func_strcpy[]; /* C name of "strcpy" */ +extern const char Func_strlen[]; /* C name of "strlen" */ diff --git a/test/val/bzero.c b/test/val/bzero.c new file mode 100644 index 000000000..4e7ed6ac1 --- /dev/null +++ b/test/val/bzero.c @@ -0,0 +1,51 @@ + +// test if memset and bzero work as expected after optimizations + +#include + +char s1[10] = { 1,2,3,4,5,6,7,8,9,10 }; +char r1[10] = { 0,0,0,0,0,6,7,8,9,10 }; + +char s2[10] = { 1,2,3,4,5,6,7,8,9,10 }; +char r2[10] = { 0,0,0,0,0,0,7,8,9,10 }; + +char s3[10] = { 1,2,3,4,5,6,7,8,9,10 }; +char r3[10] = { 0,0,0,0,0,0,0,8,9,10 }; + +char *p1, *p2, *p3; + +int res = 0; + +int main(void) +{ + /* regular bzero */ + bzero(s1, 5); + p1 = __AX__; /* this works because bzero jumps into memset */ + /* this gets converted to __bzero */ + p2 = memset(s2, 0, 6); + /* call internal __bzero (we should not do this in real code) */ + p3 = __bzero(s3, 7); + + /* check the results */ + if (memcmp(s1, r1, 10) != 0) { + res++; + } + if (memcmp(s2, r2, 10) != 0) { + res++; + } + if (memcmp(s3, r3, 10) != 0) { + res++; + } + + if (p1 != s1) { + res++; + } + if (p2 != s2) { + res++; + } + if (p3 != s3) { + res++; + } + + return res; +} From dc001cb4beeecff1e5d7bbef0852cc56d213a7a4 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:56:46 +0800 Subject: [PATCH 027/360] Reverted E_ADDRESS_OF logic fix. Added testcase. --- src/cc65/exprdesc.c | 5 +-- src/cc65/exprdesc.h | 3 +- src/cc65/loadexpr.c | 1 - test/val/bug1847-struct-field-access.c | 46 ++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 test/val/bug1847-struct-field-access.c diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 7d0ace004..3d7b7c384 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -93,7 +93,8 @@ int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) int ED_IsIndExpr (const ExprDesc* Expr) /* Check if the expression is a reference to its value */ { - return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr); + return (Expr->Flags & E_ADDRESS_OF) == 0 && + !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); } #endif @@ -281,7 +282,7 @@ ExprDesc* ED_AddrExpr (ExprDesc* Expr) case E_LOC_EXPR: Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE); - Expr->Flags |= E_ADDRESS_OF | E_LOC_PRIMARY | E_RTYPE_RVAL; + Expr->Flags |= E_LOC_PRIMARY | E_RTYPE_RVAL; break; default: diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index a1674a7cc..f1f121cc4 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -507,7 +507,8 @@ INLINE int ED_IsAddrExpr (const ExprDesc* Expr) INLINE int ED_IsIndExpr (const ExprDesc* Expr) /* Check if the expression is a reference to its value */ { - return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr); + return (Expr->Flags & E_ADDRESS_OF) == 0 && + !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); } #else int ED_IsIndExpr (const ExprDesc* Expr); diff --git a/src/cc65/loadexpr.c b/src/cc65/loadexpr.c index 0b75e0a9c..ccd694e35 100644 --- a/src/cc65/loadexpr.c +++ b/src/cc65/loadexpr.c @@ -92,7 +92,6 @@ static void LoadAddress (unsigned Flags, ExprDesc* Expr) g_leasp (Expr->IVal); break; - case E_LOC_PRIMARY: case E_LOC_EXPR: if (Expr->IVal != 0) { /* We have an expression in the primary plus a constant diff --git a/test/val/bug1847-struct-field-access.c b/test/val/bug1847-struct-field-access.c new file mode 100644 index 000000000..50ae32332 --- /dev/null +++ b/test/val/bug1847-struct-field-access.c @@ -0,0 +1,46 @@ +/* Bug #1847 - struct field access */ + +#include + +struct TestStruct { + char a; + char b; + char c; +}; + +struct TestStruct s0[2] = { {0xFF, 0, 0xFF}, {0, 0x42, 0xFF} }; +struct TestStruct* s0Ptr = s0; + +#define TEST_READ_SUB(X, E) \ + if ((X) != (E)) { \ + printf(#X ": 0x%X, expected: 0x%X\n", (X), (E)); \ + ++failures; \ + } + +#define TEST_READ(S, I, F, E) \ + TEST_READ_SUB(S[I].F, E) \ + TEST_READ_SUB((&S[I])->F, E) \ + TEST_READ_SUB((&S[I])[0].F, E) \ + TEST_READ_SUB(S##Ptr[I].F, E) \ + TEST_READ_SUB((&S##Ptr[I])->F, E) \ + TEST_READ_SUB((&(S##Ptr[I]))[0].F, E) \ + TEST_READ_SUB((&(*S##Ptr))[I].F, E) \ + TEST_READ_SUB((&(*S##Ptr)+I)->F, E) \ + TEST_READ_SUB((S##Ptr+I)->F, E) \ + TEST_READ_SUB((S##Ptr+I)[0].F, E) + +static unsigned failures = 0; + +int main(void) { + struct TestStruct s1[2] = { {0xFF, 0, 0xFF}, {0, 42, 0xFF} }; + struct TestStruct* s1Ptr = s1; + + TEST_READ(s0, 1, b, 0x42) + TEST_READ(s1, 1, b, 42) + + if (failures > 0) { + printf("Failures: %u\n", failures); + } + + return 0; +} From 942ee47d05479ab8077ed9397ade66ff1037df7c Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:58:52 +0800 Subject: [PATCH 028/360] Changed supposed usage of the original line input stack. It is now used for reusing input lines. --- src/cc65/input.c | 94 +++++++++++++++++++++++++++--------------------- src/cc65/input.h | 3 ++ 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/cc65/input.c b/src/cc65/input.c index 5754b1054..8c8007504 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -67,6 +67,9 @@ /* The current input line */ StrBuf* Line; +/* The input line to reuse as the next line */ +static StrBuf* CurReusedLine; + /* Current and next input character */ char CurC = '\0'; char NextC = '\0'; @@ -403,24 +406,6 @@ static void GetInputChar (void) /* NextC is '\0' by default */ NextC = '\0'; - /* Drop all pushed fragments that don't have data left */ - if (CurrentInputStack != 0) { - while (SB_GetIndex (Line) >= SB_GetLen (Line)) { - /* Cannot read more from this line, check next line on stack if any */ - if (CollCount (CurrentInputStack) == 0) { - /* This is THE line */ - break; - } - FreeStrBuf (Line); - Line = CollPop (CurrentInputStack); - } - - /* NextC comes from next fragment */ - if (CollCount (CurrentInputStack) > 0) { - NextC = ' '; - } - } - /* Get CurC from the line */ CurC = SB_LookAt (Line, SB_GetIndex (Line)); } @@ -461,13 +446,17 @@ void PushLine (StrBuf* L) /* Save the current input line and use a new one */ { PRECONDITION (CurrentInputStack != 0); - if (SB_GetIndex (L) < SB_GetLen (L)) { - CollAppend (CurrentInputStack, Line); - Line = L; - GetInputChar (); - } else { - FreeStrBuf (L); - } + CollAppend (CurrentInputStack, Line); + Line = L; + GetInputChar (); +} + + + +void ReuseInputLine (void) +/* Save and reuse the current line as the next line */ +{ + CurReusedLine = Line; } @@ -475,16 +464,6 @@ void PushLine (StrBuf* L) void ClearLine (void) /* Clear the current input line */ { - if (CurrentInputStack != 0) { - unsigned I; - - /* Remove all pushed fragments from the input stack */ - for (I = 0; I < CollCount (CurrentInputStack); ++I) { - FreeStrBuf (Line); - Line = CollPop (CurrentInputStack); - } - } - /* Clear the contents of Line */ SB_Clear (Line); CurC = '\0'; @@ -515,12 +494,47 @@ int NextLine (void) int C; AFile* Input; - /* Clear the current line */ - ClearLine (); - SB_Clear (Line); + /* Overwrite the next input line with the pushed line if there is one */ + if (CurReusedLine != 0) { + /* Use data move to resolve the issue that Line may be impersistent */ + if (Line != CurReusedLine) { + SB_Move (Line, CurReusedLine); + } + /* Continue with this Line */ + InitLine (Line); + CurReusedLine = 0; - /* Must have an input file when called */ - if (CollCount(&AFiles) == 0) { + return 1; + } + + /* If there are pushed input lines, read from them */ + if (CurrentInputStack != 0 && CollCount (CurrentInputStack) > 0) { + /* Drop all pushed fragments that have no data left until one can be + ** used as input. + */ + do { + /* Use data move to resolve the issue that Line may be impersistent */ + if (Line != CollLast (CurrentInputStack)) { + SB_Move (Line, CollPop (CurrentInputStack)); + } else { + CollPop (CurrentInputStack); + } + } while (CollCount (CurrentInputStack) > 0 && + SB_GetIndex (Line) >= SB_GetLen (Line)); + + if (SB_GetIndex (Line) < SB_GetLen (Line)) { + InitLine (Line); + + /* Successive */ + return 1; + } + } + + /* Otherwise, clear the current line */ + ClearLine (); + + /* Must have an input file when going on */ + if (CollCount (&AFiles) == 0) { return 0; } diff --git a/src/cc65/input.h b/src/cc65/input.h index f9565229b..cd73c80b6 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -105,6 +105,9 @@ Collection* UseInputStack (Collection* InputStack); void PushLine (StrBuf* L); /* Save the current input line and use a new one */ +void ReuseInputLine (void); +/* Save and reuse the current line as the next line */ + void ClearLine (void); /* Clear the current input line */ From 3d1e322519137968c5c1e6bc5881fc7215dfffbd Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:58:52 +0800 Subject: [PATCH 029/360] Fixed keeping spacing in certain rare cases. --- src/cc65/preproc.c | 114 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 23 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 99a8af116..4ae41252b 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -2116,7 +2116,6 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* Check if this is a function-like macro */ if (M->ParamCount >= 0) { - int OldPendingNewLines = PendingNewLines; int HaveSpace = SkipWhitespace (MultiLine) > 0; /* A function-like macro name without an immediately @@ -2139,32 +2138,50 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi ME_SetTokLens (E, strlen (M->Name)); } + /* Since we have already got on hold of the next + ** line, we have to reuse it as the next line + ** instead of reading a new line from the source. + */ + if (PendingNewLines > 0 && MultiLine) { + unsigned I = SB_GetIndex (Line); + + /* There is no way a function-like macro call + ** detection could span multiple lines within + ** the range of another just expanded macro. + */ + CHECK (CollCount (&CurRescanStack->Lines) == 1); + + /* Revert one newline */ + --PendingNewLines; + + /* Align indention */ + while (I > 0) { + --I; + if (SB_GetBuf (Line)[I] == '\n') { + ++I; + break; + } + SB_GetBuf (Line)[I] = ' '; + } + + /* Set start index */ + SB_SetIndex (Line, I); + + /* Add newlines */ + AddPreLine (Target); + + /* Reuse this line as the next line */ + ReuseInputLine (); + + /* Quit this loop */ + break; + } + /* Append back the whitespace */ if (HaveSpace) { SB_AppendChar (Target, ' '); } - /* Since we have already got on hold of the next - ** line, we have to go on preprocessing them. - */ - if (MultiLine) { - if (OldPendingNewLines < PendingNewLines && CurC == '#') { - /* If we were going to support #pragma in - ** macro argument list, it would be output - ** to OLine. - */ - if (OLine == 0) { - OLine = Target; - ParseDirectives (ModeFlags); - OLine = 0; - } else { - ParseDirectives (ModeFlags); - } - } - /* Add the source info to preprocessor output if needed */ - AddPreLine (Target); - } - /* Loop */ goto Loop; } @@ -2200,6 +2217,27 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* Switch the buffers */ TmpTarget = NewStrBuf (); + } else if (PendingNewLines > 0 && MultiLine) { + /* Cancel remaining check for pp-tokens separation + ** if there is since ther have been newlines that + ** can always separate them. + */ + if (CurRescanStack->PrevTok != 0) { + FreeStrBuf (CurRescanStack->PrevTok); + CurRescanStack->PrevTok = 0; + } + + /* Squeeze whitespace */ + SkipWhitespace (0); + + /* Add indention to preprocessor output if needed */ + if (CurC != '\0' && CollCount (&CurRescanStack->Lines) == 1) { + /* Add newlines */ + AddPreLine (Target); + + /* Align indention */ + AppendIndent (Target, SB_GetIndex (Line)); + } } /* Since we are rescanning, we needn't add the @@ -2239,7 +2277,24 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi } else if (IsQuotedString ()) { CopyQuotedString (Target); } else { - Skipped = SkipWhitespace (0); + /* We want to squeeze whitespace until the end of the current + ** input line, so we have to deal with such cases specially. + */ + if (CollCount (&CurRescanStack->Lines) > 1) { + RescanInputStack* RIS = CurRescanStack; + + /* Temporarily disable input popping */ + CurRescanStack = 0; + Skipped = SkipWhitespace (0); + CurRescanStack = RIS; + + if (CurC == '\0') { + /* Now we are at the end of the input line */ + goto Loop; + } + } else { + Skipped = SkipWhitespace (0); + } /* Punctuators must be checked after whitespace since comments ** introducers may be misinterpreted as division operators. @@ -2282,6 +2337,19 @@ Loop: if (CurC == '\0' && CollCount (&CurRescanStack->Lines) > 1) { /* Check for rescan sequence end and pp-token pasting */ Skipped = SkipWhitespace (0) || Skipped; + + /* Add indention to preprocessor output if needed */ + if (CurC != '\0' && + PendingNewLines > 0 && + (ModeFlags & MSM_MULTILINE) != 0 && + CollCount (&CurRescanStack->Lines) == 1) { + /* Add newlines */ + AddPreLine (Target); + + /* Align indention */ + AppendIndent (Target, SB_GetIndex (Line)); + Skipped = 0; + } } /* Append a space if there hasn't been one */ From 770e529b2033ebe5e0fe26f8d2f41d674080f928 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:58:52 +0800 Subject: [PATCH 030/360] Fixed newline counting inside old C style comments. --- src/cc65/preproc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 4ae41252b..87d6a7878 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -878,7 +878,7 @@ static void Stringize (StrBuf* Source, StrBuf* Target) static void OldStyleComment (void) -/* Remove an old style C comment from line. */ +/* Remove an old style C comment from line */ { /* Remember the current line number, so we can output better error ** messages if the comment is not terminated in the current file. @@ -897,6 +897,7 @@ static void OldStyleComment (void) StartingLine); return; } + ++PendingNewLines; } else { if (CurC == '/' && NextC == '*') { PPWarning ("'/*' found inside a comment"); @@ -913,7 +914,7 @@ static void OldStyleComment (void) static void NewStyleComment (void) -/* Remove a new style C comment from line. */ +/* Remove a new style C comment from line */ { /* Diagnose if this is unsupported */ if (IS_Get (&Standard) < STD_C99) { From 92f94e4e5b271142caaaa8dabf0d21c1a8db1ae2 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:58:52 +0800 Subject: [PATCH 031/360] A space character will be inserted in front of a leading '#' pp-token as the result of macro expansion. --- src/cc65/preproc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 87d6a7878..833dea9d4 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -2216,6 +2216,13 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi InitLine (TmpTarget); PushRescanLine (CurRescanStack, TmpTarget, LastTokLen); + /* Add a space before a '#' at the beginning of the line */ + if (CurC == '#' && + NextC != '#' && + (SB_IsEmpty (Target) || SB_LookAtLast (Target) == '\n')) { + SB_AppendChar (Target, ' '); + } + /* Switch the buffers */ TmpTarget = NewStrBuf (); } else if (PendingNewLines > 0 && MultiLine) { From 950606d46a45839fe1409e057cc396b5e66e6366 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:59:00 +0800 Subject: [PATCH 032/360] Improved diagnostics on wrong number of arguments in function-like macro calls. --- src/cc65/preproc.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 833dea9d4..43c2131d1 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -1551,7 +1551,10 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in /* If this is not the single empty argument for a macro with an ** empty argument list, remember it. */ - if (CurC != ')' || SB_NotEmpty (&Arg.Tokens) || M->ParamCount > 0) { + if (CurC != ')' || + CollCount (&E->Args) > 0 || + SB_NotEmpty (&Arg.Tokens) || + M->ParamCount > 0) { MacroExp* A = ME_AppendArg (E, &Arg); unsigned I; @@ -1669,11 +1672,23 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in } /* Compare formal and actual argument count */ - if (CollCount (&E->Args) != (unsigned) M->ParamCount) { - + if (CollCount (&E->Args) < (unsigned) M->ParamCount) { + /* Check further only when the parentheses are paired */ if (Parens == 0) { - /* Argument count mismatch */ - PPError ("Macro argument count mismatch"); + /* Specially casing variable argument */ + if (M->Variadic && + M->ParamCount > 0 && + CollCount (&E->Args) + 1 == (unsigned) M->ParamCount) { + /* The variable argument is left out entirely */ + E->Flags |= MES_NO_VA_COMMA; + if (IS_Get (&Standard) < STD_CC65) { + PPWarning ("ISO C does not permit leaving out the comma before the variable argument"); + } + } else { + /* Too few argument */ + PPError ("Macro \"%s\" passed only %u arguments, but requires %u", + M->Name, CollCount (&E->Args), (unsigned) M->ParamCount); + } } /* Be sure to make enough empty arguments available */ @@ -1683,6 +1698,10 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in while (CollCount (&E->Args) < (unsigned) M->ParamCount) { ME_AppendArg (E, &Arg); } + } else if (Parens == 0 && CollCount (&E->Args) > (unsigned) M->ParamCount) { + /* Too many arguments */ + PPError ("Macro \"%s\" passed %u arguments, but takes just %u", + M->Name, CollCount (&E->Args), (unsigned) M->ParamCount); } /* Deallocate argument resources */ From b4ddd01d78cb20d53fa987cf0cb4d4aad3ee1c77 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 1 Sep 2022 12:58:52 +0800 Subject: [PATCH 033/360] Fixed checks on __VA_ARGS__. --- src/cc65/preproc.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 43c2131d1..f1a525eae 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -806,6 +806,21 @@ static int MacName (char* Ident) +static void CheckForBadIdent (const char* Ident, int Std, const Macro* M) +/* Check for and warning on problematic identifiers */ +{ + if (Std >= STD_C99 && + (M == 0 || !M->Variadic) && + strcmp (Ident, "__VA_ARGS__") == 0) { + /* __VA_ARGS__ cannot be used as a macro parameter name in post-C89 + ** mode. + */ + PPWarning ("__VA_ARGS__ can only appear in the expansion of a C99 variadic macro"); + } +} + + + static void AddPreLine (StrBuf* Str) /* Add newlines to the string buffer */ { @@ -2089,6 +2104,12 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { + /* Check for bad identifier names */ + if ((ModeFlags & (MSM_MULTILINE | MSM_IN_DIRECTIVE | MSM_IN_ARG_LIST)) != 0 && + (CollCount (&CurRescanStack->Lines) == 1 || CurC == '\0')) { + CheckForBadIdent (Ident, IS_Get (&Standard), 0); + } + if ((ModeFlags & MSM_OP_DEFINED) != 0 && strcmp (Ident, "defined") == 0) { /* Handle the "defined" operator */ int HaveParen = 0; @@ -2431,6 +2452,7 @@ static int ParseMacroReplacement (StrBuf* Source, Macro* M) int HasWhiteSpace = 0; unsigned Len; ident Ident; + int Std = IS_Get (&Standard); /* Skip whitespace before the macro replacement */ SkipWhitespace (0); @@ -2448,6 +2470,9 @@ static int ParseMacroReplacement (StrBuf* Source, Macro* M) SB_AppendChar (&M->Replacement, ' '); } else if (IsQuotedString ()) { CopyQuotedString (&M->Replacement); + } else if (IsSym (Ident)) { + CheckForBadIdent (Ident, Std, M); + SB_AppendStr (&M->Replacement, Ident); } else { if (M->ParamCount >= 0 && GetPunc (Ident)) { Len = strlen (Ident); @@ -2516,7 +2541,7 @@ static void DoDefine (void) ident Ident; Macro* M = 0; Macro* Existing; - int C89; + int Std; /* Read the macro name */ SkipWhitespace (0); @@ -2524,8 +2549,8 @@ static void DoDefine (void) goto Error_Handler; } - /* Remember if we're in C89 mode */ - C89 = (IS_Get (&Standard) == STD_C89); + /* Remember the language standard we are in */ + Std = IS_Get (&Standard); /* Check for forbidden macro names */ if (strcmp (Ident, "defined") == 0) { @@ -2533,6 +2558,9 @@ static void DoDefine (void) goto Error_Handler; } + /* Check for and warn on special identifiers */ + CheckForBadIdent (Ident, Std, 0); + /* Create a new macro definition */ M = NewMacro (Ident); @@ -2557,7 +2585,7 @@ static void DoDefine (void) /* The next token must be either an identifier, or - if not in ** C89 mode - the ellipsis. */ - if (!C89 && CurC == '.') { + if (Std >= STD_C99 && CurC == '.') { /* Ellipsis */ NextChar (); if (CurC != '.' || NextC != '.') { @@ -2579,11 +2607,8 @@ static void DoDefine (void) goto Error_Handler; } - /* __VA_ARGS__ is only allowed in post-C89 mode */ - if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) { - PPWarning ("'__VA_ARGS__' can only appear in the expansion " - "of a C99 variadic macro"); - } + /* Check for and warn on special identifiers */ + CheckForBadIdent (Ident, Std, 0); /* Add the macro parameter */ AddMacroParam (M, Ident); @@ -2758,6 +2783,7 @@ static int DoIfDef (int skip, int flag) SkipWhitespace (0); if (MacName (Ident)) { + CheckForBadIdent (Ident, IS_Get (&Standard), 0); Value = IsMacro (Ident); /* Check for extra tokens */ CheckExtraTokens (flag ? "ifdef" : "ifndef"); @@ -2964,6 +2990,7 @@ static void DoUndef (void) SkipWhitespace (0); if (MacName (Ident)) { + CheckForBadIdent (Ident, IS_Get (&Standard), 0); UndefineMacro (Ident); } /* Check for extra tokens */ From 446a785f95143a924ca972e9ef38d62adaf54d29 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Fri, 2 Sep 2022 11:55:54 +0200 Subject: [PATCH 034/360] Don't hide errors in error handling You don't want the low byte, see grep _ERR_ libsrc/tgi/* --- libsrc/tgi/tgi_unload.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/tgi/tgi_unload.s b/libsrc/tgi/tgi_unload.s index 1012969d2..c01228080 100644 --- a/libsrc/tgi/tgi_unload.s +++ b/libsrc/tgi/tgi_unload.s @@ -29,6 +29,6 @@ _tgi_unload: jmp _mod_free ; Free the driver no_driver: - lda # Date: Sat, 3 Sep 2022 18:36:40 +0200 Subject: [PATCH 035/360] Force 16bit address for absolute-indirect-x-indexed in 65816 mode. should fix issue #1846 (and hopefully not break anything :)) --- src/ca65/instr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 834edfb5f..d0d7ce64c 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -1298,7 +1298,7 @@ static void EmitCode (EffAddr* A) break; case 2: - if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) { + if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y | AM65_ABS_X_IND))) { /* This is a 16 bit mode that uses an address. If in 65816, ** mode, force this address into 16 bit range to allow ** addressing inside a 64K segment. From 5493c9e7c2595b85d4dd7eb50c57b767ef72e06a Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Thu, 8 Sep 2022 17:11:30 +0200 Subject: [PATCH 036/360] Don't empty the Receive Data Register on filling the Transmit Data Register The Receive Data Register and the Transmit Data Register share share a single address. Accessing that address with STA abs,X in order to fill the Transmit Data Register causes a 6502 false read which causes the Receive Data Register to be emptied. The simplest way to work around that issue - which I chose here - is to move the base address for all ACIA accesses from page $C0 to page $BF. However, that adds an additional cycle to all read accesses. An alternative approach would be to only modify the single line `sta ACIA_DATA,x`. --- libsrc/apple2/ser/a2.ssc.s | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libsrc/apple2/ser/a2.ssc.s b/libsrc/apple2/ser/a2.ssc.s index a32110ef2..e0cd94597 100644 --- a/libsrc/apple2/ser/a2.ssc.s +++ b/libsrc/apple2/ser/a2.ssc.s @@ -57,7 +57,9 @@ ;---------------------------------------------------------------------------- ; I/O definitions -ACIA = $C088 +Offset = $8F ; Move 6502 false read out of I/O to page $BF + +ACIA = $C088-Offset ACIA_DATA = ACIA+0 ; Data register ACIA_STATUS = ACIA+1 ; Status register ACIA_CMD = ACIA+2 ; Command register @@ -197,6 +199,7 @@ SER_OPEN: asl asl asl + adc Offset ; Assume carry to be clear tax ; Check if the handshake setting is valid From fd6d00a4ddc4f015f089f0e6c64f0d9840c8cf5a Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sat, 17 Sep 2022 14:41:59 +0200 Subject: [PATCH 037/360] revert 6096a24 - this breaks the case when the "label" is an expression containing spaces. fixes bug #1853 --- src/cc65/codeseg.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index 5949c0c6f..e621147ab 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -399,10 +399,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) default: /* Absolute, maybe indexed */ - L = ReadToken (L, ", ", Arg, sizeof (Arg)); - if (*L == ' ') { - L = SkipSpace (L+1); - } + L = ReadToken (L, ",", Arg, sizeof (Arg)); if (*L == '\0') { /* Absolute, zeropage or branch */ if ((OPC->Info & OF_BRA) != 0) { From 6fc2cd9f615b32e9ec2472d00f06d5ccabe8292f Mon Sep 17 00:00:00 2001 From: mrdudz Date: Sat, 17 Sep 2022 14:42:18 +0200 Subject: [PATCH 038/360] add test related to bug #1853 --- test/val/bug1853-inline-asm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/val/bug1853-inline-asm.c diff --git a/test/val/bug1853-inline-asm.c b/test/val/bug1853-inline-asm.c new file mode 100644 index 000000000..9813566dc --- /dev/null +++ b/test/val/bug1853-inline-asm.c @@ -0,0 +1,21 @@ + +/* #1853 - Regression on inline assembly expression evaluation */ + +int main(void) +{ +/* +compiles with e.g. Git 2f4e2a3 to the expected + + lda 1 + lda 1 + 1 + rts + +However, with the current HEAD, it compiles to + + lda 1 + lda +*/ + __asm__("lda 1"); + __asm__("lda 1 + 1"); + return 0; +} From 16ba232d080cc107842fc5d794073b3edfa96bd7 Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 18 Sep 2022 22:29:01 +0800 Subject: [PATCH 039/360] Fixed some testcases. --- test/val/bug1838.c | 2 +- test/val/bug1847-struct-field-access.c | 2 +- test/val/mult1.c | 17 +++++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/test/val/bug1838.c b/test/val/bug1838.c index ba3c1164f..ea2d39a81 100644 --- a/test/val/bug1838.c +++ b/test/val/bug1838.c @@ -12,7 +12,7 @@ int main(void) fn_t bar; foo(bar); - return 0; + return failures; } void foo(int func(int)) diff --git a/test/val/bug1847-struct-field-access.c b/test/val/bug1847-struct-field-access.c index 50ae32332..71575636f 100644 --- a/test/val/bug1847-struct-field-access.c +++ b/test/val/bug1847-struct-field-access.c @@ -42,5 +42,5 @@ int main(void) { printf("Failures: %u\n", failures); } - return 0; + return failures; } diff --git a/test/val/mult1.c b/test/val/mult1.c index 6d491a427..95141d76d 100644 --- a/test/val/mult1.c +++ b/test/val/mult1.c @@ -26,15 +26,17 @@ void done() void m1(void) { - c1 = c1*5; /* char = char * lit */ + c1 = c1*5; /* char = char * lit */ + c2 = c1*c3; /* char = char * char */ - c2 = c1 *c3; /* char = char * char */ - - uc1= uc1*5; /* uchar = uchar * lit * - uc2=uc1*uc3; /* uchar = uchar * uchar */ + uc1 = uc1*3; /* uchar = uchar * lit */ + uc2 = uc1*uc3; /* uchar = uchar * uchar */ if(c2 != 25) failures++; + + if(uc2 != 36) + failures++; } void m2(unsigned char uc) @@ -96,6 +98,9 @@ int main(void) c1 = 1; c3 = 5; + uc1 = 2; + uc3 = 6; + m1(); uc1 = 0x10; @@ -107,7 +112,7 @@ int main(void) ui3 = ui1*ui2; /* uint = uint * unit */ - /*m3(TESTLIT);*/ + m3(TESTLIT); success = failures; done(); From 080ec131d852cae576a2ef0bd2e51a673c1a0cc3 Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 18 Sep 2022 22:29:30 +0800 Subject: [PATCH 040/360] Added testcase for constant operands with side-effects. --- test/val/const-side-effect.c | 160 +++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 test/val/const-side-effect.c diff --git a/test/val/const-side-effect.c b/test/val/const-side-effect.c new file mode 100644 index 000000000..7c2f074f2 --- /dev/null +++ b/test/val/const-side-effect.c @@ -0,0 +1,160 @@ +/* Check code generation for constant operands with side-effects */ + +#include + +static int failures = 0; + +#define TEST(X, Y, L) \ + if (x != X || y != Y) { \ + printf("Failed: " L "\nExpected: x = " #X ", y = " #Y ", got: x = %d, y = %d\n\n", x, y); \ + ++failures; \ + } + +#define TEST_LINE_UNARY(OP, RH, ID) \ + "x = " #OP "(set(&y, " #ID "), " #RH ")" + +#define TEST_UNARY(OP, RH, RS, ID) \ + x = -!(RS), y = -!(RS); \ + x = OP (set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_UNARY(OP, RH, ID)) + +#define TEST_LINE_RHS_EFFECT(LH, OP, RH, ID) \ + "x = " #LH " " #OP " (set(&y, " #ID "), " #RH ")" + +#define TEST_LINE_LHS_EFFECT(LH, OP, RH, ID) \ + "y = (set(&x, " #ID "), " #LH ") " #OP " " #RH + +#define TEST_BINARY(LH, OP, RH, RS, ID) \ + x = -!(RS), y = -!(RS); \ + x = LH OP (set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT(LH, OP, RH, ID)) \ + y = -!(RS), x = -!(RS); \ + y = (set(&x, ID), LH) OP RH; \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT(LH, OP, RH, ID)) \ + y = -!(RS); \ + x = (set(&x, LH), x) OP (set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT((set(&x, LH), x), OP, RH, ID)) \ + x = -!(RS); \ + y = (set(&x, ID), LH) OP (set(&y, RH), y); \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT(LH, OP, (set(&y, RH), y), ID)) + +#define TEST_LINE_RHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID) \ + "x = (" #LT ")" #LH " " #OP " (" #RT ")(set(&y, " #ID "), " #RH ")" + +#define TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID) \ + "y = (" #LT ")(set(&x, " #ID "), " #LH ") " #OP " (" #RT ")" #RH + +#define TEST_BINARY_WITH_CAST(LT, LH, OP, RT, RH, RS, ID) \ + x = -!(RS), y = -!(RS); \ + x = (LT)LH OP (RT)(set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID)) \ + y = -!(RS), x = -!(RS); \ + y = (LT)(set(&x, ID), LH) OP (RT)RH; \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID)) \ + y = -!(RS); \ + x = (LT)(set(&x, LH), x) OP (RT)(set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT_WITH_CAST(LT, (set(&x, LH), x), OP, RT, RH, ID)) \ + x = -!(RS); \ + y = (LT)(set(&x, ID), LH) OP (RT)(set(&y, RH), y); \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, (set(&y, RH), y), ID)) + +void set(int *p, int q) +{ + *p = q; +} + +int twice(int a) +{ + return a * 2; +} + +int (*twicep)(int) = twice; + +void test_unary(void) +{ + int x, y; + + TEST_UNARY(+, 42, 42, 1); + TEST_UNARY(-, -42, 42, 2); + TEST_UNARY(~, ~42, 42, 3); + TEST_UNARY(!, 42, 0, 4); +} + +void test_binary_arithmetic(void) +{ + int x, y; + + TEST_BINARY(41, +, 1, 42, 1) + TEST_BINARY(42, +, 0, 42, 1) + + TEST_BINARY(43, -, 1, 42, 2) + TEST_BINARY(42, -, 0, 42, 2) + + TEST_BINARY(6, *, 7, 42, 3) + TEST_BINARY(42, *, 1, 42, 3) + TEST_BINARY(-42, *, -1, 42, 3) + + TEST_BINARY(126, /, 3, 42, 4) + TEST_BINARY(42, /, 1, 42, 4) + TEST_BINARY(-42, /, -1, 42, 4) + + TEST_BINARY(85, %, 43, 42, 5) + TEST_BINARY(10794, %, 256, 42, 5) + + TEST_BINARY(84, >>, 1, 42, 6) + TEST_BINARY(42, >>, 0, 42, 6) + TEST_BINARY(10752, >>, 8, 42, 6) + TEST_BINARY(21504, >>, 9, 42, 6) + + TEST_BINARY(21, <<, 1, 42, 7) + TEST_BINARY(42, <<, 0, 42, 7) + TEST_BINARY(42, <<, 8, 10752, 7) + + TEST_BINARY(59, &, 238, 42, 8) + TEST_BINARY(42, &, 0, 0, 8) + TEST_BINARY(42, &, -1, 42, 8) + + TEST_BINARY(34, |, 10, 42, 9) + TEST_BINARY(42, |, 0, 42, 9) + TEST_BINARY(34, |, -1, -1, 9) + + TEST_BINARY(59, ^, 17, 42, 10) + TEST_BINARY(42, ^, 0, 42, 10) + TEST_BINARY(~42, ^, -1, 42, 10) +} + +void test_binary_comparison(void) +{ + int x, y; + + TEST_BINARY(42, ==, 42, 1, 11) + + TEST_BINARY(42, !=, 43, 1, 12) + TEST_BINARY_WITH_CAST(signed char, 42, !=, long, 65536L, 1, 12) + TEST_BINARY_WITH_CAST(long, 65536L, !=, signed char, 42, 1, 12) + + TEST_BINARY(42, >, 41, 1, 13) + TEST_BINARY_WITH_CAST(int, 0, >, unsigned, 42, 0, 13) + + TEST_BINARY(42, <, 43, 1, 14) + TEST_BINARY_WITH_CAST(unsigned, 42, <, int, 0, 0, 14) + + TEST_BINARY(42, >=, 0, 1, 15) + TEST_BINARY_WITH_CAST(unsigned, 42, >=, int, 0, 1, 15) + + TEST_BINARY(42, <=, 43, 1, 16) + TEST_BINARY_WITH_CAST(int, 0, <=, unsigned, 42, 1, 16) +} + +int main(void) +{ + test_unary(); + test_binary_arithmetic(); + test_binary_comparison(); + + if (failures != 0) { + printf("Failures: %d\n", failures); + } + + return failures; +} From 5e7d9b5fe3c14f5b705e9a17e3e133bf6004296a Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 18 Sep 2022 22:29:41 +0800 Subject: [PATCH 041/360] Renamed a few testcases. --- test/val/{bug1047.c => bug1047-bitfield-char.c} | 0 test/val/{bug1094.c => bug1094-nested-init.c} | 0 test/val/{bug1095.c => bug1095-bitfield-signed.c} | 0 test/val/{bug1139.c => bug1139-bitfield-in-if.c} | 0 test/val/{bug1178.c => bug1178-struct-copy.c} | 0 test/val/{bug1181.c => bug1181-struct-field-null-cmp.c} | 0 test/val/{bug1267.c => bug1267-bitfield-typedef-signedness.c} | 0 test/val/{bug1332.c => bug1332-bitfield.c} | 0 test/val/{bug1357.c => bug1357-pp.c} | 0 test/val/{bug1451.c => bug1451-struct-ptr-to-local.c} | 0 test/val/{bug1462.c => bug1462-biefield-assign-1.c} | 0 test/val/{bug1462-2.c => bug1462-biefield-assign-2.c} | 0 test/val/{bug1462-3.c => bug1462-biefield-assign-3.c} | 0 test/val/{bug1462-4.c => bug1462-biefield-assign-4.c} | 0 test/val/{anon-struct1.c => struct-anon1.c} | 0 test/val/{anon-struct2.c => struct-anon2.c} | 0 test/val/{return-struct.c => struct-returned.c} | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename test/val/{bug1047.c => bug1047-bitfield-char.c} (100%) rename test/val/{bug1094.c => bug1094-nested-init.c} (100%) rename test/val/{bug1095.c => bug1095-bitfield-signed.c} (100%) rename test/val/{bug1139.c => bug1139-bitfield-in-if.c} (100%) rename test/val/{bug1178.c => bug1178-struct-copy.c} (100%) rename test/val/{bug1181.c => bug1181-struct-field-null-cmp.c} (100%) rename test/val/{bug1267.c => bug1267-bitfield-typedef-signedness.c} (100%) rename test/val/{bug1332.c => bug1332-bitfield.c} (100%) rename test/val/{bug1357.c => bug1357-pp.c} (100%) rename test/val/{bug1451.c => bug1451-struct-ptr-to-local.c} (100%) rename test/val/{bug1462.c => bug1462-biefield-assign-1.c} (100%) rename test/val/{bug1462-2.c => bug1462-biefield-assign-2.c} (100%) rename test/val/{bug1462-3.c => bug1462-biefield-assign-3.c} (100%) rename test/val/{bug1462-4.c => bug1462-biefield-assign-4.c} (100%) rename test/val/{anon-struct1.c => struct-anon1.c} (100%) rename test/val/{anon-struct2.c => struct-anon2.c} (100%) rename test/val/{return-struct.c => struct-returned.c} (100%) diff --git a/test/val/bug1047.c b/test/val/bug1047-bitfield-char.c similarity index 100% rename from test/val/bug1047.c rename to test/val/bug1047-bitfield-char.c diff --git a/test/val/bug1094.c b/test/val/bug1094-nested-init.c similarity index 100% rename from test/val/bug1094.c rename to test/val/bug1094-nested-init.c diff --git a/test/val/bug1095.c b/test/val/bug1095-bitfield-signed.c similarity index 100% rename from test/val/bug1095.c rename to test/val/bug1095-bitfield-signed.c diff --git a/test/val/bug1139.c b/test/val/bug1139-bitfield-in-if.c similarity index 100% rename from test/val/bug1139.c rename to test/val/bug1139-bitfield-in-if.c diff --git a/test/val/bug1178.c b/test/val/bug1178-struct-copy.c similarity index 100% rename from test/val/bug1178.c rename to test/val/bug1178-struct-copy.c diff --git a/test/val/bug1181.c b/test/val/bug1181-struct-field-null-cmp.c similarity index 100% rename from test/val/bug1181.c rename to test/val/bug1181-struct-field-null-cmp.c diff --git a/test/val/bug1267.c b/test/val/bug1267-bitfield-typedef-signedness.c similarity index 100% rename from test/val/bug1267.c rename to test/val/bug1267-bitfield-typedef-signedness.c diff --git a/test/val/bug1332.c b/test/val/bug1332-bitfield.c similarity index 100% rename from test/val/bug1332.c rename to test/val/bug1332-bitfield.c diff --git a/test/val/bug1357.c b/test/val/bug1357-pp.c similarity index 100% rename from test/val/bug1357.c rename to test/val/bug1357-pp.c diff --git a/test/val/bug1451.c b/test/val/bug1451-struct-ptr-to-local.c similarity index 100% rename from test/val/bug1451.c rename to test/val/bug1451-struct-ptr-to-local.c diff --git a/test/val/bug1462.c b/test/val/bug1462-biefield-assign-1.c similarity index 100% rename from test/val/bug1462.c rename to test/val/bug1462-biefield-assign-1.c diff --git a/test/val/bug1462-2.c b/test/val/bug1462-biefield-assign-2.c similarity index 100% rename from test/val/bug1462-2.c rename to test/val/bug1462-biefield-assign-2.c diff --git a/test/val/bug1462-3.c b/test/val/bug1462-biefield-assign-3.c similarity index 100% rename from test/val/bug1462-3.c rename to test/val/bug1462-biefield-assign-3.c diff --git a/test/val/bug1462-4.c b/test/val/bug1462-biefield-assign-4.c similarity index 100% rename from test/val/bug1462-4.c rename to test/val/bug1462-biefield-assign-4.c diff --git a/test/val/anon-struct1.c b/test/val/struct-anon1.c similarity index 100% rename from test/val/anon-struct1.c rename to test/val/struct-anon1.c diff --git a/test/val/anon-struct2.c b/test/val/struct-anon2.c similarity index 100% rename from test/val/anon-struct2.c rename to test/val/struct-anon2.c diff --git a/test/val/return-struct.c b/test/val/struct-returned.c similarity index 100% rename from test/val/return-struct.c rename to test/val/struct-returned.c From cb8cb876ec741c96b506f03539165b12b5d342e7 Mon Sep 17 00:00:00 2001 From: Rutger van Bergen Date: Mon, 19 Sep 2022 19:56:57 +0200 Subject: [PATCH 042/360] Add documentation, make capitalization uniform --- asminc/kim1.inc | 13 ++-- cfg/kim1-60k.cfg | 6 +- cfg/kim1.cfg | 2 +- doc/index.sgml | 3 + doc/kim1.sgml | 148 ++++++++++++++++++++++++++++++++++++++++ libsrc/kim1/crt0.s | 4 +- samples/kim1/kimHello.c | 2 +- src/common/target.h | 2 +- 8 files changed, 165 insertions(+), 15 deletions(-) create mode 100644 doc/kim1.sgml diff --git a/asminc/kim1.inc b/asminc/kim1.inc index f0d1555a7..b1046b01c 100644 --- a/asminc/kim1.inc +++ b/asminc/kim1.inc @@ -7,22 +7,21 @@ RAMSTART := $0200 ; Entry point + ; --------------------------------------------------------------------------- ; Monitor Functions ; --------------------------------------------------------------------------- - - OUTCHR := $1EA0 ; Output character INTCHR := $1E5A ; Input character without case conversion DUMPT := $1800 ; Dump memory to tape LOADT := $1873 ; Load memory from tape + + +; --------------------------------------------------------------------------- +; System Memory +; --------------------------------------------------------------------------- SAL := $17F5 ; Tape load address low SAH := $17F6 ; Tape load address high EAL := $17F7 ; Tape address end low EAH := $17F8 ; Tape address end high ID := $17F9 ; Tape Identification number - -; --------------------------------------------------------------------------- -; System Memory -; --------------------------------------------------------------------------- - diff --git a/cfg/kim1-60k.cfg b/cfg/kim1-60k.cfg index a6704d9dd..087715560 100644 --- a/cfg/kim1-60k.cfg +++ b/cfg/kim1-60k.cfg @@ -1,8 +1,8 @@ -# kim1.cfg (4k) +# kim1-60k.cfg (4k) # -# for unexpanded Kim-1 +# for expanded KIM-1 # -# ld65 --config kim1.cfg -o .bin .o +# ld65 --config kim1-60k.cfg -o .bin .o FEATURES { STARTADDRESS: default = $2000; diff --git a/cfg/kim1.cfg b/cfg/kim1.cfg index 69636065e..f48fed80e 100644 --- a/cfg/kim1.cfg +++ b/cfg/kim1.cfg @@ -1,6 +1,6 @@ # kim1.cfg (4k) # -# for unexpanded Kim-1 +# for unexpanded KIM-1 # # ld65 --config kim1.cfg -o .bin .o diff --git a/doc/index.sgml b/doc/index.sgml index bb3ad5357..bfce63486 100644 --- a/doc/index.sgml +++ b/doc/index.sgml @@ -154,6 +154,9 @@ Topics specific to the Bit Corporation Gamate Console. + + Topics specific to the MOS Technology KIM-1. + Topics specific to the Atari Lynx Game Console. diff --git a/doc/kim1.sgml b/doc/kim1.sgml new file mode 100644 index 000000000..0c8b54311 --- /dev/null +++ b/doc/kim1.sgml @@ -0,0 +1,148 @@ + + +
+MOS Technology KIM-1 specific information for cc65 +<author><url url="mailto:dave@davepl.com" name="Dave Plummer"> + +<abstract> +An overview over the KIM-1 runtime system as it is implemented for the cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the KIM-1 runtime system as it comes with the cc65 C compiler. +It describes the memory layout, KIM-1 specific header files, available drivers, and any pitfalls +specific to the platform. + +Please note that KIM-1 specific functions are just mentioned here, they are described in detail +in the separate <url url="funcref.html" name="function reference">. Even functions marked as +"platform dependent" may be available on more than one platform. Please see the +function reference for more information. + +<sect>Binary format<p> + +The output format generated by the linker for the KIM-1 target is a raw binary BIN file, which +is essentially a memory image. You can convert this to a papertape format file using +Convert8bithexformat or KIMPaper, which are open-source conversion utility programs. +A papertape format files can be transferred to the KIM-1 using the RS-232 terminal port (TTY), +just as if the machine-code was entered by hand. Enter 'L' in the TTY and start the paper tape file +transfer. + +<p> + +Included with this distribution is a 4k configuration file and a 60k config file. The KIM-1 +on-board memory is limited to 4 kbytes but system memory can be increased to 60 kbytes of +contiguous RAM with aftermarket add-on boards. So choose the config file that matches your +system configuration before compiling and linking user programs. + +<sect>Memory layout<p> + +The ROMs and I/O areas are defined in the configuration files, as are most of the entry points +for useful subroutines in the KIM-1 monitor ROM. cc65 generated programs compiled and linked +using 4k config run in the memory range of $200 - $0FFF. The 60k config expands +this range to $DFFF. The starting memory location and entry point for running the program is +$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'. + +Special locations: + +<descrip> + <tag/Text screen/ + Conio support is not currently available for the KIM-1. But stdio console functions are available. + + <tag/Stack/ + The C runtime stack is located at $0FFF on 4kb KIM-1s, or at $DFFF for 60kb systems. + The stack always grows downwards. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C runtime stack. + +</descrip><p> + +<sect>Platform specific header files<p> + +Programs containing KIM-1 code may use the <tt/kim.h/ header file. See the header file for more information. + +<sect>Loadable drivers<p> + +<sect1>Graphics drivers<p> + +No graphics drivers are currently available for the KIM-1. + +<sect1>Joystick drivers<p> + +No joystick driver is currently available for the KIM-1. + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the KIM-1. + +<sect1>RS232 device drivers<p> + +No communication port drivers are currently available for the KIM-1. It has only the "master console" +e.g. stdin and stdout. + +<sect>Limitations<p> + +<sect1>Disk I/O<p> + +The existing library for the KIM-1 doesn't implement C file I/O. + +To be more specific, this limitation means that you cannot use any of the following functions (and a few others): + +<itemize> +<item>fopen +<item>fclose +<item>fread +<item>fwrite +<item>... +</itemize> + +<sect>Other hints<p> + +<sect1>kim1.h<p> +This header exposes KIM-1 specific I/O functions that are useful for reading and writing its ports and front panel. +See the <tt/kim1.h/ include file for a list of the functions available. + +<sect1>Limited memory applications<p> + +As stated earlier, there are config files for 4kb and 60kb systems. If you have 60kb RAM, then you will probably +want to use the kim1-60k configuration, but if not - if you are using the kim1-4k configuration - then you may +want to use functions like getchar, putchar, gets and puts rather than functions like scanf and printf. +Printf, for example, requires about 1KB because it needs to know how to process all the format specifiers. + +<sect1>Sample programs<p> + +These sample programs can be found in the samples/kim1 directory: + +<itemize> +<item>kimHello prints "Hello World!" and then inputs characters, which are echoed on the screen. + This program will run on both 4kb and 60kb systems.</item> +<item>kimSieve finds the prime numbers up to 100,000 using the Sieve of Eratosthenes algorithm, and prints how many + prime numbers were found. This program requires a 60kb system to run.</item> +</itemize> + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied warranty. In no event will the authors be held +liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter +it and redistribute it freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/libsrc/kim1/crt0.s b/libsrc/kim1/crt0.s index aefdc3545..f1fee86c1 100644 --- a/libsrc/kim1/crt0.s +++ b/libsrc/kim1/crt0.s @@ -40,8 +40,8 @@ _init: cld ; Clear decimal mode jsr _main -; Back from main (this is also the _exit entry). There may be a more elegant way to9 -; return to the monitor on the Kim-1, but I don't know it! +; Back from main (this is also the _exit entry). There may be a more elegant way to +; return to the monitor on the KIM-1, but I don't know it! _exit: brk diff --git a/samples/kim1/kimHello.c b/samples/kim1/kimHello.c index dcbfb4e67..0dca1345f 100644 --- a/samples/kim1/kimHello.c +++ b/samples/kim1/kimHello.c @@ -1,5 +1,5 @@ // -------------------------------------------------------------------------- -// Hello World for Kim-1 +// Hello World for KIM-1 // // Dave Plummer based on Sym-1 sample by Wayne Parham // diff --git a/src/common/target.h b/src/common/target.h index 7439fa621..0cec74b6e 100644 --- a/src/common/target.h +++ b/src/common/target.h @@ -87,7 +87,7 @@ typedef enum { TGT_C65, TGT_CX16, TGT_SYM1, - TGT_KIM1, // Added at end so as not to shift existing entries + TGT_KIM1, TGT_COUNT /* Number of target systems */ } target_t; From ab6840712b88e8c0249563d350c0b63d901a4a54 Mon Sep 17 00:00:00 2001 From: David W Plummer <davepl@davepl.com> Date: Mon, 19 Sep 2022 14:17:41 -0700 Subject: [PATCH 043/360] Update kim1.sgml --- doc/kim1.sgml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/kim1.sgml b/doc/kim1.sgml index 0c8b54311..6db9fc908 100644 --- a/doc/kim1.sgml +++ b/doc/kim1.sgml @@ -2,10 +2,10 @@ <article> <title>MOS Technology KIM-1 specific information for cc65 -<author><url url="mailto:dave@davepl.com" name="Dave Plummer"> +<author><url url="mailto:davepl@davepl.com" name="Dave Plummer"> <abstract> -An overview over the KIM-1 runtime system as it is implemented for the cc65 C compiler. +An overview of the KIM-1 runtime system as it is implemented for the cc65 C compiler. </abstract> <!-- Table of contents --> From 3b431d9fa3ca4110c23623887338685117b2bec6 Mon Sep 17 00:00:00 2001 From: Rutger van Bergen <rbergen@xs4all.nl> Date: Mon, 19 Sep 2022 23:57:26 +0200 Subject: [PATCH 044/360] Remove trailing whitespace --- asminc/kim1.inc | 2 +- doc/kim1.sgml | 12 ++++++------ samples/kim1/kimHello.c | 4 ++-- samples/kim1/kimSieve.c | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/asminc/kim1.inc b/asminc/kim1.inc index b1046b01c..68f059490 100644 --- a/asminc/kim1.inc +++ b/asminc/kim1.inc @@ -1,6 +1,6 @@ ; --------------------------------------------------------------------------- ; -; KIM-1 definitions +; KIM-1 definitions ; ; --------------------------------------------------------------------------- diff --git a/doc/kim1.sgml b/doc/kim1.sgml index 6db9fc908..c3494b9b9 100644 --- a/doc/kim1.sgml +++ b/doc/kim1.sgml @@ -27,10 +27,10 @@ function reference for more information. <sect>Binary format<p> The output format generated by the linker for the KIM-1 target is a raw binary BIN file, which -is essentially a memory image. You can convert this to a papertape format file using -Convert8bithexformat or KIMPaper, which are open-source conversion utility programs. -A papertape format files can be transferred to the KIM-1 using the RS-232 terminal port (TTY), -just as if the machine-code was entered by hand. Enter 'L' in the TTY and start the paper tape file +is essentially a memory image. You can convert this to a papertape format file using +Convert8bithexformat or KIMPaper, which are open-source conversion utility programs. +A papertape format files can be transferred to the KIM-1 using the RS-232 terminal port (TTY), +just as if the machine-code was entered by hand. Enter 'L' in the TTY and start the paper tape file transfer. <p> @@ -45,8 +45,8 @@ system configuration before compiling and linking user programs. The ROMs and I/O areas are defined in the configuration files, as are most of the entry points for useful subroutines in the KIM-1 monitor ROM. cc65 generated programs compiled and linked using 4k config run in the memory range of $200 - $0FFF. The 60k config expands -this range to $DFFF. The starting memory location and entry point for running the program is -$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'. +this range to $DFFF. The starting memory location and entry point for running the program is +$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'. Special locations: diff --git a/samples/kim1/kimHello.c b/samples/kim1/kimHello.c index 0dca1345f..9e5ca8ab6 100644 --- a/samples/kim1/kimHello.c +++ b/samples/kim1/kimHello.c @@ -9,14 +9,14 @@ #include <stdio.h> #include <kim1.h> -int main (void) +int main (void) { char str[100]; char c = 0x00; printf ("\nHello World!\n\n"); printf ("Type a line and press ENTER, please.\n\n"); - + gets( str ); printf ("\n\nThanks: %s\n\n", str); diff --git a/samples/kim1/kimSieve.c b/samples/kim1/kimSieve.c index 29cd7c7e9..d13f776ea 100644 --- a/samples/kim1/kimSieve.c +++ b/samples/kim1/kimSieve.c @@ -8,11 +8,11 @@ typedef unsigned long int ulong; #define LIMIT 100000L // BITARRAY -// +// // My bit-access macros pre-divide by two on the presumption that you'll never // try try access both odd and even bits! -#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7))) +#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7))) #define SETBIT(array, bit) (array[bit >> 4] |= (1 << ((bit >> 1) & 7))) #define CLRBIT(array, bit) (array[bit >> 4] &= ~(1 << ((bit >> 1) & 7))) @@ -65,7 +65,7 @@ int main(void) RepeatChar('*', 70); puts("\r\n** Prime Number Sieve - Dave Plummer 2022 **"); RepeatChar('*', 70); - + printf("\r\n\r\nCalculating primes to %ld using a sqrt of %ld...\r\n", LIMIT, rootOfLimit); // Calculate how much memory should be allocated @@ -80,7 +80,7 @@ int main(void) else { printf("Allocated %ld bytes for %ld slots\r\n", numBytesAllocated, LIMIT); - + // Preset all the bits to true for (iNumber = 0; iNumber < numBytesAllocated; iNumber++) @@ -102,7 +102,7 @@ int main(void) break; } } - + for (n = (ulong) currentFactor * currentFactor; n <= LIMIT; n += currentFactor * 2) CLRBIT(array, n); From 846d51db722509539136b961b982ad6d07747c75 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 22 Sep 2022 20:29:57 +0200 Subject: [PATCH 045/360] change line endings to unix style, should fix #1858 --- test/val/bug1408.c | 82 +++---- test/val/bug1451-struct-ptr-to-local.c | 78 +++--- test/val/bug1643.c | 24 +- test/val/bug1643.h | 26 +- test/val/bug1690.c | 60 ++--- test/val/bug1822-pptest.c | 50 ++-- test/val/bug1838.c | 70 +++--- test/val/bug1847-struct-field-access.c | 92 +++---- test/val/const-side-effect.c | 320 ++++++++++++------------- test/val/counter.c | 120 +++++----- test/val/counter.h | 8 +- test/val/opsize.c | 66 ++--- test/val/pr1833.c | 26 +- test/val/uneval.c | 92 +++---- 14 files changed, 557 insertions(+), 557 deletions(-) diff --git a/test/val/bug1408.c b/test/val/bug1408.c index 8ecc1be68..137899315 100644 --- a/test/val/bug1408.c +++ b/test/val/bug1408.c @@ -1,41 +1,41 @@ -/* Bug #1408: Signed char type comparisons with unsigned numeric constants */ - -#include <stdio.h> - -static int failures = 0; -static signed char x = -1; - -int main(void) -{ - if (!(x > -2u)) { - printf("x > -2u should be true\n"); - ++failures; - } - if (!(x > 0u)) { - printf("x > 0u should be true\n"); - ++failures; - } - if (!(x > 255u)) { - printf("x > 255u should be true\n"); - ++failures; - } - - if (!(-2u < x)) { - printf("-2u < x should be true\n"); - ++failures; - } - if (!(0u < x)) { - printf("0u < x should be true\n"); - ++failures; - } - if (!(255u < x)) { - printf("255u < x should be true\n"); - ++failures; - } - - if (failures != 0) { - printf("Failures: %d\n", failures); - } - - return failures; -} +/* Bug #1408: Signed char type comparisons with unsigned numeric constants */ + +#include <stdio.h> + +static int failures = 0; +static signed char x = -1; + +int main(void) +{ + if (!(x > -2u)) { + printf("x > -2u should be true\n"); + ++failures; + } + if (!(x > 0u)) { + printf("x > 0u should be true\n"); + ++failures; + } + if (!(x > 255u)) { + printf("x > 255u should be true\n"); + ++failures; + } + + if (!(-2u < x)) { + printf("-2u < x should be true\n"); + ++failures; + } + if (!(0u < x)) { + printf("0u < x should be true\n"); + ++failures; + } + if (!(255u < x)) { + printf("255u < x should be true\n"); + ++failures; + } + + if (failures != 0) { + printf("Failures: %d\n", failures); + } + + return failures; +} diff --git a/test/val/bug1451-struct-ptr-to-local.c b/test/val/bug1451-struct-ptr-to-local.c index f9cca2561..2148e034d 100644 --- a/test/val/bug1451-struct-ptr-to-local.c +++ b/test/val/bug1451-struct-ptr-to-local.c @@ -1,39 +1,39 @@ -/* Bug #1451 - local struct field access via the address of the struct */ - -#include <stdio.h> - -typedef struct { - int a; - int b; -} S; - -int failures = 0; - -int main(void) -{ - S a = {2, 5}; - S b = {1, 4}; - S m[1] = {{6, 3}}; - S *p = &a; - - (&a)->a += b.a; - p->b += b.b; - m->a += b.a; - - if ((&a)->a != 3) { - ++failures; - printf("Expected 3, got %d\n", (&a)->a); - } - - if (p->b != 9) { - ++failures; - printf("Expected 9, got %d\n", p->b); - } - - if (m->a != 7) { - ++failures; - printf("Expected 7, got %d\n", m->a); - } - - return failures; -} +/* Bug #1451 - local struct field access via the address of the struct */ + +#include <stdio.h> + +typedef struct { + int a; + int b; +} S; + +int failures = 0; + +int main(void) +{ + S a = {2, 5}; + S b = {1, 4}; + S m[1] = {{6, 3}}; + S *p = &a; + + (&a)->a += b.a; + p->b += b.b; + m->a += b.a; + + if ((&a)->a != 3) { + ++failures; + printf("Expected 3, got %d\n", (&a)->a); + } + + if (p->b != 9) { + ++failures; + printf("Expected 9, got %d\n", p->b); + } + + if (m->a != 7) { + ++failures; + printf("Expected 7, got %d\n", m->a); + } + + return failures; +} diff --git a/test/val/bug1643.c b/test/val/bug1643.c index eba733511..c6237b7fb 100644 --- a/test/val/bug1643.c +++ b/test/val/bug1643.c @@ -1,12 +1,12 @@ -/* bug #1643, macro expansion in #include */ - -#define MKSTR(a) MKSTR_IMPL(a) -#define MKSTR_IMPL(a) #a -#define BUG1643_H bug1643.h - -#include MKSTR(BUG1643_H) - -int main(void) -{ - return BUG1643_RESULT; -} +/* bug #1643, macro expansion in #include */ + +#define MKSTR(a) MKSTR_IMPL(a) +#define MKSTR_IMPL(a) #a +#define BUG1643_H bug1643.h + +#include MKSTR(BUG1643_H) + +int main(void) +{ + return BUG1643_RESULT; +} diff --git a/test/val/bug1643.h b/test/val/bug1643.h index fe0423688..068263436 100644 --- a/test/val/bug1643.h +++ b/test/val/bug1643.h @@ -1,13 +1,13 @@ -/* bug #1643, macro expansion in #include */ - -#define STDIO_H <stdio.h> -#include STDIO_H - -#ifdef string -#undef string -#endif - -#define string 0!%^&*/_= -#include <string.h> - -#define BUG1643_RESULT 0 +/* bug #1643, macro expansion in #include */ + +#define STDIO_H <stdio.h> +#include STDIO_H + +#ifdef string +#undef string +#endif + +#define string 0!%^&*/_= +#include <string.h> + +#define BUG1643_RESULT 0 diff --git a/test/val/bug1690.c b/test/val/bug1690.c index 499dc6b35..78c0cda41 100644 --- a/test/val/bug1690.c +++ b/test/val/bug1690.c @@ -1,30 +1,30 @@ -/* OptCmp1 messed up with labels */ - -#include <stdio.h> - -static int failures = 0; -static unsigned int z = 0xFF23; - -int main(void) -{ - register unsigned int x = 0x200; - register unsigned int y = 0; - - do { - ++y; - } while (--x); - if (y != 0x200) { - printf("y should be 0x200, not 0x%X.\n", y); - ++failures;; - } - - if ((z -= 0x23)) { - /* Passed -- non-zero z looks like non-zero. */ - } else { - /* Failed -- only the low byte of z was tested. */ - printf("Test thinks non-zero z is zero.\n"); - ++failures; - } - - return failures; -} +/* OptCmp1 messed up with labels */ + +#include <stdio.h> + +static int failures = 0; +static unsigned int z = 0xFF23; + +int main(void) +{ + register unsigned int x = 0x200; + register unsigned int y = 0; + + do { + ++y; + } while (--x); + if (y != 0x200) { + printf("y should be 0x200, not 0x%X.\n", y); + ++failures;; + } + + if ((z -= 0x23)) { + /* Passed -- non-zero z looks like non-zero. */ + } else { + /* Failed -- only the low byte of z was tested. */ + printf("Test thinks non-zero z is zero.\n"); + ++failures; + } + + return failures; +} diff --git a/test/val/bug1822-pptest.c b/test/val/bug1822-pptest.c index eb4d23391..133d69f6b 100644 --- a/test/val/bug1822-pptest.c +++ b/test/val/bug1822-pptest.c @@ -1,25 +1,25 @@ -/* Bug #1822 - Redefined macros failed to be all undefined with a single #undef */ - -#undef F -#undef F - -#define F 1 -#define F 1 - -#undef F -#if defined F -#error #undef F fails! -#endif - -#define F 0 - -#include <stdio.h> - -int main(void) -{ - if (F != 0) - { - printf("failed: F = %d\n", F); - } - return F; -} +/* Bug #1822 - Redefined macros failed to be all undefined with a single #undef */ + +#undef F +#undef F + +#define F 1 +#define F 1 + +#undef F +#if defined F +#error #undef F fails! +#endif + +#define F 0 + +#include <stdio.h> + +int main(void) +{ + if (F != 0) + { + printf("failed: F = %d\n", F); + } + return F; +} diff --git a/test/val/bug1838.c b/test/val/bug1838.c index ea2d39a81..45978dca4 100644 --- a/test/val/bug1838.c +++ b/test/val/bug1838.c @@ -1,35 +1,35 @@ -/* Bug 1838 - function parameters declared as function types rather than function pointers */ - -#include <stdio.h> - -static int failures = 0; - -typedef int fn_t(int); - -int main(void) -{ - void foo(fn_t*); - fn_t bar; - - foo(bar); - return failures; -} - -void foo(int func(int)) -{ - int n = func(42); - - if (n != 12) { - printf("n = %d, expected: 12\n", n); - ++failures; - } -} - -int bar(int a) -{ - if (a != 42) { - printf("a = %d, expected: 42\n", a); - ++failures; - } - return 12; -} +/* Bug 1838 - function parameters declared as function types rather than function pointers */ + +#include <stdio.h> + +static int failures = 0; + +typedef int fn_t(int); + +int main(void) +{ + void foo(fn_t*); + fn_t bar; + + foo(bar); + return failures; +} + +void foo(int func(int)) +{ + int n = func(42); + + if (n != 12) { + printf("n = %d, expected: 12\n", n); + ++failures; + } +} + +int bar(int a) +{ + if (a != 42) { + printf("a = %d, expected: 42\n", a); + ++failures; + } + return 12; +} diff --git a/test/val/bug1847-struct-field-access.c b/test/val/bug1847-struct-field-access.c index 71575636f..55ead7ec7 100644 --- a/test/val/bug1847-struct-field-access.c +++ b/test/val/bug1847-struct-field-access.c @@ -1,46 +1,46 @@ -/* Bug #1847 - struct field access */ - -#include <stdio.h> - -struct TestStruct { - char a; - char b; - char c; -}; - -struct TestStruct s0[2] = { {0xFF, 0, 0xFF}, {0, 0x42, 0xFF} }; -struct TestStruct* s0Ptr = s0; - -#define TEST_READ_SUB(X, E) \ - if ((X) != (E)) { \ - printf(#X ": 0x%X, expected: 0x%X\n", (X), (E)); \ - ++failures; \ - } - -#define TEST_READ(S, I, F, E) \ - TEST_READ_SUB(S[I].F, E) \ - TEST_READ_SUB((&S[I])->F, E) \ - TEST_READ_SUB((&S[I])[0].F, E) \ - TEST_READ_SUB(S##Ptr[I].F, E) \ - TEST_READ_SUB((&S##Ptr[I])->F, E) \ - TEST_READ_SUB((&(S##Ptr[I]))[0].F, E) \ - TEST_READ_SUB((&(*S##Ptr))[I].F, E) \ - TEST_READ_SUB((&(*S##Ptr)+I)->F, E) \ - TEST_READ_SUB((S##Ptr+I)->F, E) \ - TEST_READ_SUB((S##Ptr+I)[0].F, E) - -static unsigned failures = 0; - -int main(void) { - struct TestStruct s1[2] = { {0xFF, 0, 0xFF}, {0, 42, 0xFF} }; - struct TestStruct* s1Ptr = s1; - - TEST_READ(s0, 1, b, 0x42) - TEST_READ(s1, 1, b, 42) - - if (failures > 0) { - printf("Failures: %u\n", failures); - } - - return failures; -} +/* Bug #1847 - struct field access */ + +#include <stdio.h> + +struct TestStruct { + char a; + char b; + char c; +}; + +struct TestStruct s0[2] = { {0xFF, 0, 0xFF}, {0, 0x42, 0xFF} }; +struct TestStruct* s0Ptr = s0; + +#define TEST_READ_SUB(X, E) \ + if ((X) != (E)) { \ + printf(#X ": 0x%X, expected: 0x%X\n", (X), (E)); \ + ++failures; \ + } + +#define TEST_READ(S, I, F, E) \ + TEST_READ_SUB(S[I].F, E) \ + TEST_READ_SUB((&S[I])->F, E) \ + TEST_READ_SUB((&S[I])[0].F, E) \ + TEST_READ_SUB(S##Ptr[I].F, E) \ + TEST_READ_SUB((&S##Ptr[I])->F, E) \ + TEST_READ_SUB((&(S##Ptr[I]))[0].F, E) \ + TEST_READ_SUB((&(*S##Ptr))[I].F, E) \ + TEST_READ_SUB((&(*S##Ptr)+I)->F, E) \ + TEST_READ_SUB((S##Ptr+I)->F, E) \ + TEST_READ_SUB((S##Ptr+I)[0].F, E) + +static unsigned failures = 0; + +int main(void) { + struct TestStruct s1[2] = { {0xFF, 0, 0xFF}, {0, 42, 0xFF} }; + struct TestStruct* s1Ptr = s1; + + TEST_READ(s0, 1, b, 0x42) + TEST_READ(s1, 1, b, 42) + + if (failures > 0) { + printf("Failures: %u\n", failures); + } + + return failures; +} diff --git a/test/val/const-side-effect.c b/test/val/const-side-effect.c index 7c2f074f2..cebc6f099 100644 --- a/test/val/const-side-effect.c +++ b/test/val/const-side-effect.c @@ -1,160 +1,160 @@ -/* Check code generation for constant operands with side-effects */ - -#include <stdio.h> - -static int failures = 0; - -#define TEST(X, Y, L) \ - if (x != X || y != Y) { \ - printf("Failed: " L "\nExpected: x = " #X ", y = " #Y ", got: x = %d, y = %d\n\n", x, y); \ - ++failures; \ - } - -#define TEST_LINE_UNARY(OP, RH, ID) \ - "x = " #OP "(set(&y, " #ID "), " #RH ")" - -#define TEST_UNARY(OP, RH, RS, ID) \ - x = -!(RS), y = -!(RS); \ - x = OP (set(&y, ID), RH); \ - TEST(RS, ID, TEST_LINE_UNARY(OP, RH, ID)) - -#define TEST_LINE_RHS_EFFECT(LH, OP, RH, ID) \ - "x = " #LH " " #OP " (set(&y, " #ID "), " #RH ")" - -#define TEST_LINE_LHS_EFFECT(LH, OP, RH, ID) \ - "y = (set(&x, " #ID "), " #LH ") " #OP " " #RH - -#define TEST_BINARY(LH, OP, RH, RS, ID) \ - x = -!(RS), y = -!(RS); \ - x = LH OP (set(&y, ID), RH); \ - TEST(RS, ID, TEST_LINE_RHS_EFFECT(LH, OP, RH, ID)) \ - y = -!(RS), x = -!(RS); \ - y = (set(&x, ID), LH) OP RH; \ - TEST(ID, RS, TEST_LINE_LHS_EFFECT(LH, OP, RH, ID)) \ - y = -!(RS); \ - x = (set(&x, LH), x) OP (set(&y, ID), RH); \ - TEST(RS, ID, TEST_LINE_RHS_EFFECT((set(&x, LH), x), OP, RH, ID)) \ - x = -!(RS); \ - y = (set(&x, ID), LH) OP (set(&y, RH), y); \ - TEST(ID, RS, TEST_LINE_LHS_EFFECT(LH, OP, (set(&y, RH), y), ID)) - -#define TEST_LINE_RHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID) \ - "x = (" #LT ")" #LH " " #OP " (" #RT ")(set(&y, " #ID "), " #RH ")" - -#define TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID) \ - "y = (" #LT ")(set(&x, " #ID "), " #LH ") " #OP " (" #RT ")" #RH - -#define TEST_BINARY_WITH_CAST(LT, LH, OP, RT, RH, RS, ID) \ - x = -!(RS), y = -!(RS); \ - x = (LT)LH OP (RT)(set(&y, ID), RH); \ - TEST(RS, ID, TEST_LINE_RHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID)) \ - y = -!(RS), x = -!(RS); \ - y = (LT)(set(&x, ID), LH) OP (RT)RH; \ - TEST(ID, RS, TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID)) \ - y = -!(RS); \ - x = (LT)(set(&x, LH), x) OP (RT)(set(&y, ID), RH); \ - TEST(RS, ID, TEST_LINE_RHS_EFFECT_WITH_CAST(LT, (set(&x, LH), x), OP, RT, RH, ID)) \ - x = -!(RS); \ - y = (LT)(set(&x, ID), LH) OP (RT)(set(&y, RH), y); \ - TEST(ID, RS, TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, (set(&y, RH), y), ID)) - -void set(int *p, int q) -{ - *p = q; -} - -int twice(int a) -{ - return a * 2; -} - -int (*twicep)(int) = twice; - -void test_unary(void) -{ - int x, y; - - TEST_UNARY(+, 42, 42, 1); - TEST_UNARY(-, -42, 42, 2); - TEST_UNARY(~, ~42, 42, 3); - TEST_UNARY(!, 42, 0, 4); -} - -void test_binary_arithmetic(void) -{ - int x, y; - - TEST_BINARY(41, +, 1, 42, 1) - TEST_BINARY(42, +, 0, 42, 1) - - TEST_BINARY(43, -, 1, 42, 2) - TEST_BINARY(42, -, 0, 42, 2) - - TEST_BINARY(6, *, 7, 42, 3) - TEST_BINARY(42, *, 1, 42, 3) - TEST_BINARY(-42, *, -1, 42, 3) - - TEST_BINARY(126, /, 3, 42, 4) - TEST_BINARY(42, /, 1, 42, 4) - TEST_BINARY(-42, /, -1, 42, 4) - - TEST_BINARY(85, %, 43, 42, 5) - TEST_BINARY(10794, %, 256, 42, 5) - - TEST_BINARY(84, >>, 1, 42, 6) - TEST_BINARY(42, >>, 0, 42, 6) - TEST_BINARY(10752, >>, 8, 42, 6) - TEST_BINARY(21504, >>, 9, 42, 6) - - TEST_BINARY(21, <<, 1, 42, 7) - TEST_BINARY(42, <<, 0, 42, 7) - TEST_BINARY(42, <<, 8, 10752, 7) - - TEST_BINARY(59, &, 238, 42, 8) - TEST_BINARY(42, &, 0, 0, 8) - TEST_BINARY(42, &, -1, 42, 8) - - TEST_BINARY(34, |, 10, 42, 9) - TEST_BINARY(42, |, 0, 42, 9) - TEST_BINARY(34, |, -1, -1, 9) - - TEST_BINARY(59, ^, 17, 42, 10) - TEST_BINARY(42, ^, 0, 42, 10) - TEST_BINARY(~42, ^, -1, 42, 10) -} - -void test_binary_comparison(void) -{ - int x, y; - - TEST_BINARY(42, ==, 42, 1, 11) - - TEST_BINARY(42, !=, 43, 1, 12) - TEST_BINARY_WITH_CAST(signed char, 42, !=, long, 65536L, 1, 12) - TEST_BINARY_WITH_CAST(long, 65536L, !=, signed char, 42, 1, 12) - - TEST_BINARY(42, >, 41, 1, 13) - TEST_BINARY_WITH_CAST(int, 0, >, unsigned, 42, 0, 13) - - TEST_BINARY(42, <, 43, 1, 14) - TEST_BINARY_WITH_CAST(unsigned, 42, <, int, 0, 0, 14) - - TEST_BINARY(42, >=, 0, 1, 15) - TEST_BINARY_WITH_CAST(unsigned, 42, >=, int, 0, 1, 15) - - TEST_BINARY(42, <=, 43, 1, 16) - TEST_BINARY_WITH_CAST(int, 0, <=, unsigned, 42, 1, 16) -} - -int main(void) -{ - test_unary(); - test_binary_arithmetic(); - test_binary_comparison(); - - if (failures != 0) { - printf("Failures: %d\n", failures); - } - - return failures; -} +/* Check code generation for constant operands with side-effects */ + +#include <stdio.h> + +static int failures = 0; + +#define TEST(X, Y, L) \ + if (x != X || y != Y) { \ + printf("Failed: " L "\nExpected: x = " #X ", y = " #Y ", got: x = %d, y = %d\n\n", x, y); \ + ++failures; \ + } + +#define TEST_LINE_UNARY(OP, RH, ID) \ + "x = " #OP "(set(&y, " #ID "), " #RH ")" + +#define TEST_UNARY(OP, RH, RS, ID) \ + x = -!(RS), y = -!(RS); \ + x = OP (set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_UNARY(OP, RH, ID)) + +#define TEST_LINE_RHS_EFFECT(LH, OP, RH, ID) \ + "x = " #LH " " #OP " (set(&y, " #ID "), " #RH ")" + +#define TEST_LINE_LHS_EFFECT(LH, OP, RH, ID) \ + "y = (set(&x, " #ID "), " #LH ") " #OP " " #RH + +#define TEST_BINARY(LH, OP, RH, RS, ID) \ + x = -!(RS), y = -!(RS); \ + x = LH OP (set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT(LH, OP, RH, ID)) \ + y = -!(RS), x = -!(RS); \ + y = (set(&x, ID), LH) OP RH; \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT(LH, OP, RH, ID)) \ + y = -!(RS); \ + x = (set(&x, LH), x) OP (set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT((set(&x, LH), x), OP, RH, ID)) \ + x = -!(RS); \ + y = (set(&x, ID), LH) OP (set(&y, RH), y); \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT(LH, OP, (set(&y, RH), y), ID)) + +#define TEST_LINE_RHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID) \ + "x = (" #LT ")" #LH " " #OP " (" #RT ")(set(&y, " #ID "), " #RH ")" + +#define TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID) \ + "y = (" #LT ")(set(&x, " #ID "), " #LH ") " #OP " (" #RT ")" #RH + +#define TEST_BINARY_WITH_CAST(LT, LH, OP, RT, RH, RS, ID) \ + x = -!(RS), y = -!(RS); \ + x = (LT)LH OP (RT)(set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID)) \ + y = -!(RS), x = -!(RS); \ + y = (LT)(set(&x, ID), LH) OP (RT)RH; \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, RH, ID)) \ + y = -!(RS); \ + x = (LT)(set(&x, LH), x) OP (RT)(set(&y, ID), RH); \ + TEST(RS, ID, TEST_LINE_RHS_EFFECT_WITH_CAST(LT, (set(&x, LH), x), OP, RT, RH, ID)) \ + x = -!(RS); \ + y = (LT)(set(&x, ID), LH) OP (RT)(set(&y, RH), y); \ + TEST(ID, RS, TEST_LINE_LHS_EFFECT_WITH_CAST(LT, LH, OP, RT, (set(&y, RH), y), ID)) + +void set(int *p, int q) +{ + *p = q; +} + +int twice(int a) +{ + return a * 2; +} + +int (*twicep)(int) = twice; + +void test_unary(void) +{ + int x, y; + + TEST_UNARY(+, 42, 42, 1); + TEST_UNARY(-, -42, 42, 2); + TEST_UNARY(~, ~42, 42, 3); + TEST_UNARY(!, 42, 0, 4); +} + +void test_binary_arithmetic(void) +{ + int x, y; + + TEST_BINARY(41, +, 1, 42, 1) + TEST_BINARY(42, +, 0, 42, 1) + + TEST_BINARY(43, -, 1, 42, 2) + TEST_BINARY(42, -, 0, 42, 2) + + TEST_BINARY(6, *, 7, 42, 3) + TEST_BINARY(42, *, 1, 42, 3) + TEST_BINARY(-42, *, -1, 42, 3) + + TEST_BINARY(126, /, 3, 42, 4) + TEST_BINARY(42, /, 1, 42, 4) + TEST_BINARY(-42, /, -1, 42, 4) + + TEST_BINARY(85, %, 43, 42, 5) + TEST_BINARY(10794, %, 256, 42, 5) + + TEST_BINARY(84, >>, 1, 42, 6) + TEST_BINARY(42, >>, 0, 42, 6) + TEST_BINARY(10752, >>, 8, 42, 6) + TEST_BINARY(21504, >>, 9, 42, 6) + + TEST_BINARY(21, <<, 1, 42, 7) + TEST_BINARY(42, <<, 0, 42, 7) + TEST_BINARY(42, <<, 8, 10752, 7) + + TEST_BINARY(59, &, 238, 42, 8) + TEST_BINARY(42, &, 0, 0, 8) + TEST_BINARY(42, &, -1, 42, 8) + + TEST_BINARY(34, |, 10, 42, 9) + TEST_BINARY(42, |, 0, 42, 9) + TEST_BINARY(34, |, -1, -1, 9) + + TEST_BINARY(59, ^, 17, 42, 10) + TEST_BINARY(42, ^, 0, 42, 10) + TEST_BINARY(~42, ^, -1, 42, 10) +} + +void test_binary_comparison(void) +{ + int x, y; + + TEST_BINARY(42, ==, 42, 1, 11) + + TEST_BINARY(42, !=, 43, 1, 12) + TEST_BINARY_WITH_CAST(signed char, 42, !=, long, 65536L, 1, 12) + TEST_BINARY_WITH_CAST(long, 65536L, !=, signed char, 42, 1, 12) + + TEST_BINARY(42, >, 41, 1, 13) + TEST_BINARY_WITH_CAST(int, 0, >, unsigned, 42, 0, 13) + + TEST_BINARY(42, <, 43, 1, 14) + TEST_BINARY_WITH_CAST(unsigned, 42, <, int, 0, 0, 14) + + TEST_BINARY(42, >=, 0, 1, 15) + TEST_BINARY_WITH_CAST(unsigned, 42, >=, int, 0, 1, 15) + + TEST_BINARY(42, <=, 43, 1, 16) + TEST_BINARY_WITH_CAST(int, 0, <=, unsigned, 42, 1, 16) +} + +int main(void) +{ + test_unary(); + test_binary_arithmetic(); + test_binary_comparison(); + + if (failures != 0) { + printf("Failures: %d\n", failures); + } + + return failures; +} diff --git a/test/val/counter.c b/test/val/counter.c index 4efa18359..1867b1a66 100644 --- a/test/val/counter.c +++ b/test/val/counter.c @@ -1,60 +1,60 @@ -/* Tests for predefined macro __COUNTER__ */ - -#include <stdio.h> - -static int failures = 0; - -#if __COUNTER__ /* 0 */ -# error __COUNTER__ should begin at 0! -#elif __COUNTER__ == 1 /* 1 */ -# define CONCAT(a,b) CONCAT_impl_(a,b) -# define CONCAT_impl_(a,b) a##b -#endif - -#line 42 "What is the answer?" -int CONCAT(ident,__COUNTER__)[0+__LINE__] = {__LINE__}, CONCAT(ident,__COUNTER__)[0+__LINE__] = {__LINE__}; /* 2,3 */ - -#if __COUNTER__ == 4 ? 1 || __COUNTER__ : 0 && __COUNTER__ /* 4,5,6 */ -_Static_assert(__COUNTER__ == 7, "__COUNTER__ should be 7 here!"); /* 7 */ -# define GET_COUNTER() __COUNTER__ -# define GET_LINE() __LINE__ -# warning __COUNTER__ in #warning is just output as text and will never increase! -#else -# if __COUNTER__ + __COUNTER__ + __COUNTER__ /* Skipped as a whole and not incrementing */ -# endif -# error __COUNTER__ is skipped along with the whole #error line and will never increase anyways! */ -#endif - -#include "counter.h" -#include "counter.h" - -_Static_assert(GET_COUNTER() == 10, "__COUNTER__ should be 10 here!"); /* 10 */ - -int main(void) -{ - if (ident2[0] != 42) { - printf("Expected ident2[0]: %s, got: %s\n", 42, ident2[0]); - ++failures; - } - - if (ident3[0] != 42) { - printf("Expected ident3[0]: %s, got: %s\n", 42, ident3[0]); - ++failures; - } - - if (ident8 != 8) { - printf("Expected ident8: %s, got: %s\n", 8, ident8); - ++failures; - } - - if (ident9 != 9) { - printf("Expected ident9: %s, got: %s\n", 9, ident9); - ++failures; - } - - if (failures != 0) { - printf("Failures: %d\n", failures); - } - - return failures; -} +/* Tests for predefined macro __COUNTER__ */ + +#include <stdio.h> + +static int failures = 0; + +#if __COUNTER__ /* 0 */ +# error __COUNTER__ should begin at 0! +#elif __COUNTER__ == 1 /* 1 */ +# define CONCAT(a,b) CONCAT_impl_(a,b) +# define CONCAT_impl_(a,b) a##b +#endif + +#line 42 "What is the answer?" +int CONCAT(ident,__COUNTER__)[0+__LINE__] = {__LINE__}, CONCAT(ident,__COUNTER__)[0+__LINE__] = {__LINE__}; /* 2,3 */ + +#if __COUNTER__ == 4 ? 1 || __COUNTER__ : 0 && __COUNTER__ /* 4,5,6 */ +_Static_assert(__COUNTER__ == 7, "__COUNTER__ should be 7 here!"); /* 7 */ +# define GET_COUNTER() __COUNTER__ +# define GET_LINE() __LINE__ +# warning __COUNTER__ in #warning is just output as text and will never increase! +#else +# if __COUNTER__ + __COUNTER__ + __COUNTER__ /* Skipped as a whole and not incrementing */ +# endif +# error __COUNTER__ is skipped along with the whole #error line and will never increase anyways! */ +#endif + +#include "counter.h" +#include "counter.h" + +_Static_assert(GET_COUNTER() == 10, "__COUNTER__ should be 10 here!"); /* 10 */ + +int main(void) +{ + if (ident2[0] != 42) { + printf("Expected ident2[0]: %s, got: %s\n", 42, ident2[0]); + ++failures; + } + + if (ident3[0] != 42) { + printf("Expected ident3[0]: %s, got: %s\n", 42, ident3[0]); + ++failures; + } + + if (ident8 != 8) { + printf("Expected ident8: %s, got: %s\n", 8, ident8); + ++failures; + } + + if (ident9 != 9) { + printf("Expected ident9: %s, got: %s\n", 9, ident9); + ++failures; + } + + if (failures != 0) { + printf("Failures: %d\n", failures); + } + + return failures; +} diff --git a/test/val/counter.h b/test/val/counter.h index b6b5a98e2..b97cbf54d 100644 --- a/test/val/counter.h +++ b/test/val/counter.h @@ -1,4 +1,4 @@ -/* Tests for predefined macro __COUNTER__ */ - -#line GET_COUNTER() /* 1st: 8; 2nd: 9 */ -int CONCAT(ident,GET_LINE()) = GET_LINE(); +/* Tests for predefined macro __COUNTER__ */ + +#line GET_COUNTER() /* 1st: 8; 2nd: 9 */ +int CONCAT(ident,GET_LINE()) = GET_LINE(); diff --git a/test/val/opsize.c b/test/val/opsize.c index 20c7f0511..8ec49e8a8 100644 --- a/test/val/opsize.c +++ b/test/val/opsize.c @@ -1,33 +1,33 @@ - -/* Test for result types of certain unary operations */ - -#include <stdio.h> - -signed char x; -struct S { - unsigned char a : 3; - unsigned int b : 3; -} s; - -int main(void) -{ - _Static_assert(sizeof (++x) == sizeof (char), "++x result should not have promoted type"); - _Static_assert(sizeof (--x) == sizeof (char), "--x result should not have promoted type"); - _Static_assert(sizeof (x++) == sizeof (char), "x++ result should not have promoted type"); - _Static_assert(sizeof (x--) == sizeof (char), "x-- result should not have promoted type"); - _Static_assert(sizeof (x=0) == sizeof (char), "x=0 result should not have promoted type"); - - _Static_assert(sizeof (+x) == sizeof (int), "+x result should have promoted type"); - _Static_assert(sizeof (-x) == sizeof (int), "-x result should have promoted type"); - _Static_assert(sizeof (~x) == sizeof (int), "~x result should have promoted type"); - - _Static_assert(sizeof (+s.a) == sizeof (int), "+s.a result should have promoted type"); - _Static_assert(sizeof (-s.a) == sizeof (int), "-s.a result should have promoted type"); - _Static_assert(sizeof (~s.a) == sizeof (int), "~s.a result should have promoted type"); - - _Static_assert(sizeof (+s.b) == sizeof (int), "+s.b result should have promoted type"); - _Static_assert(sizeof (-s.b) == sizeof (int), "-s.b result should have promoted type"); - _Static_assert(sizeof (~s.b) == sizeof (int), "~s.b result should have promoted type"); - - return 0; -} + +/* Test for result types of certain unary operations */ + +#include <stdio.h> + +signed char x; +struct S { + unsigned char a : 3; + unsigned int b : 3; +} s; + +int main(void) +{ + _Static_assert(sizeof (++x) == sizeof (char), "++x result should not have promoted type"); + _Static_assert(sizeof (--x) == sizeof (char), "--x result should not have promoted type"); + _Static_assert(sizeof (x++) == sizeof (char), "x++ result should not have promoted type"); + _Static_assert(sizeof (x--) == sizeof (char), "x-- result should not have promoted type"); + _Static_assert(sizeof (x=0) == sizeof (char), "x=0 result should not have promoted type"); + + _Static_assert(sizeof (+x) == sizeof (int), "+x result should have promoted type"); + _Static_assert(sizeof (-x) == sizeof (int), "-x result should have promoted type"); + _Static_assert(sizeof (~x) == sizeof (int), "~x result should have promoted type"); + + _Static_assert(sizeof (+s.a) == sizeof (int), "+s.a result should have promoted type"); + _Static_assert(sizeof (-s.a) == sizeof (int), "-s.a result should have promoted type"); + _Static_assert(sizeof (~s.a) == sizeof (int), "~s.a result should have promoted type"); + + _Static_assert(sizeof (+s.b) == sizeof (int), "+s.b result should have promoted type"); + _Static_assert(sizeof (-s.b) == sizeof (int), "-s.b result should have promoted type"); + _Static_assert(sizeof (~s.b) == sizeof (int), "~s.b result should have promoted type"); + + return 0; +} diff --git a/test/val/pr1833.c b/test/val/pr1833.c index bdc820811..177069eb4 100644 --- a/test/val/pr1833.c +++ b/test/val/pr1833.c @@ -1,13 +1,13 @@ -/* Test for PR #1833 fixes */ - -#define char 1 - -#if char && !int && L'A' - L'B' == 'A' - 'B' && L'A' == 'A' -#else -#error -#endif - -int main(void) -{ - return 0; -} +/* Test for PR #1833 fixes */ + +#define char 1 + +#if char && !int && L'A' - L'B' == 'A' - 'B' && L'A' == 'A' +#else +#error +#endif + +int main(void) +{ + return 0; +} diff --git a/test/val/uneval.c b/test/val/uneval.c index 50e00973a..fe42cc592 100644 --- a/test/val/uneval.c +++ b/test/val/uneval.c @@ -1,46 +1,46 @@ -/* - Copyright 2021, The cc65 Authors - - This software is provided "as-is", without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications; and, to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated, but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/* - Test of deferred operations in unevaluated context resulted from 'sizeof' and - short-circuited code-paths in AND, OR and tenary operations. - - https://github.com/cc65/cc65/issues/1406 -*/ - -#include <stdio.h> - -int main(void) -{ - int i = 0; - int j = 0; - - sizeof(i++ | j--); - 0 && (i++ | j--); - 1 || (i++ | j--); - 0 ? i++ | j-- : 0; - 1 ? 0 : i++ | j--; - - if (i != 0 || j != 0) { - printf("i = %d, j = %d\n", i, j); - printf("Failures: %d\n", i - j); - } - return i - j; -} +/* + Copyright 2021, The cc65 Authors + + This software is provided "as-is", without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications; and, to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated, but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + Test of deferred operations in unevaluated context resulted from 'sizeof' and + short-circuited code-paths in AND, OR and tenary operations. + + https://github.com/cc65/cc65/issues/1406 +*/ + +#include <stdio.h> + +int main(void) +{ + int i = 0; + int j = 0; + + sizeof(i++ | j--); + 0 && (i++ | j--); + 1 || (i++ | j--); + 0 ? i++ | j-- : 0; + 1 ? 0 : i++ | j--; + + if (i != 0 || j != 0) { + printf("i = %d, j = %d\n", i, j); + printf("Failures: %d\n", i - j); + } + return i - j; +} From 133507b031fe6b5e31fa2732651363521728576f Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 29 Sep 2022 17:55:09 +0800 Subject: [PATCH 046/360] Fixed line info for #pragma messages and diagnostics. --- src/cc65/preproc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 0835bac1e..99a8af116 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -3025,6 +3025,7 @@ static int ParseDirectives (unsigned ModeFlags) if (!PPSkip) { if ((ModeFlags & MSM_IN_ARG_LIST) == 0) { DoPragma (); + return Whitespace; } else { PPError ("Embedded #pragma directive within macro arguments is unsupported"); } @@ -3153,16 +3154,12 @@ static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFl ** whitespace and comments, then do macro replacement. */ { - int OldIndex = SB_GetIndex (Source); MacroExp E; SkipWhitespace (0); InitMacroExp (&E); ReplaceMacros (Source, Target, &E, ModeFlags | MSM_IN_DIRECTIVE); DoneMacroExp (&E); - - /* Restore the source input index */ - SB_SetIndex (Source, OldIndex); } @@ -3186,7 +3183,9 @@ void Preprocess (void) AddPreLine (PLine); /* Add leading whitespace to prettify preprocessor output */ - AppendIndent (PLine, SB_GetIndex (Line)); + if (CurC != '\0') { + AppendIndent (PLine, SB_GetIndex (Line)); + } /* Expand macros if any */ InitMacroExp (&E); From 376afd0edbb3bd152a21e6c686d0300079d75a84 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 29 Sep 2022 18:23:32 +0800 Subject: [PATCH 047/360] Fixed trailing spaces in some testcases. --- test/val/bug1838.c | 4 ++-- test/val/bug1847-struct-field-access.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/val/bug1838.c b/test/val/bug1838.c index 45978dca4..38becf5e9 100644 --- a/test/val/bug1838.c +++ b/test/val/bug1838.c @@ -1,11 +1,11 @@ /* Bug 1838 - function parameters declared as function types rather than function pointers */ #include <stdio.h> - + static int failures = 0; typedef int fn_t(int); - + int main(void) { void foo(fn_t*); diff --git a/test/val/bug1847-struct-field-access.c b/test/val/bug1847-struct-field-access.c index 55ead7ec7..f7e19e40b 100644 --- a/test/val/bug1847-struct-field-access.c +++ b/test/val/bug1847-struct-field-access.c @@ -41,6 +41,6 @@ int main(void) { if (failures > 0) { printf("Failures: %u\n", failures); } - + return failures; } From 1cbd6bc3f93ad029d30e5a3062c5db483a7a8c4e Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 29 Sep 2022 18:23:41 +0800 Subject: [PATCH 048/360] Fixed comments in test/val/bug1462-biefield-assign-4.c. --- test/val/bug1462-biefield-assign-4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/val/bug1462-biefield-assign-4.c b/test/val/bug1462-biefield-assign-4.c index f811ddbd6..e607dbd25 100644 --- a/test/val/bug1462-biefield-assign-4.c +++ b/test/val/bug1462-biefield-assign-4.c @@ -1,6 +1,6 @@ /* issue #1462 - Bit-fields are still broken */ -/* More tests on "op= expression result value" that a naive fix might fail with */ +/* When (un-)signedness involves with integral promotion */ #include <stdio.h> #include <limits.h> From 96df4e8b5e894b7f3837c4a2f033196ac569f3db Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 29 Sep 2022 19:38:32 +0800 Subject: [PATCH 049/360] Added a diagnostic level "note" for infomative messages. --- src/cc65/error.c | 119 +++++++++++++++++++++++++++++++++++------------ src/cc65/error.h | 17 +++++-- 2 files changed, 102 insertions(+), 34 deletions(-) diff --git a/src/cc65/error.c b/src/cc65/error.c index f0e023969..e99465c87 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -108,6 +108,36 @@ Collection DiagnosticStrBufs; +/*****************************************************************************/ +/* Helpers */ +/*****************************************************************************/ + + + +static const char* GetDiagnosticFileName (void) +/* Get the source file name where the diagnostic info refers to */ +{ + if (CurTok.LI) { + return GetInputName (CurTok.LI); + } else { + return GetCurrentFile (); + } +} + + + +static unsigned GetDiagnosticLineNum (void) +/* Get the source line number where the diagnostic info refers to */ +{ + if (CurTok.LI) { + return GetInputLine (CurTok.LI); + } else { + return GetCurrentLine (); + } +} + + + /*****************************************************************************/ /* Handling of fatal errors */ /*****************************************************************************/ @@ -119,17 +149,7 @@ void Fatal (const char* Format, ...) { va_list ap; - const char* FileName; - unsigned LineNum; - if (CurTok.LI) { - FileName = GetInputName (CurTok.LI); - LineNum = GetInputLine (CurTok.LI); - } else { - FileName = GetCurrentFile (); - LineNum = GetCurrentLine (); - } - - fprintf (stderr, "%s:%u: Fatal: ", FileName, LineNum); + fprintf (stderr, "%s:%u: Fatal: ", GetDiagnosticFileName (), GetDiagnosticLineNum ()); va_start (ap, Format); vfprintf (stderr, Format, ap); @@ -145,22 +165,12 @@ void Fatal (const char* Format, ...) void Internal (const char* Format, ...) -/* Print a message about an internal compiler error and die. */ +/* Print a message about an internal compiler error and die */ { va_list ap; - const char* FileName; - unsigned LineNum; - if (CurTok.LI) { - FileName = GetInputName (CurTok.LI); - LineNum = GetInputLine (CurTok.LI); - } else { - FileName = GetCurrentFile (); - LineNum = GetCurrentLine (); - } - fprintf (stderr, "%s:%u: Internal compiler error:\n", - FileName, LineNum); + GetDiagnosticFileName (), GetDiagnosticLineNum ()); va_start (ap, Format); vfprintf (stderr, Format, ap); @@ -184,7 +194,7 @@ void Internal (const char* Format, ...) static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) -/* Print an error message - internal function*/ +/* Print an error message - internal function */ { fprintf (stderr, "%s:%u: Error: ", Filename, LineNo); vfprintf (stderr, Msg, ap); @@ -206,7 +216,7 @@ void Error (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap); + IntError (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); va_end (ap); } @@ -224,7 +234,7 @@ void LIError (const LineInfo* LI, const char* Format, ...) void PPError (const char* Format, ...) -/* Print an error message. For use within the preprocessor. */ +/* Print an error message. For use within the preprocessor */ { va_list ap; va_start (ap, Format); @@ -241,7 +251,7 @@ void PPError (const char* Format, ...) static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) -/* Print warning message - internal function. */ +/* Print a warning message - internal function */ { if (IS_Get (&WarningsAreErrors)) { @@ -265,11 +275,11 @@ static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, void Warning (const char* Format, ...) -/* Print warning message. */ +/* Print a warning message */ { va_list ap; va_start (ap, Format); - IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap); + IntWarning (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); va_end (ap); } @@ -287,7 +297,7 @@ void LIWarning (const LineInfo* LI, const char* Format, ...) void PPWarning (const char* Format, ...) -/* Print warning message. For use within the preprocessor. */ +/* Print a warning message. For use within the preprocessor */ { va_list ap; va_start (ap, Format); @@ -326,6 +336,55 @@ void ListWarnings (FILE* F) +/*****************************************************************************/ +/* Handling of other infos */ +/*****************************************************************************/ + + + +static void IntNote (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) +/* Print a note message - internal function */ +{ + fprintf (stderr, "%s:%u: Note: ", Filename, LineNo); + vfprintf (stderr, Msg, ap); + fprintf (stderr, "\n"); +} + + + +void Note (const char* Format, ...) +/* Print a note message */ +{ + va_list ap; + va_start (ap, Format); + IntNote (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap); + va_end (ap); +} + + + +void LINote (const LineInfo* LI, const char* Format, ...) +/* Print a note message with the line info given explicitly */ +{ + va_list ap; + va_start (ap, Format); + IntNote (GetInputName (LI), GetInputLine (LI), Format, ap); + va_end (ap); +} + + + +void PPNote (const char* Format, ...) +/* Print a note message. For use within the preprocessor */ +{ + va_list ap; + va_start (ap, Format); + IntNote (GetCurrentFile(), GetCurrentLine(), Format, ap); + va_end (ap); +} + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ diff --git a/src/cc65/error.h b/src/cc65/error.h index c4420c434..7fcb03467 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -92,7 +92,7 @@ void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2) /* Print a message about a fatal error and die */ void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2))); -/* Print a message about an internal compiler error and die. */ +/* Print a message about an internal compiler error and die */ void Error (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print an error message */ @@ -101,16 +101,16 @@ void LIError (const LineInfo* LI, const char* Format, ...) attribute ((format (p /* Print an error message with the line info given explicitly */ void PPError (const char* Format, ...) attribute ((format (printf, 1, 2))); -/* Print an error message. For use within the preprocessor. */ +/* Print an error message. For use within the preprocessor */ void Warning (const char* Format, ...) attribute ((format (printf, 1, 2))); -/* Print warning message. */ +/* Print a warning message */ void LIWarning (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print a warning message with the line info given explicitly */ void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2))); -/* Print warning message. For use within the preprocessor. */ +/* Print a warning message. For use within the preprocessor */ IntStack* FindWarning (const char* Name); /* Search for a warning in the WarnMap table and return a pointer to the @@ -120,6 +120,15 @@ IntStack* FindWarning (const char* Name); void ListWarnings (FILE* F); /* Print a list of warning types/names to the given file */ +void Note (const char* Format, ...) attribute ((format (printf, 1, 2))); +/* Print a note message */ + +void LINote (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); +/* Print a note message with the line info given explicitly */ + +void PPNote (const char* Format, ...) attribute ((format (printf, 1, 2))); +/* Print a note message. For use within the preprocessor */ + void ErrorReport (void); /* Report errors (called at end of compile) */ From 29c9cb3e0063c8cfe6fbf64e4ad53dc41d462298 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 29 Sep 2022 19:38:32 +0800 Subject: [PATCH 050/360] Improved diagnostics on conflicting type declarations. --- src/cc65/symtab.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index aa4a9a44a..7de889d39 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -702,6 +702,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags if (SCType == SC_TYPEDEF) { if (IsDistinctRedef (E_Type, T, TC_IDENTICAL, TCF_MASK_QUAL)) { Error ("Conflicting types for typedef '%s'", Entry->Name); + Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); Entry = 0; } } else { @@ -728,7 +729,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags /* New type must be compatible with the composite prototype */ if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) { Error ("Conflicting function types for '%s'", Entry->Name); - TypeCompatibilityDiagnostic (T, E_Type, 0, "'%s' vs '%s'"); + Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); Entry = 0; } else { /* Refine the existing composite prototype with this new @@ -760,6 +761,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags IsDistinctRedef (E_Type + 1, T + 1, TC_IDENTICAL, TCF_MASK_QUAL)) { /* Conflicting element types */ Error ("Conflicting array types for '%s[]'", Entry->Name); + Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); Entry = 0; } else { /* Check if we have a size in the existing definition */ @@ -777,6 +779,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags Entry = 0; } else if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) { Error ("Conflicting types for '%s'", Entry->Name); + Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); Entry = 0; } else if (E_SCType == SC_ENUMERATOR) { /* Enumerators aren't allowed to be redeclared at all, even if From 715aa919e67ab0808d18badd8dac35e6553ba3e5 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 29 Sep 2022 19:47:31 +0800 Subject: [PATCH 051/360] C++ style comments in C89 mode will cause errors only once per input file. --- src/cc65/global.c | 1 + src/cc65/global.h | 1 + src/cc65/preproc.c | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cc65/global.c b/src/cc65/global.c index 8b9838dc5..b2c3ef0a0 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -49,6 +49,7 @@ unsigned char DebugInfo = 0; /* Add debug info to the obj */ unsigned char PreprocessOnly = 0; /* Just preprocess the input */ unsigned char DebugOptOutput = 0; /* Output debug stuff */ unsigned RegisterSpace = 6; /* Space available for register vars */ +unsigned AllowNewComments = 0; /* Allow new style comments in C89 mode */ /* Stackable options */ IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */ diff --git a/src/cc65/global.h b/src/cc65/global.h index 266035346..ba7105130 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -57,6 +57,7 @@ extern unsigned char DebugInfo; /* Add debug info to the obj */ extern unsigned char PreprocessOnly; /* Just preprocess the input */ extern unsigned char DebugOptOutput; /* Output debug stuff */ extern unsigned RegisterSpace; /* Space available for register vars */ +extern unsigned AllowNewComments; /* Allow new style comments in C89 mode */ /* Stackable options */ extern IntStack WritableStrings; /* Literal strings are r/w */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 020df011a..56331266f 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -402,8 +402,10 @@ static void NewStyleComment (void) /* Remove a new style C comment from line. */ { /* Diagnose if this is unsupported */ - if (IS_Get (&Standard) < STD_C99) { + if (IS_Get (&Standard) < STD_C99 && !AllowNewComments) { PPError ("C++ style comments are not allowed in C89"); + PPNote ("(this will be reported only once per input file)"); + AllowNewComments = 1; } /* Beware: Because line continuation chars are handled when reading @@ -1800,6 +1802,9 @@ void PreprocessBegin (void) /* Remember to update source file location in preprocess-only mode */ FileChanged = 1; + + /* Enable diagnostics on new style comments in C89 mode */ + AllowNewComments = 0; } From 9900e7361de858198ec7b06f6d770bf8c061d32f Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Fri, 30 Sep 2022 09:09:09 +0800 Subject: [PATCH 052/360] #pragma message now uses the new "note" level message routine. --- src/cc65/pragma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index b0478ce2a..83ed362c8 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -784,7 +784,7 @@ static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High) static void MakeMessage (const char* Message) { - fprintf (stderr, "%s:%u: Note: %s\n", GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Message); + Note ("%s", Message); } From f6003b8e8c669c7b171f7bebdd91253cd25711a7 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Fri, 30 Sep 2022 09:41:54 +0800 Subject: [PATCH 053/360] Renamed some testcases. --- test/val/{assign-use1.c => assign-shift-use1.c} | 0 test/val/{fields.c => bitfield-1.c} | 0 test/val/{char-bitfield.c => bitfield-char-1.c} | 0 test/val/{call1.c => boolean-call1.c} | 0 test/val/{bool3.c => compare-bool3.c} | 0 test/val/{nestfor.c => for-nested.c} | 0 test/val/{casttochar.c => type-cast-to-char.c} | 0 test/val/{char-promote.c => type-char-promote.c} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename test/val/{assign-use1.c => assign-shift-use1.c} (100%) rename test/val/{fields.c => bitfield-1.c} (100%) rename test/val/{char-bitfield.c => bitfield-char-1.c} (100%) rename test/val/{call1.c => boolean-call1.c} (100%) rename test/val/{bool3.c => compare-bool3.c} (100%) rename test/val/{nestfor.c => for-nested.c} (100%) rename test/val/{casttochar.c => type-cast-to-char.c} (100%) rename test/val/{char-promote.c => type-char-promote.c} (100%) diff --git a/test/val/assign-use1.c b/test/val/assign-shift-use1.c similarity index 100% rename from test/val/assign-use1.c rename to test/val/assign-shift-use1.c diff --git a/test/val/fields.c b/test/val/bitfield-1.c similarity index 100% rename from test/val/fields.c rename to test/val/bitfield-1.c diff --git a/test/val/char-bitfield.c b/test/val/bitfield-char-1.c similarity index 100% rename from test/val/char-bitfield.c rename to test/val/bitfield-char-1.c diff --git a/test/val/call1.c b/test/val/boolean-call1.c similarity index 100% rename from test/val/call1.c rename to test/val/boolean-call1.c diff --git a/test/val/bool3.c b/test/val/compare-bool3.c similarity index 100% rename from test/val/bool3.c rename to test/val/compare-bool3.c diff --git a/test/val/nestfor.c b/test/val/for-nested.c similarity index 100% rename from test/val/nestfor.c rename to test/val/for-nested.c diff --git a/test/val/casttochar.c b/test/val/type-cast-to-char.c similarity index 100% rename from test/val/casttochar.c rename to test/val/type-cast-to-char.c diff --git a/test/val/char-promote.c b/test/val/type-char-promote.c similarity index 100% rename from test/val/char-promote.c rename to test/val/type-char-promote.c From 9eab36b95a4890f86c5f84e9f4fae7033f933778 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Fri, 30 Sep 2022 14:32:08 +0800 Subject: [PATCH 054/360] Fixed block-scope extern declarations visibility. Fixed missing file-scope static function codegen output in a rare care. --- src/cc65/locals.c | 8 +++++--- src/cc65/symentry.h | 4 ++-- src/cc65/symtab.c | 49 +++++++++++++++++++++++++++++++++++---------- test/val/extern.c | 31 ++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 test/val/extern.c diff --git a/src/cc65/locals.c b/src/cc65/locals.c index ad36bded0..5f182f061 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -465,8 +465,8 @@ static void ParseOneDecl (const DeclSpec* Spec) /* The default storage class could be wrong. Just clear them */ Decl.StorageClass &= ~SC_STORAGEMASK; - /* This is always a declaration */ - Decl.StorageClass |= SC_DECL; + /* This is always an extern declaration */ + Decl.StorageClass |= SC_DECL | SC_EXTERN; } /* If we don't have a name, this was flagged as an error earlier. @@ -524,7 +524,9 @@ static void ParseOneDecl (const DeclSpec* Spec) if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN || (Decl.StorageClass & SC_FUNC) == SC_FUNC) { - /* Add the global symbol to the local symbol table */ + /* Add the global symbol to both of the global and local symbol + ** tables. + */ AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); } else { /* Add the local symbol to the local symbol table */ diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index bcf586510..52e590e2e 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -105,8 +105,8 @@ struct CodeEntry; #define SC_SPADJUSTMENT 0x400000U #define SC_GOTO_IND 0x800000U /* Indirect goto */ -#define SC_ALIAS 0x01000000U /* Alias of anonymous field */ -#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious */ +#define SC_ALIAS 0x01000000U /* Alias of global or anonymous field */ +#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious (for error recovery) */ #define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index aa4a9a44a..4d293ac3c 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -567,6 +567,11 @@ static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name) /* Try to find the symbol in this table */ SymEntry* E = FindSymInTable (Tab, Name, Hash); + while (E != 0 && (E->Flags & SC_ALIAS) == SC_ALIAS) { + /* Get the aliased entry */ + E = E->V.A.Field; + } + /* Bail out if we found it */ if (E != 0) { return E; @@ -1279,6 +1284,11 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs /* Generate the assembler name from the data label number */ Entry->V.L.Label = Offs; Entry->AsmName = xstrdup (LocalDataLabelName (Entry->V.L.Label)); + } else if ((Flags & SC_ALIAS) == SC_ALIAS) { + /* Just clear the info */ + Entry->V.A.Field = 0; + Entry->V.A.ANumber = 0; + Entry->V.A.Offs = 0; } else { Internal ("Invalid flags in AddLocalSym: %04X", Flags); } @@ -1296,13 +1306,26 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add an external or global symbol to the symbol table and return the entry */ { - /* Start from the local symbol table */ - SymTable* Tab = SymTab; + /* Add the new declaration to the global symbol table if no errors */ + SymTable* Tab = SymTab0; + + /* Only search this name in the local and global symbol tables */ + SymEntry* Entry = 0; + SymEntry* Alias = 0; + + if (SymTab != SymTab0) { + Alias = Entry = FindLocalSym (Name); + while (Entry && (Entry->Flags & SC_ALIAS) == SC_ALIAS) { + /* Get the aliased entry */ + Entry = Entry->V.A.Field; + } + } + + if (Entry == 0) { + Entry = FindGlobalSym (Name); + } - /* Do we have an entry with this name already? */ - SymEntry* Entry = FindSymInTree (Tab, Name); if (Entry) { - /* We have a symbol with this name already */ if (HandleSymRedefinition (Entry, T, Flags)) { Entry = 0; @@ -1317,7 +1340,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) ** declaration if both declarations are global, otherwise give an ** error. */ - if (Tab == SymTab0 && + if (SymTab == SymTab0 && (Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) { Warning ("Static declaration of '%s' follows non-static declaration", Name); @@ -1353,12 +1376,9 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Use the fail-safe table for fictitious symbols */ Tab = FailSafeTab; } - - } else if ((Flags & (SC_EXTERN | SC_FUNC)) != 0) { - /* Add the new declaration to the global symbol table instead */ - Tab = SymTab0; } - if (Entry == 0 || Entry->Owner != Tab) { + + if (Entry == 0) { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); @@ -1376,6 +1396,13 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); + + } + + /* Add an alias of the global symbol to the local symbol table */ + if (Tab == SymTab0 && SymTab != SymTab0 && Entry->Owner != SymTab && Alias == 0) { + Alias = AddLocalSym (Name, T, SC_ALIAS, 0); + Alias->V.A.Field = Entry; } /* Return the entry */ diff --git a/test/val/extern.c b/test/val/extern.c new file mode 100644 index 000000000..6df3c9d50 --- /dev/null +++ b/test/val/extern.c @@ -0,0 +1,31 @@ +/* Test for shadowing and linkage of file-scope "static" and block-scope "extern" declarations */ + +static int g(int x); /* Generated functions with internal linkage are not always kept in cc65 */ + +int main(void) +{ + char f = 'f'; /* Shadows global "int f(void)" (if any) */ + char c = 'c'; /* Shadows global "int c" (if any) */ + { + void* f = 0; /* Shadows local "char f" */ + void* c = 0; /* Shadows local "char c" */ + { + int f(void); /* Shadows local "char f" and "void* f" */ + extern int g(int); /* Shadows global "int g(int x)" */ + extern int c; /* Shadows local "char c" and "void* c" */ + return f() ^ g(c); /* Link to global "int g(int x)" */ + } + } +} + +int c = 42; + +int f(void) +{ + return 42; +} + +int g(int x) +{ + return x; +} From 959be2c98c11d8098f47c6954a38ea7604a6b22e Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Tue, 11 Oct 2022 14:14:38 +0800 Subject: [PATCH 055/360] SymEntry struct cleanups. --- src/cc65/symentry.c | 8 +++-- src/cc65/symentry.h | 77 +++++++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index cc790c931..c9402a64b 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -40,6 +40,7 @@ /* cc65 */ #include "anonname.h" +#include "asmlabel.h" #include "declare.h" #include "error.h" #include "symentry.h" @@ -65,13 +66,12 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags) E->NextHash = 0; E->PrevSym = 0; E->NextSym = 0; - E->Link = 0; E->Owner = 0; E->Flags = Flags; E->Type = 0; E->Attr = 0; E->AsmName = 0; - E->V.BssName = 0; + memset (&E->V, 0, sizeof (E->V)); memcpy (E->Name, Name, Len+1); /* Return the new entry */ @@ -250,7 +250,9 @@ void SymUseAttr (SymEntry* Sym, struct Declaration* D) void SymSetAsmName (SymEntry* Sym) -/* Set the assembler name for an external symbol from the name of the symbol */ +/* Set the assembler name for an external symbol from the name of the symbol. +** The symbol must have no assembler name set yet. +*/ { unsigned Len; diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 52e590e2e..0f4b145be 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -128,7 +128,6 @@ struct SymEntry { SymEntry* NextHash; /* Next entry in hash list */ SymEntry* PrevSym; /* Previous symbol in dl list */ SymEntry* NextSym; /* Next symbol double linked list */ - SymEntry* Link; /* General purpose single linked list */ struct SymTable* Owner; /* Symbol table the symbol is in */ unsigned Flags; /* Symbol flags */ Type* Type; /* Symbol type */ @@ -138,27 +137,9 @@ struct SymEntry { /* Data that differs for the different symbol types */ union { - /* Offset for locals or struct members */ + /* Offset for locals */ int Offs; - /* Data for anonymous struct or union members */ - struct { - int Offs; /* Byte offset into struct */ - unsigned ANumber; /* Numeric ID */ - SymEntry* Field; /* The real field aliased */ - } A; - - - /* Label name for static symbols */ - struct { - unsigned Label; - Collection *DefsOrRefs; - struct CodeEntry *IndJumpFrom; - } L; - - /* Value of SP adjustment needed after forward 'goto' */ - unsigned short SPAdjustment; - /* Register bank offset and offset of the saved copy on stack for ** register variables. */ @@ -167,32 +148,50 @@ struct SymEntry { int SaveOffs; } R; - /* Value for constants (including enums) */ + /* Segment name for tentantive global definitions */ + const char* BssName; + + /* Value for integer constants (including enumerators) */ long ConstVal; - /* Data for structs/unions */ - struct { - struct SymTable* SymTab; /* Member symbol table */ - unsigned Size; /* Size of the union/struct */ - unsigned ACount; /* Count of anonymous fields */ - } S; - - /* Data for enums */ - struct { - struct SymTable* SymTab; /* Member symbol table */ - const Type* Type; /* Underlying type */ - } E; - /* Data for functions */ struct { struct Segments* Seg; /* Segments for this function */ struct LiteralPool* LitPool; /* Literal pool for this function */ } F; - /* Segment name for tentantive global definitions */ - const char* BssName; + /* Label name for static symbols */ + struct { + unsigned Label; + Collection *DefsOrRefs; + struct CodeEntry *IndJumpFrom; + } L; + + /* Value of SP adjustment needed after forward 'goto' */ + unsigned short SPAdjustment; + + /* Data for anonymous struct or union members */ + struct { + int Offs; /* Byte offset into struct */ + unsigned ANumber; /* Numeric ID */ + SymEntry* Field; /* The real field aliased */ + } A; + + /* Data for structs/unions tags */ + struct { + struct SymTable* SymTab; /* Member symbol table */ + unsigned Size; /* Size of the union/struct */ + unsigned ACount; /* Count of anonymous fields */ + } S; + + /* Data for enums tags */ + struct { + struct SymTable* SymTab; /* Member symbol table */ + const Type* Type; /* Underlying type */ + } E; + } V; - char Name[1]; /* Name, dynamically allocated */ + char Name[1]; /* Name, dynamically allocated */ }; @@ -303,7 +302,9 @@ void SymUseAttr (SymEntry* Sym, struct Declaration* D); /* Use the attributes from the declaration for this symbol */ void SymSetAsmName (SymEntry* Sym); -/* Set the assembler name for an external symbol from the name of the symbol */ +/* Set the assembler name for an external symbol from the name of the symbol. +** The symbol must have no assembler name set yet. +*/ void CvtRegVarToAuto (SymEntry* Sym); /* Convert a register variable to an auto variable */ From 2cda47cd36c824a505f66d685ed2f0410ba3873d Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Tue, 11 Oct 2022 14:14:48 +0800 Subject: [PATCH 056/360] More descriptive names for SymEntry usage. --- src/cc65/compile.c | 43 +++++++++---------- src/cc65/datatype.c | 4 +- src/cc65/declare.c | 100 ++++++++++++++++++++++---------------------- src/cc65/expr.c | 5 +-- src/cc65/initdata.c | 48 ++++++++++----------- src/cc65/symtab.c | 82 ++++++++++++++++++------------------ 6 files changed, 140 insertions(+), 142 deletions(-) diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 11dcbced0..63c2ef081 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -79,7 +79,7 @@ static void Parse (void) /* Top level parser routine. */ { int comma; - SymEntry* Entry; + SymEntry* Sym; FuncDesc* FuncDef = 0; /* Initialization for deferred operations */ @@ -142,7 +142,7 @@ static void Parse (void) } /* Read declarations for this type */ - Entry = 0; + Sym = 0; comma = 0; while (1) { @@ -196,10 +196,10 @@ static void Parse (void) } /* Add an entry to the symbol table */ - Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); + Sym = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); /* Add declaration attributes */ - SymUseAttr (Entry, &Decl); + SymUseAttr (Sym, &Decl); /* Reserve storage for the variable if we need to */ if (Decl.StorageClass & SC_STORAGE) { @@ -211,11 +211,11 @@ static void Parse (void) if (CurTok.Tok == TOK_ASSIGN) { /* This is a definition with storage */ - if (SymIsDef (Entry)) { + if (SymIsDef (Sym)) { Error ("Global variable '%s' has already been defined", - Entry->Name); + Sym->Name); } - Entry->Flags |= SC_DEF; + Sym->Flags |= SC_DEF; /* We cannot initialize types of unknown size, or ** void types in ISO modes. @@ -245,21 +245,21 @@ static void Parse (void) } /* Define a label */ - g_defgloblabel (Entry->Name); + g_defgloblabel (Sym->Name); /* Skip the '=' */ NextToken (); /* Parse the initialization */ - ParseInit (Entry->Type); + ParseInit (Sym->Type); } else { /* This is a declaration */ if (IsTypeVoid (Decl.Type)) { /* We cannot declare variables of type void */ Error ("Illegal type for variable '%s'", Decl.Ident); - Entry->Flags &= ~(SC_STORAGE | SC_DEF); - } else if (Size == 0 && SymIsDef (Entry) && !IsEmptiableObjectType (Decl.Type)) { + Sym->Flags &= ~(SC_STORAGE | SC_DEF); + } else if (Size == 0 && SymIsDef (Sym) && !IsEmptiableObjectType (Decl.Type)) { /* Size is unknown. Is it an array? */ if (!IsTypeArray (Decl.Type)) { Error ("Variable '%s' has unknown size", Decl.Ident); @@ -286,11 +286,11 @@ static void Parse (void) */ const char* bssName = GetSegName (SEG_BSS); - if (Entry->V.BssName && strcmp (Entry->V.BssName, bssName) != 0) { + if (Sym->V.BssName && strcmp (Sym->V.BssName, bssName) != 0) { Error ("Global variable '%s' already was defined in the '%s' segment.", - Entry->Name, Entry->V.BssName); + Sym->Name, Sym->V.BssName); } - Entry->V.BssName = xstrdup (bssName); + Sym->V.BssName = xstrdup (bssName); /* This is to make the automatical zeropage setting of the symbol ** work right. @@ -300,9 +300,9 @@ static void Parse (void) } /* Make the symbol zeropage according to the segment address size */ - if ((Entry->Flags & SC_STATIC) != 0) { + if ((Sym->Flags & SC_STATIC) != 0) { if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) { - Entry->Flags |= SC_ZEROPAGE; + Sym->Flags |= SC_ZEROPAGE; } } @@ -318,7 +318,7 @@ static void Parse (void) } /* Function declaration? */ - if (Entry && IsTypeFunc (Entry->Type)) { + if (Sym && IsTypeFunc (Sym->Type)) { /* Function */ if (!comma) { @@ -327,7 +327,7 @@ static void Parse (void) NextToken (); } else { /* Parse the function body */ - NewFunc (Entry, FuncDef); + NewFunc (Sym, FuncDef); /* Make sure we aren't omitting any work */ CheckDeferredOpAllDone (); @@ -478,8 +478,9 @@ void Compile (const char* FileName) for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) { if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) { /* Assembly definition of uninitialized global variable */ - SymEntry* Sym = GetSymType (Entry->Type); + SymEntry* TagSym = GetSymType (Entry->Type); unsigned Size = SizeOf (Entry->Type); + if (Size == 0 && IsTypeArray (Entry->Type)) { if (GetElementCount (Entry->Type) == UNSPECIFIED) { /* Assume array size of 1 */ @@ -488,11 +489,11 @@ void Compile (const char* FileName) Warning ("Incomplete array '%s[]' assumed to have one element", Entry->Name); } - Sym = GetSymType (GetElementType (Entry->Type)); + TagSym = GetSymType (GetElementType (Entry->Type)); } /* For non-ESU types, Size != 0 */ - if (Size != 0 || (Sym != 0 && SymIsDef (Sym))) { + if (Size != 0 || (TagSym != 0 && SymIsDef (TagSym))) { /* Set the segment name only when it changes */ if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) { SetSegName (SEG_BSS, Entry->V.BssName); diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 6d9afa403..471b3d60a 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -1307,9 +1307,9 @@ int IsESUType (const Type* T) int IsIncompleteESUType (const Type* T) /* Return true if this is an incomplete ESU type */ { - SymEntry* Sym = GetSymType (T); + SymEntry* TagSym = GetSymType (T); - return Sym != 0 && !SymIsDef (Sym); + return TagSym != 0 && !SymIsDef (TagSym); } diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 7cc7444b6..b88a8db02 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -502,18 +502,18 @@ static SymEntry* ESUForwardDecl (const char* Name, unsigned Flags, unsigned* DSF /* Try to find an enum/struct/union with the given name. If there is none, ** insert a forward declaration into the current lexical level. */ - SymEntry* Entry = FindTagSym (Name); - if (Entry == 0) { + SymEntry* TagEntry = FindTagSym (Name); + if (TagEntry == 0) { if ((Flags & SC_ESUTYPEMASK) != SC_ENUM) { - Entry = AddStructSym (Name, Flags, 0, 0, DSFlags); + TagEntry = AddStructSym (Name, Flags, 0, 0, DSFlags); } else { - Entry = AddEnumSym (Name, Flags, 0, 0, DSFlags); + TagEntry = AddEnumSym (Name, Flags, 0, 0, DSFlags); } - } else if ((Entry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) { + } else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) { /* Already defined, but not the same type class */ Error ("Symbol '%s' is already different kind", Name); } - return Entry; + return TagEntry; } @@ -809,15 +809,13 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon) */ { unsigned Count = 0; + SymEntry* Field; SymEntry* Alias; - /* Get the pointer to the symbol table entry of the anon struct */ - SymEntry* Entry = GetESUSymEntry (D->Type); - /* Get the symbol table containing the fields. If it is empty, there has ** been an error before, so bail out. */ - SymTable* Tab = Entry->V.S.SymTab; + SymTable* Tab = GetESUSymEntry (D->Type)->V.S.SymTab; if (Tab == 0) { /* Incomplete definition - has been flagged before */ return 0; @@ -826,24 +824,24 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon) /* Get a pointer to the list of symbols. Then walk the list adding copies ** of the embedded struct to the current level. */ - Entry = Tab->SymHead; - while (Entry) { + Field = Tab->SymHead; + while (Field) { /* Enter an alias of this symbol */ - if (!IsAnonName (Entry->Name)) { - Alias = AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD|SC_ALIAS, 0); - Alias->V.A.Field = Entry; - Alias->V.A.Offs = Anon->V.Offs + Entry->V.Offs; + if (!IsAnonName (Field->Name)) { + Alias = AddLocalSym (Field->Name, Field->Type, SC_STRUCTFIELD|SC_ALIAS, 0); + Alias->V.A.Field = Field; + Alias->V.A.Offs = Anon->V.Offs + Field->V.Offs; ++Count; } /* Currently, there can not be any attributes, but if there will be ** some in the future, we want to know this. */ - CHECK (Entry->Attr == 0); + CHECK (Field->Attr == 0); /* Next entry */ - Entry = Entry->NextSym; + Field = Field->NextSym; } /* Return the count of created aliases */ @@ -861,7 +859,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) int FieldWidth; /* Width in bits, -1 if not a bit-field */ SymTable* FieldTab; SymEntry* UnionTagEntry; - SymEntry* Entry; + SymEntry* Field; unsigned Flags = 0; unsigned PrevErrorCount = ErrorCount; @@ -945,17 +943,17 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth, SignednessSpecified); } else if (Decl.Ident[0] != '\0') { - Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); + Field = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); if (IsAnonName (Decl.Ident)) { - Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++; - AliasAnonStructFields (&Decl, Entry); + Field->V.A.ANumber = UnionTagEntry->V.S.ACount++; + AliasAnonStructFields (&Decl, Field); } /* Check if the field itself has a flexible array member */ if (IsClassStruct (Decl.Type)) { - SymEntry* Sym = GetSymType (Decl.Type); - if (Sym && SymHasFlexibleArrayMember (Sym)) { - Entry->Flags |= SC_HAVEFAM; + SymEntry* TagEntry = GetSymType (Decl.Type); + if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { + Field->Flags |= SC_HAVEFAM; Flags |= SC_HAVEFAM; } } @@ -1002,7 +1000,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) int FieldWidth; /* Width in bits, -1 if not a bit-field */ SymTable* FieldTab; SymEntry* StructTagEntry; - SymEntry* Entry; + SymEntry* Field; unsigned Flags = 0; unsigned PrevErrorCount = ErrorCount; @@ -1147,17 +1145,17 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) StructSize += BitOffs / CHAR_BITS; BitOffs %= CHAR_BITS; } else if (Decl.Ident[0] != '\0') { - Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); + Field = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); if (IsAnonName (Decl.Ident)) { - Entry->V.A.ANumber = StructTagEntry->V.S.ACount++; - AliasAnonStructFields (&Decl, Entry); + Field->V.A.ANumber = StructTagEntry->V.S.ACount++; + AliasAnonStructFields (&Decl, Field); } /* Check if the field itself has a flexible array member */ if (IsClassStruct (Decl.Type)) { - SymEntry* Sym = GetSymType (Decl.Type); - if (Sym && SymHasFlexibleArrayMember (Sym)) { - Entry->Flags |= SC_HAVEFAM; + SymEntry* TagEntry = GetSymType (Decl.Type); + if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { + Field->Flags |= SC_HAVEFAM; Flags |= SC_HAVEFAM; } } @@ -1214,7 +1212,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, */ { ident Ident; - SymEntry* Entry; + SymEntry* TagEntry; if (SignednessSpecified != NULL) { *SignednessSpecified = 0; @@ -1384,10 +1382,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Declare the union in the current scope */ - Entry = ParseUnionDecl (Ident, &D->Flags); + TagEntry = ParseUnionDecl (Ident, &D->Flags); /* Encode the union entry into the type */ D->Type[0].C = T_UNION; - SetESUSymEntry (D->Type, Entry); + SetESUSymEntry (D->Type, TagEntry); D->Type[1].C = T_END; break; @@ -1403,10 +1401,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Declare the struct in the current scope */ - Entry = ParseStructDecl (Ident, &D->Flags); + TagEntry = ParseStructDecl (Ident, &D->Flags); /* Encode the struct entry into the type */ D->Type[0].C = T_STRUCT; - SetESUSymEntry (D->Type, Entry); + SetESUSymEntry (D->Type, TagEntry); D->Type[1].C = T_END; break; @@ -1426,10 +1424,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Parse the enum decl */ - Entry = ParseEnumDecl (Ident, &D->Flags); + TagEntry = ParseEnumDecl (Ident, &D->Flags); /* Encode the enum entry into the type */ D->Type[0].C |= T_ENUM; - SetESUSymEntry (D->Type, Entry); + SetESUSymEntry (D->Type, TagEntry); D->Type[1].C = T_END; /* The signedness of enums is determined by the type, so say this is specified to avoid ** the int -> unsigned int handling for plain int bit-fields in AddBitField. @@ -1442,11 +1440,11 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, case TOK_IDENT: /* This could be a label */ if (NextTok.Tok != TOK_COLON || GetLexicalLevel () == LEX_LEVEL_STRUCT) { - Entry = FindSym (CurTok.Ident); - if (Entry && SymIsTypeDef (Entry)) { + TagEntry = FindSym (CurTok.Ident); + if (TagEntry && SymIsTypeDef (TagEntry)) { /* It's a typedef */ NextToken (); - TypeCopy (D->Type, Entry->Type); + TypeCopy (D->Type, TagEntry->Type); /* If it's a typedef, we should actually use whether the signedness was ** specified on the typedef, but that information has been lost. Treat the ** signedness as being specified to work around the ICE in #1267. @@ -1591,19 +1589,19 @@ static void ParseOldStyleParamList (FuncDesc* F) if (Decl.Ident[0] != '\0') { /* We have a name given. Search for the symbol */ - SymEntry* Sym = FindLocalSym (Decl.Ident); - if (Sym) { + SymEntry* Param = FindLocalSym (Decl.Ident); + if (Param) { /* Check if we already changed the type for this ** parameter */ - if (Sym->Flags & SC_DEFTYPE) { + if (Param->Flags & SC_DEFTYPE) { /* Found it, change the default type to the one given */ - ChangeSymType (Sym, ParamTypeCvt (Decl.Type)); + ChangeSymType (Param, ParamTypeCvt (Decl.Type)); /* Reset the "default type" flag */ - Sym->Flags &= ~SC_DEFTYPE; + Param->Flags &= ~SC_DEFTYPE; } else { /* Type has already been changed */ - Error ("Redefinition for parameter '%s'", Sym->Name); + Error ("Redefinition for parameter '%s'", Param->Name); } } else { Error ("Unknown identifier: '%s'", Decl.Ident); @@ -1633,7 +1631,7 @@ static void ParseAnsiParamList (FuncDesc* F) DeclSpec Spec; Declaration Decl; - SymEntry* Sym; + SymEntry* Param; /* Allow an ellipsis as last parameter */ if (CurTok.Tok == TOK_ELLIPSIS) { @@ -1681,10 +1679,10 @@ static void ParseAnsiParamList (FuncDesc* F) ParseAttribute (&Decl); /* Create a symbol table entry */ - Sym = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0); + Param = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0); /* Add attributes if we have any */ - SymUseAttr (Sym, &Decl); + SymUseAttr (Param, &Decl); /* If the parameter is a struct or union, emit a warning */ if (IsClassStruct (Decl.Type)) { diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 8c042cc3c..9666877ae 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -280,11 +280,10 @@ static unsigned ExprCheckedSizeOf (const Type* T) /* Specially checked SizeOf() used in 'sizeof' expressions */ { unsigned Size = SizeOf (T); - SymEntry* Sym; if (Size == 0) { - Sym = GetSymType (T); - if (Sym == 0 || !SymIsDef (Sym)) { + SymEntry* TagSym = GetSymType (T); + if (TagSym == 0 || !SymIsDef (TagSym)) { Error ("Cannot apply 'sizeof' to incomplete type '%s'", GetFullTypeName (T)); } } diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index 99dacdca9..1c5d21460 100644 --- a/src/cc65/initdata.c +++ b/src/cc65/initdata.c @@ -437,7 +437,7 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers) static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) /* Parse initialization of a struct or union. Return the number of data bytes. */ { - SymEntry* Sym; + SymEntry* TagSym; SymTable* Tab; StructInitData SI; int HasCurly = 0; @@ -452,15 +452,15 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) } /* Get a pointer to the struct entry from the type */ - Sym = GetESUSymEntry (T); + TagSym = GetESUSymEntry (T); /* Get the size of the struct from the symbol table entry */ - SI.Size = Sym->V.S.Size; + SI.Size = TagSym->V.S.Size; /* Check if this struct definition has a field table. If it doesn't, it ** is an incomplete definition. */ - Tab = Sym->V.S.SymTab; + Tab = TagSym->V.S.SymTab; if (Tab == 0) { Error ("Cannot initialize variables with incomplete type"); /* Try error recovery */ @@ -470,7 +470,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) } /* Get a pointer to the list of symbols */ - Sym = Tab->SymHead; + TagSym = Tab->SymHead; /* Initialize fields */ SI.Offs = 0; @@ -479,7 +479,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) while (CurTok.Tok != TOK_RCURLY) { /* Check for excess elements */ - if (Sym == 0) { + if (TagSym == 0) { /* Is there just one trailing comma before a closing curly? */ if (NextTok.Tok == TOK_RCURLY && CurTok.Tok == TOK_COMMA) { /* Skip comma and exit scope */ @@ -495,7 +495,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) } /* Check for special members that don't consume the initializer */ - if ((Sym->Flags & SC_ALIAS) == SC_ALIAS) { + if ((TagSym->Flags & SC_ALIAS) == SC_ALIAS) { /* Just skip */ goto NextMember; } @@ -503,13 +503,13 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) /* This may be an anonymous bit-field, in which case it doesn't ** have an initializer. */ - if (SymIsBitField (Sym) && (IsAnonName (Sym->Name))) { + if (SymIsBitField (TagSym) && (IsAnonName (TagSym->Name))) { /* Account for the data and output it if we have at least a full ** byte. We may have more if there was storage unit overlap, for ** example two consecutive 7 bit fields. Those would be packed ** into 2 bytes. */ - SI.ValBits += Sym->Type->A.B.Width; + SI.ValBits += TagSym->Type->A.B.Width; CHECK (SI.ValBits <= CHAR_BIT * sizeof(SI.BitVal)); /* TODO: Generalize this so any type can be used. */ CHECK (SI.ValBits <= LONG_BITS); @@ -526,7 +526,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) SkipComma = 0; } - if (SymIsBitField (Sym)) { + if (SymIsBitField (TagSym)) { /* Parse initialization of one field. Bit-fields need a special ** handling. @@ -537,14 +537,14 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) unsigned Shift; /* Calculate the bitmask from the bit-field data */ - unsigned long Mask = shl_l (1UL, Sym->Type->A.B.Width) - 1UL; + unsigned long Mask = shl_l (1UL, TagSym->Type->A.B.Width) - 1UL; /* Safety ... */ - CHECK (Sym->V.Offs * CHAR_BITS + Sym->Type->A.B.Offs == + CHECK (TagSym->V.Offs * CHAR_BITS + TagSym->Type->A.B.Offs == SI.Offs * CHAR_BITS + SI.ValBits); /* Read the data, check for a constant integer, do a range check */ - Field = ParseScalarInitInternal (IntPromotion (Sym->Type)); + Field = ParseScalarInitInternal (IntPromotion (TagSym->Type)); if (!ED_IsConstAbsInt (&Field)) { Error ("Constant initializer expected"); ED_MakeConstAbsInt (&Field, 1); @@ -554,19 +554,19 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) ** any useful bits. */ Val = (unsigned long) Field.IVal & Mask; - if (IsSignUnsigned (Sym->Type)) { + if (IsSignUnsigned (TagSym->Type)) { if (Field.IVal < 0 || (unsigned long) Field.IVal != Val) { Warning (IsSignUnsigned (Field.Type) ? "Implicit truncation from '%s' to '%s : %u' in bit-field initializer" " changes value from %lu to %lu" : "Implicit truncation from '%s' to '%s : %u' in bit-field initializer" " changes value from %ld to %lu", - GetFullTypeName (Field.Type), GetFullTypeName (Sym->Type), - Sym->Type->A.B.Width, Field.IVal, Val); + GetFullTypeName (Field.Type), GetFullTypeName (TagSym->Type), + TagSym->Type->A.B.Width, Field.IVal, Val); } } else { /* Sign extend back to full width of host long. */ - unsigned ShiftBits = sizeof (long) * CHAR_BIT - Sym->Type->A.B.Width; + unsigned ShiftBits = sizeof (long) * CHAR_BIT - TagSym->Type->A.B.Width; long RestoredVal = asr_l (asl_l (Val, ShiftBits), ShiftBits); if (Field.IVal != RestoredVal) { Warning (IsSignUnsigned (Field.Type) ? @@ -574,17 +574,17 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) " changes value from %lu to %ld" : "Implicit truncation from '%s' to '%s : %u' in bit-field initializer" " changes value from %ld to %ld", - GetFullTypeName (Field.Type), GetFullTypeName (Sym->Type), - Sym->Type->A.B.Width, Field.IVal, RestoredVal); + GetFullTypeName (Field.Type), GetFullTypeName (TagSym->Type), + TagSym->Type->A.B.Width, Field.IVal, RestoredVal); } } /* Add the value to the currently stored bit-field value */ - Shift = (Sym->V.Offs - SI.Offs) * CHAR_BITS + Sym->Type->A.B.Offs; + Shift = (TagSym->V.Offs - SI.Offs) * CHAR_BITS + TagSym->Type->A.B.Offs; SI.BitVal |= (Val << Shift); /* Account for the data and output any full bytes we have. */ - SI.ValBits += Sym->Type->A.B.Width; + SI.ValBits += TagSym->Type->A.B.Width; /* Make sure unsigned is big enough to hold the value, 32 bits. ** This cannot be more than 32 bits because a 16-bit or 32-bit ** bit-field will always be byte-aligned with padding before it @@ -609,7 +609,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) /* Flexible array members may only be initialized if they are ** the last field (or part of the last struct field). */ - SI.Offs += ParseInitInternal (Sym->Type, Braces, AllowFlexibleMembers && Sym->NextSym == 0); + SI.Offs += ParseInitInternal (TagSym->Type, Braces, AllowFlexibleMembers && TagSym->NextSym == 0); } /* More initializers? */ @@ -624,10 +624,10 @@ NextMember: /* Next member. For unions, only the first one can be initialized */ if (IsTypeUnion (T)) { /* Union */ - Sym = 0; + TagSym = 0; } else { /* Struct */ - Sym = Sym->NextSym; + TagSym = TagSym->NextSym; } } diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index e5741ea1d..385b5a831 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -625,8 +625,8 @@ SymEntry FindStructField (const Type* T, const char* Name) ** value, or an empty entry struct if the field is not found. */ { - SymEntry* Entry = 0; - SymEntry Field; + SymEntry* Field = 0; + SymEntry Res; int Offs = 0; /* The given type may actually be a pointer to struct/union */ @@ -637,35 +637,35 @@ SymEntry FindStructField (const Type* T, const char* Name) /* Only structs/unions have struct/union fields... */ if (IsClassStruct (T)) { - /* Get a pointer to the struct/union type */ - const SymEntry* Struct = GetESUSymEntry (T); - CHECK (Struct != 0); + /* Get a pointer to the struct/union tag */ + const SymEntry* TagSym = GetESUSymEntry (T); + CHECK (TagSym != 0); /* Now search in the struct/union symbol table. Beware: The table may ** not exist. */ - if (Struct->V.S.SymTab) { - Entry = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); + if (TagSym->V.S.SymTab) { + Field = FindSymInTable (TagSym->V.S.SymTab, Name, HashStr (Name)); - if (Entry != 0) { - Offs = Entry->V.Offs; + if (Field != 0) { + Offs = Field->V.Offs; } - while (Entry != 0 && (Entry->Flags & SC_ALIAS) == SC_ALIAS) { + while (Field != 0 && (Field->Flags & SC_ALIAS) == SC_ALIAS) { /* Get the real field */ - Entry = Entry->V.A.Field; + Field = Field->V.A.Field; } } } - if (Entry != 0) { - Field = *Entry; - Field.V.Offs = Offs; + if (Field != 0) { + Res = *Field; + Res.V.Offs = Offs; } else { - memset (&Field, 0, sizeof(SymEntry)); + memset (&Res, 0, sizeof(SymEntry)); } - return Field; + return Res; } @@ -689,15 +689,15 @@ static int IsDistinctRedef (const Type* lhst, const Type* rhst, typecmpcode_t Co } -static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags) +static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags) /* Check and handle redefinition of existing symbols. ** Complete array sizes and function descriptors as well. ** Return true if there *is* an error. */ { /* Get the type info of the existing symbol */ - Type* E_Type = Entry->Type; - unsigned E_SCType = Entry->Flags & SC_TYPEMASK; + Type* E_Type = Sym->Type; + unsigned E_SCType = Sym->Flags & SC_TYPEMASK; unsigned SCType = Flags & SC_TYPEMASK; /* Some symbols may be redeclared if certain requirements are met */ @@ -706,16 +706,16 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags /* Existing typedefs cannot be redeclared as anything different */ if (SCType == SC_TYPEDEF) { if (IsDistinctRedef (E_Type, T, TC_IDENTICAL, TCF_MASK_QUAL)) { - Error ("Conflicting types for typedef '%s'", Entry->Name); + Error ("Conflicting types for typedef '%s'", Sym->Name); Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); - Entry = 0; + Sym = 0; } } else { - Error ("Redefinition of typedef '%s' as different kind of symbol", Entry->Name); - Entry = 0; + Error ("Redefinition of typedef '%s' as different kind of symbol", Sym->Name); + Sym = 0; } - } else if ((Entry->Flags & SC_FUNC) == SC_FUNC) { + } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) { /* In case of a function, use the new type descriptor, since it ** contains pointers to the new symbol tables that are needed if @@ -726,27 +726,27 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags if (IsTypeFunc (T)) { /* Check for duplicate function definitions */ - if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) { + if (SymIsDef (Sym) && (Flags & SC_DEF) == SC_DEF) { Error ("Body for function '%s' has already been defined", - Entry->Name); - Entry = 0; + Sym->Name); + Sym = 0; } else { /* New type must be compatible with the composite prototype */ if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) { - Error ("Conflicting function types for '%s'", Entry->Name); + Error ("Conflicting function types for '%s'", Sym->Name); Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); - Entry = 0; + Sym = 0; } else { /* Refine the existing composite prototype with this new ** one. */ - RefineFuncDesc (Entry->Type, T); + RefineFuncDesc (Sym->Type, T); } } } else { - Error ("Redefinition of function '%s' as different kind of symbol", Entry->Name); - Entry = 0; + Error ("Redefinition of function '%s' as different kind of symbol", Sym->Name); + Sym = 0; } } else { @@ -765,9 +765,9 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || IsDistinctRedef (E_Type + 1, T + 1, TC_IDENTICAL, TCF_MASK_QUAL)) { /* Conflicting element types */ - Error ("Conflicting array types for '%s[]'", Entry->Name); + Error ("Conflicting array types for '%s[]'", Sym->Name); Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); - Entry = 0; + Sym = 0; } else { /* Check if we have a size in the existing definition */ if (ESize == UNSPECIFIED) { @@ -780,25 +780,25 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags /* New type must be equivalent */ if (SCType != E_SCType) { - Error ("Redefinition of '%s' as different kind of symbol", Entry->Name); - Entry = 0; + Error ("Redefinition of '%s' as different kind of symbol", Sym->Name); + Sym = 0; } else if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) { - Error ("Conflicting types for '%s'", Entry->Name); + Error ("Conflicting types for '%s'", Sym->Name); Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type)); - Entry = 0; + Sym = 0; } else if (E_SCType == SC_ENUMERATOR) { /* Enumerators aren't allowed to be redeclared at all, even if ** all occurences are identical. The current code logic won't ** get here, but let's just do it. */ - Error ("Redeclaration of enumerator constant '%s'", Entry->Name); - Entry = 0; + Error ("Redeclaration of enumerator constant '%s'", Sym->Name); + Sym = 0; } } } /* Return if there are any errors */ - return Entry == 0; + return Sym == 0; } From 164eb198cec7e09aef1ca93ff4e53a978bd49a26 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 12 Oct 2022 13:10:17 +0800 Subject: [PATCH 057/360] Moved type facility functions for deciding code generation type flags. --- src/cc65/datatype.c | 93 -------------------------------------------- src/cc65/datatype.h | 6 --- src/cc65/expr.c | 94 +++++++++++++++++++++++++++++++++++++++++++++ src/cc65/expr.h | 6 +++ src/cc65/function.c | 1 + src/cc65/loadexpr.c | 1 + 6 files changed, 102 insertions(+), 99 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 0990396af..fe0b9e0a3 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -590,25 +590,6 @@ static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth) } -static unsigned TypeOfBySize (unsigned Size) -/* Get the code generator replacement type of the object by its size */ -{ - unsigned NewType; - /* If the size is less than or equal to that of a a long, we will copy - ** the struct using the primary register, otherwise we use memcpy. - */ - switch (Size) { - case 1: NewType = CF_CHAR; break; - case 2: NewType = CF_INT; break; - case 3: /* FALLTHROUGH */ - case 4: NewType = CF_LONG; break; - default: NewType = CF_NONE; break; - } - - return NewType; -} - - const Type* GetUnderlyingType (const Type* Type) /* Get the underlying type of an enum or other integer class type */ @@ -858,80 +839,6 @@ unsigned CheckedPSizeOf (const Type* T) -unsigned TypeOf (const Type* T) -/* Get the code generator base type of the object */ -{ - unsigned NewType; - - switch (GetUnderlyingTypeCode (T)) { - - case T_SCHAR: - return CF_CHAR; - - case T_UCHAR: - return CF_CHAR | CF_UNSIGNED; - - case T_SHORT: - case T_INT: - return CF_INT; - - case T_USHORT: - case T_UINT: - case T_PTR: - case T_ARRAY: - return CF_INT | CF_UNSIGNED; - - case T_LONG: - return CF_LONG; - - case T_ULONG: - return CF_LONG | CF_UNSIGNED; - - case T_FLOAT: - case T_DOUBLE: - /* These two are identical in the backend */ - return CF_FLOAT; - - case T_FUNC: - /* Treat this as a function pointer */ - return CF_INT | CF_UNSIGNED; - - case T_STRUCT: - case T_UNION: - NewType = TypeOfBySize (SizeOf (T)); - if (NewType != CF_NONE) { - return NewType; - } - /* Address of ... */ - return CF_INT | CF_UNSIGNED; - - case T_VOID: - case T_ENUM: - /* Incomplete enum type */ - Error ("Incomplete type '%s'", GetFullTypeName (T)); - return CF_INT; - - default: - Error ("Illegal type %04lX", T->C); - return CF_INT; - } -} - - - -unsigned FuncTypeOf (const Type* T) -/* Get the code generator flag for calling the function */ -{ - if (GetUnderlyingTypeCode (T) == T_FUNC) { - return (T->A.F->Flags & FD_VARIADIC) ? 0 : CF_FIXARGC; - } else { - Error ("Illegal function type %04lX", T->C); - return 0; - } -} - - - const Type* Indirect (const Type* T) /* Do one indirection for the given type, that is, return the type where the ** given type points to. diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index d7e8d2e99..be5b4a31c 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -333,12 +333,6 @@ unsigned CheckedPSizeOf (const Type* T); ** rest of the compiler doesn't have to work with invalid sizes). */ -unsigned TypeOf (const Type* T); -/* Get the code generator base type of the object */ - -unsigned FuncTypeOf (const Type* T); -/* Get the code generator flag for calling the function */ - const Type* Indirect (const Type* T); /* Do one indirection for the given type, that is, return the type where the ** given type points to. diff --git a/src/cc65/expr.c b/src/cc65/expr.c index c95a5a401..8f493ad03 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -103,6 +103,100 @@ unsigned GlobalModeFlags (const ExprDesc* Expr) +static unsigned TypeOfBySize (unsigned Size) +/* Get the code generator replacement type of the object by its size */ +{ + unsigned NewType; + /* If the size is less than or equal to that of a a long, we will copy + ** the struct using the primary register, otherwise we use memcpy. + */ + switch (Size) { + case 1: NewType = CF_CHAR; break; + case 2: NewType = CF_INT; break; + case 3: /* FALLTHROUGH */ + case 4: NewType = CF_LONG; break; + default: NewType = CF_NONE; break; + } + + return NewType; +} + + + +unsigned TypeOf (const Type* T) +/* Get the code generator base type of the object */ +{ + unsigned NewType; + + switch (GetUnderlyingTypeCode (T)) { + + case T_SCHAR: + return CF_CHAR; + + case T_UCHAR: + return CF_CHAR | CF_UNSIGNED; + + case T_SHORT: + case T_INT: + return CF_INT; + + case T_USHORT: + case T_UINT: + case T_PTR: + case T_ARRAY: + return CF_INT | CF_UNSIGNED; + + case T_LONG: + return CF_LONG; + + case T_ULONG: + return CF_LONG | CF_UNSIGNED; + + case T_FLOAT: + case T_DOUBLE: + /* These two are identical in the backend */ + return CF_FLOAT; + + case T_FUNC: + /* Treat this as a function pointer */ + return CF_INT | CF_UNSIGNED; + + case T_STRUCT: + case T_UNION: + NewType = TypeOfBySize (SizeOf (T)); + if (NewType != CF_NONE) { + return NewType; + } + /* Address of ... */ + return CF_INT | CF_UNSIGNED; + + case T_VOID: + case T_ENUM: + /* Incomplete enum type */ + Error ("Incomplete type '%s'", GetFullTypeName (T)); + return CF_INT; + + default: + Error ("Illegal type %04lX", T->C); + return CF_INT; + } +} + + + +unsigned FuncTypeOf (const Type* T) +/* Get the code generator flag for calling the function */ +{ + if (GetUnderlyingTypeCode (T) == T_FUNC) { + return (T->A.F->Flags & FD_VARIADIC) ? 0 : CF_FIXARGC; + } else { + Error ("Illegal function type %04lX", T->C); + return 0; + } +} + + + void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Call an expression function with checks. */ { diff --git a/src/cc65/expr.h b/src/cc65/expr.h index 7c2f426d7..5644fb82d 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -51,6 +51,12 @@ typedef struct GenDesc { unsigned GlobalModeFlags (const ExprDesc* Expr); /* Return the addressing mode flags for the given expression */ +unsigned TypeOf (const Type* T); +/* Get the code generator base type of the object */ + +unsigned FuncTypeOf (const Type* T); +/* Get the code generator flag for calling the function */ + void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Call an expression function with checks. */ diff --git a/src/cc65/function.c b/src/cc65/function.c index 44d566de8..737b068a3 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -42,6 +42,7 @@ #include "asmlabel.h" #include "codegen.h" #include "error.h" +#include "expr.h" #include "funcdesc.h" #include "global.h" #include "litpool.h" diff --git a/src/cc65/loadexpr.c b/src/cc65/loadexpr.c index ccd694e35..c5ac43f78 100644 --- a/src/cc65/loadexpr.c +++ b/src/cc65/loadexpr.c @@ -36,6 +36,7 @@ /* cc65 */ #include "codegen.h" #include "error.h" +#include "expr.h" #include "exprdesc.h" #include "global.h" #include "loadexpr.h" From a2dfa7c721ae0a0c3393c58740e0e286ec7e9b4c Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 12 Oct 2022 13:10:17 +0800 Subject: [PATCH 058/360] More consistent names for SymEntry functions. --- src/cc65/compile.c | 4 +- src/cc65/datatype.c | 160 +++++++++++++++++++++++++------------------- src/cc65/datatype.h | 10 +-- src/cc65/declare.c | 14 ++-- src/cc65/expr.c | 2 +- src/cc65/function.c | 2 +- src/cc65/initdata.c | 2 +- src/cc65/symentry.c | 51 +++----------- src/cc65/symentry.h | 18 ++--- src/cc65/symtab.c | 94 +++++++++++++------------- src/cc65/symtab.h | 4 +- src/cc65/typecmp.c | 8 +-- 12 files changed, 175 insertions(+), 194 deletions(-) diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 63c2ef081..a8ef56af6 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -478,7 +478,7 @@ void Compile (const char* FileName) for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) { if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) { /* Assembly definition of uninitialized global variable */ - SymEntry* TagSym = GetSymType (Entry->Type); + SymEntry* TagSym = GetESUTagSym (Entry->Type); unsigned Size = SizeOf (Entry->Type); if (Size == 0 && IsTypeArray (Entry->Type)) { @@ -489,7 +489,7 @@ void Compile (const char* FileName) Warning ("Incomplete array '%s[]' assumed to have one element", Entry->Name); } - TagSym = GetSymType (GetElementType (Entry->Type)); + TagSym = GetESUTagSym (GetElementType (Entry->Type)); } /* For non-ESU types, Size != 0 */ diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 471b3d60a..0990396af 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -48,6 +48,7 @@ #include "fp.h" #include "funcdesc.h" #include "global.h" +#include "ident.h" #include "symtab.h" @@ -86,6 +87,83 @@ const Type type_c_void_p[] = { TYPE(T_PTR), TYPE(T_C_VOID), TYPE(T_END) }; +const char* GetBasicTypeName (const Type* T) +/* Return a const name string of the basic type. +** Return "type" for unknown basic types. +*/ +{ + switch (GetRawType (T)) { + case T_TYPE_ENUM: return "enum"; + case T_TYPE_BITFIELD: return "bit-field"; + case T_TYPE_FLOAT: return "float"; + case T_TYPE_DOUBLE: return "double"; + case T_TYPE_VOID: return "void"; + case T_TYPE_STRUCT: return "struct"; + case T_TYPE_UNION: return "union"; + case T_TYPE_ARRAY: return "array"; + case T_TYPE_PTR: return "pointer"; + case T_TYPE_FUNC: return "function"; + case T_TYPE_NONE: /* FALLTHROUGH */ + default: break; + } + if (IsClassInt (T)) { + if (IsRawSignSigned (T)) { + switch (GetRawType (T)) { + case T_TYPE_CHAR: return "signed char"; + case T_TYPE_SHORT: return "short"; + case T_TYPE_INT: return "int"; + case T_TYPE_LONG: return "long"; + case T_TYPE_LONGLONG: return "long long"; + default: + return "signed integer"; + } + } else if (IsRawSignUnsigned (T)) { + switch (GetRawType (T)) { + case T_TYPE_CHAR: return "unsigned char"; + case T_TYPE_SHORT: return "unsigned short"; + case T_TYPE_INT: return "unsigned int"; + case T_TYPE_LONG: return "unsigned long"; + case T_TYPE_LONGLONG: return "unsigned long long"; + default: + return "unsigned integer"; + } + } else { + switch (GetRawType (T)) { + case T_TYPE_CHAR: return "char"; + case T_TYPE_SHORT: return "short"; + case T_TYPE_INT: return "int"; + case T_TYPE_LONG: return "long"; + case T_TYPE_LONGLONG: return "long long"; + default: + return "integer"; + } + } + } + return "type"; +} + + + +static const char* GetTagSymName (const Type* T) +/* Return a name string of the type or the symbol name if it is an ESU type. +** Note: This may use a static buffer that could be overwritten by other calls. +*/ +{ + static char TypeName [IDENTSIZE + 16]; + SymEntry* TagSym; + + TagSym = GetESUTagSym (T); + if (TagSym == 0) { + return GetBasicTypeName (T); + } + sprintf (TypeName, "%s %s", GetBasicTypeName (T), + TagSym->Name[0] != '\0' ? TagSym->Name : "<unknown>"); + + return TypeName; +} + + + static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBuf* East, const Type* T) /* Return the name string of the given type split into a western part and an ** eastern part. @@ -208,7 +286,7 @@ static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBu } if (!IsTypeBitField (T)) { - SB_AppendStr (&Buf, GetSymTypeName (T)); + SB_AppendStr (&Buf, GetTagSymName (T)); } else { SB_AppendStr (&Buf, GetBasicTypeName (T + 1)); } @@ -228,63 +306,6 @@ static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBu -const char* GetBasicTypeName (const Type* T) -/* Return a const name string of the basic type. -** Return "type" for unknown basic types. -*/ -{ - switch (GetRawType (T)) { - case T_TYPE_ENUM: return "enum"; - case T_TYPE_BITFIELD: return "bit-field"; - case T_TYPE_FLOAT: return "float"; - case T_TYPE_DOUBLE: return "double"; - case T_TYPE_VOID: return "void"; - case T_TYPE_STRUCT: return "struct"; - case T_TYPE_UNION: return "union"; - case T_TYPE_ARRAY: return "array"; - case T_TYPE_PTR: return "pointer"; - case T_TYPE_FUNC: return "function"; - case T_TYPE_NONE: /* FALLTHROUGH */ - default: break; - } - if (IsClassInt (T)) { - if (IsRawSignSigned (T)) { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "signed char"; - case T_TYPE_SHORT: return "short"; - case T_TYPE_INT: return "int"; - case T_TYPE_LONG: return "long"; - case T_TYPE_LONGLONG: return "long long"; - default: - return "signed integer"; - } - } else if (IsRawSignUnsigned (T)) { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "unsigned char"; - case T_TYPE_SHORT: return "unsigned short"; - case T_TYPE_INT: return "unsigned int"; - case T_TYPE_LONG: return "unsigned long"; - case T_TYPE_LONGLONG: return "unsigned long long"; - default: - return "unsigned integer"; - } - } else { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "char"; - case T_TYPE_SHORT: return "short"; - case T_TYPE_INT: return "int"; - case T_TYPE_LONG: return "long"; - case T_TYPE_LONGLONG: return "long long"; - default: - return "integer"; - } - } - } - return "type"; -} - - - const char* GetFullTypeName (const Type* T) /* Return the full name string of the given type */ { @@ -1307,7 +1328,7 @@ int IsESUType (const Type* T) int IsIncompleteESUType (const Type* T) /* Return true if this is an incomplete ESU type */ { - SymEntry* TagSym = GetSymType (T); + SymEntry* TagSym = GetESUTagSym (T); return TagSym != 0 && !SymIsDef (TagSym); } @@ -1486,20 +1507,21 @@ const Type* GetBaseElementType (const Type* T) -struct SymEntry* GetESUSymEntry (const Type* T) -/* Return a SymEntry pointer from an enum/struct/union type */ +struct SymEntry* GetESUTagSym (const Type* T) +/* Get the tag symbol entry of the enum/struct/union type. +** Return 0 if it is not an enum/struct/union. +*/ { - /* Only enums, structs or unions have a SymEntry attribute */ - CHECK (IsClassStruct (T) || IsTypeEnum (T)); - - /* Return the attribute */ - return T->A.S; + if ((IsClassStruct (T) || IsTypeEnum (T))) { + return T->A.S; + } + return 0; } -void SetESUSymEntry (Type* T, struct SymEntry* S) -/* Set the SymEntry pointer for an enum/struct/union type */ +void SetESUTagSym (Type* T, struct SymEntry* S) +/* Set the tag symbol entry of the enum/struct/union type */ { /* Only enums, structs or unions have a SymEntry attribute */ CHECK (IsClassStruct (T) || IsTypeEnum (T)); @@ -1570,7 +1592,7 @@ void PrintFuncSig (FILE* F, const char* Name, const Type* T) if (SymIsRegVar (Param)) { SB_AppendStr (&ParamList, "register "); } - if (!HasAnonName (Param)) { + if (!SymHasAnonName (Param)) { SB_AppendStr (&Buf, Param->Name); } SB_AppendStr (&ParamList, SB_GetConstBuf (GetFullTypeNameBuf (&Buf, Param->Type))); diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index e8ba7b6c0..d7e8d2e99 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -943,11 +943,13 @@ const Type* GetBaseElementType (const Type* T); ** the element type that is not an array. */ -struct SymEntry* GetESUSymEntry (const Type* T) attribute ((const)); -/* Return a SymEntry pointer from an enum/struct/union type */ +struct SymEntry* GetESUTagSym (const Type* T) attribute ((const)); +/* Get the tag symbol entry of the enum/struct/union type. +** Return 0 if it is not an enum/struct/union. +*/ -void SetESUSymEntry (Type* T, struct SymEntry* S); -/* Set the SymEntry pointer for an enum/struct/union type */ +void SetESUTagSym (Type* T, struct SymEntry* S); +/* Set the tag symbol entry of the enum/struct/union type */ TypeCode AddrSizeQualifier (unsigned AddrSize); /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ diff --git a/src/cc65/declare.c b/src/cc65/declare.c index b88a8db02..2298450b2 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -815,7 +815,7 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon) /* Get the symbol table containing the fields. If it is empty, there has ** been an error before, so bail out. */ - SymTable* Tab = GetESUSymEntry (D->Type)->V.S.SymTab; + SymTable* Tab = GetESUTagSym (D->Type)->V.S.SymTab; if (Tab == 0) { /* Incomplete definition - has been flagged before */ return 0; @@ -951,7 +951,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) /* Check if the field itself has a flexible array member */ if (IsClassStruct (Decl.Type)) { - SymEntry* TagEntry = GetSymType (Decl.Type); + SymEntry* TagEntry = GetESUTagSym (Decl.Type); if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { Field->Flags |= SC_HAVEFAM; Flags |= SC_HAVEFAM; @@ -1153,7 +1153,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) /* Check if the field itself has a flexible array member */ if (IsClassStruct (Decl.Type)) { - SymEntry* TagEntry = GetSymType (Decl.Type); + SymEntry* TagEntry = GetESUTagSym (Decl.Type); if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { Field->Flags |= SC_HAVEFAM; Flags |= SC_HAVEFAM; @@ -1385,7 +1385,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, TagEntry = ParseUnionDecl (Ident, &D->Flags); /* Encode the union entry into the type */ D->Type[0].C = T_UNION; - SetESUSymEntry (D->Type, TagEntry); + SetESUTagSym (D->Type, TagEntry); D->Type[1].C = T_END; break; @@ -1404,7 +1404,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, TagEntry = ParseStructDecl (Ident, &D->Flags); /* Encode the struct entry into the type */ D->Type[0].C = T_STRUCT; - SetESUSymEntry (D->Type, TagEntry); + SetESUTagSym (D->Type, TagEntry); D->Type[1].C = T_END; break; @@ -1427,7 +1427,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, TagEntry = ParseEnumDecl (Ident, &D->Flags); /* Encode the enum entry into the type */ D->Type[0].C |= T_ENUM; - SetESUSymEntry (D->Type, TagEntry); + SetESUTagSym (D->Type, TagEntry); D->Type[1].C = T_END; /* The signedness of enums is determined by the type, so say this is specified to avoid ** the int -> unsigned int handling for plain int bit-fields in AddBitField. @@ -1596,7 +1596,7 @@ static void ParseOldStyleParamList (FuncDesc* F) */ if (Param->Flags & SC_DEFTYPE) { /* Found it, change the default type to the one given */ - ChangeSymType (Param, ParamTypeCvt (Decl.Type)); + SymChangeType (Param, ParamTypeCvt (Decl.Type)); /* Reset the "default type" flag */ Param->Flags &= ~SC_DEFTYPE; } else { diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 9666877ae..517f53733 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -282,7 +282,7 @@ static unsigned ExprCheckedSizeOf (const Type* T) unsigned Size = SizeOf (T); if (Size == 0) { - SymEntry* TagSym = GetSymType (T); + SymEntry* TagSym = GetESUTagSym (T); if (TagSym == 0 || !SymIsDef (TagSym)) { Error ("Cannot apply 'sizeof' to incomplete type '%s'", GetFullTypeName (T)); } diff --git a/src/cc65/function.c b/src/cc65/function.c index 452181af9..44d566de8 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -613,7 +613,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D) /* Could we allocate a register? */ if (Reg < 0) { /* No register available: Convert parameter to auto */ - CvtRegVarToAuto (Param); + SymCvtRegVarToAuto (Param); } else { /* Remember the register offset */ Param->V.R.RegOffs = Reg; diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index 1c5d21460..6195e0929 100644 --- a/src/cc65/initdata.c +++ b/src/cc65/initdata.c @@ -452,7 +452,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) } /* Get a pointer to the struct entry from the type */ - TagSym = GetESUSymEntry (T); + TagSym = GetESUTagSym (T); /* Get the size of the struct from the symbol table entry */ SI.Size = TagSym->V.S.Size; diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index c9402a64b..115d47e3f 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -268,7 +268,7 @@ void SymSetAsmName (SymEntry* Sym) -void CvtRegVarToAuto (SymEntry* Sym) +void SymCvtRegVarToAuto (SymEntry* Sym) /* Convert a register variable to an auto variable */ { /* Change the storage class */ @@ -280,59 +280,26 @@ void CvtRegVarToAuto (SymEntry* Sym) -SymEntry* GetSymType (const Type* T) -/* Get the symbol entry of the enum/struct/union type -** Return 0 if it is not an enum/struct/union. -*/ -{ - if ((IsClassStruct (T) || IsTypeEnum (T))) { - return T->A.S; - } - return 0; -} - - - -const char* GetSymTypeName (const Type* T) -/* Return a name string of the type or the symbol name if it is an ESU type. -** Note: This may use a static buffer that could be overwritten by other calls. -*/ -{ - static char TypeName [IDENTSIZE + 16]; - SymEntry* Sym; - - Sym = GetSymType (T); - if (Sym == 0) { - return GetBasicTypeName (T); - } - sprintf (TypeName, "%s %s", GetBasicTypeName (T), - Sym->Name[0] != '\0' ? Sym->Name : "<unknown>"); - - return TypeName; -} - - - -void ChangeSymType (SymEntry* Entry, const Type* T) +void SymChangeType (SymEntry* Sym, const Type* T) /* Change the type of the given symbol */ { - TypeFree (Entry->Type); - Entry->Type = TypeDup (T); + TypeFree (Sym->Type); + Sym->Type = TypeDup (T); } -void ChangeAsmName (SymEntry* Entry, const char* NewAsmName) +void SymChangeAsmName (SymEntry* Sym, const char* NewAsmName) /* Change the assembler name of the symbol */ { - xfree (Entry->AsmName); - Entry->AsmName = xstrdup (NewAsmName); + xfree (Sym->AsmName); + Sym->AsmName = xstrdup (NewAsmName); } -int HasAnonName (const SymEntry* Entry) +int SymHasAnonName (const SymEntry* Sym) /* Return true if the symbol entry has an anonymous name */ { - return IsAnonName (Entry->Name); + return IsAnonName (Sym->Name); } diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 0f4b145be..d973e6586 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -306,26 +306,16 @@ void SymSetAsmName (SymEntry* Sym); ** The symbol must have no assembler name set yet. */ -void CvtRegVarToAuto (SymEntry* Sym); +void SymCvtRegVarToAuto (SymEntry* Sym); /* Convert a register variable to an auto variable */ -SymEntry* GetSymType (const Type* T); -/* Get the symbol entry of the enum/struct/union type -** Return 0 if it is not an enum/struct/union. -*/ - -const char* GetSymTypeName (const Type* T); -/* Return a name string of the type or the symbol name if it is an ESU type. -** Note: This may use a static buffer that could be overwritten by other calls. -*/ - -void ChangeSymType (SymEntry* Entry, const Type* T); +void SymChangeType (SymEntry* Sym, const Type* T); /* Change the type of the given symbol */ -void ChangeAsmName (SymEntry* Entry, const char* NewAsmName); +void SymChangeAsmName (SymEntry* Sym, const char* NewAsmName); /* Change the assembler name of the symbol */ -int HasAnonName (const SymEntry* Entry); +int SymHasAnonName (const SymEntry* Sym); /* Return true if the symbol entry has an anonymous name */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 385b5a831..56e267f85 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -638,7 +638,7 @@ SymEntry FindStructField (const Type* T, const char* Name) if (IsClassStruct (T)) { /* Get a pointer to the struct/union tag */ - const SymEntry* TagSym = GetESUSymEntry (T); + const SymEntry* TagSym = GetESUTagSym (T); CHECK (TagSym != 0); /* Now search in the struct/union symbol table. Beware: The table may @@ -832,38 +832,38 @@ static void AddSymEntry (SymTable* T, SymEntry* S) SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags) -/* Add an enum entry and return it */ +/* Add an enum tag entry and return it */ { SymTable* CurTagTab = TagTab; - SymEntry* Entry; + SymEntry* TagEntry; if ((Flags & SC_FICTITIOUS) == 0) { /* Do we have an entry with this name already? */ - Entry = FindSymInTable (CurTagTab, Name, HashStr (Name)); + TagEntry = FindSymInTable (CurTagTab, Name, HashStr (Name)); } else { /* Add a fictitious symbol in the fail-safe table */ - Entry = 0; + TagEntry = 0; CurTagTab = FailSafeTab; } - if (Entry) { + if (TagEntry) { /* We do have an entry. This may be a forward, so check it. */ - if ((Entry->Flags & SC_TYPEMASK) != SC_ENUM) { + if ((TagEntry->Flags & SC_TYPEMASK) != SC_ENUM) { /* Existing symbol is not an enum */ Error ("Symbol '%s' is already different kind", Name); - Entry = 0; + TagEntry = 0; } else if (Type != 0) { /* Define the struct size if the underlying type is given. */ - if (Entry->V.E.Type != 0) { + if (TagEntry->V.E.Type != 0) { /* Both are definitions. */ Error ("Multiple definition for 'enum %s'", Name); - Entry = 0; + TagEntry = 0; } else { - Entry->V.E.SymTab = Tab; - Entry->V.E.Type = Type; - Entry->Flags &= ~SC_DECL; - Entry->Flags |= SC_DEF; + TagEntry->V.E.SymTab = Tab; + TagEntry->V.E.Type = Type; + TagEntry->Flags &= ~SC_DECL; + TagEntry->Flags |= SC_DEF; /* Remember this is the first definition of this type */ if (DSFlags != 0) { @@ -872,83 +872,83 @@ SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTab } } - if (Entry == 0) { + if (TagEntry == 0) { /* Use the fail-safe table for fictitious symbols */ CurTagTab = FailSafeTab; } } - if (Entry == 0) { + if (TagEntry == 0) { /* Create a new entry */ - Entry = NewSymEntry (Name, SC_ENUM); + TagEntry = NewSymEntry (Name, SC_ENUM); /* Set the enum type data */ - Entry->V.E.SymTab = Tab; - Entry->V.E.Type = Type; + TagEntry->V.E.SymTab = Tab; + TagEntry->V.E.Type = Type; if (Type != 0) { - Entry->Flags |= SC_DEF; + TagEntry->Flags |= SC_DEF; } /* Remember this is the first definition of this type */ if (CurTagTab != FailSafeTab && DSFlags != 0) { - if ((Entry->Flags & SC_DEF) != 0) { + if ((TagEntry->Flags & SC_DEF) != 0) { *DSFlags |= DS_NEW_TYPE_DEF; } *DSFlags |= DS_NEW_TYPE_DECL; } /* Add it to the current table */ - AddSymEntry (CurTagTab, Entry); + AddSymEntry (CurTagTab, TagEntry); } /* Return the entry */ - return Entry; + return TagEntry; } SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags) -/* Add a struct/union entry and return it */ +/* Add a struct/union tag entry and return it */ { SymTable* CurTagTab = TagTab; - SymEntry* Entry; - unsigned Type = (Flags & SC_TYPEMASK); + SymEntry* TagEntry; + unsigned SCType = (Flags & SC_TYPEMASK); - /* Type must be struct or union */ - PRECONDITION (Type == SC_STRUCT || Type == SC_UNION); + /* SCType must be struct or union */ + PRECONDITION (SCType == SC_STRUCT || SCType == SC_UNION); if ((Flags & SC_FICTITIOUS) == 0) { /* Do we have an entry with this name already? */ - Entry = FindSymInTable (CurTagTab, Name, HashStr (Name)); + TagEntry = FindSymInTable (CurTagTab, Name, HashStr (Name)); } else { /* Add a fictitious symbol in the fail-safe table */ - Entry = 0; + TagEntry = 0; CurTagTab = FailSafeTab; } - if (Entry) { + if (TagEntry) { /* We do have an entry. This may be a forward, so check it. */ - if ((Entry->Flags & SC_TYPEMASK) != Type) { + if ((TagEntry->Flags & SC_TYPEMASK) != SCType) { /* Existing symbol is not a struct */ Error ("Symbol '%s' is already different kind", Name); - Entry = 0; - } else if ((Entry->Flags & Flags & SC_DEF) == SC_DEF) { + TagEntry = 0; + } else if ((TagEntry->Flags & Flags & SC_DEF) == SC_DEF) { /* Both structs are definitions. */ - if (Type == SC_STRUCT) { + if (SCType == SC_STRUCT) { Error ("Multiple definition for 'struct %s'", Name); } else { Error ("Multiple definition for 'union %s'", Name); } - Entry = 0; + TagEntry = 0; } else { /* Define the struct size if it is a definition */ if ((Flags & SC_DEF) == SC_DEF) { - Entry->Flags = Flags; - Entry->V.S.SymTab = Tab; - Entry->V.S.Size = Size; + TagEntry->Flags = Flags; + TagEntry->V.S.SymTab = Tab; + TagEntry->V.S.Size = Size; /* Remember this is the first definition of this type */ if (DSFlags != 0) { @@ -957,35 +957,35 @@ SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTabl } } - if (Entry == 0) { + if (TagEntry == 0) { /* Use the fail-safe table for fictitious symbols */ CurTagTab = FailSafeTab; } } - if (Entry == 0) { + if (TagEntry == 0) { /* Create a new entry */ - Entry = NewSymEntry (Name, Flags); + TagEntry = NewSymEntry (Name, Flags); /* Set the struct data */ - Entry->V.S.SymTab = Tab; - Entry->V.S.Size = Size; + TagEntry->V.S.SymTab = Tab; + TagEntry->V.S.Size = Size; /* Remember this is the first definition of this type */ if (CurTagTab != FailSafeTab && DSFlags != 0) { - if ((Entry->Flags & SC_DEF) != 0) { + if ((TagEntry->Flags & SC_DEF) != 0) { *DSFlags |= DS_NEW_TYPE_DEF; } *DSFlags |= DS_NEW_TYPE_DECL; } /* Add it to the current tag table */ - AddSymEntry (CurTagTab, Entry); + AddSymEntry (CurTagTab, TagEntry); } /* Return the entry */ - return Entry; + return TagEntry; } diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index 1df61a822..b711fe606 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -169,10 +169,10 @@ unsigned short FindSPAdjustment (const char* Name); SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags); -/* Add an enum entry and return it */ +/* Add an enum tag entry and return it */ SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags); -/* Add a struct/union entry and return it */ +/* Add a struct/union tag entry and return it */ SymEntry* AddBitField (const char* Name, const Type* Type, unsigned Offs, unsigned BitOffs, unsigned BitWidth, int SignednessSpecified); diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 6052f4a84..29c8fe51e 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -303,8 +303,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) { /* Compare the tag types */ - Sym1 = IsTypeEnum (lhs) ? GetESUSymEntry (lhs) : 0; - Sym2 = IsTypeEnum (rhs) ? GetESUSymEntry (rhs) : 0; + Sym1 = IsTypeEnum (lhs) ? GetESUTagSym (lhs) : 0; + Sym2 = IsTypeEnum (rhs) ? GetESUTagSym (rhs) : 0; if (Sym1 != Sym2) { if (Sym1 == 0 || Sym2 == 0) { @@ -420,8 +420,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) case T_TYPE_STRUCT: case T_TYPE_UNION: /* Compare the tag types */ - Sym1 = GetESUSymEntry (lhs); - Sym2 = GetESUSymEntry (rhs); + Sym1 = GetESUTagSym (lhs); + Sym2 = GetESUTagSym (rhs); CHECK (Sym1 != 0 || Sym2 != 0); From feaedc5b5031192c7a16f32c0b294030cf0c11b3 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 12 Oct 2022 13:10:17 +0800 Subject: [PATCH 059/360] Better organized stuff related to C types. --- src/cc65/datatype.c | 1264 ++++++++++++++++++++++--------------------- src/cc65/datatype.h | 389 +++++++------ 2 files changed, 883 insertions(+), 770 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index fe0b9e0a3..9a661c037 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -87,317 +87,6 @@ const Type type_c_void_p[] = { TYPE(T_PTR), TYPE(T_C_VOID), TYPE(T_END) }; -const char* GetBasicTypeName (const Type* T) -/* Return a const name string of the basic type. -** Return "type" for unknown basic types. -*/ -{ - switch (GetRawType (T)) { - case T_TYPE_ENUM: return "enum"; - case T_TYPE_BITFIELD: return "bit-field"; - case T_TYPE_FLOAT: return "float"; - case T_TYPE_DOUBLE: return "double"; - case T_TYPE_VOID: return "void"; - case T_TYPE_STRUCT: return "struct"; - case T_TYPE_UNION: return "union"; - case T_TYPE_ARRAY: return "array"; - case T_TYPE_PTR: return "pointer"; - case T_TYPE_FUNC: return "function"; - case T_TYPE_NONE: /* FALLTHROUGH */ - default: break; - } - if (IsClassInt (T)) { - if (IsRawSignSigned (T)) { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "signed char"; - case T_TYPE_SHORT: return "short"; - case T_TYPE_INT: return "int"; - case T_TYPE_LONG: return "long"; - case T_TYPE_LONGLONG: return "long long"; - default: - return "signed integer"; - } - } else if (IsRawSignUnsigned (T)) { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "unsigned char"; - case T_TYPE_SHORT: return "unsigned short"; - case T_TYPE_INT: return "unsigned int"; - case T_TYPE_LONG: return "unsigned long"; - case T_TYPE_LONGLONG: return "unsigned long long"; - default: - return "unsigned integer"; - } - } else { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "char"; - case T_TYPE_SHORT: return "short"; - case T_TYPE_INT: return "int"; - case T_TYPE_LONG: return "long"; - case T_TYPE_LONGLONG: return "long long"; - default: - return "integer"; - } - } - } - return "type"; -} - - - -static const char* GetTagSymName (const Type* T) -/* Return a name string of the type or the symbol name if it is an ESU type. -** Note: This may use a static buffer that could be overwritten by other calls. -*/ -{ - static char TypeName [IDENTSIZE + 16]; - SymEntry* TagSym; - - TagSym = GetESUTagSym (T); - if (TagSym == 0) { - return GetBasicTypeName (T); - } - sprintf (TypeName, "%s %s", GetBasicTypeName (T), - TagSym->Name[0] != '\0' ? TagSym->Name : "<unknown>"); - - return TypeName; -} - - - -static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBuf* East, const Type* T) -/* Return the name string of the given type split into a western part and an -** eastern part. -*/ -{ - struct StrBuf Buf = AUTO_STRBUF_INITIALIZER; - - if (IsTypeArray (T)) { - - long Count = GetElementCount (T); - if (!SB_IsEmpty (East)) { - if (Count > 0) { - SB_Printf (&Buf, "[%ld]", Count); - } else { - SB_Printf (&Buf, "[]"); - } - SB_Append (East, &Buf); - SB_Terminate (East); - - } else { - if (Count > 0) { - SB_Printf (East, "[%ld]", Count); - } else { - SB_Printf (East, "[]"); - } - - if (!SB_IsEmpty (West)) { - /* Add parentheses to West */ - SB_Printf (&Buf, "(%s)", SB_GetConstBuf (West)); - SB_Copy (West, &Buf); - SB_Terminate (West); - } - } - - /* Get element type */ - GetFullTypeNameWestEast (West, East, T + 1); - - } else if (IsTypeFunc (T)) { - - FuncDesc* D = GetFuncDesc (T); - struct StrBuf ParamList = AUTO_STRBUF_INITIALIZER; - - /* First argument */ - SymEntry* Param = D->SymTab->SymHead; - unsigned I; - for (I = 0; I < D->ParamCount; ++I) { - CHECK (Param != 0 && (Param->Flags & SC_PARAM) != 0); - if (I > 0) { - SB_AppendStr (&ParamList, ", "); - } - SB_AppendStr (&ParamList, SB_GetConstBuf (GetFullTypeNameBuf (&Buf, Param->Type))); - SB_Clear (&Buf); - /* Next argument */ - Param = Param->NextSym; - } - if ((D->Flags & FD_VARIADIC) == 0) { - if (D->ParamCount == 0 && (D->Flags & FD_EMPTY) == 0) { - SB_AppendStr (&ParamList, "void"); - } - } else { - if (D->ParamCount > 0) { - SB_AppendStr (&ParamList, ", ..."); - } else { - SB_AppendStr (&ParamList, "..."); - } - } - SB_Terminate (&ParamList); - - /* Join the existing West and East together */ - if (!SB_IsEmpty (East)) { - SB_Append (West, East); - SB_Terminate (West); - SB_Clear (East); - } - - if (SB_IsEmpty (West)) { - /* Just use the param list */ - SB_Printf (West, "(%s)", SB_GetConstBuf (&ParamList)); - } else { - /* Append the param list to the existing West */ - SB_Printf (&Buf, "(%s)(%s)", SB_GetConstBuf (West), SB_GetConstBuf (&ParamList)); - SB_Printf (West, "%s", SB_GetConstBuf (&Buf)); - } - SB_Done (&ParamList); - - /* Return type */ - GetFullTypeNameWestEast (West, East, T + 1); - - } else if (IsTypePtr (T)) { - - int QualCount = 0; - - SB_Printf (&Buf, "*"); - - /* Add qualifiers */ - if ((GetQualifier (T) & ~T_QUAL_NEAR) != T_QUAL_NONE) { - QualCount = GetQualifierTypeCodeNameBuf (&Buf, T->C, T_QUAL_NEAR); - } - - if (!SB_IsEmpty (West)) { - if (QualCount > 0) { - SB_AppendChar (&Buf, ' '); - } - SB_Append (&Buf, West); - } - - SB_Copy (West, &Buf); - SB_Terminate (West); - - /* Get indirection type */ - GetFullTypeNameWestEast (West, East, T + 1); - - } else { - - /* Add qualifiers */ - if ((GetQualifier (T) & ~T_QUAL_NEAR) != 0) { - if (GetQualifierTypeCodeNameBuf (&Buf, T->C, T_QUAL_NEAR) > 0) { - SB_AppendChar (&Buf, ' '); - } - } - - if (!IsTypeBitField (T)) { - SB_AppendStr (&Buf, GetTagSymName (T)); - } else { - SB_AppendStr (&Buf, GetBasicTypeName (T + 1)); - } - - if (!SB_IsEmpty (West)) { - SB_AppendChar (&Buf, ' '); - SB_Append (&Buf, West); - } - - SB_Copy (West, &Buf); - SB_Terminate (West); - } - - SB_Done (&Buf); - return West; -} - - - -const char* GetFullTypeName (const Type* T) -/* Return the full name string of the given type */ -{ - struct StrBuf* Buf = NewDiagnosticStrBuf (); - GetFullTypeNameBuf (Buf, T); - - return SB_GetConstBuf (Buf); -} - - - -struct StrBuf* GetFullTypeNameBuf (struct StrBuf* S, const Type* T) -/* Return the full name string of the given type */ -{ - struct StrBuf East = AUTO_STRBUF_INITIALIZER; - GetFullTypeNameWestEast (S, &East, T); - - /* Join West and East */ - SB_Append (S, &East); - SB_Terminate (S); - SB_Done (&East); - - return S; -} - - - -int GetQualifierTypeCodeNameBuf (struct StrBuf* S, TypeCode Qual, TypeCode IgnoredQual) -/* Return the names of the qualifiers of the type. -** Qualifiers to be ignored can be specified with the IgnoredQual flags. -** Return the count of added qualifier names. -*/ -{ - int Count = 0; - - Qual &= T_MASK_QUAL & ~IgnoredQual; - if (Qual & T_QUAL_CONST) { - if (!SB_IsEmpty (S)) { - SB_AppendChar (S, ' '); - } - SB_AppendStr (S, "const"); - ++Count; - } - if (Qual & T_QUAL_VOLATILE) { - if (Count > 0) { - SB_AppendChar (S, ' '); - } - SB_AppendStr (S, "volatile"); - ++Count; - } - if (Qual & T_QUAL_RESTRICT) { - if (Count > 0) { - SB_AppendChar (S, ' '); - } - SB_AppendStr (S, "restrict"); - ++Count; - } - if (Qual & T_QUAL_NEAR) { - if (Count > 0) { - SB_AppendChar (S, ' '); - } - SB_AppendStr (S, "__near__"); - ++Count; - } - if (Qual & T_QUAL_FAR) { - SB_AppendStr (S, "__far__"); - ++Count; - } - if (Qual & T_QUAL_FASTCALL) { - if (Count > 0) { - SB_AppendChar (S, ' '); - } - SB_AppendStr (S, "__fastcall__"); - ++Count; - } - if (Qual & T_QUAL_CDECL) { - if (Count > 0) { - SB_AppendChar (S, ' '); - } - SB_AppendStr (S, "__cdecl__"); - ++Count; - } - - if (Count > 0) { - SB_Terminate (S); - } - - return Count; -} - - - unsigned TypeLen (const Type* T) /* Return the length of the type string */ { @@ -454,6 +143,12 @@ void TypeFree (Type* T) +/*****************************************************************************/ +/* Type info extraction */ +/*****************************************************************************/ + + + int SignExtendChar (int C) /* Do correct sign extension of a character */ { @@ -466,70 +161,6 @@ int SignExtendChar (int C) -Type* GetCharArrayType (unsigned Len) -/* Return the type for a char array of the given length */ -{ - /* Allocate memory for the type string */ - Type* T = TypeAlloc (3); /* array/char/terminator */ - - /* Fill the type string */ - T[0].C = T_ARRAY; - T[0].A.L = Len; /* Array length is in the L attribute */ - T[1].C = T_CHAR; - T[2].C = T_END; - - /* Return the new type */ - return T; -} - - - -Type* GetImplicitFuncType (void) -/* Return a type string for an inplicitly declared function */ -{ - /* Get a new function descriptor */ - FuncDesc* F = NewFuncDesc (); - - /* Allocate memory for the type string */ - Type* T = TypeAlloc (3); /* func/returns int/terminator */ - - /* Prepare the function descriptor */ - F->Flags = FD_EMPTY; - F->SymTab = &EmptySymTab; - F->TagTab = &EmptySymTab; - - /* Fill the type string */ - T[0].C = T_FUNC | CodeAddrSizeQualifier (); - T[0].A.F = F; - T[1].C = T_INT; - T[2].C = T_END; - - /* Return the new type */ - return T; -} - - - -const Type* GetStructReplacementType (const Type* SType) -/* Get a replacement type for passing a struct/union in the primary register */ -{ - const Type* NewType; - /* If the size is less than or equal to that of a long, we will copy the - ** struct using the primary register, otherwise we will use memcpy. - */ - switch (SizeOf (SType)) { - case 1: NewType = type_uchar; break; - case 2: NewType = type_uint; break; - case 3: /* FALLTHROUGH */ - case 4: NewType = type_ulong; break; - default: NewType = SType; break; - } - - return NewType; -} - - - long GetIntegerTypeMin (const Type* Type) /* Get the smallest possible value of the integer type. ** The type must have a known size. @@ -572,150 +203,8 @@ unsigned long GetIntegerTypeMax (const Type* Type) -static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth) -/* Return the size of the smallest integer type that may have BitWidth bits */ -{ - /* Since all integer types supported in cc65 for bit-fields have sizes that - ** are powers of 2, we can just use this bit-twiddling trick. - */ - unsigned V = (int)(BitWidth - 1U) / (int)CHAR_BITS; - V |= V >> 1; - V |= V >> 2; - V |= V >> 4; - V |= V >> 8; - V |= V >> 16; - - /* Return the result size */ - return V + 1U; -} - - - -const Type* GetUnderlyingType (const Type* Type) -/* Get the underlying type of an enum or other integer class type */ -{ - if (IsISOChar (Type)) { - return IS_Get (&SignedChars) ? type_schar : type_uchar; - } else if (IsTypeEnum (Type)) { - /* This should not happen, but just in case */ - if (Type->A.S == 0) { - Internal ("Enum tag type error in GetUnderlyingTypeCode"); - } - - /* If incomplete enum type is used, just return its raw type */ - if (Type->A.S->V.E.Type != 0) { - return Type->A.S->V.E.Type; - } - } else if (IsTypeBitField (Type)) { - /* We consider the smallest type that can represent all values of the - ** bit-field, instead of the type used in the declaration, the truly - ** underlying of the bit-field. - */ - switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) { - case SIZEOF_CHAR: Type = IsSignSigned (Type) ? type_schar : type_uchar; break; - case SIZEOF_INT: Type = IsSignSigned (Type) ? type_int : type_uint; break; - case SIZEOF_LONG: Type = IsSignSigned (Type) ? type_long : type_ulong; break; - default: Type = IsSignSigned (Type) ? type_int : type_uint; break; - } - } - - return Type; -} - - - -TypeCode GetUnderlyingTypeCode (const Type* Type) -/* Get the type code of the unqualified underlying type of TCode. -** Return UnqualifiedType (TCode) if TCode is not scalar. -*/ -{ - TypeCode Underlying = UnqualifiedType (Type->C); - - if (IsISOChar (Type)) { - - return IS_Get (&SignedChars) ? T_SCHAR : T_UCHAR; - - } else if (IsTypeEnum (Type)) { - TypeCode TCode; - - /* This should not happen, but just in case */ - if (Type->A.S == 0) { - Internal ("Enum tag type error in GetUnderlyingTypeCode"); - } - - /* Inspect the underlying type of the enum */ - if (Type->A.S->V.E.Type == 0) { - /* Incomplete enum type is used */ - return Underlying; - } - TCode = UnqualifiedType (Type->A.S->V.E.Type->C); - - /* Replace the type code with integer */ - Underlying = (TCode & ~T_MASK_TYPE); - switch (TCode & T_MASK_SIZE) { - case T_SIZE_INT: Underlying |= T_TYPE_INT; break; - case T_SIZE_LONG: Underlying |= T_TYPE_LONG; break; - case T_SIZE_SHORT: Underlying |= T_TYPE_SHORT; break; - case T_SIZE_CHAR: Underlying |= T_TYPE_CHAR; break; - case T_SIZE_LONGLONG: Underlying |= T_TYPE_LONGLONG; break; - default: Underlying |= T_TYPE_INT; break; - } - } else if (IsTypeBitField (Type)) { - /* We consider the smallest type that can represent all values of the - ** bit-field, instead of the type used in the declaration, the truly - ** underlying of the bit-field. - */ - switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) { - case SIZEOF_CHAR: Underlying = T_CHAR; break; - case SIZEOF_INT: Underlying = T_INT; break; - case SIZEOF_LONG: Underlying = T_LONG; break; - case SIZEOF_LONGLONG: Underlying = T_LONGLONG; break; - default: Underlying = T_INT; break; - } - Underlying &= ~T_MASK_SIGN; - Underlying |= Type->C & T_MASK_SIGN; - } - - return Underlying; -} - - - -const Type* GetBitFieldChunkType (const Type* Type) -/* Get the type needed to operate on the byte chunk containing the bit-field */ -{ - unsigned ChunkSize; - if ((Type->A.B.Width - 1U) / CHAR_BITS == - (Type->A.B.Offs + Type->A.B.Width - 1U) / CHAR_BITS) { - /* T bit-field fits within its underlying type */ - return GetUnderlyingType (Type); - } - - ChunkSize = GetBitFieldMinimalTypeSize (Type->A.B.Offs + Type->A.B.Width); - if (ChunkSize < SizeOf (Type + 1)) { - /* The end of the bit-field is offset by some bits so that it requires - ** more bytes to be accessed as a whole than its underlying type does. - ** Note: In cc65 the bit offset is always less than CHAR_BITS. - */ - switch (ChunkSize) { - case SIZEOF_CHAR: return IsSignSigned (Type) ? type_schar : type_uchar; - case SIZEOF_INT: return IsSignSigned (Type) ? type_int : type_uint; - case SIZEOF_LONG: return IsSignSigned (Type) ? type_long : type_ulong; - default: return IsSignSigned (Type) ? type_int : type_uint; - } - } - - /* We can always use the declarartion integer type as the chunk type. - ** Note: A bit-field will not occupy bits located in bytes more than that - ** of its declaration type in cc65. So this is OK. - */ - return Type + 1; -} - - - unsigned SizeOf (const Type* T) -/* Compute size of object represented by type array. */ +/* Compute size (in bytes) of object represented by type array */ { switch (GetUnderlyingTypeCode (T)) { @@ -788,7 +277,7 @@ unsigned SizeOf (const Type* T) unsigned PSizeOf (const Type* T) -/* Compute size of pointer object. */ +/* Compute size (in bytes) of pointee object */ { /* We are expecting a pointer expression */ CHECK (IsClassPtr (T)); @@ -800,9 +289,9 @@ unsigned PSizeOf (const Type* T) unsigned CheckedSizeOf (const Type* T) -/* Return the size of a data type. If the size is zero, emit an error and -** return some valid size instead (so the rest of the compiler doesn't have -** to work with invalid sizes). +/* Return the size (in bytes) of a data type. If the size is zero, emit an +** error and return some valid size instead (so the rest of the compiler +** doesn't have to work with invalid sizes). */ { unsigned Size = SizeOf (T); @@ -820,9 +309,9 @@ unsigned CheckedSizeOf (const Type* T) unsigned CheckedPSizeOf (const Type* T) -/* Return the size of a data type that is pointed to by a pointer. If the -** size is zero, emit an error and return some valid size instead (so the -** rest of the compiler doesn't have to work with invalid sizes). +/* Return the size (in bytes) of a data type that is pointed to by a pointer. +** If the size is zero, emit an error and return some valid size instead (so +** the rest of the compiler doesn't have to work with invalid sizes). */ { unsigned Size = PSizeOf (T); @@ -839,6 +328,205 @@ unsigned CheckedPSizeOf (const Type* T) +static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth) +/* Return the size of the smallest integer type that may have BitWidth bits */ +{ + /* Since all integer types supported in cc65 for bit-fields have sizes that + ** are powers of 2, we can just use this bit-twiddling trick. + */ + unsigned V = (int)(BitWidth - 1U) / (int)CHAR_BITS; + V |= V >> 1; + V |= V >> 2; + V |= V >> 4; + V |= V >> 8; + V |= V >> 16; + + /* Return the result size */ + return V + 1U; +} + + + +TypeCode GetUnderlyingTypeCode (const Type* Type) +/* Get the type code of the unqualified underlying type of TCode. +** Return UnqualTypeCode (Type) if Type is not scalar. +*/ +{ + TypeCode Underlying = UnqualifiedType (Type->C); + + if (IsISOChar (Type)) { + + return IS_Get (&SignedChars) ? T_SCHAR : T_UCHAR; + + } else if (IsTypeEnum (Type)) { + TypeCode TCode; + + /* This should not happen, but just in case */ + if (Type->A.S == 0) { + Internal ("Enum tag type error in GetUnderlyingTypeCode"); + } + + /* Inspect the underlying type of the enum */ + if (Type->A.S->V.E.Type == 0) { + /* Incomplete enum type is used */ + return Underlying; + } + TCode = UnqualifiedType (Type->A.S->V.E.Type->C); + + /* Replace the type code with integer */ + Underlying = (TCode & ~T_MASK_TYPE); + switch (TCode & T_MASK_SIZE) { + case T_SIZE_INT: Underlying |= T_TYPE_INT; break; + case T_SIZE_LONG: Underlying |= T_TYPE_LONG; break; + case T_SIZE_SHORT: Underlying |= T_TYPE_SHORT; break; + case T_SIZE_CHAR: Underlying |= T_TYPE_CHAR; break; + case T_SIZE_LONGLONG: Underlying |= T_TYPE_LONGLONG; break; + default: Underlying |= T_TYPE_INT; break; + } + } else if (IsTypeBitField (Type)) { + /* We consider the smallest type that can represent all values of the + ** bit-field, instead of the type used in the declaration, the truly + ** underlying of the bit-field. + */ + switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) { + case SIZEOF_CHAR: Underlying = T_CHAR; break; + case SIZEOF_INT: Underlying = T_INT; break; + case SIZEOF_LONG: Underlying = T_LONG; break; + case SIZEOF_LONGLONG: Underlying = T_LONGLONG; break; + default: Underlying = T_INT; break; + } + Underlying &= ~T_MASK_SIGN; + Underlying |= Type->C & T_MASK_SIGN; + } + + return Underlying; +} + + + +/*****************************************************************************/ +/* Type manipulation */ +/*****************************************************************************/ + + + +Type* GetImplicitFuncType (void) +/* Return a type string for an implicitly declared function */ +{ + /* Get a new function descriptor */ + FuncDesc* F = NewFuncDesc (); + + /* Allocate memory for the type string */ + Type* T = TypeAlloc (3); /* func/returns int/terminator */ + + /* Prepare the function descriptor */ + F->Flags = FD_EMPTY; + F->SymTab = &EmptySymTab; + F->TagTab = &EmptySymTab; + + /* Fill the type string */ + T[0].C = T_FUNC | CodeAddrSizeQualifier (); + T[0].A.F = F; + T[1].C = T_INT; + T[2].C = T_END; + + /* Return the new type */ + return T; +} + + + +Type* GetCharArrayType (unsigned Len) +/* Return the type for a char array of the given length */ +{ + /* Allocate memory for the type string */ + Type* T = TypeAlloc (3); /* array/char/terminator */ + + /* Fill the type string */ + T[0].C = T_ARRAY; + T[0].A.L = Len; /* Array length is in the L attribute */ + T[1].C = T_CHAR; + T[2].C = T_END; + + /* Return the new type */ + return T; +} + + + +Type* NewPointerTo (const Type* T) +/* Return a type string that is "pointer to T". The type string is allocated +** on the heap and may be freed after use. +*/ +{ + /* Get the size of the type string including the terminator */ + unsigned Size = TypeLen (T) + 1; + + /* Allocate the new type string */ + Type* P = TypeAlloc (Size + 1); + + /* Create the return type... */ + P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE); + memcpy (P+1, T, Size * sizeof (Type)); + + /* ...and return it */ + return P; +} + + + +Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth) +/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type +** string is allocated on the heap and may be freed after use. +*/ +{ + Type* P; + + /* The type specifier must be integeral */ + CHECK (IsClassInt (T)); + + /* Allocate the new type string */ + P = TypeAlloc (3); + + /* Create the return type... */ + P[0].C = IsSignSigned (T) ? T_SBITFIELD : T_UBITFIELD; + P[0].C |= (T[0].C & T_QUAL_ADDRSIZE); + P[0].A.B.Offs = BitOffs; + P[0].A.B.Width = BitWidth; + + /* Get the declaration type */ + memcpy (&P[1], GetUnderlyingType (T), sizeof (P[1])); + + /* Get done... */ + P[2].C = T_END; + + /* ...and return it */ + return P; +} + + + +const Type* AddressOf (const Type* T) +/* Return a type string that is "address of T". The type string is allocated +** on the heap and may be freed after use. +*/ +{ + /* Get the size of the type string including the terminator */ + unsigned Size = TypeLen (T) + 1; + + /* Allocate the new type string */ + Type* P = TypeAlloc (Size + 1); + + /* Create the return type... */ + P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE) | T_QUAL_CONST; + memcpy (P+1, T, Size * sizeof (Type)); + + /* ...and return it */ + return P; +} + + + const Type* Indirect (const Type* T) /* Do one indirection for the given type, that is, return the type where the ** given type points to. @@ -867,48 +555,6 @@ Type* IndirectModifiable (Type* T) -Type* NewPointerTo (const Type* T) -/* Return a type string that is "pointer to T". The type string is allocated -** on the heap and may be freed after use. -*/ -{ - /* Get the size of the type string including the terminator */ - unsigned Size = TypeLen (T) + 1; - - /* Allocate the new type string */ - Type* P = TypeAlloc (Size + 1); - - /* Create the return type... */ - P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE); - memcpy (P+1, T, Size * sizeof (Type)); - - /* ...and return it */ - return P; -} - - - -const Type* AddressOf (const Type* T) -/* Return a type string that is "address of T". The type string is allocated -** on the heap and may be freed after use. -*/ -{ - /* Get the size of the type string including the terminator */ - unsigned Size = TypeLen (T) + 1; - - /* Allocate the new type string */ - Type* P = TypeAlloc (Size + 1); - - /* Create the return type... */ - P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE) | T_QUAL_CONST; - memcpy (P+1, T, Size * sizeof (Type)); - - /* ...and return it */ - return P; -} - - - Type* ArrayToPtr (const Type* T) /* Convert an array to a pointer to it's first element */ { @@ -1109,37 +755,98 @@ const Type* UnsignedType (const Type* T) -Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth) -/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type -** string is allocated on the heap and may be freed after use. -*/ +const Type* GetUnderlyingType (const Type* Type) +/* Get the underlying type of an enum or other integer class type */ { - Type* P; + if (IsISOChar (Type)) { + return IS_Get (&SignedChars) ? type_schar : type_uchar; + } else if (IsTypeEnum (Type)) { + /* This should not happen, but just in case */ + if (Type->A.S == 0) { + Internal ("Enum tag type error in GetUnderlyingTypeCode"); + } - /* The type specifier must be integeral */ - CHECK (IsClassInt (T)); + /* If incomplete enum type is used, just return its raw type */ + if (Type->A.S->V.E.Type != 0) { + return Type->A.S->V.E.Type; + } + } else if (IsTypeBitField (Type)) { + /* We consider the smallest type that can represent all values of the + ** bit-field, instead of the type used in the declaration, the truly + ** underlying of the bit-field. + */ + switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) { + case SIZEOF_CHAR: Type = IsSignSigned (Type) ? type_schar : type_uchar; break; + case SIZEOF_INT: Type = IsSignSigned (Type) ? type_int : type_uint; break; + case SIZEOF_LONG: Type = IsSignSigned (Type) ? type_long : type_ulong; break; + default: Type = IsSignSigned (Type) ? type_int : type_uint; break; + } + } - /* Allocate the new type string */ - P = TypeAlloc (3); - - /* Create the return type... */ - P[0].C = IsSignSigned (T) ? T_SBITFIELD : T_UBITFIELD; - P[0].C |= (T[0].C & T_QUAL_ADDRSIZE); - P[0].A.B.Offs = BitOffs; - P[0].A.B.Width = BitWidth; - - /* Get the declaration type */ - memcpy (&P[1], GetUnderlyingType (T), sizeof (P[1])); - - /* Get done... */ - P[2].C = T_END; - - /* ...and return it */ - return P; + return Type; } +const Type* GetStructReplacementType (const Type* SType) +/* Get a replacement type for passing a struct/union in the primary register */ +{ + const Type* NewType; + /* If the size is less than or equal to that of a long, we will copy the + ** struct using the primary register, otherwise we will use memcpy. + */ + switch (SizeOf (SType)) { + case 1: NewType = type_uchar; break; + case 2: NewType = type_uint; break; + case 3: /* FALLTHROUGH */ + case 4: NewType = type_ulong; break; + default: NewType = SType; break; + } + + return NewType; +} + + + +const Type* GetBitFieldChunkType (const Type* Type) +/* Get the type needed to operate on the byte chunk containing the bit-field */ +{ + unsigned ChunkSize; + if ((Type->A.B.Width - 1U) / CHAR_BITS == + (Type->A.B.Offs + Type->A.B.Width - 1U) / CHAR_BITS) { + /* T bit-field fits within its underlying type */ + return GetUnderlyingType (Type); + } + + ChunkSize = GetBitFieldMinimalTypeSize (Type->A.B.Offs + Type->A.B.Width); + if (ChunkSize < SizeOf (Type + 1)) { + /* The end of the bit-field is offset by some bits so that it requires + ** more bytes to be accessed as a whole than its underlying type does. + ** Note: In cc65 the bit offset is always less than CHAR_BITS. + */ + switch (ChunkSize) { + case SIZEOF_CHAR: return IsSignSigned (Type) ? type_schar : type_uchar; + case SIZEOF_INT: return IsSignSigned (Type) ? type_int : type_uint; + case SIZEOF_LONG: return IsSignSigned (Type) ? type_long : type_ulong; + default: return IsSignSigned (Type) ? type_int : type_uint; + } + } + + /* We can always use the declarartion integer type as the chunk type. + ** Note: A bit-field will not occupy bits located in bytes more than that + ** of its declaration type in cc65. So this is OK. + */ + return Type + 1; +} + + + +/*****************************************************************************/ +/* Type Predicates */ +/*****************************************************************************/ + + + int IsTypeFragBitField (const Type* T) /* Return true if this is a bit-field that shares byte space with other fields */ { @@ -1261,6 +968,46 @@ int HasUnknownSize (const Type* T) +int TypeHasAttr (const Type* T) +/* Return true if the given type has attribute data */ +{ + return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T); +} + + + +/*****************************************************************************/ +/* Qualifier helpers */ +/*****************************************************************************/ + + + +TypeCode AddrSizeQualifier (unsigned AddrSize) +/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ +{ + switch (AddrSize) { + + case ADDR_SIZE_ABS: + return T_QUAL_NEAR; + + case ADDR_SIZE_FAR: + return T_QUAL_FAR; + + default: + Error ("Invalid address size"); + return T_QUAL_NEAR; + + } +} + + + +/*****************************************************************************/ +/* Function type helpers */ +/*****************************************************************************/ + + + int IsVariadicFunc (const Type* T) /* Return true if this is a function type or pointer to function type with ** variable parameter list. @@ -1369,6 +1116,12 @@ const FuncDesc* GetFuncDefinitionDesc (const Type* T) +/*****************************************************************************/ +/* Array type helpers */ +/*****************************************************************************/ + + + long GetElementCount (const Type* T) /* Get the element count of the array specified in T (which must be of ** array type). @@ -1414,6 +1167,12 @@ const Type* GetBaseElementType (const Type* T) +/*****************************************************************************/ +/* ESU types helpers */ +/*****************************************************************************/ + + + struct SymEntry* GetESUTagSym (const Type* T) /* Get the tag symbol entry of the enum/struct/union type. ** Return 0 if it is not an enum/struct/union. @@ -1439,30 +1198,319 @@ void SetESUTagSym (Type* T, struct SymEntry* S) -TypeCode AddrSizeQualifier (unsigned AddrSize) -/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ +/*****************************************************************************/ +/* Helpers */ +/*****************************************************************************/ + + + +const char* GetBasicTypeName (const Type* T) +/* Return a const name string of the basic type. +** Return "type" for unknown basic types. +*/ { - switch (AddrSize) { - - case ADDR_SIZE_ABS: - return T_QUAL_NEAR; - - case ADDR_SIZE_FAR: - return T_QUAL_FAR; - - default: - Error ("Invalid address size"); - return T_QUAL_NEAR; - + switch (GetRawType (T)) { + case T_TYPE_ENUM: return "enum"; + case T_TYPE_BITFIELD: return "bit-field"; + case T_TYPE_FLOAT: return "float"; + case T_TYPE_DOUBLE: return "double"; + case T_TYPE_VOID: return "void"; + case T_TYPE_STRUCT: return "struct"; + case T_TYPE_UNION: return "union"; + case T_TYPE_ARRAY: return "array"; + case T_TYPE_PTR: return "pointer"; + case T_TYPE_FUNC: return "function"; + case T_TYPE_NONE: /* FALLTHROUGH */ + default: break; } + if (IsClassInt (T)) { + if (IsRawSignSigned (T)) { + switch (GetRawType (T)) { + case T_TYPE_CHAR: return "signed char"; + case T_TYPE_SHORT: return "short"; + case T_TYPE_INT: return "int"; + case T_TYPE_LONG: return "long"; + case T_TYPE_LONGLONG: return "long long"; + default: + return "signed integer"; + } + } else if (IsRawSignUnsigned (T)) { + switch (GetRawType (T)) { + case T_TYPE_CHAR: return "unsigned char"; + case T_TYPE_SHORT: return "unsigned short"; + case T_TYPE_INT: return "unsigned int"; + case T_TYPE_LONG: return "unsigned long"; + case T_TYPE_LONGLONG: return "unsigned long long"; + default: + return "unsigned integer"; + } + } else { + switch (GetRawType (T)) { + case T_TYPE_CHAR: return "char"; + case T_TYPE_SHORT: return "short"; + case T_TYPE_INT: return "int"; + case T_TYPE_LONG: return "long"; + case T_TYPE_LONGLONG: return "long long"; + default: + return "integer"; + } + } + } + return "type"; } -int TypeHasAttr (const Type* T) -/* Return true if the given type has attribute data */ +static const char* GetTagSymName (const Type* T) +/* Return a name string of the type or the symbol name if it is an ESU type. +** Note: This may use a static buffer that could be overwritten by other calls. +*/ { - return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T); + static char TypeName [IDENTSIZE + 16]; + SymEntry* Sym; + + Sym = GetESUTagSym (T); + if (Sym == 0) { + return GetBasicTypeName (T); + } + sprintf (TypeName, "%s %s", GetBasicTypeName (T), + Sym->Name[0] != '\0' ? Sym->Name : "<unknown>"); + + return TypeName; +} + + + +const char* GetFullTypeName (const Type* T) +/* Return the full name string of the given type */ +{ + struct StrBuf* Buf = NewDiagnosticStrBuf (); + GetFullTypeNameBuf (Buf, T); + + return SB_GetConstBuf (Buf); +} + + + +static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBuf* East, const Type* T) +/* Return the name string of the given type split into a western part and an +** eastern part. +*/ +{ + struct StrBuf Buf = AUTO_STRBUF_INITIALIZER; + + if (IsTypeArray (T)) { + + long Count = GetElementCount (T); + if (!SB_IsEmpty (East)) { + if (Count > 0) { + SB_Printf (&Buf, "[%ld]", Count); + } else { + SB_Printf (&Buf, "[]"); + } + SB_Append (East, &Buf); + SB_Terminate (East); + + } else { + if (Count > 0) { + SB_Printf (East, "[%ld]", Count); + } else { + SB_Printf (East, "[]"); + } + + if (!SB_IsEmpty (West)) { + /* Add parentheses to West */ + SB_Printf (&Buf, "(%s)", SB_GetConstBuf (West)); + SB_Copy (West, &Buf); + SB_Terminate (West); + } + } + + /* Get element type */ + GetFullTypeNameWestEast (West, East, T + 1); + + } else if (IsTypeFunc (T)) { + + FuncDesc* D = GetFuncDesc (T); + struct StrBuf ParamList = AUTO_STRBUF_INITIALIZER; + + /* First argument */ + SymEntry* Param = D->SymTab->SymHead; + unsigned I; + for (I = 0; I < D->ParamCount; ++I) { + CHECK (Param != 0 && (Param->Flags & SC_PARAM) != 0); + if (I > 0) { + SB_AppendStr (&ParamList, ", "); + } + SB_AppendStr (&ParamList, SB_GetConstBuf (GetFullTypeNameBuf (&Buf, Param->Type))); + SB_Clear (&Buf); + /* Next argument */ + Param = Param->NextSym; + } + if ((D->Flags & FD_VARIADIC) == 0) { + if (D->ParamCount == 0 && (D->Flags & FD_EMPTY) == 0) { + SB_AppendStr (&ParamList, "void"); + } + } else { + if (D->ParamCount > 0) { + SB_AppendStr (&ParamList, ", ..."); + } else { + SB_AppendStr (&ParamList, "..."); + } + } + SB_Terminate (&ParamList); + + /* Join the existing West and East together */ + if (!SB_IsEmpty (East)) { + SB_Append (West, East); + SB_Terminate (West); + SB_Clear (East); + } + + if (SB_IsEmpty (West)) { + /* Just use the param list */ + SB_Printf (West, "(%s)", SB_GetConstBuf (&ParamList)); + } else { + /* Append the param list to the existing West */ + SB_Printf (&Buf, "(%s)(%s)", SB_GetConstBuf (West), SB_GetConstBuf (&ParamList)); + SB_Printf (West, "%s", SB_GetConstBuf (&Buf)); + } + SB_Done (&ParamList); + + /* Return type */ + GetFullTypeNameWestEast (West, East, T + 1); + + } else if (IsTypePtr (T)) { + + int QualCount = 0; + + SB_Printf (&Buf, "*"); + + /* Add qualifiers */ + if ((GetQualifier (T) & ~T_QUAL_NEAR) != T_QUAL_NONE) { + QualCount = GetQualifierTypeCodeNameBuf (&Buf, T->C, T_QUAL_NEAR); + } + + if (!SB_IsEmpty (West)) { + if (QualCount > 0) { + SB_AppendChar (&Buf, ' '); + } + SB_Append (&Buf, West); + } + + SB_Copy (West, &Buf); + SB_Terminate (West); + + /* Get indirection type */ + GetFullTypeNameWestEast (West, East, T + 1); + + } else { + + /* Add qualifiers */ + if ((GetQualifier (T) & ~T_QUAL_NEAR) != 0) { + if (GetQualifierTypeCodeNameBuf (&Buf, T->C, T_QUAL_NEAR) > 0) { + SB_AppendChar (&Buf, ' '); + } + } + + if (!IsTypeBitField (T)) { + SB_AppendStr (&Buf, GetTagSymName (T)); + } else { + SB_AppendStr (&Buf, GetBasicTypeName (T + 1)); + } + + if (!SB_IsEmpty (West)) { + SB_AppendChar (&Buf, ' '); + SB_Append (&Buf, West); + } + + SB_Copy (West, &Buf); + SB_Terminate (West); + } + + SB_Done (&Buf); + return West; +} + + + +struct StrBuf* GetFullTypeNameBuf (struct StrBuf* S, const Type* T) +/* Return the full name string of the given type */ +{ + struct StrBuf East = AUTO_STRBUF_INITIALIZER; + GetFullTypeNameWestEast (S, &East, T); + + /* Join West and East */ + SB_Append (S, &East); + SB_Terminate (S); + SB_Done (&East); + + return S; +} + + + +int GetQualifierTypeCodeNameBuf (struct StrBuf* S, TypeCode Qual, TypeCode IgnoredQual) +/* Return the names of the qualifiers of the type. +** Qualifiers to be ignored can be specified with the IgnoredQual flags. +** Return the count of added qualifier names. +*/ +{ + int Count = 0; + + Qual &= T_MASK_QUAL & ~IgnoredQual; + if (Qual & T_QUAL_CONST) { + if (!SB_IsEmpty (S)) { + SB_AppendChar (S, ' '); + } + SB_AppendStr (S, "const"); + ++Count; + } + if (Qual & T_QUAL_VOLATILE) { + if (Count > 0) { + SB_AppendChar (S, ' '); + } + SB_AppendStr (S, "volatile"); + ++Count; + } + if (Qual & T_QUAL_RESTRICT) { + if (Count > 0) { + SB_AppendChar (S, ' '); + } + SB_AppendStr (S, "restrict"); + ++Count; + } + if (Qual & T_QUAL_NEAR) { + if (Count > 0) { + SB_AppendChar (S, ' '); + } + SB_AppendStr (S, "__near__"); + ++Count; + } + if (Qual & T_QUAL_FAR) { + SB_AppendStr (S, "__far__"); + ++Count; + } + if (Qual & T_QUAL_FASTCALL) { + if (Count > 0) { + SB_AppendChar (S, ' '); + } + SB_AppendStr (S, "__fastcall__"); + ++Count; + } + if (Qual & T_QUAL_CDECL) { + if (Count > 0) { + SB_AppendChar (S, ' '); + } + SB_AppendStr (S, "__cdecl__"); + ++Count; + } + + if (Count > 0) { + SB_Terminate (S); + } + + return Count; } diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index be5b4a31c..5e4e2e39b 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -239,23 +239,6 @@ extern const Type type_c_void_p[]; -const char* GetBasicTypeName (const Type* T); -/* Return a const name string of the basic type. -** Return "type" for unknown basic types. -*/ - -const char* GetFullTypeName (const Type* T); -/* Return the full name string of the given type */ - -struct StrBuf* GetFullTypeNameBuf (struct StrBuf* S, const Type* T); -/* Return the full name string of the given type */ - -int GetQualifierTypeCodeNameBuf (struct StrBuf* S, TypeCode Qual, TypeCode IgnoredQual); -/* Return the names of the qualifiers of the type. -** Qualifiers to be ignored can be specified with the IgnoredQual flags. -** Return the count of added qualifier names. -*/ - unsigned TypeLen (const Type* T); /* Return the length of the type string */ @@ -273,17 +256,26 @@ Type* TypeAlloc (unsigned Len); void TypeFree (Type* T); /* Free a type string */ +#if defined(HAVE_INLINE) +INLINE void CopyTypeAttr (const Type* Src, Type* Dest) +/* Copy attribute data from Src to Dest */ +{ + Dest->A = Src->A; +} +#else +# define CopyTypeAttr(Src, Dest) ((Dest)->A = (Src)->A) +#endif + + + +/*****************************************************************************/ +/* Type info extraction */ +/*****************************************************************************/ + + + int SignExtendChar (int C); -/* Do correct sign extension of a character */ - -Type* GetCharArrayType (unsigned Len); -/* Return the type for a char array of the given length */ - -Type* GetImplicitFuncType (void); -/* Return a type string for an inplicitly declared function */ - -const Type* GetStructReplacementType (const Type* SType); -/* Get a replacement type for passing a struct/union in the primary register */ +/* Do correct sign extension of a character to an int */ long GetIntegerTypeMin (const Type* Type); /* Get the smallest possible value of the integer type. @@ -295,9 +287,42 @@ unsigned long GetIntegerTypeMax (const Type* Type); ** The type must have a known size. */ +unsigned SizeOf (const Type* T); +/* Compute size (in bytes) of object represented by type array */ + +unsigned PSizeOf (const Type* T); +/* Compute size (in bytes) of pointee object */ + +unsigned CheckedSizeOf (const Type* T); +/* Return the size (in bytes) of a data type. If the size is zero, emit an +** error and return some valid size instead (so the rest of the compiler +** doesn't have to work with invalid sizes). +*/ + +unsigned CheckedPSizeOf (const Type* T); +/* Return the size (in bytes) of a data type that is pointed to by a pointer. +** If the size is zero, emit an error and return some valid size instead (so +** the rest of the compiler doesn't have to work with invalid sizes). +*/ + +#if defined(HAVE_INLINE) +INLINE TypeCode GetQualifier (const Type* T) +/* Get the qualifier from the given type string */ +{ + return (T->C & T_MASK_QUAL); +} +#else +# define GetQualifier(T) ((T)->C & T_MASK_QUAL) +#endif + +TypeCode GetUnderlyingTypeCode (const Type* Type); +/* Get the type code of the unqualified underlying type of TCode. +** Return TCode if it is not scalar. +*/ + #if defined(HAVE_INLINE) INLINE TypeCode UnqualifiedType (TypeCode T) -/* Return the unqalified type code */ +/* Return the unqualified type code */ { return (T & ~T_MASK_QUAL); } @@ -305,32 +330,93 @@ INLINE TypeCode UnqualifiedType (TypeCode T) # define UnqualifiedType(T) ((T) & ~T_MASK_QUAL) #endif -const Type* GetUnderlyingType (const Type* Type); -/* Get the underlying type of an enum or other integer class type */ +#if defined(HAVE_INLINE) +INLINE TypeCode GetClass (const Type* T) +/* Get the class of a type string */ +{ + return (T->C & T_MASK_CLASS); +} +#else +# define GetClass(T) ((T)->C & T_MASK_CLASS) +#endif -TypeCode GetUnderlyingTypeCode (const Type* Type); -/* Get the type code of the unqualified underlying type of TCode. -** Return TCode if it is not scalar. +#if defined(HAVE_INLINE) +INLINE TypeCode GetSignedness (const Type* T) +/* Get the signedness of a type */ +{ + return (GetUnderlyingTypeCode (T) & T_MASK_SIGN); +} +#else +# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN) +#endif + +#if defined(HAVE_INLINE) +INLINE TypeCode GetSizeModifier (const Type* T) +/* Get the size modifier of a type */ +{ + return (GetUnderlyingTypeCode (T) & T_MASK_SIZE); +} +#else +# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE) +#endif + +#if defined(HAVE_INLINE) +INLINE TypeCode GetRawType (const Type* T) +/* Get the raw type */ +{ + return (T->C & T_MASK_TYPE); +} +#else +# define GetRawType(T) ((T)->C & T_MASK_TYPE) +#endif + +#if defined(HAVE_INLINE) +INLINE TypeCode GetRawSignedness (const Type* T) +/* Get the raw signedness of a type */ +{ + return ((T)->C & T_MASK_SIGN); +} +#else +# define GetRawSignedness(T) ((T)->C & T_MASK_SIGN) +#endif + +#if defined(HAVE_INLINE) +INLINE TypeCode GetRawSizeModifier (const Type* T) +/* Get the size modifier of a raw type */ +{ + return (T->C & T_MASK_SIZE); +} +#else +# define GetRawSizeModifier(T) ((T)->C & T_MASK_SIZE) +#endif + + + +/*****************************************************************************/ +/* Type manipulation */ +/*****************************************************************************/ + + + +Type* GetImplicitFuncType (void); +/* Return a type string for an implicitly declared function */ + +Type* GetCharArrayType (unsigned Len); +/* Return the type for a char array of the given length */ + +Type* NewPointerTo (const Type* T); +/* Return a type string that is "pointer to T". The type string is allocated +** on the heap and may be freed after use. */ -const Type* GetBitFieldChunkType (const Type* Type); -/* Get the type needed to operate on the byte chunk containing the bit-field */ - -unsigned SizeOf (const Type* T); -/* Compute size of object represented by type array. */ - -unsigned PSizeOf (const Type* T); -/* Compute size of pointer object. */ - -unsigned CheckedSizeOf (const Type* T); -/* Return the size of a data type. If the size is zero, emit an error and -** return some valid size instead (so the rest of the compiler doesn't have -** to work with invalid sizes). +Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth); +/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type +** string is allocated on the heap and may be freed after use. */ -unsigned CheckedPSizeOf (const Type* T); -/* Return the size of a data type that is pointed to by a pointer. If the -** size is zero, emit an error and return some valid size instead (so the -** rest of the compiler doesn't have to work with invalid sizes). + +const Type* AddressOf (const Type* T); +/* Return a type string that is "address of T". The type string is allocated +** on the heap and may be freed after use. */ const Type* Indirect (const Type* T); @@ -343,16 +429,6 @@ Type* IndirectModifiable (Type* T); ** given type points to. */ -Type* NewPointerTo (const Type* T); -/* Return a type string that is "pointer to T". The type string is allocated -** on the heap and may be freed after use. -*/ - -const Type* AddressOf (const Type* T); -/* Return a type string that is "address of T". The type string is allocated -** on the heap and may be freed after use. -*/ - Type* ArrayToPtr (const Type* T); /* Convert an array to a pointer to it's first element */ @@ -382,20 +458,22 @@ const Type* SignedType (const Type* T); const Type* UnsignedType (const Type* T); /* Get unsigned counterpart of the integral type */ -Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth); -/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type -** string is allocated on the heap and may be freed after use. -*/ +const Type* GetUnderlyingType (const Type* Type); +/* Get the underlying type of an enum or other integer class type */ + +const Type* GetStructReplacementType (const Type* SType); +/* Get a replacement type for passing a struct/union in the primary register */ + +const Type* GetBitFieldChunkType (const Type* Type); +/* Get the type needed to operate on the byte chunk containing the bit-field */ + + + +/*****************************************************************************/ +/* Type Predicates */ +/*****************************************************************************/ + -#if defined(HAVE_INLINE) -INLINE TypeCode GetRawType (const Type* T) -/* Get the raw type */ -{ - return (T->C & T_MASK_TYPE); -} -#else -# define GetRawType(T) ((T)->C & T_MASK_TYPE) -#endif #if defined(HAVE_INLINE) INLINE int IsTypeChar (const Type* T) @@ -414,7 +492,7 @@ INLINE int IsTypeShort (const Type* T) return (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT); } #else -# define IsTypeShort(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT) +# define IsTypeShort(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT) #endif #if defined(HAVE_INLINE) @@ -579,7 +657,7 @@ INLINE int IsTypeUnion (const Type* T) return (GetRawType (T) == T_TYPE_UNION); } #else -# define IsTypeUnion(T) (GetRawType (T) == T_TYPE_UNION) +# define IsTypeUnion(T) (GetRawType (T) == T_TYPE_UNION) #endif #if defined(HAVE_INLINE) @@ -622,16 +700,6 @@ INLINE int IsTypeFuncPtr (const Type* T) # define IsTypeFuncPtr(T) (IsTypePtr (T) && IsTypeFunc (T+1)) #endif -#if defined(HAVE_INLINE) -INLINE TypeCode GetClass (const Type* T) -/* Get the class of a type string */ -{ - return (T->C & T_MASK_CLASS); -} -#else -# define GetClass(T) ((T)->C & T_MASK_CLASS) -#endif - #if defined(HAVE_INLINE) INLINE int IsClassInt (const Type* T) /* Return true if this is an integer type */ @@ -721,25 +789,8 @@ int IsEmptiableObjectType (const Type* T); int HasUnknownSize (const Type* T); /* Return true if this is an incomplete ESU type or an array of unknown size */ -#if defined(HAVE_INLINE) -INLINE TypeCode GetRawSignedness (const Type* T) -/* Get the raw signedness of a type */ -{ - return ((T)->C & T_MASK_SIGN); -} -#else -# define GetRawSignedness(T) ((T)->C & T_MASK_SIGN) -#endif - -#if defined(HAVE_INLINE) -INLINE TypeCode GetSignedness (const Type* T) -/* Get the signedness of a type */ -{ - return (GetUnderlyingTypeCode (T) & T_MASK_SIGN); -} -#else -# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN) -#endif +int TypeHasAttr (const Type* T); +/* Return true if the given type has attribute data */ #if defined(HAVE_INLINE) INLINE int IsRawSignUnsigned (const Type* T) @@ -781,35 +832,13 @@ INLINE int IsSignSigned (const Type* T) # define IsSignSigned(T) (GetSignedness (T) == T_SIGN_SIGNED) #endif -#if defined(HAVE_INLINE) -INLINE TypeCode GetRawSizeModifier (const Type* T) -/* Get the size modifier of a raw type */ -{ - return (T->C & T_MASK_SIZE); -} -#else -# define GetRawSizeModifier(T) ((T)->C & T_MASK_SIZE) -#endif -#if defined(HAVE_INLINE) -INLINE TypeCode GetSizeModifier (const Type* T) -/* Get the size modifier of a type */ -{ - return (GetUnderlyingTypeCode (T) & T_MASK_SIZE); -} -#else -# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE) -#endif -#if defined(HAVE_INLINE) -INLINE TypeCode GetQualifier (const Type* T) -/* Get the qualifier from the given type string */ -{ - return (T->C & T_MASK_QUAL); -} -#else -# define GetQualifier(T) ((T)->C & T_MASK_QUAL) -#endif +/*****************************************************************************/ +/* Qualifier helpers */ +/*****************************************************************************/ + + #if defined(HAVE_INLINE) INLINE int IsQualConst (const Type* T) @@ -891,6 +920,37 @@ INLINE int IsQualCConv (const Type* T) # define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0) #endif +TypeCode AddrSizeQualifier (unsigned AddrSize); +/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ + +#if defined(HAVE_INLINE) +INLINE TypeCode CodeAddrSizeQualifier (void) +/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */ +{ + return AddrSizeQualifier (CodeAddrSize); +} +#else +# define CodeAddrSizeQualifier() (AddrSizeQualifier (CodeAddrSize)) +#endif + +#if defined(HAVE_INLINE) +INLINE TypeCode DataAddrSizeQualifier (void) +/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */ +{ + return AddrSizeQualifier (DataAddrSize); +} +#else +# define DataAddrSizeQualifier() (AddrSizeQualifier (DataAddrSize)) +#endif + + + +/*****************************************************************************/ +/* Function type helpers */ +/*****************************************************************************/ + + + int IsVariadicFunc (const Type* T) attribute ((const)); /* Return true if this is a function type or pointer to function type with ** variable parameter list. @@ -918,6 +978,14 @@ Type* GetFuncReturnModifiable (Type* T) attribute ((const)); const FuncDesc* GetFuncDefinitionDesc (const Type* T) attribute ((const)); /* Get the function descriptor of the function definition */ + + +/*****************************************************************************/ +/* Array type helpers */ +/*****************************************************************************/ + + + long GetElementCount (const Type* T); /* Get the element count of the array specified in T (which must be of ** array type). @@ -937,6 +1005,14 @@ const Type* GetBaseElementType (const Type* T); ** the element type that is not an array. */ + + +/*****************************************************************************/ +/* ESU types helpers */ +/*****************************************************************************/ + + + struct SymEntry* GetESUTagSym (const Type* T) attribute ((const)); /* Get the tag symbol entry of the enum/struct/union type. ** Return 0 if it is not an enum/struct/union. @@ -945,41 +1021,30 @@ struct SymEntry* GetESUTagSym (const Type* T) attribute ((const)); void SetESUTagSym (Type* T, struct SymEntry* S); /* Set the tag symbol entry of the enum/struct/union type */ -TypeCode AddrSizeQualifier (unsigned AddrSize); -/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ -#if defined(HAVE_INLINE) -INLINE TypeCode CodeAddrSizeQualifier (void) -/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */ -{ - return AddrSizeQualifier (CodeAddrSize); -} -#else -# define CodeAddrSizeQualifier() (AddrSizeQualifier (CodeAddrSize)) -#endif -#if defined(HAVE_INLINE) -INLINE TypeCode DataAddrSizeQualifier (void) -/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */ -{ - return AddrSizeQualifier (DataAddrSize); -} -#else -# define DataAddrSizeQualifier() (AddrSizeQualifier (DataAddrSize)) -#endif +/*****************************************************************************/ +/* Helpers */ +/*****************************************************************************/ -int TypeHasAttr (const Type* T); -/* Return true if the given type has attribute data */ -#if defined(HAVE_INLINE) -INLINE void CopyTypeAttr (const Type* Src, Type* Dest) -/* Copy attribute data from Src to Dest */ -{ - Dest->A = Src->A; -} -#else -# define CopyTypeAttr(Src, Dest) ((Dest)->A = (Src)->A) -#endif + +const char* GetBasicTypeName (const Type* T); +/* Return a const name string of the basic type. +** Return "type" for unknown basic types. +*/ + +const char* GetFullTypeName (const Type* T); +/* Return the full name string of the given type */ + +struct StrBuf* GetFullTypeNameBuf (struct StrBuf* S, const Type* T); +/* Return the full name string of the given type */ + +int GetQualifierTypeCodeNameBuf (struct StrBuf* S, TypeCode Qual, TypeCode IgnoredQual); +/* Return the names of the qualifiers of the type. +** Qualifiers to be ignored can be specified with the IgnoredQual flags. +** Return the count of added qualifier names. +*/ void PrintType (FILE* F, const Type* T); /* Print fulle name of the type */ From a4a1230c62d8920950b3c2ab0f751a47cd1f0840 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 12 Oct 2022 13:10:17 +0800 Subject: [PATCH 060/360] Renamed some C type facility and fixed a few comments. Added some new C type code facility. Removed some unused type predicates. --- src/cc65/assignment.c | 2 +- src/cc65/codeseg.c | 2 +- src/cc65/datatype.c | 231 +++++++++++++++--------------- src/cc65/datatype.h | 324 ++++++++++++++++++++---------------------- src/cc65/declare.c | 16 +-- src/cc65/expr.c | 12 +- src/cc65/function.c | 4 +- src/cc65/initdata.c | 8 +- src/cc65/stdfunc.c | 12 +- src/cc65/swstmt.c | 2 +- src/cc65/symtab.c | 4 +- src/cc65/typecmp.c | 63 ++++---- src/cc65/typeconv.c | 2 +- 13 files changed, 330 insertions(+), 352 deletions(-) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index 54ab28d4e..30e2f0fca 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -607,7 +607,7 @@ void OpAssign (const GenDesc* Gen, ExprDesc* Expr, const char* Op) Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR; /* Only "=" accept struct/union */ - if (IsClassStruct (ltype) ? Gen != 0 : !IsClassScalar (ltype)) { + if (IsClassStruct (ltype) ? Gen != 0 : !IsScalarType (ltype)) { Error ("Invalid left operand for binary operator '%s'", Op); /* Continue. Wrong code will be generated, but the compiler won't ** break, so this is the best error recovery. diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index e621147ab..9f1bf4cc5 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -521,7 +521,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) /* If we have a function given, get the return type of the function. ** Assume ANY return type besides void will use the A and X registers. */ - if (S->Func && !IsTypeVoid ((RetType = GetFuncReturn (Func->Type)))) { + if (S->Func && !IsTypeVoid ((RetType = GetFuncReturnType (Func->Type)))) { if (SizeOf (RetType) == SizeOf (type_long)) { S->ExitRegs = REG_EAX; } else { diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 023aefaf7..6907ee099 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -150,7 +150,7 @@ void TypeFree (Type* T) int SignExtendChar (int C) -/* Do correct sign extension of a character */ +/* Do correct sign extension of a character to an int */ { if (IS_Get (&SignedChars) && (C & 0x80) != 0) { return C | ~0xFF; @@ -214,7 +214,7 @@ unsigned BitSizeOf (const Type* T) unsigned SizeOf (const Type* T) /* Compute size (in bytes) of object represented by type array */ { - switch (GetUnderlyingTypeCode (T)) { + switch (GetUnqualTypeCode (T)) { case T_VOID: /* A void variable is a cc65 extension. @@ -347,7 +347,7 @@ unsigned CheckedPSizeOf (const Type* T) -static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth) +static unsigned GetMinimalTypeSizeByBitWidth (unsigned BitWidth) /* Return the size of the smallest integer type that may have BitWidth bits */ { /* Since all integer types supported in cc65 for bit-fields have sizes that @@ -366,14 +366,14 @@ static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth) -TypeCode GetUnderlyingTypeCode (const Type* Type) -/* Get the type code of the unqualified underlying type of TCode. -** Return UnqualTypeCode (Type) if Type is not scalar. +TypeCode GetUnqualTypeCode (const Type* Type) +/* Get the type code of the unqualified underlying type of Type. +** Return GetUnqualRawTypeCode (Type) if Type is not scalar. */ { - TypeCode Underlying = UnqualifiedType (Type->C); + TypeCode Underlying = GetUnqualRawTypeCode (Type); - if (IsISOChar (Type)) { + if (IsDeclTypeChar (Type)) { return IS_Get (&SignedChars) ? T_SCHAR : T_UCHAR; @@ -382,7 +382,7 @@ TypeCode GetUnderlyingTypeCode (const Type* Type) /* This should not happen, but just in case */ if (Type->A.S == 0) { - Internal ("Enum tag type error in GetUnderlyingTypeCode"); + Internal ("Enum tag type error in GetUnqualTypeCode"); } /* Inspect the underlying type of the enum */ @@ -390,24 +390,24 @@ TypeCode GetUnderlyingTypeCode (const Type* Type) /* Incomplete enum type is used */ return Underlying; } - TCode = UnqualifiedType (Type->A.S->V.E.Type->C); + TCode = GetUnqualRawTypeCode (Type->A.S->V.E.Type); /* Replace the type code with integer */ - Underlying = (TCode & ~T_MASK_TYPE); + Underlying = (TCode & ~T_MASK_RANK); switch (TCode & T_MASK_SIZE) { - case T_SIZE_INT: Underlying |= T_TYPE_INT; break; - case T_SIZE_LONG: Underlying |= T_TYPE_LONG; break; - case T_SIZE_SHORT: Underlying |= T_TYPE_SHORT; break; - case T_SIZE_CHAR: Underlying |= T_TYPE_CHAR; break; - case T_SIZE_LONGLONG: Underlying |= T_TYPE_LONGLONG; break; - default: Underlying |= T_TYPE_INT; break; + case T_SIZE_INT: Underlying |= T_RANK_INT; break; + case T_SIZE_LONG: Underlying |= T_RANK_LONG; break; + case T_SIZE_SHORT: Underlying |= T_RANK_SHORT; break; + case T_SIZE_CHAR: Underlying |= T_RANK_CHAR; break; + case T_SIZE_LONGLONG: Underlying |= T_RANK_LONGLONG; break; + default: Underlying |= T_RANK_INT; break; } } else if (IsTypeBitField (Type)) { /* We consider the smallest type that can represent all values of the ** bit-field, instead of the type used in the declaration, the truly ** underlying of the bit-field. */ - switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) { + switch (GetMinimalTypeSizeByBitWidth (Type->A.B.Width)) { case SIZEOF_CHAR: Underlying = T_CHAR; break; case SIZEOF_INT: Underlying = T_INT; break; case SIZEOF_LONG: Underlying = T_LONG; break; @@ -494,7 +494,7 @@ Type* NewPointerTo (const Type* T) -Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth) +Type* NewBitFieldOf (const Type* T, unsigned BitOffs, unsigned BitWidth) /* Return a type string that is "T : BitWidth" aligned on BitOffs. The type ** string is allocated on the heap and may be freed after use. */ @@ -560,20 +560,6 @@ const Type* Indirect (const Type* T) -Type* IndirectModifiable (Type* T) -/* Do one indirection for the given type, that is, return the type where the -** given type points to. -*/ -{ - /* We are expecting a pointer expression */ - CHECK (IsClassPtr (T)); - - /* Skip the pointer or array token itself */ - return T + 1; -} - - - Type* ArrayToPtr (const Type* T) /* Convert an array to a pointer to it's first element */ { @@ -648,12 +634,12 @@ const Type* IntPromotion (const Type* T) return IsSignUnsigned (T) ? type_ulong : type_long; } return T->A.B.Width == INT_BITS && IsSignUnsigned (T) ? type_uint : type_int; - } else if (IsTypeChar (T)) { + } else if (IsRankChar (T)) { /* An integer can represent all values from either signed or unsigned char, so convert ** chars to int. */ return type_int; - } else if (IsTypeShort (T)) { + } else if (IsRankShort (T)) { /* An integer cannot represent all values from unsigned short, so convert unsigned short ** to unsigned int. */ @@ -690,8 +676,8 @@ const Type* ArithmeticConvert (const Type* lhst, const Type* rhst) /* If either operand has type unsigned long int, the other operand is converted to ** unsigned long int. */ - if ((IsTypeLong (lhst) && IsSignUnsigned (lhst)) || - (IsTypeLong (rhst) && IsSignUnsigned (rhst))) { + if ((IsRankLong (lhst) && IsSignUnsigned (lhst)) || + (IsRankLong (rhst) && IsSignUnsigned (rhst))) { return type_ulong; } @@ -700,74 +686,74 @@ const Type* ArithmeticConvert (const Type* lhst, const Type* rhst) ** is converted to long int ; if a long int cannot represent all the values of an unsigned int, ** both operands are converted to unsigned long int. */ - if ((IsTypeLong (lhst) && IsTypeInt (rhst) && IsSignUnsigned (rhst)) || - (IsTypeLong (rhst) && IsTypeInt (lhst) && IsSignUnsigned (lhst))) { + if ((IsRankLong (lhst) && IsRankInt (rhst) && IsSignUnsigned (rhst)) || + (IsRankLong (rhst) && IsRankInt (lhst) && IsSignUnsigned (lhst))) { /* long can represent all unsigneds, so we are in the first sub-case. */ return type_long; } /* Otherwise, if either operand has type long int, the other operand is converted to long int. */ - if (IsTypeLong (lhst) || IsTypeLong (rhst)) { + if (IsRankLong (lhst) || IsRankLong (rhst)) { return type_long; } /* Otherwise, if either operand has type unsigned int, the other operand is converted to ** unsigned int. */ - if ((IsTypeInt (lhst) && IsSignUnsigned (lhst)) || - (IsTypeInt (rhst) && IsSignUnsigned (rhst))) { + if ((IsRankInt (lhst) && IsSignUnsigned (lhst)) || + (IsRankInt (rhst) && IsSignUnsigned (rhst))) { return type_uint; } /* Otherwise, both operands have type int. */ - CHECK (IsTypeInt (lhst)); + CHECK (IsRankInt (lhst)); CHECK (IsSignSigned (lhst)); - CHECK (IsTypeInt (rhst)); + CHECK (IsRankInt (rhst)); CHECK (IsSignSigned (rhst)); return type_int; } -const Type* SignedType (const Type* T) +const Type* GetSignedType (const Type* T) /* Get signed counterpart of the integral type */ { - switch (GetUnderlyingTypeCode (T) & T_MASK_TYPE) { - case T_TYPE_CHAR: + switch (GetUnqualTypeCode (T) & T_MASK_RANK) { + case T_RANK_CHAR: return type_schar; - case T_TYPE_INT: - case T_TYPE_SHORT: + case T_RANK_INT: + case T_RANK_SHORT: return type_int; - case T_TYPE_LONG: + case T_RANK_LONG: return type_long; default: - Internal ("Unknown type code: %lX", GetUnderlyingTypeCode (T)); + Internal ("Unknown type code: %lX", GetUnqualTypeCode (T)); return T; } } -const Type* UnsignedType (const Type* T) +const Type* GetUnsignedType (const Type* T) /* Get unsigned counterpart of the integral type */ { - switch (GetUnderlyingTypeCode (T) & T_MASK_TYPE) { - case T_TYPE_CHAR: + switch (GetUnqualTypeCode (T) & T_MASK_RANK) { + case T_RANK_CHAR: return type_uchar; - case T_TYPE_INT: - case T_TYPE_SHORT: + case T_RANK_INT: + case T_RANK_SHORT: return type_uint; - case T_TYPE_LONG: + case T_RANK_LONG: return type_ulong; default: - Internal ("Unknown type code: %lX", GetUnderlyingTypeCode (T)); + Internal ("Unknown type code: %lX", GetUnqualTypeCode (T)); return T; } } @@ -777,12 +763,12 @@ const Type* UnsignedType (const Type* T) const Type* GetUnderlyingType (const Type* Type) /* Get the underlying type of an enum or other integer class type */ { - if (IsISOChar (Type)) { + if (IsDeclTypeChar (Type)) { return IS_Get (&SignedChars) ? type_schar : type_uchar; } else if (IsTypeEnum (Type)) { /* This should not happen, but just in case */ if (Type->A.S == 0) { - Internal ("Enum tag type error in GetUnderlyingTypeCode"); + Internal ("Enum tag type error in GetUnderlyingType"); } /* If incomplete enum type is used, just return its raw type */ @@ -794,7 +780,7 @@ const Type* GetUnderlyingType (const Type* Type) ** bit-field, instead of the type used in the declaration, the truly ** underlying of the bit-field. */ - switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) { + switch (GetMinimalTypeSizeByBitWidth (Type->A.B.Width)) { case SIZEOF_CHAR: Type = IsSignSigned (Type) ? type_schar : type_uchar; break; case SIZEOF_INT: Type = IsSignSigned (Type) ? type_int : type_uint; break; case SIZEOF_LONG: Type = IsSignSigned (Type) ? type_long : type_ulong; break; @@ -808,7 +794,7 @@ const Type* GetUnderlyingType (const Type* Type) const Type* GetStructReplacementType (const Type* SType) -/* Get a replacement type for passing a struct/union in the primary register */ +/* Get a replacement type for passing a struct/union by value in the primary */ { const Type* NewType; /* If the size is less than or equal to that of a long, we will copy the @@ -837,7 +823,7 @@ const Type* GetBitFieldChunkType (const Type* Type) return GetUnderlyingType (Type); } - ChunkSize = GetBitFieldMinimalTypeSize (Type->A.B.Offs + Type->A.B.Width); + ChunkSize = GetMinimalTypeSizeByBitWidth (Type->A.B.Offs + Type->A.B.Width); if (ChunkSize < SizeOf (Type + 1)) { /* The end of the bit-field is offset by some bits so that it requires ** more bytes to be accessed as a whole than its underlying type does. @@ -875,50 +861,50 @@ int IsTypeFragBitField (const Type* T) -int IsClassObject (const Type* T) +int IsObjectType (const Type* T) /* Return true if this is a fully described object type */ { - return !IsTypeFunc (T) && !IsClassIncomplete (T); + return !IsTypeFunc (T) && !IsIncompleteType (T); } -int IsClassIncomplete (const Type* T) +int IsIncompleteType (const Type* T) /* Return true if this is an object type lacking size info */ { if (IsTypeArray (T)) { - return GetElementCount (T) == UNSPECIFIED || IsClassIncomplete (T + 1); + return GetElementCount (T) == UNSPECIFIED || IsIncompleteType (T + 1); } return IsTypeVoid (T) || IsIncompleteESUType (T); } -int IsClassArithmetic (const Type* T) -/* Return true if this is an integer or real floating type */ +int IsArithmeticType (const Type* T) +/* Return true if this is an integer or floating type */ { return IsClassInt (T) || IsClassFloat (T); } -int IsClassBasic (const Type* T) -/* Return true if this is a char, integer or floating type */ +int IsBasicType (const Type* T) +/* Return true if this is a character, integer or floating type */ { - return IsClassChar (T) || IsClassInt (T) || IsClassFloat (T); + return IsDeclRankChar (T) || IsClassInt (T) || IsClassFloat (T); } -int IsClassScalar (const Type* T) +int IsScalarType (const Type* T) /* Return true if this is an arithmetic or pointer type */ { - return IsClassArithmetic (T) || IsTypePtr (T); + return IsArithmeticType (T) || IsTypePtr (T); } -int IsClassDerived (const Type* T) +int IsDerivedType (const Type* T) /* Return true if this is an array, struct, union, function or pointer type */ { return IsTypeArray (T) || IsClassStruct (T) || IsClassFunc (T) || IsTypePtr (T); @@ -926,7 +912,7 @@ int IsClassDerived (const Type* T) -int IsClassAggregate (const Type* T) +int IsAggregateType (const Type* T) /* Return true if this is an array or struct type */ { return IsTypeArray (T) || IsTypeStruct (T); @@ -937,7 +923,7 @@ int IsClassAggregate (const Type* T) int IsRelationType (const Type* T) /* Return true if this is an arithmetic, array or pointer type */ { - return IsClassArithmetic (T) || IsClassPtr (T); + return IsArithmeticType (T) || IsClassPtr (T); } @@ -945,7 +931,7 @@ int IsRelationType (const Type* T) int IsCastType (const Type* T) /* Return true if this type can be used for casting */ { - return IsClassScalar (T) || IsTypeVoid (T); + return IsScalarType (T) || IsTypeVoid (T); } @@ -987,7 +973,7 @@ int HasUnknownSize (const Type* T) -int TypeHasAttr (const Type* T) +int TypeHasAttrData (const Type* T) /* Return true if the given type has attribute data */ { return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T); @@ -1044,7 +1030,7 @@ int IsFastcallFunc (const Type* T) ** Check fails if the type is not a function or a pointer to function. */ { - if (UnqualifiedType (T->C) == T_PTR) { + if (GetUnqualRawTypeCode (T) == T_PTR) { /* Pointer to function */ ++T; } @@ -1056,7 +1042,7 @@ int IsFastcallFunc (const Type* T) FuncDesc* GetFuncDesc (const Type* T) /* Get the FuncDesc pointer from a function or pointer-to-function type */ { - if (UnqualifiedType (T->C) == T_PTR) { + if (GetUnqualRawTypeCode (T) == T_PTR) { /* Pointer to function */ ++T; } @@ -1073,7 +1059,7 @@ FuncDesc* GetFuncDesc (const Type* T) void SetFuncDesc (Type* T, FuncDesc* F) /* Set the FuncDesc pointer in a function or pointer-to-function type */ { - if (UnqualifiedType (T->C) == T_PTR) { + if (GetUnqualRawTypeCode (T) == T_PTR) { /* Pointer to function */ ++T; } @@ -1087,10 +1073,10 @@ void SetFuncDesc (Type* T, FuncDesc* F) -const Type* GetFuncReturn (const Type* T) +const Type* GetFuncReturnType (const Type* T) /* Return a pointer to the return type of a function or pointer-to-function type */ { - if (UnqualifiedType (T->C) == T_PTR) { + if (GetUnqualRawTypeCode (T) == T_PTR) { /* Pointer to function */ ++T; } @@ -1104,10 +1090,10 @@ const Type* GetFuncReturn (const Type* T) -Type* GetFuncReturnModifiable (Type* T) +Type* GetFuncReturnTypeModifiable (Type* T) /* Return a non-const pointer to the return type of a function or pointer-to-function type */ { - if (UnqualifiedType (T->C) == T_PTR) { + if (GetUnqualRawTypeCode (T) == T_PTR) { /* Pointer to function */ ++T; } @@ -1164,7 +1150,16 @@ void SetElementCount (Type* T, long Count) const Type* GetElementType (const Type* T) -/* Return the element type of the given array type. */ +/* Return the element type of the given array type */ +{ + CHECK (IsTypeArray (T)); + return T + 1; +} + + + +Type* GetElementTypeModifiable (Type* T) +/* Return the element type of the given array type */ { CHECK (IsTypeArray (T)); return T + 1; @@ -1228,48 +1223,48 @@ const char* GetBasicTypeName (const Type* T) ** Return "type" for unknown basic types. */ { - switch (GetRawType (T)) { - case T_TYPE_ENUM: return "enum"; - case T_TYPE_BITFIELD: return "bit-field"; - case T_TYPE_FLOAT: return "float"; - case T_TYPE_DOUBLE: return "double"; - case T_TYPE_VOID: return "void"; - case T_TYPE_STRUCT: return "struct"; - case T_TYPE_UNION: return "union"; - case T_TYPE_ARRAY: return "array"; - case T_TYPE_PTR: return "pointer"; - case T_TYPE_FUNC: return "function"; - case T_TYPE_NONE: /* FALLTHROUGH */ + switch (GetRawTypeRank (T)) { + case T_RANK_ENUM: return "enum"; + case T_RANK_BITFIELD: return "bit-field"; + case T_RANK_FLOAT: return "float"; + case T_RANK_DOUBLE: return "double"; + case T_RANK_VOID: return "void"; + case T_RANK_STRUCT: return "struct"; + case T_RANK_UNION: return "union"; + case T_RANK_ARRAY: return "array"; + case T_RANK_PTR: return "pointer"; + case T_RANK_FUNC: return "function"; + case T_RANK_NONE: /* FALLTHROUGH */ default: break; } if (IsClassInt (T)) { if (IsRawSignSigned (T)) { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "signed char"; - case T_TYPE_SHORT: return "short"; - case T_TYPE_INT: return "int"; - case T_TYPE_LONG: return "long"; - case T_TYPE_LONGLONG: return "long long"; + switch (GetRawTypeRank (T)) { + case T_RANK_CHAR: return "signed char"; + case T_RANK_SHORT: return "short"; + case T_RANK_INT: return "int"; + case T_RANK_LONG: return "long"; + case T_RANK_LONGLONG: return "long long"; default: return "signed integer"; } } else if (IsRawSignUnsigned (T)) { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "unsigned char"; - case T_TYPE_SHORT: return "unsigned short"; - case T_TYPE_INT: return "unsigned int"; - case T_TYPE_LONG: return "unsigned long"; - case T_TYPE_LONGLONG: return "unsigned long long"; + switch (GetRawTypeRank (T)) { + case T_RANK_CHAR: return "unsigned char"; + case T_RANK_SHORT: return "unsigned short"; + case T_RANK_INT: return "unsigned int"; + case T_RANK_LONG: return "unsigned long"; + case T_RANK_LONGLONG: return "unsigned long long"; default: return "unsigned integer"; } } else { - switch (GetRawType (T)) { - case T_TYPE_CHAR: return "char"; - case T_TYPE_SHORT: return "short"; - case T_TYPE_INT: return "int"; - case T_TYPE_LONG: return "long"; - case T_TYPE_LONGLONG: return "long long"; + switch (GetRawTypeRank (T)) { + case T_RANK_CHAR: return "char"; + case T_RANK_SHORT: return "short"; + case T_RANK_INT: return "int"; + case T_RANK_LONG: return "long"; + case T_RANK_LONGLONG: return "long long"; default: return "integer"; } @@ -1600,7 +1595,7 @@ void PrintFuncSig (FILE* F, const char* Name, const Type* T) SB_Done (&ParamList); /* Complete with the return type */ - GetFullTypeNameWestEast (&West, &East, GetFuncReturn (T)); + GetFullTypeNameWestEast (&West, &East, GetFuncReturnType (T)); SB_Append (&West, &East); SB_Terminate (&West); diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 4a20422fb..eebd3abd8 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -71,24 +71,24 @@ struct SymEntry; enum { T_END = 0x000000, - /* Basic types */ - T_TYPE_NONE = 0x000000, - T_TYPE_CHAR = 0x000001, - T_TYPE_SHORT = 0x000002, - T_TYPE_INT = 0x000003, - T_TYPE_LONG = 0x000004, - T_TYPE_LONGLONG = 0x000005, - T_TYPE_ENUM = 0x000008, - T_TYPE_BITFIELD = 0x000009, - T_TYPE_FLOAT = 0x00000A, - T_TYPE_DOUBLE = 0x00000B, - T_TYPE_VOID = 0x000010, - T_TYPE_STRUCT = 0x000011, - T_TYPE_UNION = 0x000012, - T_TYPE_ARRAY = 0x000018, - T_TYPE_PTR = 0x000019, - T_TYPE_FUNC = 0x00001A, - T_MASK_TYPE = 0x00001F, + /* Basic type ranks */ + T_RANK_NONE = 0x000000, + T_RANK_CHAR = 0x000001, + T_RANK_SHORT = 0x000002, + T_RANK_INT = 0x000003, + T_RANK_LONG = 0x000004, + T_RANK_LONGLONG = 0x000005, + T_RANK_ENUM = 0x000008, + T_RANK_BITFIELD = 0x000009, + T_RANK_FLOAT = 0x00000A, + T_RANK_DOUBLE = 0x00000B, + T_RANK_VOID = 0x000010, + T_RANK_STRUCT = 0x000011, + T_RANK_UNION = 0x000012, + T_RANK_ARRAY = 0x000018, + T_RANK_PTR = 0x000019, + T_RANK_FUNC = 0x00001A, + T_MASK_RANK = 0x00001F, /* Type classes */ T_CLASS_NONE = 0x000000, @@ -129,28 +129,28 @@ enum { T_MASK_QUAL = 0x7F0000, /* Types */ - T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_NONE | T_SIZE_CHAR, - T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_CHAR, - T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR, - T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT, - T_USHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT, - T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_INT, - T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_INT, - T_LONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG, - T_ULONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG, - T_LONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG, - T_ULONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG, - T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_NONE | T_SIZE_NONE, - T_SBITFIELD = T_TYPE_BITFIELD | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, - T_UBITFIELD = T_TYPE_BITFIELD | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, - T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, - T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, - T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE, - T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, - T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, - T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, - T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, - T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE, + T_CHAR = T_RANK_CHAR | T_CLASS_INT | T_SIGN_NONE | T_SIZE_CHAR, + T_SCHAR = T_RANK_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_CHAR, + T_UCHAR = T_RANK_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR, + T_SHORT = T_RANK_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT, + T_USHORT = T_RANK_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT, + T_INT = T_RANK_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_INT, + T_UINT = T_RANK_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_INT, + T_LONG = T_RANK_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG, + T_ULONG = T_RANK_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG, + T_LONGLONG = T_RANK_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG, + T_ULONGLONG = T_RANK_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG, + T_ENUM = T_RANK_ENUM | T_CLASS_INT | T_SIGN_NONE | T_SIZE_NONE, + T_SBITFIELD = T_RANK_BITFIELD | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, + T_UBITFIELD = T_RANK_BITFIELD | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, + T_FLOAT = T_RANK_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, + T_DOUBLE = T_RANK_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, + T_VOID = T_RANK_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE, + T_STRUCT = T_RANK_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, + T_UNION = T_RANK_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, + T_ARRAY = T_RANK_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, + T_PTR = T_RANK_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, + T_FUNC = T_RANK_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE, /* More types for convenience */ T_C_CHAR = T_CHAR | T_QUAL_CONST, @@ -316,7 +316,9 @@ unsigned CheckedPSizeOf (const Type* T); #if defined(HAVE_INLINE) INLINE TypeCode GetQualifier (const Type* T) -/* Get the qualifier from the given type string */ +/* Get the qualifier from the given type. This doesn't have a "raw" version +** since an underlying type can never be qualified. +*/ { return (T->C & T_MASK_QUAL); } @@ -324,66 +326,78 @@ INLINE TypeCode GetQualifier (const Type* T) # define GetQualifier(T) ((T)->C & T_MASK_QUAL) #endif -TypeCode GetUnderlyingTypeCode (const Type* Type); -/* Get the type code of the unqualified underlying type of TCode. -** Return TCode if it is not scalar. +TypeCode GetUnqualTypeCode (const Type* Type); +/* Get the type code of the unqualified underlying type of Type. +** Return GetUnqualRawTypeCode (Type) if Type is not scalar. */ #if defined(HAVE_INLINE) -INLINE TypeCode UnqualifiedType (TypeCode T) -/* Return the unqualified type code */ +INLINE TypeCode GetUnqualRawTypeCode (const Type* T) +/* Return the unqualified raw type code */ { - return (T & ~T_MASK_QUAL); + return (T->C & ~T_MASK_QUAL); } #else -# define UnqualifiedType(T) ((T) & ~T_MASK_QUAL) +# define GetUnqualRawTypeCode(T) ((T)->C & ~T_MASK_QUAL) #endif #if defined(HAVE_INLINE) -INLINE TypeCode GetClass (const Type* T) -/* Get the class of a type string */ +INLINE TypeCode GetTypeClass (const Type* T) +/* Get the class of a type. This doesn't have a "raw" version since an +** underlying type can never be in a different class. +*/ { return (T->C & T_MASK_CLASS); } #else -# define GetClass(T) ((T)->C & T_MASK_CLASS) +# define GetTypeClass(T) ((T)->C & T_MASK_CLASS) +#endif + +#if defined(HAVE_INLINE) +INLINE TypeCode GetTypeRank (const Type* T) +/* Get the type rank of a type */ +{ + return (GetUnqualTypeCode (T) & T_MASK_RANK); +} +#else +# define GetTypeRank(T) (GetUnqualTypeCode (T) & T_MASK_RANK) #endif #if defined(HAVE_INLINE) INLINE TypeCode GetSignedness (const Type* T) /* Get the signedness of a type */ { - return (GetUnderlyingTypeCode (T) & T_MASK_SIGN); + return (GetUnqualTypeCode (T) & T_MASK_SIGN); } #else -# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN) +# define GetSignedness(T) (GetUnqualTypeCode (T) & T_MASK_SIGN) #endif #if defined(HAVE_INLINE) INLINE TypeCode GetSizeModifier (const Type* T) /* Get the size modifier of a type */ { - return (GetUnderlyingTypeCode (T) & T_MASK_SIZE); + return (GetUnqualTypeCode (T) & T_MASK_SIZE); } #else -# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE) +# define GetSizeModifier(T) (GetUnqualTypeCode (T) & T_MASK_SIZE) #endif #if defined(HAVE_INLINE) -INLINE TypeCode GetRawType (const Type* T) -/* Get the raw type */ +INLINE TypeCode GetRawTypeRank (const Type* T) +/* Get the raw type rank of a type */ { - return (T->C & T_MASK_TYPE); + return (T->C & T_MASK_RANK); } #else -# define GetRawType(T) ((T)->C & T_MASK_TYPE) +# define GetRawTypeRank(T) ((T)->C & T_MASK_RANK) #endif #if defined(HAVE_INLINE) INLINE TypeCode GetRawSignedness (const Type* T) /* Get the raw signedness of a type */ { - return ((T)->C & T_MASK_SIGN); + return (T->C & T_MASK_SIGN); } #else # define GetRawSignedness(T) ((T)->C & T_MASK_SIGN) @@ -391,7 +405,7 @@ INLINE TypeCode GetRawSignedness (const Type* T) #if defined(HAVE_INLINE) INLINE TypeCode GetRawSizeModifier (const Type* T) -/* Get the size modifier of a raw type */ +/* Get the raw size modifier of a type */ { return (T->C & T_MASK_SIZE); } @@ -418,7 +432,7 @@ Type* NewPointerTo (const Type* T); ** on the heap and may be freed after use. */ -Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth); +Type* NewBitFieldOf (const Type* T, unsigned BitOffs, unsigned BitWidth); /* Return a type string that is "T : BitWidth" aligned on BitOffs. The type ** string is allocated on the heap and may be freed after use. */ @@ -433,11 +447,6 @@ const Type* Indirect (const Type* T); ** given type points to. */ -Type* IndirectModifiable (Type* T); -/* Do one indirection for the given type, that is, return the type where the -** given type points to. -*/ - Type* ArrayToPtr (const Type* T); /* Convert an array to a pointer to it's first element */ @@ -461,17 +470,17 @@ const Type* IntPromotion (const Type* T); const Type* ArithmeticConvert (const Type* lhst, const Type* rhst); /* Perform the usual arithmetic conversions for binary operators. */ -const Type* SignedType (const Type* T); +const Type* GetSignedType (const Type* T); /* Get signed counterpart of the integral type */ -const Type* UnsignedType (const Type* T); +const Type* GetUnsignedType (const Type* T); /* Get unsigned counterpart of the integral type */ const Type* GetUnderlyingType (const Type* Type); /* Get the underlying type of an enum or other integer class type */ const Type* GetStructReplacementType (const Type* SType); -/* Get a replacement type for passing a struct/union in the primary register */ +/* Get a replacement type for passing a struct/union by value in the primary */ const Type* GetBitFieldChunkType (const Type* Type); /* Get the type needed to operate on the byte chunk containing the bit-field */ @@ -485,155 +494,127 @@ const Type* GetBitFieldChunkType (const Type* Type); #if defined(HAVE_INLINE) -INLINE int IsTypeChar (const Type* T) -/* Return true if this is a char type */ +INLINE int IsRankChar (const Type* T) +/* Return true if this is a character type */ { - return (GetRawType (GetUnderlyingType (T)) == T_TYPE_CHAR); + return (GetTypeRank (T) == T_RANK_CHAR); } #else -# define IsTypeChar(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_CHAR) +# define IsRankChar(T) (GetTypeRank (T) == T_RANK_CHAR) #endif #if defined(HAVE_INLINE) -INLINE int IsTypeShort (const Type* T) +INLINE int IsRankShort (const Type* T) /* Return true if this is a short type (signed or unsigned) */ { - return (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT); + return (GetTypeRank (T) == T_RANK_SHORT); } #else -# define IsTypeShort(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT) +# define IsRankShort(T) (GetTypeRank (T) == T_RANK_SHORT) #endif #if defined(HAVE_INLINE) -INLINE int IsTypeInt (const Type* T) +INLINE int IsRankInt (const Type* T) /* Return true if this is an int type (signed or unsigned) */ { - return (GetRawType (GetUnderlyingType (T)) == T_TYPE_INT); + return (GetTypeRank (T) == T_RANK_INT); } #else -# define IsTypeInt(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_INT) +# define IsRankInt(T) (GetTypeRank (T) == T_RANK_INT) #endif #if defined(HAVE_INLINE) -INLINE int IsTypeLong (const Type* T) +INLINE int IsRankLong (const Type* T) /* Return true if this is a long int type (signed or unsigned) */ { - return (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG); + return (GetTypeRank (T) == T_RANK_LONG); } #else -# define IsTypeLong(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG) +# define IsRankLong(T) (GetTypeRank (T) == T_RANK_LONG) #endif #if defined(HAVE_INLINE) -INLINE int IsISOChar (const Type* T) -/* Return true if this is a narrow character type (without signed/unsigned) */ -{ - return (UnqualifiedType (T->C) == T_CHAR); -} -#else -# define IsISOChar(T) (UnqualifiedType ((T)->C) == T_CHAR) -#endif - -#if defined(HAVE_INLINE) -INLINE int IsClassChar (const Type* T) -/* Return true if this is a narrow character type (including signed/unsigned). -** For now this is the same as IsRawTypeChar(T). +INLINE int IsDeclTypeChar (const Type* T) +/* Return true if this is declared as a char type (without signed/unsigned). +** This function is to exclude enums whose underlying type is char. */ { - return (GetRawType (T) == T_TYPE_CHAR); + return (GetUnqualRawTypeCode (T) == T_CHAR); } #else -# define IsClassChar(T) (GetRawType (T) == T_TYPE_CHAR) +# define IsDeclTypeChar(T) (GetUnqualRawTypeCode (T) == T_CHAR) #endif #if defined(HAVE_INLINE) -INLINE int IsRawTypeChar (const Type* T) -/* Return true if this is a char raw type (including signed/unsigned) */ +INLINE int IsDeclRankChar (const Type* T) +/* Return true if this is declared as a character type (including signed/unsigned). +** This function is to exclude enums whose underlying types are character types. +*/ { - return (GetRawType (T) == T_TYPE_CHAR); + return (GetRawTypeRank (T) == T_RANK_CHAR); } #else -# define IsRawTypeChar(T) (GetRawType (T) == T_TYPE_CHAR) -#endif - -#if defined(HAVE_INLINE) -INLINE int IsRawTypeInt (const Type* T) -/* Return true if this is an int raw type (signed or unsigned) */ -{ - return (GetRawType (T) == T_TYPE_INT); -} -#else -# define IsRawTypeInt(T) (GetRawType (T) == T_TYPE_INT) -#endif - -#if defined(HAVE_INLINE) -INLINE int IsRawTypeLong (const Type* T) -/* Return true if this is a long raw type (signed or unsigned) */ -{ - return (GetRawType (T) == T_TYPE_LONG); -} -#else -# define IsRawTypeLong(T) (GetRawType (T) == T_TYPE_LONG) +# define IsDeclRankChar(T) (GetRawTypeRank (T) == T_RANK_CHAR) #endif #if defined(HAVE_INLINE) INLINE int IsTypeFloat (const Type* T) /* Return true if this is a float type */ { - return (GetRawType (T) == T_TYPE_FLOAT); + return (GetRawTypeRank (T) == T_RANK_FLOAT); } #else -# define IsTypeFloat(T) (GetRawType (T) == T_TYPE_FLOAT) +# define IsTypeFloat(T) (GetRawTypeRank (T) == T_RANK_FLOAT) #endif #if defined(HAVE_INLINE) INLINE int IsTypeDouble (const Type* T) /* Return true if this is a double type */ { - return (GetRawType (T) == T_TYPE_DOUBLE); + return (GetRawTypeRank (T) == T_RANK_DOUBLE); } #else -# define IsTypeDouble(T) (GetRawType (T) == T_TYPE_DOUBLE) +# define IsTypeDouble(T) (GetRawTypeRank (T) == T_RANK_DOUBLE) #endif #if defined(HAVE_INLINE) INLINE int IsTypePtr (const Type* T) /* Return true if this is a pointer type */ { - return (GetRawType (T) == T_TYPE_PTR); + return (GetRawTypeRank (T) == T_RANK_PTR); } #else -# define IsTypePtr(T) (GetRawType (T) == T_TYPE_PTR) +# define IsTypePtr(T) (GetRawTypeRank (T) == T_RANK_PTR) #endif #if defined(HAVE_INLINE) INLINE int IsTypeEnum (const Type* T) /* Return true if this is an enum type */ { - return (GetRawType (T) == T_TYPE_ENUM); + return (GetRawTypeRank (T) == T_RANK_ENUM); } #else -# define IsTypeEnum(T) (GetRawType (T) == T_TYPE_ENUM) +# define IsTypeEnum(T) (GetRawTypeRank (T) == T_RANK_ENUM) #endif #if defined(HAVE_INLINE) INLINE int IsTypeSignedBitField (const Type* T) /* Return true if this is a signed bit-field */ { - return (UnqualifiedType (T->C) == T_SBITFIELD); + return (GetUnqualRawTypeCode (T) == T_SBITFIELD); } #else -# define IsTypeSignedBitField(T) (UnqualifiedType ((T)->C) == T_SBITFIELD) +# define IsTypeSignedBitField(T) (GetUnqualRawTypeCode (T) == T_SBITFIELD) #endif #if defined(HAVE_INLINE) INLINE int IsTypeUnsignedBitField (const Type* T) /* Return true if this is an unsigned bit-field */ { - return (UnqualifiedType (T->C) == T_UBITFIELD); + return (GetUnqualRawTypeCode (T) == T_UBITFIELD); } #else -# define IsTypeUnsignedBitField(T) (UnqualifiedType ((T)->C) == T_UBITFIELD) +# define IsTypeUnsignedBitField(T) (GetUnqualRawTypeCode (T) == T_UBITFIELD) #endif #if defined(HAVE_INLINE) @@ -653,55 +634,55 @@ int IsTypeFragBitField (const Type* T); INLINE int IsTypeStruct (const Type* T) /* Return true if this is a struct type */ { - return (GetRawType (T) == T_TYPE_STRUCT); + return (GetRawTypeRank (T) == T_RANK_STRUCT); } #else -# define IsTypeStruct(T) (GetRawType (T) == T_TYPE_STRUCT) +# define IsTypeStruct(T) (GetRawTypeRank (T) == T_RANK_STRUCT) #endif #if defined(HAVE_INLINE) INLINE int IsTypeUnion (const Type* T) /* Return true if this is a union type */ { - return (GetRawType (T) == T_TYPE_UNION); + return (GetRawTypeRank (T) == T_RANK_UNION); } #else -# define IsTypeUnion(T) (GetRawType (T) == T_TYPE_UNION) +# define IsTypeUnion(T) (GetRawTypeRank (T) == T_RANK_UNION) #endif #if defined(HAVE_INLINE) INLINE int IsTypeArray (const Type* T) /* Return true if this is an array type */ { - return (GetRawType (T) == T_TYPE_ARRAY); + return (GetRawTypeRank (T) == T_RANK_ARRAY); } #else -# define IsTypeArray(T) (GetRawType (T) == T_TYPE_ARRAY) +# define IsTypeArray(T) (GetRawTypeRank (T) == T_RANK_ARRAY) #endif #if defined(HAVE_INLINE) INLINE int IsTypeVoid (const Type* T) /* Return true if this is a void type */ { - return (GetRawType (T) == T_TYPE_VOID); + return (GetRawTypeRank (T) == T_RANK_VOID); } #else -# define IsTypeVoid(T) (GetRawType (T) == T_TYPE_VOID) +# define IsTypeVoid(T) (GetRawTypeRank (T) == T_RANK_VOID) #endif #if defined(HAVE_INLINE) INLINE int IsTypeFunc (const Type* T) -/* Return true if this is a function class */ +/* Return true if this is a function type */ { - return (GetRawType (T) == T_TYPE_FUNC); + return (GetRawTypeRank (T) == T_RANK_FUNC); } #else -# define IsTypeFunc(T) (GetRawType (T) == T_TYPE_FUNC) +# define IsTypeFunc(T) (GetRawTypeRank (T) == T_RANK_FUNC) #endif #if defined(HAVE_INLINE) INLINE int IsTypeFuncPtr (const Type* T) -/* Return true if this is a function pointer */ +/* Return true if this is a function pointer type */ { return (IsTypePtr (T) && IsTypeFunc (T+1)); } @@ -713,71 +694,71 @@ INLINE int IsTypeFuncPtr (const Type* T) INLINE int IsClassInt (const Type* T) /* Return true if this is an integer type */ { - return (GetClass (T) == T_CLASS_INT); + return (GetTypeClass (T) == T_CLASS_INT); } #else -# define IsClassInt(T) (GetClass (T) == T_CLASS_INT) +# define IsClassInt(T) (GetTypeClass (T) == T_CLASS_INT) #endif #if defined(HAVE_INLINE) INLINE int IsClassFloat (const Type* T) -/* Return true if this is a float type */ +/* Return true if this is a floating type */ { - return (GetClass (T) == T_CLASS_FLOAT); + return (GetTypeClass (T) == T_CLASS_FLOAT); } #else -# define IsClassFloat(T) (GetClass (T) == T_CLASS_FLOAT) +# define IsClassFloat(T) (GetTypeClass (T) == T_CLASS_FLOAT) #endif #if defined(HAVE_INLINE) INLINE int IsClassPtr (const Type* T) -/* Return true if this is a pointer type */ +/* Return true if this is a pointer or array type */ { - return (GetClass (T) == T_CLASS_PTR); + return (GetTypeClass (T) == T_CLASS_PTR); } #else -# define IsClassPtr(T) (GetClass (T) == T_CLASS_PTR) +# define IsClassPtr(T) (GetTypeClass (T) == T_CLASS_PTR) #endif #if defined(HAVE_INLINE) INLINE int IsClassStruct (const Type* T) /* Return true if this is a struct or union type */ { - return (GetClass (T) == T_CLASS_STRUCT); + return (GetTypeClass (T) == T_CLASS_STRUCT); } #else -# define IsClassStruct(T) (GetClass (T) == T_CLASS_STRUCT) +# define IsClassStruct(T) (GetTypeClass (T) == T_CLASS_STRUCT) #endif #if defined(HAVE_INLINE) INLINE int IsClassFunc (const Type* T) /* Return true if this is a function type */ { - return (GetClass (T) == T_CLASS_FUNC); + return (GetTypeClass (T) == T_CLASS_FUNC); } #else -# define IsClassFunc(T) (GetClass (T) == T_CLASS_FUNC) +# define IsClassFunc(T) (GetTypeClass (T) == T_CLASS_FUNC) #endif -int IsClassObject (const Type* T); +int IsObjectType (const Type* T); /* Return true if this is a fully described object type */ -int IsClassIncomplete (const Type* T); +int IsIncompleteType (const Type* T); /* Return true if this is an object type lacking size info */ -int IsClassArithmetic (const Type* T); -/* Return true if this is an integer or real floating type */ +int IsArithmeticType (const Type* T); +/* Return true if this is an integer or floating type */ -int IsClassBasic (const Type* T); +int IsBasicType (const Type* T); /* Return true if this is a char, integer or floating type */ -int IsClassScalar (const Type* T); +int IsScalarType (const Type* T); /* Return true if this is an arithmetic or pointer type */ -int IsClassDerived (const Type* T); +int IsDerivedType (const Type* T); /* Return true if this is an array, struct, union, function or pointer type */ -int IsClassAggregate (const Type* T); +int IsAggregateType (const Type* T); /* Return true if this is an array or struct type */ int IsRelationType (const Type* T); @@ -798,7 +779,7 @@ int IsEmptiableObjectType (const Type* T); int HasUnknownSize (const Type* T); /* Return true if this is an incomplete ESU type or an array of unknown size */ -int TypeHasAttr (const Type* T); +int TypeHasAttrData (const Type* T); /* Return true if the given type has attribute data */ #if defined(HAVE_INLINE) @@ -978,10 +959,10 @@ FuncDesc* GetFuncDesc (const Type* T) attribute ((const)); void SetFuncDesc (Type* T, FuncDesc* F); /* Set the FuncDesc pointer in a function or pointer-to-function type */ -const Type* GetFuncReturn (const Type* T) attribute ((const)); +const Type* GetFuncReturnType (const Type* T) attribute ((const)); /* Return a pointer to the return type of a function or pointer-to-function type */ -Type* GetFuncReturnModifiable (Type* T) attribute ((const)); +Type* GetFuncReturnTypeModifiable (Type* T) attribute ((const)); /* Return a non-const pointer to the return type of a function or pointer-to-function type */ const FuncDesc* GetFuncDefinitionDesc (const Type* T) attribute ((const)); @@ -1006,7 +987,10 @@ void SetElementCount (Type* T, long Count); */ const Type* GetElementType (const Type* T); -/* Return the element type of the given array type. */ +/* Return the element type of the given array type */ + +Type* GetElementTypeModifiable (Type* T); +/* Return the element type of the given array type */ const Type* GetBaseElementType (const Type* T); /* Return the base element type of a given type. If T is not an array, this diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 459ffa103..59eb555c4 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -406,7 +406,7 @@ static void FixQualifiers (Type* DataType) if (IsTypeArray (T)) { /* Extract any type qualifiers */ Q |= GetQualifier (T); - T->C = UnqualifiedType (T->C); + T->C = GetUnqualRawTypeCode (T); } else { /* Add extracted type qualifiers here */ T->C |= Q; @@ -646,7 +646,7 @@ static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags) /* Enumerate by adding one to the previous value */ EnumVal = (long)(((unsigned long)EnumVal + 1UL) & 0xFFFFFFFFUL); - if (UnqualifiedType (MemberType->C) == T_ULONG && EnumVal == 0) { + if (GetUnqualRawTypeCode (MemberType) == T_ULONG && EnumVal == 0) { /* Error since the new value cannot be represented in the ** largest unsigned integer type supported by cc65 for enum. */ @@ -688,7 +688,7 @@ static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags) if (PrevErrorCount == ErrorCount && IsIncremented && (!IsSigned || EnumVal >= 0) && - NewType->C != UnqualifiedType (MemberType->C)) { + NewType->C != GetUnqualRawTypeCode (MemberType)) { /* The possible overflow here can only be when EnumVal > 0 */ Warning ("Enumerator '%s' (value = %lu) implies type '%s'", Ident, @@ -959,7 +959,7 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags) } /* Check for incomplete types including 'void' */ - if (IsClassIncomplete (Decl.Type)) { + if (IsIncompleteType (Decl.Type)) { Error ("Field '%s' has incomplete type '%s'", Decl.Ident, GetFullTypeName (Decl.Type)); @@ -1159,7 +1159,7 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags) } /* Check for incomplete types including 'void' */ - if (IsClassIncomplete (Decl.Type)) { + if (IsIncompleteType (Decl.Type)) { Error ("Field '%s' has incomplete type '%s'", Decl.Ident, GetFullTypeName (Decl.Type)); @@ -2036,7 +2036,7 @@ void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode) if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) { /* A function. Check the return type */ - Type* RetType = GetFuncReturnModifiable (D->Type); + Type* RetType = GetFuncReturnTypeModifiable (D->Type); /* Functions may not return functions or arrays */ if (IsTypeFunc (RetType)) { @@ -2048,13 +2048,13 @@ void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode) /* The return type must not be qualified */ if (GetQualifier (RetType) != T_QUAL_NONE && RetType[1].C == T_END) { - if (GetRawType (RetType) == T_TYPE_VOID) { + if (GetRawTypeRank (RetType) == T_RANK_VOID) { /* A qualified void type is always an error */ Error ("function definition has qualified void return type"); } else { /* For others, qualifiers are ignored */ Warning ("type qualifiers ignored on function return type"); - RetType[0].C = UnqualifiedType (RetType[0].C); + RetType[0].C = GetUnqualRawTypeCode (RetType); } } diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 78a4c516a..691010b0a 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -128,7 +128,7 @@ unsigned TypeOf (const Type* T) { unsigned NewType; - switch (GetUnderlyingTypeCode (T)) { + switch (GetUnqualTypeCode (T)) { case T_SCHAR: return CF_CHAR; @@ -187,7 +187,7 @@ unsigned TypeOf (const Type* T) unsigned FuncTypeOf (const Type* T) /* Get the code generator flag for calling the function */ { - if (GetUnderlyingTypeCode (T) == T_FUNC) { + if (GetUnqualTypeCode (T) == T_FUNC) { return (T->A.F->Flags & FD_VARIADIC) ? 0 : CF_FIXARGC; } else { Error ("Illegal function type %04lX", T->C); @@ -290,7 +290,7 @@ static unsigned typeadjust (ExprDesc* lhs, const ExprDesc* rhs, int NoPush) void LimitExprValue (ExprDesc* Expr, int WarnOverflow) /* Limit the constant value of the expression to the range of its type */ { - switch (GetUnderlyingTypeCode (Expr->Type)) { + switch (GetUnqualTypeCode (Expr->Type)) { case T_INT: case T_SHORT: if (WarnOverflow && ((Expr->IVal < -0x8000) || (Expr->IVal > 0x7FFF))) { @@ -1146,7 +1146,7 @@ static void FunctionCall (ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - ReturnType = GetFuncReturn (Expr->Type); + ReturnType = GetFuncReturnType (Expr->Type); /* Handle struct/union specially */ if (IsClassStruct (ReturnType)) { @@ -2568,7 +2568,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ } /* Determine the type of the operation. */ - if (IsTypeChar (Expr->Type) && rconst && (!LeftSigned || RightSigned)) { + if (IsRankChar (Expr->Type) && rconst && (!LeftSigned || RightSigned)) { /* Left side is unsigned char, right side is constant. ** Determine the minimum and maximum values @@ -2651,7 +2651,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ flags |= CF_UNSIGNED; } - } else if (IsTypeChar (Expr->Type) && IsTypeChar (Expr2.Type) && + } else if (IsRankChar (Expr->Type) && IsRankChar (Expr2.Type) && GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) { /* Both are chars with the same signedness. We can encode the diff --git a/src/cc65/function.c b/src/cc65/function.c index 737b068a3..39f04843f 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -81,7 +81,7 @@ static Function* NewFunction (struct SymEntry* Sym, FuncDesc* D) /* Initialize the fields */ F->FuncEntry = Sym; - F->ReturnType = GetFuncReturn (Sym->Type); + F->ReturnType = GetFuncReturnType (Sym->Type); F->Desc = D; F->Reserved = 0; F->RetLab = 0; @@ -540,7 +540,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D) /* Determine if this is a main function in a C99 environment that ** returns an int. */ - if (IsRawTypeInt (F_GetReturnType (CurrentFunc)) && + if (GetUnqualRawTypeCode (ReturnType) == T_INT && IS_Get (&Standard) == STD_C99) { C99MainFunc = 1; } diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index 2b151e59e..619fe4897 100644 --- a/src/cc65/initdata.c +++ b/src/cc65/initdata.c @@ -330,12 +330,12 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers) int HasCurly = 0; /* Get the array data */ - Type* ElementType = IndirectModifiable (T); + Type* ElementType = GetElementTypeModifiable (T); unsigned ElementSize = SizeOf (ElementType); long ElementCount = GetElementCount (T); /* Special handling for a character array initialized by a literal */ - if (IsClassChar (ElementType) && + if (IsDeclRankChar (ElementType) && (CurTok.Tok == TOK_SCONST || CurTok.Tok == TOK_WCSCONST || (CurTok.Tok == TOK_LCURLY && (NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST)))) { @@ -669,7 +669,7 @@ static unsigned ParseVoidInit (Type* T) Size = 0; do { ExprDesc Expr = NoCodeConstExpr (hie1); - switch (GetUnderlyingTypeCode (&Expr.Type[0])) { + switch (GetUnqualTypeCode (&Expr.Type[0])) { case T_SCHAR: case T_UCHAR: @@ -737,7 +737,7 @@ static unsigned ParseVoidInit (Type* T) static unsigned ParseInitInternal (Type* T, int *Braces, int AllowFlexibleMembers) /* Parse initialization of variables. Return the number of data bytes. */ { - switch (GetUnderlyingTypeCode (T)) { + switch (GetUnqualTypeCode (T)) { case T_SCHAR: case T_UCHAR: diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index fc19ce7f0..d22c73dcf 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -531,7 +531,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - Expr->Type = GetFuncReturn (Expr->Type); + Expr->Type = GetFuncReturnType (Expr->Type); /* Bail out, no need for further processing */ goto ExitPoint; @@ -540,7 +540,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - Expr->Type = GetFuncReturn (Expr->Type); + Expr->Type = GetFuncReturnType (Expr->Type); ExitPoint: /* We expect the closing brace */ @@ -757,7 +757,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - Expr->Type = GetFuncReturn (Expr->Type); + Expr->Type = GetFuncReturnType (Expr->Type); /* Bail out, no need for further processing */ goto ExitPoint; @@ -766,7 +766,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - Expr->Type = GetFuncReturn (Expr->Type); + Expr->Type = GetFuncReturnType (Expr->Type); ExitPoint: /* We expect the closing brace */ @@ -968,7 +968,7 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - Expr->Type = GetFuncReturn (Expr->Type); + Expr->Type = GetFuncReturnType (Expr->Type); /* We expect the closing brace */ ConsumeRParen (); @@ -1165,7 +1165,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* The function result is an rvalue in the primary register */ ED_FinalizeRValLoad (Expr); - Expr->Type = GetFuncReturn (Expr->Type); + Expr->Type = GetFuncReturnType (Expr->Type); ExitPoint: /* We expect the closing brace */ diff --git a/src/cc65/swstmt.c b/src/cc65/swstmt.c index 00555ffc3..0466ddf4a 100644 --- a/src/cc65/swstmt.c +++ b/src/cc65/swstmt.c @@ -133,7 +133,7 @@ void SwitchStatement (void) /* Setup the control structure, save the old and activate the new one */ SwitchData.Nodes = NewCollection (); - SwitchData.ExprType = GetUnderlyingTypeCode (&SwitchExpr.Type[0]); + SwitchData.ExprType = GetUnqualTypeCode (&SwitchExpr.Type[0]); SwitchData.Depth = SizeOf (SwitchExpr.Type); SwitchData.DefaultLabel = 0; OldSwitch = Switch; diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 961f36046..72a2ac007 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -1007,7 +1007,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs, Entry = NewSymEntry (Name, SC_BITFIELD); /* Set the symbol attributes. Bit-fields are always integral types. */ - Entry->Type = NewBitFieldType (T, BitOffs, BitWidth); + Entry->Type = NewBitFieldOf (T, BitOffs, BitWidth); Entry->V.Offs = Offs; if (!SignednessSpecified) { @@ -1019,7 +1019,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs, ** `char -> unsigned char` adjustment that is performed with other integral types. */ CHECK ((Entry->Type->C & T_MASK_SIGN) == T_SIGN_SIGNED || - IsTypeChar (Entry->Type)); + IsRankChar (Entry->Type)); Entry->Type[0].C &= ~T_MASK_SIGN; Entry->Type[0].C |= T_SIGN_UNSIGNED; Entry->Type[1].C &= ~T_MASK_SIGN; diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 1a108159f..c3239652f 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -244,7 +244,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) SymEntry* Sym2; FuncDesc* F1; FuncDesc* F2; - TypeCode LeftType, RightType; + TypeCode LeftRank, RightRank; long LeftCount, RightCount; @@ -262,9 +262,23 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) return; } - /* Get the left and right types */ - LeftType = (GetUnderlyingTypeCode (lhs) & T_MASK_TYPE); - RightType = (GetUnderlyingTypeCode (rhs) & T_MASK_TYPE); + /* Get the ranks of the left and right hands */ + LeftRank = (GetUnqualTypeCode (lhs) & T_MASK_RANK); + RightRank = (GetUnqualTypeCode (rhs) & T_MASK_RANK); + + /* If one side is a pointer and the other side is an array, both are + ** compatible. + */ + if (Result->Indirections == 0) { + if (LeftRank == T_RANK_PTR && RightRank == T_RANK_ARRAY) { + RightRank = T_RANK_PTR; + SetResult (Result, TC_PTR_DECAY); + } + if (LeftRank == T_RANK_ARRAY && RightRank == T_RANK_PTR) { + LeftRank = T_RANK_PTR; + SetResult (Result, TC_STRICT_COMPATIBLE); + } + } /* Bit-fields are considered compatible if they have the same ** signedness, bit-offset and bit-width. @@ -275,29 +289,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) lhs->A.B.Offs != rhs->A.B.Offs || lhs->A.B.Width != rhs->A.B.Width) { SetResult (Result, TC_INCOMPATIBLE); - return; } - if (LeftType != RightType) { + if (LeftRank != RightRank) { SetResult (Result, TC_STRICT_COMPATIBLE); } } - /* If one side is a pointer and the other side is an array, both are - ** compatible. - */ - if (Result->Indirections == 0) { - if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { - RightType = T_TYPE_PTR; - SetResult (Result, TC_PTR_DECAY); - } - if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) { - LeftType = T_TYPE_PTR; - SetResult (Result, TC_STRICT_COMPATIBLE); - } - } - - /* If the underlying types are not identical, the types are incompatible */ - if (LeftType != RightType) { + /* If the ranks are different, the types are incompatible */ + if (LeftRank != RightRank) { SetResult (Result, TC_INCOMPATIBLE); return; } @@ -337,8 +336,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } /* 'char' is neither 'signed char' nor 'unsigned char' */ - if ((IsISOChar (lhs) && !IsISOChar (rhs)) || - (!IsISOChar (lhs) && IsISOChar (rhs))) { + if ((IsDeclTypeChar (lhs) && !IsDeclTypeChar (rhs)) || + (!IsDeclTypeChar (lhs) && IsDeclTypeChar (rhs))) { SetResult (Result, TC_SIGN_DIFF); } @@ -350,14 +349,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } /* Check for special type elements */ - switch (LeftType) { - case T_TYPE_PTR: + switch (LeftRank) { + case T_RANK_PTR: ++Result->Indirections; if (Result->Indirections == 1) { - if ((GetUnderlyingTypeCode (lhs + 1) & T_MASK_TYPE) == T_TYPE_VOID) { + if ((GetUnqualTypeCode (lhs + 1) & T_MASK_RANK) == T_RANK_VOID) { Result->F |= TCF_VOID_PTR_ON_LEFT; } - if ((GetUnderlyingTypeCode (rhs + 1) & T_MASK_TYPE) == T_TYPE_VOID) { + if ((GetUnqualTypeCode (rhs + 1) & T_MASK_RANK) == T_RANK_VOID) { Result->F |= TCF_VOID_PTR_ON_RIGHT; } } else { @@ -365,7 +364,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } break; - case T_TYPE_FUNC: + case T_RANK_FUNC: /* Compare the function descriptors */ F1 = GetFuncDesc (lhs); F2 = GetFuncDesc (rhs); @@ -399,7 +398,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Keep on and compare the return type */ break; - case T_TYPE_ARRAY: + case T_RANK_ARRAY: /* Check member count */ LeftCount = GetElementCount (lhs); RightCount = GetElementCount (rhs); @@ -420,8 +419,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } break; - case T_TYPE_STRUCT: - case T_TYPE_UNION: + case T_RANK_STRUCT: + case T_RANK_UNION: /* Compare the tag types */ Sym1 = GetESUTagSym (lhs); Sym2 = GetESUTagSym (rhs); diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index c72b2c5eb..18a9f4dfa 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -430,7 +430,7 @@ void TypeComposition (Type* lhs, const Type* rhs) } /* Check for sanity */ - CHECK (GetUnderlyingTypeCode (lhs) == GetUnderlyingTypeCode (rhs)); + CHECK (GetUnqualTypeCode (lhs) == GetUnqualTypeCode (rhs)); /* Check for special type elements */ if (IsTypeFunc (lhs)) { From d52ef67d5195d36ff12d7248b035aaea3f51a147 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 10:28:14 +0300 Subject: [PATCH 061/360] Fix compilation after the postproc merge --- src/cc65/input.h | 3 +-- src/cc65/preproc.h | 12 +----------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/cc65/input.h b/src/cc65/input.h index f9565229b..f56f12462 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -41,6 +41,7 @@ #include <stdio.h> /* common */ +#include "coll.h" #include "strbuf.h" @@ -70,8 +71,6 @@ extern StrBuf* Line; extern char CurC; extern char NextC; -typedef struct Collection Collection; - /*****************************************************************************/ diff --git a/src/cc65/preproc.h b/src/cc65/preproc.h index a4619e545..153d0d68a 100644 --- a/src/cc65/preproc.h +++ b/src/cc65/preproc.h @@ -36,17 +36,7 @@ #ifndef PREPROC_H #define PREPROC_H - - -/*****************************************************************************/ -/* Forwards */ -/*****************************************************************************/ - - - -typedef struct Macro Macro; - - +#include "macrotab.h" /*****************************************************************************/ /* Data */ From 1e6279aee5c4b427fb935d42709dd8623bcd584a Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 18:38:33 +0300 Subject: [PATCH 062/360] Clarify sprintf-test's output so it doesn't look like the entire test bench summary --- test/todo/sprintf-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/todo/sprintf-test.c b/test/todo/sprintf-test.c index bd5de44b4..ea50f418a 100644 --- a/test/todo/sprintf-test.c +++ b/test/todo/sprintf-test.c @@ -564,9 +564,9 @@ int main (void) /* Output the result */ if (Failures) { - printf ("%u tests, %u failures\n", Tests, Failures); + printf ("sprintf-test: %u tests, %u failures\n", Tests, Failures); } else { - printf ("%u tests: Ok\n", Tests); + printf ("sprintf-test: %u tests: Ok\n", Tests); } /* Wait for a key so we can read the result */ From 4540205b0d4ac2785f74369deebdcd80b3642259 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Thu, 13 Oct 2022 23:49:07 -0400 Subject: [PATCH 063/360] Emit warning for signed integer constant overflow --- src/cc65/expr.c | 16 +++++++++++----- src/cc65/expr.h | 2 +- src/cc65/shiftexpr.c | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index afb5e1960..8c042cc3c 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -193,12 +193,15 @@ static unsigned typeadjust (ExprDesc* lhs, const ExprDesc* rhs, int NoPush) -void LimitExprValue (ExprDesc* Expr) +void LimitExprValue (ExprDesc* Expr, int WarnOverflow) /* Limit the constant value of the expression to the range of its type */ { switch (GetUnderlyingTypeCode (Expr->Type)) { case T_INT: case T_SHORT: + if (WarnOverflow && ((Expr->IVal < -0x8000) || (Expr->IVal > 0x7FFF))) { + Warning ("Signed integer constant overflow"); + } Expr->IVal = (int16_t)Expr->IVal; break; @@ -218,6 +221,9 @@ void LimitExprValue (ExprDesc* Expr) break; case T_SCHAR: + if (WarnOverflow && ((Expr->IVal < -0x80) || (Expr->IVal > 0x7F))) { + Warning ("Signed character constant overflow"); + } Expr->IVal = (int8_t)Expr->IVal; break; @@ -1822,7 +1828,7 @@ static void UnaryOp (ExprDesc* Expr) Expr->Type = IntPromotion (Expr->Type); /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); + LimitExprValue (Expr, 1); } else { unsigned Flags; @@ -2162,7 +2168,7 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ } /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); + LimitExprValue (Expr, 1); } else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) { /* If the LHS constant is an int that fits into an unsigned char, change the @@ -2789,7 +2795,7 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) Expr->Type = rhst; } else { /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); + LimitExprValue (Expr, 1); } /* The result is always an rvalue */ @@ -3260,7 +3266,7 @@ static void parsesub (ExprDesc* Expr) /* Just adjust the result type */ Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type); /* And limit the calculated value to the range of it */ - LimitExprValue (Expr); + LimitExprValue (Expr, 1); } /* The result is always an rvalue */ ED_MarkExprAsRVal (Expr); diff --git a/src/cc65/expr.h b/src/cc65/expr.h index abdf8ab0d..7c2f426d7 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -59,7 +59,7 @@ void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr); ** generated code. */ -void LimitExprValue (ExprDesc* Expr); +void LimitExprValue (ExprDesc* Expr, int WarnOverflow); /* Limit the constant value of the expression to the range of its type */ void PushAddr (const ExprDesc* Expr); diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c index eb879a475..312086f3c 100644 --- a/src/cc65/shiftexpr.c +++ b/src/cc65/shiftexpr.c @@ -173,7 +173,7 @@ void ShiftExpr (struct ExprDesc* Expr) } /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr); + LimitExprValue (Expr, 1); } /* Result is already got, remove the generated code */ From 66698d4b1a03dc7fbff8d1f99d1365a17fef56b6 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 14 Oct 2022 16:47:11 -0400 Subject: [PATCH 064/360] Rephrasing warnings for suspicious decimal integer constants --- src/cc65/scanner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 66ce6906e..36fd1301b 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -643,7 +643,7 @@ static void NumericConst (void) if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && (WarnTypes & IT_LONG) != 0) { - Warning ("Integer constant is long"); + Warning ("Integer constant implies signed long"); } } if (IVal > 0xFFFF) { @@ -660,7 +660,7 @@ static void NumericConst (void) ** a preceding unary op or when it is used in constant calculation. */ if (WarnTypes & IT_ULONG) { - Warning ("Integer constant is unsigned long"); + Warning ("Integer constant implies unsigned long"); } } From b052e64089f0f1b5d5462a17b480bcefbca46f38 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Mon, 17 Oct 2022 13:32:38 +0300 Subject: [PATCH 065/360] Speed up sim65 by 10% --- src/sim65/memory.c | 10 +--------- src/sim65/memory.h | 11 ++++++++++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/sim65/memory.c b/src/sim65/memory.c index 11f0be55a..68e7bb93b 100644 --- a/src/sim65/memory.c +++ b/src/sim65/memory.c @@ -46,7 +46,7 @@ /* THE memory */ -static unsigned char Mem[0x10000]; +unsigned char Mem[0x10000]; @@ -73,14 +73,6 @@ void MemWriteWord (unsigned Addr, unsigned Val) -unsigned char MemReadByte (unsigned Addr) -/* Read a byte from a memory location */ -{ - return Mem[Addr]; -} - - - unsigned MemReadWord (unsigned Addr) /* Read a word from a memory location */ { diff --git a/src/sim65/memory.h b/src/sim65/memory.h index 41cc800d3..cef786aaa 100644 --- a/src/sim65/memory.h +++ b/src/sim65/memory.h @@ -36,7 +36,9 @@ #ifndef MEMORY_H #define MEMORY_H +#include "inline.h" +extern unsigned char Mem[0x10000]; /*****************************************************************************/ /* Code */ @@ -50,8 +52,15 @@ void MemWriteByte (unsigned Addr, unsigned char Val); void MemWriteWord (unsigned Addr, unsigned Val); /* Write a word to a memory location */ -unsigned char MemReadByte (unsigned Addr); +#if defined(HAVE_INLINE) +INLINE unsigned char MemReadByte (unsigned Addr) /* Read a byte from a memory location */ +{ + return Mem[Addr]; +} +#else +#define MemReadByte(Addr) Mem[Addr] +#endif unsigned MemReadWord (unsigned Addr); /* Read a word from a memory location */ From b81e54c1d2fc784eb33c522f34fe970957cb7975 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Mon, 24 Oct 2022 14:55:39 +0800 Subject: [PATCH 066/360] Organized ExprDesc functions and fixed several comments. --- src/cc65/exprdesc.c | 405 +++++++++++++++++++++++--------------------- src/cc65/exprdesc.h | 312 +++++++++++++++++++--------------- 2 files changed, 387 insertions(+), 330 deletions(-) diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 3d7b7c384..5924ab6cf 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -67,75 +67,9 @@ ExprDesc* ED_Init (ExprDesc* Expr) -#if !defined(HAVE_INLINE) -int ED_IsLocQuasiConst (const ExprDesc* Expr) -/* Return true if the expression is a constant location of some sort or on the -** stack. -*/ -{ - return ED_IsLocConst (Expr) || ED_IsLocStack (Expr); -} -#endif - - - -#if !defined(HAVE_INLINE) -int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) -/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ -{ - return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr); -} -#endif - - - -#if !defined(HAVE_INLINE) -int ED_IsIndExpr (const ExprDesc* Expr) -/* Check if the expression is a reference to its value */ -{ - return (Expr->Flags & E_ADDRESS_OF) == 0 && - !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); -} -#endif - - - -int ED_YetToLoad (const ExprDesc* Expr) -/* Check if the expression needs to be loaded somehow. */ -{ - return ED_NeedsPrimary (Expr) || - ED_YetToTest (Expr) || - (ED_IsLVal (Expr) && IsQualVolatile (Expr->Type)); -} - - - -void ED_MarkForUneval (ExprDesc* Expr) -/* Mark the expression as not to be evaluated */ -{ - Expr->Flags = (Expr->Flags & ~E_MASK_EVAL) | E_EVAL_UNEVAL; -} - - - -void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End) -/* Set the code range for this expression */ -{ - Expr->Flags |= E_HAVE_MARKS; - Expr->Start = *Start; - Expr->End = *End; -} - - - -int ED_CodeRangeIsEmpty (const ExprDesc* Expr) -/* Return true if no code was output for this expression */ -{ - /* We must have code marks */ - PRECONDITION (Expr->Flags & E_HAVE_MARKS); - - return CodeRangeIsEmpty (&Expr->Start, &Expr->End); -} +/*****************************************************************************/ +/* Info Extraction */ +/*****************************************************************************/ @@ -215,6 +149,190 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs) +/*****************************************************************************/ +/* Predicates */ +/*****************************************************************************/ + + + +#if !defined(HAVE_INLINE) +int ED_IsLocQuasiConst (const ExprDesc* Expr) +/* Return true if the expression is a constant location of some sort or on the +** stack. +*/ +{ + return ED_IsLocConst (Expr) || ED_IsLocStack (Expr); +} +#endif + + + +#if !defined(HAVE_INLINE) +int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) +/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ +{ + return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr); +} +#endif + + + +#if !defined(HAVE_INLINE) +int ED_IsIndExpr (const ExprDesc* Expr) +/* Check if the expression is a reference to its value */ +{ + return (Expr->Flags & E_ADDRESS_OF) == 0 && + !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); +} +#endif + + + +int ED_YetToLoad (const ExprDesc* Expr) +/* Check if the expression needs to be loaded somehow. */ +{ + return ED_NeedsPrimary (Expr) || + ED_YetToTest (Expr) || + (ED_IsLVal (Expr) && IsQualVolatile (Expr->Type)); +} + + + +#if !defined(HAVE_INLINE) +int ED_IsAbs (const ExprDesc* Expr) +/* Return true if the expression denotes a numeric value or address. */ +{ + return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) || + (Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF); +} +#endif + + + +#if !defined(HAVE_INLINE) +int ED_IsConstAbs (const ExprDesc* Expr) +/* Return true if the expression denotes a constant absolute value. This can be +** a numeric constant, cast to any type. +*/ +{ + return ED_IsRVal (Expr) && ED_IsAbs (Expr); +} +#endif + + + +int ED_IsConstAbsInt (const ExprDesc* Expr) +/* Return true if the expression is a constant (numeric) integer. */ +{ + return ED_IsConstAbs (Expr) && IsClassInt (Expr->Type); +} + + + +int ED_IsConstBool (const ExprDesc* Expr) +/* Return true if the expression can be constantly evaluated as a boolean. */ +{ + return ED_IsConstAbsInt (Expr) || ED_IsAddrExpr (Expr); +} + + + +int ED_IsConstTrue (const ExprDesc* Expr) +/* Return true if the constant expression can be evaluated as boolean true at +** compile time. +*/ +{ + /* Non-zero arithmetics and objects addresses are boolean true */ + return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) || + (ED_IsAddrExpr (Expr)); +} + + + +int ED_IsConstFalse (const ExprDesc* Expr) +/* Return true if the constant expression can be evaluated as boolean false at +** compile time. +*/ +{ + /* Zero arithmetics and null pointers are boolean false */ + return (ED_IsConstAbsInt (Expr) && Expr->IVal == 0) || + ED_IsNullPtr (Expr); +} + + + +int ED_IsConst (const ExprDesc* Expr) +/* Return true if the expression denotes a constant of some sort. This can be a +** numeric constant, the address of a global variable (maybe with offset) or +** similar. +*/ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsConstAddr (Expr); +} + + + +int ED_IsQuasiConst (const ExprDesc* Expr) +/* Return true if the expression denotes a quasi-constant of some sort. This +** can be a numeric constant, a constant address or a stack variable address. +*/ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsQuasiConstAddr (Expr); +} + + + +int ED_IsConstAddr (const ExprDesc* Expr) +/* Return true if the expression denotes a constant address of some sort. This +** can be the address of a global variable (maybe with offset) or similar. +*/ +{ + return ED_IsAddrExpr (Expr) && ED_IsLocConst (Expr); +} + + + +int ED_IsQuasiConstAddr (const ExprDesc* Expr) +/* Return true if the expression denotes a quasi-constant address of some sort. +** This can be a constant address or a stack variable address. +*/ +{ + return ED_IsAddrExpr (Expr) && ED_IsLocQuasiConst (Expr); +} + + + +int ED_IsNullPtr (const ExprDesc* Expr) +/* Return true if the given expression is a NULL pointer constant */ +{ + return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == + (E_LOC_NONE|E_RTYPE_RVAL) && + Expr->IVal == 0 && + IsClassInt (Expr->Type); +} + + + +int ED_IsBool (const ExprDesc* Expr) +/* Return true if the expression can be treated as a boolean, that is, it can +** be an operand to a compare operation. +*/ +{ + /* Either ints, floats, or pointers can be used in a boolean context */ + return IsClassInt (Expr->Type) || + IsClassFloat (Expr->Type) || + IsClassPtr (Expr->Type) || + IsClassFunc (Expr->Type); +} + + + +/*****************************************************************************/ +/* Manipulation */ +/*****************************************************************************/ + + + ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type) /* Replace Expr with an absolute const with the given value and type */ { @@ -331,7 +449,7 @@ ExprDesc* ED_IndExpr (ExprDesc* Expr) ** original address. We simply mark this as E_LOC_EXPR so that ** some info about the original location can be retained. ** If it's really meant to dereference a "pointer value", it - ** should be done in two steps where the pointervalue should + ** should be done in two steps where the pointer value should ** be the manually loaded first before a call into this, and ** the offset should be manually cleared somewhere outside. */ @@ -345,131 +463,27 @@ ExprDesc* ED_IndExpr (ExprDesc* Expr) -#if !defined(HAVE_INLINE) -int ED_IsAbs (const ExprDesc* Expr) -/* Return true if the expression denotes a numeric value or address. */ +void ED_MarkForUneval (ExprDesc* Expr) +/* Mark the expression as not to be evaluated */ { - return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) || - (Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF); -} -#endif - - - -#if !defined(HAVE_INLINE) -int ED_IsConstAbs (const ExprDesc* Expr) -/* Return true if the expression denotes a constant absolute value. This can be -** a numeric constant, cast to any type. -*/ -{ - return ED_IsRVal (Expr) && ED_IsAbs (Expr); -} -#endif - - - -int ED_IsConstAbsInt (const ExprDesc* Expr) -/* Return true if the expression is a constant (numeric) integer. */ -{ - return ED_IsConstAbs (Expr) && IsClassInt (Expr->Type); + Expr->Flags = (Expr->Flags & ~E_MASK_EVAL) | E_EVAL_UNEVAL; } -int ED_IsConstBool (const ExprDesc* Expr) -/* Return true if the expression can be constantly evaluated as a boolean. */ +const Type* ReplaceType (ExprDesc* Expr, const Type* NewType) +/* Replace the type of Expr by a copy of Newtype and return the old type string */ { - return ED_IsConstAbsInt (Expr) || ED_IsAddrExpr (Expr); + const Type* OldType = Expr->Type; + Expr->Type = TypeDup (NewType); + return OldType; } -int ED_IsConstTrue (const ExprDesc* Expr) -/* Return true if the constant expression can be evaluated as boolean true at -** compile time. -*/ -{ - /* Non-zero arithmetics and objects addresses are boolean true */ - return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) || - (ED_IsAddrExpr (Expr)); -} - - - -int ED_IsConstFalse (const ExprDesc* Expr) -/* Return true if the constant expression can be evaluated as boolean false at -** compile time. -*/ -{ - /* Zero arithmetics and null pointers are boolean false */ - return (ED_IsConstAbsInt (Expr) && Expr->IVal == 0) || - ED_IsNullPtr (Expr); -} - - - -int ED_IsConst (const ExprDesc* Expr) -/* Return true if the expression denotes a constant of some sort. This can be a -** numeric constant, the address of a global variable (maybe with offset) or -** similar. -*/ -{ - return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsConstAddr (Expr); -} - - - -int ED_IsQuasiConst (const ExprDesc* Expr) -/* Return true if the expression denotes a quasi-constant of some sort. This -** can be a numeric constant, a constant address or a stack variable address. -*/ -{ - return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsQuasiConstAddr (Expr); -} - - -int ED_IsConstAddr (const ExprDesc* Expr) -/* Return true if the expression denotes a constant address of some sort. This -** can be the address of a global variable (maybe with offset) or similar. -*/ -{ - return ED_IsAddrExpr (Expr) && ED_IsLocConst (Expr); -} - - - -int ED_IsQuasiConstAddr (const ExprDesc* Expr) -/* Return true if the expression denotes a quasi-constant address of some sort. -** This can be a constant address or a stack variable address. -*/ -{ - return ED_IsAddrExpr (Expr) && ED_IsLocQuasiConst (Expr); -} - - - -int ED_IsNullPtr (const ExprDesc* Expr) -/* Return true if the given expression is a NULL pointer constant */ -{ - return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == - (E_LOC_NONE|E_RTYPE_RVAL) && - Expr->IVal == 0 && - IsClassInt (Expr->Type); -} - - - -int ED_IsBool (const ExprDesc* Expr) -/* Return true if the expression can be treated as a boolean, that is, it can -** be an operand to a compare operation. -*/ -{ - /* Either ints, floats, or pointers can be used in a boolean context */ - return IsClassInt (Expr->Type) || - IsClassFloat (Expr->Type) || - IsClassPtr (Expr->Type) || - IsClassFunc (Expr->Type); -} +/*****************************************************************************/ +/* Other Helpers */ +/*****************************************************************************/ @@ -577,10 +591,21 @@ void PrintExprDesc (FILE* F, ExprDesc* E) -const Type* ReplaceType (ExprDesc* Expr, const Type* NewType) -/* Replace the type of Expr by a copy of Newtype and return the old type string */ +void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End) +/* Set the code range for this expression */ { - const Type* OldType = Expr->Type; - Expr->Type = TypeDup (NewType); - return OldType; + Expr->Flags |= E_HAVE_MARKS; + Expr->Start = *Start; + Expr->End = *End; +} + + + +int ED_CodeRangeIsEmpty (const ExprDesc* Expr) +/* Return true if no code was output for this expression */ +{ + /* We must have code marks */ + PRECONDITION (Expr->Flags & E_HAVE_MARKS); + + return CodeRangeIsEmpty (&Expr->Start, &Expr->End); } diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index f1f121cc4..2ef8b617f 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -227,6 +227,14 @@ struct ExprDesc { ExprDesc* ED_Init (ExprDesc* Expr); /* Initialize an ExprDesc */ + + +/*****************************************************************************/ +/* Info Extraction */ +/*****************************************************************************/ + + + #if defined(HAVE_INLINE) INLINE int ED_GetLoc (const ExprDesc* Expr) /* Return the location flags from the expression */ @@ -237,6 +245,35 @@ INLINE int ED_GetLoc (const ExprDesc* Expr) # define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC) #endif +#if defined(HAVE_INLINE) +INLINE int ED_GetNeeds (const ExprDesc* Expr) +/* Get flags about what the expression needs. */ +{ + return (Expr->Flags & E_MASK_NEED); +} +#else +# define ED_GetNeeds(Expr) ((Expr)->Flags & E_MASK_NEED) +#endif + +const char* ED_GetLabelName (const ExprDesc* Expr, long Offs); +/* Return the assembler label name of the given expression. Beware: This +** function may use a static buffer, so the name may get "lost" on the second +** call to the function. +*/ + +int ED_GetStackOffs (const ExprDesc* Expr, int Offs); +/* Get the stack offset of an address on the stack in Expr taking into account +** an additional offset in Offs. +*/ + + + +/*****************************************************************************/ +/* Predicates */ +/*****************************************************************************/ + + + #if defined(HAVE_INLINE) INLINE int ED_IsLocNone (const ExprDesc* Expr) /* Return true if the expression is an absolute value */ @@ -279,7 +316,7 @@ INLINE int ED_IsLocStack (const ExprDesc* Expr) #if defined(HAVE_INLINE) INLINE int ED_IsLocPrimary (const ExprDesc* Expr) -/* Return true if the expression is an expression in the register pseudo variable */ +/* Return true if the expression is an expression in the primary */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY; } @@ -289,7 +326,7 @@ INLINE int ED_IsLocPrimary (const ExprDesc* Expr) #if defined(HAVE_INLINE) INLINE int ED_IsLocExpr (const ExprDesc* Expr) -/* Return true if the expression is an expression in the primary */ +/* Return true if the expression is an expression referenced in the primary */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR; } @@ -333,33 +370,14 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr); #endif #if defined(HAVE_INLINE) -INLINE void ED_RequireTest (ExprDesc* Expr) -/* Mark the expression for a test. */ +INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) +/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ { - Expr->Flags |= E_NEED_TEST; + return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr); } #else -# define ED_RequireTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0) -#endif - -#if defined(HAVE_INLINE) -INLINE void ED_RequireNoTest (ExprDesc* Expr) -/* Mark the expression not for a test. */ -{ - Expr->Flags &= ~E_NEED_TEST; -} -#else -# define ED_RequireNoTest(Expr) do { (Expr)->Flags &= ~E_NEED_TEST; } while (0) -#endif - -#if defined(HAVE_INLINE) -INLINE int ED_GetNeeds (const ExprDesc* Expr) -/* Get flags about what the expression needs. */ -{ - return (Expr->Flags & E_MASK_NEED); -} -#else -# define ED_GetNeeds(Expr) ((Expr)->Flags & E_MASK_NEED) +int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr); +/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ #endif #if defined(HAVE_INLINE) @@ -382,27 +400,6 @@ INLINE int ED_NeedsTest (const ExprDesc* Expr) # define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0) #endif -#if defined(HAVE_INLINE) -INLINE int ED_YetToTest (const ExprDesc* Expr) -/* Check if the expression needs to be tested but not yet. */ -{ - return ((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST; -} -#else -# define ED_YetToTest(Expr) (((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST) -#endif - -#if defined(HAVE_INLINE) -INLINE void ED_TestDone (ExprDesc* Expr) -/* Mark the expression as tested and condition codes set. */ -{ - Expr->Flags |= E_CC_SET; -} -#else -# define ED_TestDone(Expr) \ - do { (Expr)->Flags |= E_CC_SET; } while (0) -#endif - #if defined(HAVE_INLINE) INLINE int ED_IsTested (const ExprDesc* Expr) /* Check if the expression has set the condition codes. */ @@ -414,13 +411,13 @@ INLINE int ED_IsTested (const ExprDesc* Expr) #endif #if defined(HAVE_INLINE) -INLINE void ED_MarkAsUntested (ExprDesc* Expr) -/* Mark the expression as not tested (condition codes not set). */ +INLINE int ED_YetToTest (const ExprDesc* Expr) +/* Check if the expression needs to be tested but not yet. */ { - Expr->Flags &= ~E_CC_SET; + return ((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST; } #else -# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0) +# define ED_YetToTest(Expr) (((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST) #endif #if defined(HAVE_INLINE) @@ -448,9 +445,6 @@ INLINE int ED_NeedsConst (const ExprDesc* Expr) # define ED_NeedsConst(Expr) (((Expr)->Flags & E_EVAL_IMMUTABLE_RESULT) == E_EVAL_IMMUTABLE_RESULT) #endif -void ED_MarkForUneval (ExprDesc* Expr); -/* Mark the expression as not to be evaluated */ - #if defined(HAVE_INLINE) INLINE int ED_IsUneval (const ExprDesc* Expr) /* Check if the expression is not to be evaluated */ @@ -471,27 +465,6 @@ INLINE int ED_MayHaveNoEffect (const ExprDesc* Expr) # define ED_MayHaveNoEffect(Expr) (((Expr)->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED) #endif -#if defined(HAVE_INLINE) -INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr) -/* Propagate viral flags from subexpression */ -{ - Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL; -} -#else -# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL) -#endif - -#if defined(HAVE_INLINE) -INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) -/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ -{ - return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr); -} -#else -int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr); -/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ -#endif - #if defined(HAVE_INLINE) INLINE int ED_IsAddrExpr (const ExprDesc* Expr) /* Check if the expression is taken address of instead of its value. @@ -515,35 +488,6 @@ int ED_IsIndExpr (const ExprDesc* Expr); /* Check if the expression is a reference to its value */ #endif -void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End); -/* Set the code range for this expression */ - -int ED_CodeRangeIsEmpty (const ExprDesc* Expr); -/* Return true if no code was output for this expression */ - -const char* ED_GetLabelName (const ExprDesc* Expr, long Offs); -/* Return the assembler label name of the given expression. Beware: This -** function may use a static buffer, so the name may get "lost" on the second -** call to the function. -*/ - -int ED_GetStackOffs (const ExprDesc* Expr, int Offs); -/* Get the stack offset of an address on the stack in Expr taking into account -** an additional offset in Offs. -*/ - -ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type); -/* Replace Expr with an absolute const with the given value and type */ - -ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value); -/* Replace Expr with an constant integer with the given value */ - -ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value); -/* Replace Expr with a constant boolean expression with the given value */ - -ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr); -/* Finalize the result of LoadExpr to be an rvalue in the primary register */ - #if defined(HAVE_INLINE) INLINE int ED_IsLVal (const ExprDesc* Expr) /* Return true if the expression is a reference */ @@ -564,40 +508,6 @@ INLINE int ED_IsRVal (const ExprDesc* Expr) # define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL) #endif -#if defined(HAVE_INLINE) -INLINE void ED_MarkExprAsLVal (ExprDesc* Expr) -/* Mark the expression as an lvalue. -** HINT: Consider using ED_IndExpr instead of this, unless you know what -** consequence there will be, as there are both a big part in the code -** assuming rvalue = const and a big part assuming rvalue = address. -*/ -{ - Expr->Flags |= E_RTYPE_LVAL; -} -#else -# define ED_MarkExprAsLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0) -#endif - -#if defined(HAVE_INLINE) -INLINE void ED_MarkExprAsRVal (ExprDesc* Expr) -/* Mark the expression as an rvalue. -** HINT: Consider using ED_AddrExpr instead of this, unless you know what -** consequence there will be, as there are both a big part in the code -** assuming rvalue = const and a big part assuming rvalue = address. -*/ -{ - Expr->Flags &= ~E_RTYPE_LVAL; -} -#else -# define ED_MarkExprAsRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0) -#endif - -ExprDesc* ED_AddrExpr (ExprDesc* Expr); -/* Take address of Expr */ - -ExprDesc* ED_IndExpr (ExprDesc* Expr); -/* Dereference Expr */ - #if defined(HAVE_INLINE) INLINE int ED_IsAbs (const ExprDesc* Expr) /* Return true if the expression denotes a numeric value or address. */ @@ -670,14 +580,136 @@ int ED_IsBool (const ExprDesc* Expr); ** be an operand to a compare operation with 0/NULL. */ -void PrintExprDesc (FILE* F, ExprDesc* Expr); -/* Print an ExprDesc */ + + +/*****************************************************************************/ +/* Manipulation */ +/*****************************************************************************/ + + + +ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type); +/* Replace Expr with an absolute const with the given value and type */ + +ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value); +/* Replace Expr with an constant integer with the given value */ + +ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value); +/* Replace Expr with a constant boolean expression with the given value */ + +ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr); +/* Finalize the result of LoadExpr to be an rvalue in the primary register */ + +#if defined(HAVE_INLINE) +INLINE void ED_MarkExprAsLVal (ExprDesc* Expr) +/* Mark the expression as an lvalue. +** HINT: Consider using ED_IndExpr instead of this, unless you know what +** consequence there will be, as there are both a big part in the code +** assuming rvalue = const and a big part assuming rvalue = address. +*/ +{ + Expr->Flags |= E_RTYPE_LVAL; +} +#else +# define ED_MarkExprAsLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0) +#endif + +#if defined(HAVE_INLINE) +INLINE void ED_MarkExprAsRVal (ExprDesc* Expr) +/* Mark the expression as an rvalue. +** HINT: Consider using ED_AddrExpr instead of this, unless you know what +** consequence there will be, as there are both a big part in the code +** assuming rvalue = const and a big part assuming rvalue = address. +*/ +{ + Expr->Flags &= ~E_RTYPE_LVAL; +} +#else +# define ED_MarkExprAsRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0) +#endif + +ExprDesc* ED_AddrExpr (ExprDesc* Expr); +/* Take address of Expr */ + +ExprDesc* ED_IndExpr (ExprDesc* Expr); +/* Dereference Expr */ + +#if defined(HAVE_INLINE) +INLINE void ED_RequireTest (ExprDesc* Expr) +/* Mark the expression for a test. */ +{ + Expr->Flags |= E_NEED_TEST; +} +#else +# define ED_RequireTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0) +#endif + +#if defined(HAVE_INLINE) +INLINE void ED_RequireNoTest (ExprDesc* Expr) +/* Mark the expression not for a test. */ +{ + Expr->Flags &= ~E_NEED_TEST; +} +#else +# define ED_RequireNoTest(Expr) do { (Expr)->Flags &= ~E_NEED_TEST; } while (0) +#endif + +#if defined(HAVE_INLINE) +INLINE void ED_TestDone (ExprDesc* Expr) +/* Mark the expression as tested and condition codes set. */ +{ + Expr->Flags |= E_CC_SET; +} +#else +# define ED_TestDone(Expr) \ + do { (Expr)->Flags |= E_CC_SET; } while (0) +#endif + +#if defined(HAVE_INLINE) +INLINE void ED_MarkAsUntested (ExprDesc* Expr) +/* Mark the expression as not tested (condition codes not set). */ +{ + Expr->Flags &= ~E_CC_SET; +} +#else +# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0) +#endif + +void ED_MarkForUneval (ExprDesc* Expr); +/* Mark the expression as not to be evaluated */ + +#if defined(HAVE_INLINE) +INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr) +/* Propagate viral flags from subexpression */ +{ + Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL; +} +#else +# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL) +#endif const Type* ReplaceType (ExprDesc* Expr, const Type* NewType); /* Replace the type of Expr by a copy of Newtype and return the old type string */ +/*****************************************************************************/ +/* Other Helpers */ +/*****************************************************************************/ + + + +void PrintExprDesc (FILE* F, ExprDesc* Expr); +/* Print an ExprDesc */ + +void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End); +/* Set the code range for this expression */ + +int ED_CodeRangeIsEmpty (const ExprDesc* Expr); +/* Return true if no code was output for this expression */ + + + /* End of exprdesc.h */ #endif From c95c9c27496ba0302203f29ec5597c491dddf543 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Thu, 27 Oct 2022 18:19:44 +0300 Subject: [PATCH 067/360] Allow specifying range end as a size --- doc/da65.sgml | 3 ++- src/da65/infofile.c | 16 +++++++++++++--- src/da65/scanner.c | 8 ++++++++ src/da65/scanner.h | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/doc/da65.sgml b/doc/da65.sgml index bf074a667..185dbe0e6 100644 --- a/doc/da65.sgml +++ b/doc/da65.sgml @@ -461,7 +461,8 @@ following attributes are recognized: <tag><tt>END</tt></tag> This gives the end address of the range. The end address is inclusive, that means, it is part of the range. Of course, it may not be smaller than the - start address. + start address. Optionally, the end may be given as a decimal offset instead + of an absolute address, "+3", to specify it as a size. <tag><tt>NAME</tt></tag> This is a convenience attribute. It takes a string argument and will cause diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 6db82cb36..48a95c9b0 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -592,9 +592,19 @@ static void RangeSection (void) case INFOTOK_END: AddAttr ("END", &Attributes, tEnd); InfoNextTok (); - InfoAssureInt (); - InfoRangeCheck (0x0000, 0xFFFF); - End = InfoIVal; + + if (InfoTok == INFOTOK_OFFSET_INTCON) { + InfoRangeCheck (0x0000, 0xFFFF); + if (!(Attributes & tStart)) + InfoError ("When using End with an offset, Start must be specified before"); + End = Start + InfoIVal - 1; + if (End > 0xFFFF) + InfoError ("Range error"); + } else { + InfoAssureInt (); + InfoRangeCheck (0x0000, 0xFFFF); + End = InfoIVal; + } InfoNextTok (); break; diff --git a/src/da65/scanner.c b/src/da65/scanner.c index 33fb3a826..d0301c08a 100644 --- a/src/da65/scanner.c +++ b/src/da65/scanner.c @@ -372,6 +372,14 @@ Again: return; } + /* Decimal number offset? */ + if (C == '+') { + NextChar (); + InfoIVal = GetDecimalToken (); + InfoTok = INFOTOK_OFFSET_INTCON; + return; + } + /* Other characters */ switch (C) { diff --git a/src/da65/scanner.h b/src/da65/scanner.h index d4e38177b..63d3273f6 100644 --- a/src/da65/scanner.h +++ b/src/da65/scanner.h @@ -48,6 +48,7 @@ typedef enum token_t { INFOTOK_NONE, INFOTOK_INTCON, + INFOTOK_OFFSET_INTCON, INFOTOK_STRCON, INFOTOK_CHARCON, INFOTOK_IDENT, From d84cc2d1229831e35af27401a5fd5c647402b40e Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 13:56:55 +0800 Subject: [PATCH 068/360] Fixed errors in the conditional operator "? :" parser. --- src/cc65/expr.c | 16 +++++++++------- src/cc65/ppexpr.c | 2 +- test/err/bug1893.c | 8 ++++++++ 3 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 test/err/bug1893.c diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 8c042cc3c..b1c5059bc 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3869,9 +3869,9 @@ static void hieQuest (ExprDesc* Expr) ED_FinalizeRValLoad (&Expr2); } else { - /* Constant boolean subexpression could still have deferred inc/ - ** dec operations, so just flush their side-effects at this - ** sequence point. + /* Constant subexpression could still have deferred inc/dec + ** operations, so just flush their side-effects at this sequence + ** point. */ DoDeferred (SQP_KEEP_NONE, &Expr2); } @@ -3907,7 +3907,7 @@ static void hieQuest (ExprDesc* Expr) /* Parse third expression. Remember for later if it is a NULL pointer ** expression, then load it into the primary. */ - ExprWithCheck (hie1, &Expr3); + ExprWithCheck (hieQuest, &Expr3); Expr3IsNULL = ED_IsNullPtr (&Expr3); if (!IsTypeVoid (Expr3.Type) && ED_YetToLoad (&Expr3) && @@ -3920,9 +3920,9 @@ static void hieQuest (ExprDesc* Expr) ED_FinalizeRValLoad (&Expr3); } else { - /* Constant boolean subexpression could still have deferred inc/ - ** dec operations, so just flush their side-effects at this - ** sequence point. + /* Constant subexpression could still have deferred inc/dec + ** operations, so just flush their side-effects at this sequence + ** point. */ DoDeferred (SQP_KEEP_NONE, &Expr3); } @@ -4036,6 +4036,8 @@ static void hieQuest (ExprDesc* Expr) } else { *Expr = Expr3; } + /* The result expression is always an rvalue */ + ED_MarkExprAsRVal (Expr); } /* Setup the target expression */ diff --git a/src/cc65/ppexpr.c b/src/cc65/ppexpr.c index dd129ced9..0942dc8f8 100644 --- a/src/cc65/ppexpr.c +++ b/src/cc65/ppexpr.c @@ -752,7 +752,7 @@ static void PPhieQuest (PPExpr* Expr) /* Parse third expression */ PPExprInit (&Expr3); - PPhie1 (&Expr3); + PPhieQuest (&Expr3); /* Set the result */ Expr->IVal = Expr->IVal ? Expr2.IVal != 0 : Expr3.IVal != 0; diff --git a/test/err/bug1893.c b/test/err/bug1893.c new file mode 100644 index 000000000..455256179 --- /dev/null +++ b/test/err/bug1893.c @@ -0,0 +1,8 @@ +/* bug #1893 - Compiler accepts a ternary expression where it shouldn't */ + +int main(void) +{ + int a, b, c; + a == 1? b : c = 3; + return 0; +} From 8fb25766263ad3a6201666828e5bed3266f35900 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 14:09:15 +0800 Subject: [PATCH 069/360] Fixed processing '\\' followed with a newline and line number output (-E) with it. --- src/cc65/input.c | 13 +++++++------ src/cc65/preproc.c | 24 ++++++++++++++++++++---- src/cc65/preproc.h | 3 +++ test/val/bug1891.c | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 test/val/bug1891.c diff --git a/src/cc65/input.c b/src/cc65/input.c index 8c8007504..f01723783 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -578,15 +578,16 @@ int NextLine (void) SB_Drop (Line, 1); } - /* If we don't have a line continuation character at the end, - ** we're done with this line. Otherwise replace the character - ** by a newline and continue reading. + /* If we don't have a line continuation character at the end, we + ** are done with this line. Otherwise just skip the character and + ** continue reading. */ - if (SB_LookAtLast (Line) == '\\') { - Line->Buf[Line->Len-1] = '\n'; - } else { + if (SB_LookAtLast (Line) != '\\') { Input->MissingNL = 0; break; + } else { + SB_Drop (Line, 1); + ContinueLine (); } } else if (C != '\0') { /* Ignore embedded NULs */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 4bde66318..961e20e0d 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -114,7 +114,8 @@ static StrBuf* MLine; /* Buffer for macro expansion in #pragma */ static StrBuf* OLine; /* Buffer for #pragma output */ /* Newlines to be added to preprocessed text */ -static int PendingNewLines; +static unsigned PendingNewLines; +static unsigned ContinuedLines; static int FileChanged; /* Structure used when expanding macros */ @@ -824,18 +825,24 @@ static void CheckForBadIdent (const char* Ident, int Std, const Macro* M) static void AddPreLine (StrBuf* Str) /* Add newlines to the string buffer */ { + /* No need to prettify the non-exist output */ if (!PreprocessOnly) { PendingNewLines = 0; + ContinuedLines = 0; return; } + /* We'll adjust the line number later if necessary */ + PendingNewLines += ContinuedLines; + if (FileChanged || PendingNewLines > 6) { /* Output #line directives as source info */ StrBuf Comment = AUTO_STRBUF_INITIALIZER; if (SB_NotEmpty (Str) && SB_LookAtLast (Str) != '\n') { SB_AppendChar (Str, '\n'); } - SB_Printf (&Comment, "#line %u \"%s\"\n", GetCurrentLine (), GetCurrentFile ()); + SB_Printf (&Comment, "#line %u \"%s\"\n", + GetCurrentLine () - ContinuedLines, GetCurrentFile ()); SB_Append (Str, &Comment); } else { /* Output new lines */ @@ -846,6 +853,7 @@ static void AddPreLine (StrBuf* Str) } FileChanged = 0; PendingNewLines = 0; + ContinuedLines = 0; } @@ -1528,14 +1536,14 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in /* Read the actual macro arguments */ while (1) { /* Squeeze runs of blanks within an arg */ - int OldPendingNewLines = PendingNewLines; + unsigned OldPendingNewLines = PendingNewLines; int Skipped = SkipWhitespace (MultiLine); /* Directives can only be found in an argument list that spans ** multiple lines. */ if (MultiLine && OldPendingNewLines < PendingNewLines && CurC == '#') { - int Newlines = 0; + unsigned Newlines = 0; while (OldPendingNewLines < PendingNewLines && CurC == '#') { Newlines += PendingNewLines - OldPendingNewLines; @@ -3362,6 +3370,14 @@ void SetPPIfStack (PPIfStack* Stack) +void ContinueLine (void) +/* Continue the current line ended with a '\\' */ +{ + ++ContinuedLines; +} + + + void PreprocessBegin (void) /* Initialize preprocessor with current file */ { diff --git a/src/cc65/preproc.h b/src/cc65/preproc.h index 153d0d68a..e2a1b073c 100644 --- a/src/cc65/preproc.h +++ b/src/cc65/preproc.h @@ -68,6 +68,9 @@ void Preprocess (void); void SetPPIfStack (PPIfStack* Stack); /* Specify which PP #if stack to use */ +void ContinueLine (void); +/* Continue the current line ended with a '\\' */ + void PreprocessBegin (void); /* Initialize preprocessor with current file */ diff --git a/test/val/bug1891.c b/test/val/bug1891.c new file mode 100644 index 000000000..0373ba46d --- /dev/null +++ b/test/val/bug1891.c @@ -0,0 +1,19 @@ +/* bug #1891 - backslash/newline sequence in string constants is treated wrong */ + +#include <stdio.h> +#include <string.h> + +const char* a = "hello \ +world"; +const char* b = \ +"hello world"; + +int main(void) +{ + if (strcmp(a, b) != 0) { + printf("a:\n%s\n", a); + printf("b:\n%s\n", b); + return 1; + } + return 0; +} From e9413567d7b10c7eb34f9825378fc3cdeb869c64 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 14:16:15 +0800 Subject: [PATCH 070/360] Renamed several functions relevent with input file info. --- src/cc65/error.c | 10 +++++----- src/cc65/input.c | 6 +++--- src/cc65/input.h | 6 +++--- src/cc65/locals.c | 2 +- src/cc65/preproc.c | 12 ++++++------ src/cc65/symtab.c | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/cc65/error.c b/src/cc65/error.c index e99465c87..3f36d9e97 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -120,7 +120,7 @@ static const char* GetDiagnosticFileName (void) if (CurTok.LI) { return GetInputName (CurTok.LI); } else { - return GetCurrentFile (); + return GetCurrentFilename (); } } @@ -132,7 +132,7 @@ static unsigned GetDiagnosticLineNum (void) if (CurTok.LI) { return GetInputLine (CurTok.LI); } else { - return GetCurrentLine (); + return GetCurrentLineNum (); } } @@ -238,7 +238,7 @@ void PPError (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntError (GetCurrentFile(), GetCurrentLine(), Format, ap); + IntError (GetCurrentFilename(), GetCurrentLineNum(), Format, ap); va_end (ap); } @@ -301,7 +301,7 @@ void PPWarning (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap); + IntWarning (GetCurrentFilename(), GetCurrentLineNum(), Format, ap); va_end (ap); } @@ -379,7 +379,7 @@ void PPNote (const char* Format, ...) { va_list ap; va_start (ap, Format); - IntNote (GetCurrentFile(), GetCurrentLine(), Format, ap); + IntNote (GetCurrentFilename(), GetCurrentLineNum(), Format, ap); va_end (ap); } diff --git a/src/cc65/input.c b/src/cc65/input.c index f01723783..89c471687 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -653,7 +653,7 @@ const char* GetInputFile (const struct IFile* IF) -const char* GetCurrentFile (void) +const char* GetCurrentFilename (void) /* Return the name of the current input file */ { unsigned AFileCount = CollCount (&AFiles); @@ -668,7 +668,7 @@ const char* GetCurrentFile (void) -unsigned GetCurrentLine (void) +unsigned GetCurrentLineNum (void) /* Return the line number in the current input file */ { unsigned AFileCount = CollCount (&AFiles); @@ -683,7 +683,7 @@ unsigned GetCurrentLine (void) -void SetCurrentLine (unsigned LineNum) +void SetCurrentLineNum (unsigned LineNum) /* Set the line number in the current input file */ { unsigned AFileCount = CollCount (&AFiles); diff --git a/src/cc65/input.h b/src/cc65/input.h index 951ad3b96..9457bdf9b 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -128,13 +128,13 @@ int PreprocessNextLine (void); const char* GetInputFile (const struct IFile* IF); /* Return a filename from an IFile struct */ -const char* GetCurrentFile (void); +const char* GetCurrentFilename (void); /* Return the name of the current input file */ -unsigned GetCurrentLine (void); +unsigned GetCurrentLineNum (void); /* Return the line number in the current input file */ -void SetCurrentLine (unsigned LineNum); +void SetCurrentLineNum (unsigned LineNum); /* Set the line number in the current input file */ void SetCurrentFilename (const char* Name); diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 5f182f061..0ec28b6c2 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -287,7 +287,7 @@ static void ParseAutoDecl (Declaration* Decl) ** We abuse the Collection somewhat by using it to store line ** numbers. */ - CollReplace (&CurrentFunc->LocalsBlockStack, (void *)(size_t)GetCurrentLine (), + CollReplace (&CurrentFunc->LocalsBlockStack, (void *)(size_t)GetCurrentLineNum (), CollCount (&CurrentFunc->LocalsBlockStack) - 1); } else { diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 961e20e0d..0a9b94bf2 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -842,7 +842,7 @@ static void AddPreLine (StrBuf* Str) SB_AppendChar (Str, '\n'); } SB_Printf (&Comment, "#line %u \"%s\"\n", - GetCurrentLine () - ContinuedLines, GetCurrentFile ()); + GetCurrentLineNum () - ContinuedLines, GetCurrentFilename ()); SB_Append (Str, &Comment); } else { /* Output new lines */ @@ -906,7 +906,7 @@ static void OldStyleComment (void) /* Remember the current line number, so we can output better error ** messages if the comment is not terminated in the current file. */ - unsigned StartingLine = GetCurrentLine (); + unsigned StartingLine = GetCurrentLineNum (); /* Skip the start of comment chars */ NextChar (); @@ -2953,7 +2953,7 @@ static void DoLine (void) /* #line actually sets the line number of the next line */ if (LineNum > 0) { - SetCurrentLine (LineNum - 1); + SetCurrentLineNum (LineNum - 1); /* Check for extra tokens at the end */ CheckExtraTokens ("line"); } @@ -3216,11 +3216,11 @@ void HandleSpecialMacro (Macro* M, const char* Name) SB_Printf (&M->Replacement, "%u", GetCurrentCounter ()); } else if (strcmp (Name, "__LINE__") == 0) { /* Replace __LINE__ with the current line number */ - SB_Printf (&M->Replacement, "%u", GetCurrentLine ()); + SB_Printf (&M->Replacement, "%u", GetCurrentLineNum ()); } else if (strcmp (Name, "__FILE__") == 0) { /* Replace __FILE__ with the current filename */ StrBuf B = AUTO_STRBUF_INITIALIZER; - SB_InitFromString (&B, GetCurrentFile ()); + SB_InitFromString (&B, GetCurrentFilename ()); SB_Clear (&M->Replacement); Stringize (&B, &M->Replacement); SB_Done (&B); @@ -3332,7 +3332,7 @@ void Preprocess (void) PLine = InitLine (PLine); if (Verbosity > 1 && SB_NotEmpty (Line)) { - printf ("%s:%u: %.*s\n", GetCurrentFile (), GetCurrentLine (), + printf ("%s:%u: %.*s\n", GetCurrentFilename (), GetCurrentLineNum (), (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 56e267f85..961f36046 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -1076,7 +1076,7 @@ DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags) DOR = xmalloc (sizeof (DefOrRef)); CollAppend (E->V.L.DefsOrRefs, DOR); - DOR->Line = GetCurrentLine (); + DOR->Line = GetCurrentLineNum (); DOR->LocalsBlockId = (size_t)CollLast (&CurrentFunc->LocalsBlockStack); DOR->Flags = Flags; DOR->StackPtr = StackPtr; @@ -1144,7 +1144,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags) (size_t)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) { Warning ("Goto at line %d to label %s jumps into a block with " "initialization of an object that has automatic storage duration", - GetCurrentLine (), Name); + GetCurrentLineNum (), Name); } } From deb5e977325959430f95d2f7cbf52421aab52657 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 14:22:21 +0800 Subject: [PATCH 071/360] Fixed diagnostic messages on enumerator overflow. An enumerator that would be incremented greater than ULONG_MAX now causes an error. --- src/cc65/declare.c | 25 +++++++++++++------------ test/err/bug1890.c | 9 +++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 test/err/bug1890.c diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 7cc7444b6..2eedfd386 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -611,20 +611,20 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags) } else { - /* Defaulted with the same signedness as the previous member's */ + /* Defaulted with the same signedness as the previous member's */ IsSigned = IsSignSigned (MemberType) && (unsigned long)EnumVal != GetIntegerTypeMax (MemberType); - /* Enumerate. Signed integer overflow is UB but unsigned integers - ** are guaranteed to wrap around. - */ - EnumVal = (long)((unsigned long)EnumVal + 1UL); + /* Enumerate by adding one to the previous value */ + EnumVal = (long)(((unsigned long)EnumVal + 1UL) & 0xFFFFFFFFUL); if (UnqualifiedType (MemberType->C) == T_ULONG && EnumVal == 0) { - /* Warn on 'unsigned long' overflow in enumeration */ - Warning ("Enumerator '%s' overflows the range of '%s'", - Ident, - GetBasicTypeName (type_ulong)); + /* Error since the new value cannot be represented in the + ** largest unsigned integer type supported by cc65 for enum. + */ + Error ("Enumerator '%s' overflows the range of '%s'", + Ident, + GetBasicTypeName (type_ulong)); } IsIncremented = 1; @@ -657,11 +657,12 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags) /* Warn if the incremented value exceeds the range of the previous ** type. */ - if (IsIncremented && - EnumVal >= 0 && + if (PrevErrorCount == ErrorCount && + IsIncremented && + (!IsSigned || EnumVal >= 0) && NewType->C != UnqualifiedType (MemberType->C)) { /* The possible overflow here can only be when EnumVal > 0 */ - Warning ("Enumerator '%s' (value = %lu) is of type '%s'", + Warning ("Enumerator '%s' (value = %lu) implies type '%s'", Ident, (unsigned long)EnumVal, GetBasicTypeName (NewType)); diff --git a/test/err/bug1890.c b/test/err/bug1890.c new file mode 100644 index 000000000..afe04f071 --- /dev/null +++ b/test/err/bug1890.c @@ -0,0 +1,9 @@ +/* bug #1890 - Overflow in enumerator value is not detected */ + +#include <limits.h> +enum { a = ULONG_MAX, b } c = b; + +int main(void) +{ + return 0; +} From d2f74db4d8e0bd03c947cef213110f2340d7503a Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 22:44:57 +0800 Subject: [PATCH 072/360] Fixed compatibility checks on "pointer to pointer" vs "pointer to array" etc. --- src/cc65/typecmp.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 6052f4a84..a84fd2e2e 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -266,18 +266,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) LeftType = (GetUnderlyingTypeCode (lhs) & T_MASK_TYPE); RightType = (GetUnderlyingTypeCode (rhs) & T_MASK_TYPE); - /* If one side is a pointer and the other side is an array, both are - ** compatible. - */ - if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { - RightType = T_TYPE_PTR; - SetResult (Result, TC_PTR_DECAY); - } - if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) { - LeftType = T_TYPE_PTR; - SetResult (Result, TC_STRICT_COMPATIBLE); - } - /* Bit-fields are considered compatible if they have the same ** signedness, bit-offset and bit-width. */ @@ -287,12 +275,27 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) lhs->A.B.Offs != rhs->A.B.Offs || lhs->A.B.Width != rhs->A.B.Width) { SetResult (Result, TC_INCOMPATIBLE); + return; } if (LeftType != RightType) { SetResult (Result, TC_STRICT_COMPATIBLE); } } + /* If one side is a pointer and the other side is an array, both are + ** compatible. + */ + if (Result->Indirections == 0) { + if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { + RightType = T_TYPE_PTR; + SetResult (Result, TC_PTR_DECAY); + } + if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) { + LeftType = T_TYPE_PTR; + SetResult (Result, TC_STRICT_COMPATIBLE); + } + } + /* If the underlying types are not identical, the types are incompatible */ if (LeftType != RightType) { SetResult (Result, TC_INCOMPATIBLE); From 9b39c3f9495d63d8cdf004363bb21055c0e8865d Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 23:58:18 +0800 Subject: [PATCH 073/360] Fixed garbage enum tag name appeared in diagnostic messages if the enum tag declaration failed. --- src/cc65/declare.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 7cc7444b6..2117b0498 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -1419,9 +1419,8 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, } else { if (CurTok.Tok != TOK_LCURLY) { Error ("Identifier expected"); - } else { - AnonName (Ident, "enum"); } + AnonName (Ident, "enum"); } /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; From aa5d44b2b0bc2fb8b8649f214eaa203ec4abd5e7 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Wed, 2 Nov 2022 23:58:20 +0800 Subject: [PATCH 074/360] Fixed endlessly repeated error messages when a declaration lacks a required identifier. --- src/cc65/declare.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 2117b0498..5c55bfb5b 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -1831,7 +1831,13 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) NextToken (); } else { if (Mode == DM_NEED_IDENT) { + /* Some fix point tokens that are used for error recovery */ + static const token_t TokenList[] = { TOK_COMMA, TOK_SEMI }; + Error ("Identifier expected"); + + /* Try some smart error recovery */ + SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); } D->Ident[0] = '\0'; } From c90d078fb7d5ec262bd89595b5d418ea444b7b28 Mon Sep 17 00:00:00 2001 From: Silver Dream ! <silverdr@srebrnysen.com> Date: Wed, 2 Nov 2022 16:43:21 +0000 Subject: [PATCH 075/360] Silencing confusing util/zlib 'warning' target --- util/zlib/Makefile | 10 ++++++---- util/zlib/readme.txt | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 util/zlib/readme.txt diff --git a/util/zlib/Makefile b/util/zlib/Makefile index 3770e1f3c..3b2c7c816 100644 --- a/util/zlib/Makefile +++ b/util/zlib/Makefile @@ -9,17 +9,19 @@ CFLAGS += -O3 -Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) .PHONY: mostlyclean clean -zlib: warning +zlib: +#zlib: warning #zlib: deflater warning: - @echo "deflater needs zlib installed, use 'make deflater' to build" + @echo "util/zlib/deflater is no longer built by default" + @echo "use 'make deflater' to build if you need it" + @echo "note that you need zlib installed first" deflater: deflater.c $(CC) $(CFLAGS) -o deflater deflater.c -lz mostlyclean clean: $(RM) deflater - -install zip: +install zip: diff --git a/util/zlib/readme.txt b/util/zlib/readme.txt new file mode 100644 index 000000000..90e15871c --- /dev/null +++ b/util/zlib/readme.txt @@ -0,0 +1,2 @@ +Deflater program in this directory is not built by default +Use 'make deflater' to build. Note that you need zlib installed first From 67384a29b7789875662617eb7c7b56ff1f892385 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 11:03:57 +0300 Subject: [PATCH 076/360] Start on 65816 --- doc/da65.sgml | 28 +++++++++++++++--- src/da65/code.c | 11 ++++++++ src/da65/code.h | 3 ++ src/da65/handler.c | 57 +++++++++++++++++++++++++++++++------ src/da65/main.c | 9 ++++-- src/da65/opctable.c | 1 + util/parse-bsnes-log.awk | 61 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 156 insertions(+), 14 deletions(-) create mode 100755 util/parse-bsnes-log.awk diff --git a/doc/da65.sgml b/doc/da65.sgml index 185dbe0e6..aa6ad40bf 100644 --- a/doc/da65.sgml +++ b/doc/da65.sgml @@ -115,14 +115,14 @@ Here is a description of all the command line options: <item>6502dtv <item>65sc02 <item>65c02 + <item>65816 <item>huc6280 <item>4510 </itemize> 6502x is for the NMOS 6502 with unofficial opcodes. 6502dtv is for the emulated CPU of the C64DTV device. huc6280 is the CPU of the PC engine. - 4510 is the CPU of the Commodore C65. Support for the 65816 currently - is not available. + 4510 is the CPU of the Commodore C65. 65816 is the CPU of the SNES. <label id="option--formfeeds"> @@ -263,8 +263,9 @@ can produce output that can not be re-assembled, when one or more of those branches point outside of the disassembled memory. This can happen when text or binary data is processed. -While there is some code for the 65816 in the sources, it is currently -unsupported. +The 65816 support requires annotating ranges with the M and X flag states. +This can be recorded with an emulator that supports Code and Data Logging, +for example. Disassemble one bank at a time. <sect1>Attribute map<p> @@ -521,6 +522,11 @@ following attributes are recognized: </descrip> + <tag><tt>ADDRMODE</tt></tag> + When disassembling 65816 code, this specifies the M and X flag states + for this range. It's a string argument of the form "mx", capital letters + mean the flag is enabled. + </descrip> @@ -693,6 +699,20 @@ directives explained above: +<sect>Helper scripts<p> + +<tt>util/parse-bsnes-log.awk</tt> is a supplied script for 65816 disassembly, +to parse bsnes-plus Code-Data log files and output the RANGE sections +for your info file. For typical usage, you'd check the S-CPU log and trace +log mask boxes in the bsnes-plus debugger, play through the game, then grep +for the bank you're disassembling, and pass that to this script. + +<tscreen><verb> +grep ^83 my-game-log | parse-bsnes-log.awk +</verb></tscreen> + + + <sect>Copyright<p> da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von diff --git a/src/da65/code.c b/src/da65/code.c index 3fb6a21d3..a162e6482 100644 --- a/src/da65/code.c +++ b/src/da65/code.c @@ -194,6 +194,17 @@ unsigned long GetCodeDWord (unsigned Addr) +unsigned GetCodeLongAddr (unsigned Addr) +/* Get a word from the given address */ +{ + unsigned Lo = GetCodeByte (Addr); + unsigned Mid = GetCodeByte (Addr+1); + unsigned Hi = GetCodeByte (Addr+2); + return Lo | (Mid << 8) | (Hi << 16); +} + + + unsigned GetRemainingBytes (void) /* Return the number of remaining code bytes */ { diff --git a/src/da65/code.h b/src/da65/code.h index 50e68ebdf..aa3c6a290 100644 --- a/src/da65/code.h +++ b/src/da65/code.h @@ -72,6 +72,9 @@ unsigned GetCodeWord (unsigned Addr); unsigned long GetCodeDWord (unsigned Addr); /* Get a dword from the given address */ +unsigned GetCodeLongAddr (unsigned Addr); +/* Get a 24-bit address from the given address */ + unsigned GetRemainingBytes (void); /* Return the number of remaining code bytes */ diff --git a/src/da65/handler.c b/src/da65/handler.c index 255b8da86..605d6219d 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -121,8 +121,10 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr) static char Buf [32]; if (Addr < 0x100) { xsprintf (Buf, sizeof (Buf), "$%02X", Addr); - } else { + } else if (Addr < 0x10000) { xsprintf (Buf, sizeof (Buf), "$%04X", Addr); + } else { + xsprintf (Buf, sizeof (Buf), "$%06X", Addr); } return Buf; } @@ -322,14 +324,28 @@ void OH_AbsoluteY (const OpcDesc* D) void OH_AbsoluteLong (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + /* Get the operand */ + unsigned Addr = GetCodeLongAddr (PC+1); + + /* Generate a label in pass 1 */ + GenerateLabel (D->Flags, Addr); + + /* Output the line */ + OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + /* Get the operand */ + unsigned Addr = GetCodeLongAddr (PC+1); + + /* Generate a label in pass 1 */ + GenerateLabel (D->Flags, Addr); + + /* Output the line */ + OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } @@ -358,7 +374,17 @@ void OH_Relative (const OpcDesc* D) void OH_RelativeLong (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + /* Get the operand */ + signed short Offs = GetCodeWord (PC+1); + + /* Calculate the target address */ + unsigned Addr = (((int) PC+3) + Offs) & 0xFFFF; + + /* Generate a label in pass 1 */ + GenerateLabel (D->Flags, Addr); + + /* Output the line */ + OneLine (D, "%s", GetAddrArg (D->Flags, Addr)); } @@ -541,14 +567,15 @@ void OH_ImmediateAbsoluteX (const OpcDesc* D) void OH_StackRelative (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + /* Output the line */ + OneLine (D, "$%02X,s", GetCodeByte (PC+1)); } void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + Error ("Not implemented %s", __FUNCTION__); } @@ -571,14 +598,28 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc* D attribute ((unused))) void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + /* Get the operand */ + unsigned Addr = GetCodeByte (PC+1); + + /* Generate a label in pass 1 */ + GenerateLabel (D->Flags, Addr); + + /* Output the line */ + OneLine (D, "[%s]", GetAddrArg (D->Flags, Addr)); } void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused))) { - Error ("Not implemented"); + /* Get the operand */ + unsigned Addr = GetCodeByte (PC+1); + + /* Generate a label in pass 1 */ + GenerateLabel (D->Flags, Addr); + + /* Output the line */ + OneLine (D, "[%s],y", GetAddrArg (D->Flags, Addr)); } diff --git a/src/da65/main.c b/src/da65/main.c index 1fc07f006..772846ad9 100644 --- a/src/da65/main.c +++ b/src/da65/main.c @@ -427,8 +427,13 @@ static void OneOpcode (unsigned RemainingBytes) switch (Style) { case atDefault: - D->Handler (D); - PC += D->Size; + if (CPU == CPU_65816) { + DataByteLine (1); + ++PC; + } else { + D->Handler (D); + PC += D->Size; + } break; case atCode: diff --git a/src/da65/opctable.c b/src/da65/opctable.c index 255a3557f..d9068d253 100644 --- a/src/da65/opctable.c +++ b/src/da65/opctable.c @@ -74,6 +74,7 @@ void SetOpcTable (cpu_t CPU) case CPU_6502DTV: OpcTable = OpcTable_6502DTV; break; case CPU_65SC02: OpcTable = OpcTable_65SC02; break; case CPU_65C02: OpcTable = OpcTable_65C02; break; + case CPU_65816: OpcTable = OpcTable_65816; break; case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break; case CPU_M740: OpcTable = OpcTable_M740; break; case CPU_4510: OpcTable = OpcTable_4510; break; diff --git a/util/parse-bsnes-log.awk b/util/parse-bsnes-log.awk new file mode 100755 index 000000000..d6a014165 --- /dev/null +++ b/util/parse-bsnes-log.awk @@ -0,0 +1,61 @@ +#!/usr/bin/awk -nf +# +# Parse the bsnes-plus cpu log for the 65816 address mode ranges. +# Since the log doesn't show the op size, we have to be careful +# and add +3 to the range end - this may need manual cleanup. +# +# Grep the input for only one bank's content beforehand. +# +# (C) Lauri Kasanen, under the cc65 license +# + +{ + addr = $1 + + IGNORECASE = 1 + if ($9 ~ /^nv/) { + val = $9 + } else if ($10 ~ /^nv/) { + val = $10 + } else { + val = $11 + } + IGNORECASE = 0 + + val = substr(val, 3, 2) + if (val == "1B") # emulation mode + val = "MX" + + addrs["0x" substr(addr, 3)] = val +} + +END { + PROCINFO["sorted_in"] = "@ind_num_asc" + + start = -1 + prevval = "" + + for (addr in addrs) { + cur = addrs[addr] + if (start == -1) { # first range + start = addr + } else { + if (prevval != cur || addr - prevaddr > 4) { # start a new range + #print "diff " addr - prevaddr ", addr " addr ", pa " prevaddr + if (prevaddr + 3 >= addr + 0) + fmt = sprintf("%04x", addr - 1) + else + fmt = sprintf("%04x", prevaddr + 3) + print "RANGE { START $" substr(start, 3) "; END $" fmt "; ADDRMODE \"" prevval "\"; TYPE Code;};" + start = addr + } + } + #print "\t" addr " " addrs[addr] + + prevval = cur + prevaddr = addr + } + + fmt = sprintf("%04x", prevaddr + 3) + print "RANGE { START $" substr(start, 3) "; END $" fmt "; ADDRMODE \"" prevval "\"; TYPE Code;};" +} From ea924ededd0ed3d5ba1bdb133550644c54192d08 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 11:41:20 +0300 Subject: [PATCH 077/360] Teach attrtab, labels and comments about long addresses --- src/da65/attrtab.c | 58 +++++++++++++++++++++++++++++++-- src/da65/attrtab.h | 3 ++ src/da65/comments.c | 47 ++++++++++++++++++++++++--- src/da65/labels.c | 79 ++++++++++++++++++++++++++++++++++++++------- 4 files changed, 169 insertions(+), 18 deletions(-) diff --git a/src/da65/attrtab.c b/src/da65/attrtab.c index a9143584a..b70e017a1 100644 --- a/src/da65/attrtab.c +++ b/src/da65/attrtab.c @@ -34,6 +34,7 @@ /* da65 */ +#include "cpu.h" #include "error.h" #include "attrtab.h" @@ -48,6 +49,12 @@ /* Attribute table */ static unsigned short AttrTab[0x10000]; +/* 65816 attribute table */ +#define MAX_LONG_ATTRS 256 +static unsigned short LongAttrVal[MAX_LONG_ATTRS]; +static unsigned LongAttrAddr[MAX_LONG_ATTRS]; +static unsigned LongAttrsUsed; + /*****************************************************************************/ @@ -59,12 +66,19 @@ static unsigned short AttrTab[0x10000]; void AddrCheck (unsigned Addr) /* Check if the given address has a valid range */ { - if (Addr >= 0x10000) { + if (Addr >= 0x10000 && CPU != CPU_65816) { Error ("Address out of range: %08X", Addr); } } +unsigned char IsLongAddr (unsigned Addr) +/* Is it 24-bit? */ +{ + return Addr >= 0x10000 && CPU == CPU_65816; +} + + attr_t GetAttr (unsigned Addr) /* Return the attribute for the given address */ @@ -72,6 +86,17 @@ attr_t GetAttr (unsigned Addr) /* Check the given address */ AddrCheck (Addr); + if (IsLongAddr (Addr)) { + unsigned i; + for (i = 0; i < LongAttrsUsed; i++) { + if (LongAttrAddr[i] == Addr) { + return LongAttrVal[i]; + } + } + + return 0; + } + /* Return the attribute */ return AttrTab[Addr]; } @@ -148,6 +173,33 @@ void MarkAddr (unsigned Addr, attr_t Attr) /* Check the given address */ AddrCheck (Addr); + if (IsLongAddr (Addr)) { + unsigned i; + for (i = 0; i < LongAttrsUsed; i++) { + if (LongAttrAddr[i] == Addr) { + + /* We must not have more than one style bit */ + if (Attr & atStyleMask) { + if (LongAttrVal[i] & atStyleMask) { + Error ("Duplicate style for long address %06X", Addr); + } + } + LongAttrVal[i] |= Attr; + + return; + } + } + + if (LongAttrsUsed >= MAX_LONG_ATTRS) { + Error ("Too many long addresses"); + } + LongAttrVal[LongAttrsUsed] |= Attr; + LongAttrAddr[LongAttrsUsed] = Addr; + LongAttrsUsed++; + + return; + } + /* We must not have more than one style bit */ if (Attr & atStyleMask) { if (AttrTab[Addr] & atStyleMask) { @@ -168,7 +220,7 @@ attr_t GetStyleAttr (unsigned Addr) AddrCheck (Addr); /* Return the attribute */ - return (AttrTab[Addr] & atStyleMask); + return (GetAttr (Addr) & atStyleMask); } @@ -180,5 +232,5 @@ attr_t GetLabelAttr (unsigned Addr) AddrCheck (Addr); /* Return the attribute */ - return (AttrTab[Addr] & atLabelMask); + return (GetAttr (Addr) & atLabelMask); } diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index 18515ce49..c9af89a4d 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -88,6 +88,9 @@ typedef enum attr_t { void AddrCheck (unsigned Addr); /* Check if the given address has a valid range */ +unsigned char IsLongAddr (unsigned Addr); +/* Check if the given address is 24-bit */ + attr_t GetAttr (unsigned Addr); /* Return the attribute for the given address */ diff --git a/src/da65/comments.c b/src/da65/comments.c index 7c671131f..f136ae3d2 100644 --- a/src/da65/comments.c +++ b/src/da65/comments.c @@ -52,6 +52,11 @@ /* Comment table */ static const char* CommentTab[0x10000]; +#define MAX_LONG_COMMENTS 256 +static const char* LongCommentVal[MAX_LONG_COMMENTS]; +static unsigned LongCommentAddr[MAX_LONG_COMMENTS]; +static unsigned LongCommentsUsed; + /*****************************************************************************/ @@ -60,17 +65,43 @@ static const char* CommentTab[0x10000]; +static unsigned FindLongIndex (unsigned Addr) +{ + unsigned i; + for (i = 0; i < LongCommentsUsed; i++) { + if (LongCommentAddr[i] == Addr) { + return i; + } + } + return -1; +} + + + void SetComment (unsigned Addr, const char* Comment) /* Set a comment for the given address */ { /* Check the given address */ AddrCheck (Addr); - /* If we do already have a comment, warn and ignore the new one */ - if (CommentTab[Addr]) { - Warning ("Duplicate comment for address $%04X", Addr); + if (IsLongAddr (Addr)) { + if (FindLongIndex (Addr)) { + Warning ("Duplicate comment for address $%06X", Addr); + } else { + if (LongCommentsUsed >= MAX_LONG_COMMENTS) { + Error("Too many long-address comments"); + } + LongCommentVal[LongCommentsUsed] = xstrdup (Comment); + LongCommentAddr[LongCommentsUsed] = Addr; + LongCommentsUsed++; + } } else { - CommentTab[Addr] = xstrdup (Comment); + /* If we do already have a comment, warn and ignore the new one */ + if (CommentTab[Addr]) { + Warning ("Duplicate comment for address $%04X", Addr); + } else { + CommentTab[Addr] = xstrdup (Comment); + } } } @@ -82,6 +113,14 @@ const char* GetComment (unsigned Addr) /* Check the given address */ AddrCheck (Addr); + if (IsLongAddr (Addr)) { + const unsigned i = FindLongIndex (Addr); + if (i < LongCommentsUsed) { + return LongCommentVal[i]; + } + return NULL; + } + /* Return the label if any */ return CommentTab[Addr]; } diff --git a/src/da65/labels.c b/src/da65/labels.c index 542205c11..5ca303a33 100644 --- a/src/da65/labels.c +++ b/src/da65/labels.c @@ -60,6 +60,12 @@ /* Symbol table */ static const char* SymTab[0x10000]; +/* 65816 symbol table */ +#define MAX_LONG_LABELS 256 +static const char* LongSymVal[MAX_LONG_LABELS]; +static unsigned LongSymAddr[MAX_LONG_LABELS]; +static unsigned LongLabelsUsed; + /*****************************************************************************/ @@ -74,12 +80,27 @@ static const char* MakeLabelName (unsigned Addr) */ { static char LabelBuf [32]; - xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr); + xsprintf (LabelBuf, sizeof (LabelBuf), + IsLongAddr (Addr) ? "L%06X" : "L%04X", Addr); return LabelBuf; } +static unsigned FindLongIndex (unsigned Addr) +{ + unsigned i; + for (i = 0; i < LongLabelsUsed; i++) { + if (LongSymAddr[i] == Addr) { + return i; + } + } + + return -1; +} + + + static void AddLabel (unsigned Addr, attr_t Attr, const char* Name) /* Add a label */ { @@ -91,19 +112,41 @@ static void AddLabel (unsigned Addr, attr_t Attr, const char* Name) /* Allow redefinition if identical. Beware: Unnamed labels don't ** have a name (you guessed that, didn't you?). */ - if (ExistingAttr == Attr && - ((Name == 0 && SymTab[Addr] == 0) || - (Name != 0 && SymTab[Addr] != 0 && - strcmp (SymTab[Addr], Name) == 0))) { - return; + if (IsLongAddr (Addr)) { + const unsigned i = FindLongIndex (Addr); + if (ExistingAttr == Attr && + ((Name == 0 && LongSymVal[i] == 0) || + (Name != 0 && LongSymVal[i] != 0 && + strcmp (LongSymVal[i], Name) == 0))) { + return; + } + Error ("Duplicate label for address $%06X (%s): '%s'", Addr, + LongSymVal[i] == 0 ? "<unnamed label>" : LongSymVal[i], + Name == 0 ? "<unnamed label>" : Name); + } else { + if (ExistingAttr == Attr && + ((Name == 0 && SymTab[Addr] == 0) || + (Name != 0 && SymTab[Addr] != 0 && + strcmp (SymTab[Addr], Name) == 0))) { + return; + } + Error ("Duplicate label for address $%04X (%s): '%s'", Addr, + SymTab[Addr] == 0 ? "<unnamed label>" : SymTab[Addr], + Name == 0 ? "<unnamed label>" : Name); } - Error ("Duplicate label for address $%04X (%s): '%s'", Addr, - SymTab[Addr] == 0 ? "<unnamed label>" : SymTab[Addr], - Name == 0 ? "<unnamed label>" : Name); } /* Create a new label (xstrdup will return NULL if input NULL) */ - SymTab[Addr] = xstrdup (Name); + if (IsLongAddr (Addr)) { + if (LongLabelsUsed >= MAX_LONG_LABELS) { + Error ("Too many long labels"); + } + LongSymAddr[LongLabelsUsed] = Addr; + LongSymVal[LongLabelsUsed] = xstrdup (Name); + LongLabelsUsed++; + } else { + SymTab[Addr] = xstrdup (Name); + } /* Remember the attribute */ MarkAddr (Addr, Attr); @@ -254,6 +297,10 @@ const char* GetLabelName (unsigned Addr) */ if (A == atUnnamedLabel) { return ""; + } else if (IsLongAddr (Addr)) { + /* Return the label if any */ + const unsigned i = FindLongIndex (Addr); + return i < LongLabelsUsed ? LongSymVal[i] : NULL; } else { /* Return the label if any */ return SymTab[Addr]; @@ -327,6 +374,10 @@ const char* GetLabel (unsigned Addr, unsigned RefFrom) return FwdLabels[Count-1]; } + } else if (IsLongAddr (Addr)) { + /* Return the label if any */ + const unsigned i = FindLongIndex (Addr); + return i < LongLabelsUsed ? LongSymVal[i] : NULL; } else { /* Return the label if any */ return SymTab[Addr]; @@ -371,7 +422,13 @@ static void DefOutOfRangeLabel (unsigned long Addr) case atIntLabel: case atExtLabel: - DefConst (SymTab[Addr], GetComment (Addr), Addr); + if (IsLongAddr (Addr)) { + const unsigned i = FindLongIndex (Addr); + DefConst (i < LongLabelsUsed ? LongSymVal[i] : NULL, + GetComment (Addr), Addr); + } else { + DefConst (SymTab[Addr], GetComment (Addr), Addr); + } break; case atUnnamedLabel: From 89fc5e30c49439f178279be783ef2bac14e05638 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 12:19:01 +0300 Subject: [PATCH 078/360] Remove unused and conflicting value --- src/da65/attrtab.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index c9af89a4d..847f44b8a 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -66,8 +66,6 @@ typedef enum attr_t { atDepLabel = 0x0040, /* Dependent label */ atUnnamedLabel = 0x0080, /* Unnamed label */ - atLabelDefined = 0x0100, /* True if we defined the label */ - atStyleMask = 0x000F, /* Output style */ atLabelMask = 0x00F0, /* Label information */ From e8ee8435e90c191f5e74c4a73e80ad0b708da27d Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 12:36:26 +0300 Subject: [PATCH 079/360] Add addrMode to RANGE --- src/da65/attrtab.h | 15 ++++++++-- src/da65/infofile.c | 68 +++++++++++++++++++++++++++++++++++++-------- src/da65/scanner.h | 1 + 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index 847f44b8a..37143c0d1 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -66,13 +66,22 @@ typedef enum attr_t { atDepLabel = 0x0040, /* Dependent label */ atUnnamedLabel = 0x0080, /* Unnamed label */ - atStyleMask = 0x000F, /* Output style */ - atLabelMask = 0x00F0, /* Label information */ - /* Segment */ atSegment = 0x0100, /* Code is in a segment */ atSegmentEnd = 0x0200, /* Segment end */ atSegmentStart = 0x0400, /* Segment start */ + + /* 65816 addressing mode */ + atMem8 = 0x1000, /* M flag enabled, 8-bit */ + atMem16 = 0x2000, /* M flag disabled, 16-bit */ + atIdx8 = 0x4000, /* X flag enabled, 8-bit */ + atIdx16 = 0x8000, /* X flag disabled, 16-bit */ + + atStyleMask = 0x000F, /* Output style */ + atLabelMask = 0x00F0, /* Label information */ + atSegmentMask = 0x0F00, /* Segment information */ + at65816Mask = 0xF000, /* 65816 information */ + } attr_t; diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 48a95c9b0..923cc53c9 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -35,6 +35,7 @@ #include <stdio.h> #include <string.h> +#include <ctype.h> #include <limits.h> #if defined(_MSC_VER) /* Microsoft compiler */ @@ -521,11 +522,12 @@ static void RangeSection (void) /* Parse a range section */ { static const IdentTok RangeDefs[] = { - { "COMMENT", INFOTOK_COMMENT }, - { "END", INFOTOK_END }, - { "NAME", INFOTOK_NAME }, - { "START", INFOTOK_START }, - { "TYPE", INFOTOK_TYPE }, + { "COMMENT", INFOTOK_COMMENT }, + { "END", INFOTOK_END }, + { "NAME", INFOTOK_NAME }, + { "START", INFOTOK_START }, + { "TYPE", INFOTOK_TYPE }, + { "ADDRMODE", INFOTOK_ADDRMODE }, }; static const IdentTok TypeDefs[] = { @@ -543,12 +545,13 @@ static void RangeSection (void) /* Which values did we get? */ enum { - tNone = 0x00, - tStart = 0x01, - tEnd = 0x02, - tType = 0x04, - tName = 0x08, - tComment= 0x10, + tNone = 0x00, + tStart = 0x01, + tEnd = 0x02, + tType = 0x04, + tName = 0x08, + tComment = 0x10, + tAddrMode = 0x20, tNeeded = (tStart | tEnd | tType) }; unsigned Attributes = tNone; @@ -557,6 +560,7 @@ static void RangeSection (void) unsigned Start = 0; unsigned End = 0; unsigned char Type = 0; + unsigned AddrMode = 0; char* Name = 0; char* Comment = 0; unsigned MemberSize = 0; @@ -647,6 +651,37 @@ static void RangeSection (void) InfoNextTok (); break; + case INFOTOK_ADDRMODE: + AddAttr ("ADDRMODE", &Attributes, tAddrMode); + InfoNextTok (); + InfoAssureStr (); + if (InfoSVal[0] == '\0') { + InfoError ("AddrMode may not be empty"); + } + if (InfoSVal[1] == '\0') { + InfoError ("AddrMode must be two characters long"); + } + if (tolower(InfoSVal[0]) == 'm') { + if (InfoSVal[0] == 'm') { + AddrMode = atMem16; + } else { + AddrMode = atMem8; + } + } else { + InfoError ("AddrMode syntax: mx"); + } + if (tolower(InfoSVal[1]) == 'x') { + if (InfoSVal[1] == 'x') { + AddrMode |= atIdx16; + } else { + AddrMode |= atIdx8; + } + } else { + InfoError ("AddrMode syntax: mx"); + } + InfoNextTok (); + break; + default: Internal ("Unexpected token: %u", InfoTok); } @@ -661,6 +696,15 @@ static void RangeSection (void) InfoError ("Required values missing from this section"); } + if (CPU == CPU_65816) { + if (Type == atCode && !(Attributes & tAddrMode)) { + InfoError ("65816 code sections require addressing mode"); + } + if (Type != atCode && (Attributes & tAddrMode)) { + InfoError ("AddrMode is only valid for code sections"); + } + } + /* Start must be less than end */ if (Start > End) { InfoError ("Start value must not be greater than end value"); @@ -672,7 +716,7 @@ static void RangeSection (void) } /* Set the range */ - MarkRange (Start, End, Type); + MarkRange (Start, End, Type | AddrMode); /* Do we have a label? */ if (Attributes & tName) { diff --git a/src/da65/scanner.h b/src/da65/scanner.h index 63d3273f6..60648a40c 100644 --- a/src/da65/scanner.h +++ b/src/da65/scanner.h @@ -90,6 +90,7 @@ typedef enum token_t { INFOTOK_START, INFOTOK_END, INFOTOK_TYPE, + INFOTOK_ADDRMODE, INFOTOK_CODE, INFOTOK_BYTETAB, From 1294c1c2539396d79a280fb2d51bd4d50ad9e025 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 14:45:10 +0300 Subject: [PATCH 080/360] Implement changing-size opcodes --- src/da65/handler.c | 22 ++++++++++++++++++++++ src/da65/handler.h | 2 ++ src/da65/main.c | 9 +++++++++ src/da65/opc65816.c | 24 ++++++++++++------------ src/da65/opcdesc.h | 3 ++- 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/da65/handler.c b/src/da65/handler.c index 605d6219d..97c79db6d 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -231,6 +231,28 @@ void OH_Immediate (const OpcDesc* D) +void OH_Immediate65816M (const OpcDesc* D) +{ + if (GetAttr (PC) & atMem16) { + OneLine (D, "#$%04X", GetCodeWord (PC+1)); + } else { + OneLine (D, "#$%02X", GetCodeByte (PC+1)); + } +} + + + +void OH_Immediate65816X (const OpcDesc* D) +{ + if (GetAttr (PC) & atIdx16) { + OneLine (D, "#$%04X", GetCodeWord (PC+1)); + } else { + OneLine (D, "#$%02X", GetCodeByte (PC+1)); + } +} + + + void OH_ImmediateWord (const OpcDesc* D) { OneLine (D, "#$%04X", GetCodeWord (PC+1)); diff --git a/src/da65/handler.h b/src/da65/handler.h index eaa66e7fd..2bfaed9c3 100644 --- a/src/da65/handler.h +++ b/src/da65/handler.h @@ -57,6 +57,8 @@ void OH_Illegal (const OpcDesc* D attribute ((unused))); void OH_Accumulator (const OpcDesc*); void OH_Implicit (const OpcDesc*); void OH_Immediate (const OpcDesc*); +void OH_Immediate65816M (const OpcDesc*); +void OH_Immediate65816X (const OpcDesc*); void OH_ImmediateWord (const OpcDesc*); void OH_Direct (const OpcDesc*); void OH_DirectX (const OpcDesc*); diff --git a/src/da65/main.c b/src/da65/main.c index 772846ad9..8d68dc4cc 100644 --- a/src/da65/main.c +++ b/src/da65/main.c @@ -55,6 +55,7 @@ #include "data.h" #include "error.h" #include "global.h" +#include "handler.h" #include "infofile.h" #include "labels.h" #include "opctable.h" @@ -447,6 +448,14 @@ static void OneOpcode (unsigned RemainingBytes) } /* Output the insn */ D->Handler (D); + if (CPU == CPU_65816 && (D->Flags & flSizeChanges)) { + if ((D->Handler == OH_Immediate65816M && + GetAttr (PC) & atMem16) || + (D->Handler == OH_Immediate65816X && + GetAttr (PC) & atIdx16)) { + PC++; + } + } PC += D->Size; break; } diff --git a/src/da65/opc65816.c b/src/da65/opc65816.c index b7775d2e2..877e5536f 100644 --- a/src/da65/opc65816.c +++ b/src/da65/opc65816.c @@ -56,7 +56,7 @@ const OpcDesc OpcTable_65816[256] = { { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "ora", 2, flUseLabel, OH_DirectIndirectLong }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ - { "ora", 2, flNone, OH_Immediate }, /* $09 */ + { "ora", 2, flSizeChanges, OH_Immediate65816M }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "phd", 1, flNone, OH_Implicit }, /* $0b */ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ @@ -88,7 +88,7 @@ const OpcDesc OpcTable_65816[256] = { { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "and", 2, flUseLabel, OH_DirectIndirectLong }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ - { "and", 2, flNone, OH_Immediate }, /* $29 */ + { "and", 2, flSizeChanges, OH_Immediate65816M }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "pld", 1, flNone, OH_Implicit }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ @@ -120,7 +120,7 @@ const OpcDesc OpcTable_65816[256] = { { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "eor", 2, flUseLabel, OH_DirectIndirectLong }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ - { "eor", 2, flNone, OH_Immediate }, /* $49 */ + { "eor", 2, flSizeChanges, OH_Immediate65816M }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "phk", 1, flNone, OH_Implicit }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ @@ -152,7 +152,7 @@ const OpcDesc OpcTable_65816[256] = { { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "adc", 2, flUseLabel, OH_DirectIndirectLong }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ - { "adc", 2, flNone, OH_Immediate }, /* $69 */ + { "adc", 2, flSizeChanges, OH_Immediate65816M }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "rtl", 1, flNone, OH_Implicit }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ @@ -184,7 +184,7 @@ const OpcDesc OpcTable_65816[256] = { { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "sta", 2, flUseLabel, OH_DirectIndirectLong }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ - { "bit", 2, flNone, OH_Immediate }, /* $89 */ + { "bit", 2, flSizeChanges, OH_Immediate65816M }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "phb", 1, flNone, OH_Implicit }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ @@ -207,16 +207,16 @@ const OpcDesc OpcTable_65816[256] = { { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ { "sta", 4, flUseLabel, OH_AbsoluteLongX }, /* $9f */ - { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ + { "ldy", 2, flSizeChanges, OH_Immediate65816X }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ - { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ + { "ldx", 2, flSizeChanges, OH_Immediate65816X }, /* $a2 */ { "lda", 2, flNone, OH_StackRelative }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "lda", 2, flUseLabel, OH_DirectIndirectLong }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ - { "lda", 2, flNone, OH_Immediate }, /* $a9 */ + { "lda", 2, flSizeChanges, OH_Immediate65816M }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "plb", 1, flNone, OH_Implicit }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ @@ -239,7 +239,7 @@ const OpcDesc OpcTable_65816[256] = { { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "lda", 4, flUseLabel, OH_AbsoluteLongX }, /* $bf */ - { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ + { "cpy", 2, flSizeChanges, OH_Immediate65816X }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "rep", 2, flNone, OH_Immediate }, /* $c2 */ { "cmp", 2, flNone, OH_StackRelative }, /* $c3 */ @@ -248,7 +248,7 @@ const OpcDesc OpcTable_65816[256] = { { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "cmp", 2, flUseLabel, OH_DirectIndirectLong }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ - { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ + { "cmp", 2, flSizeChanges, OH_Immediate65816M }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "wai", 1, flNone, OH_Implicit }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ @@ -271,7 +271,7 @@ const OpcDesc OpcTable_65816[256] = { { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "cmp", 4, flUseLabel, OH_AbsoluteLongX }, /* $df */ - { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ + { "cpx", 2, flSizeChanges, OH_Immediate65816X }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "sep", 2, flNone, OH_Immediate }, /* $e2 */ { "sbc", 2, flNone, OH_StackRelative }, /* $e3 */ @@ -280,7 +280,7 @@ const OpcDesc OpcTable_65816[256] = { { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "sbc", 2, flUseLabel, OH_DirectIndirectLong }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ - { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ + { "sbc", 2, flSizeChanges, OH_Immediate65816M }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "xba", 1, flNone, OH_Implicit }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ diff --git a/src/da65/opcdesc.h b/src/da65/opcdesc.h index 399a0962d..6baffe377 100644 --- a/src/da65/opcdesc.h +++ b/src/da65/opcdesc.h @@ -53,7 +53,8 @@ enum { flLabel = flUseLabel|flGenLabel, /* Generate and use a label */ flIllegal = 0x10, /* Illegal instruction */ flAbsOverride = 0x20, /* Need a: override */ - flFarOverride = 0x40 /* Need f: override */ + flFarOverride = 0x40, /* Need f: override */ + flSizeChanges = 0x80 /* 65816: size may change */ }; /* Forward/typedef for struct OpcDesc */ From 4b04f81d3773321a14d998915d40b408c5e7d4e1 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 14:59:51 +0300 Subject: [PATCH 081/360] Fix jsl length --- src/da65/opc65816.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/da65/opc65816.c b/src/da65/opc65816.c index 877e5536f..7457a25c2 100644 --- a/src/da65/opc65816.c +++ b/src/da65/opc65816.c @@ -81,7 +81,7 @@ const OpcDesc OpcTable_65816[256] = { { "ora", 4, flUseLabel, OH_AbsoluteLongX }, /* $1f */ { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ - { "jsl", 3, flLabel, OH_AbsoluteLong }, /* $22 */ + { "jsl", 4, flLabel, OH_AbsoluteLong }, /* $22 */ { "and", 2, flNone, OH_StackRelative }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ From 65907b1f105b52af2b9b263425056cbea2019587 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 15:16:24 +0300 Subject: [PATCH 082/360] Output MX states --- src/da65/main.c | 20 ++++++++++++++++++++ src/da65/output.c | 20 ++++++++++++++++++++ src/da65/output.h | 6 ++++++ 3 files changed, 46 insertions(+) diff --git a/src/da65/main.c b/src/da65/main.c index 8d68dc4cc..67a01dc3b 100644 --- a/src/da65/main.c +++ b/src/da65/main.c @@ -64,6 +64,8 @@ #include "segment.h" +static unsigned PrevAddrMode; + /*****************************************************************************/ /* Code */ @@ -442,6 +444,22 @@ static void OneOpcode (unsigned RemainingBytes) ** following insn, fall through to byte mode. */ if (D->Size <= RemainingBytes) { + if (CPU == CPU_65816) { + const unsigned AddrMode = GetAttr (PC) & at65816Mask; + if (PrevAddrMode != AddrMode) { + if ((PrevAddrMode & atMem8) != (AddrMode & atMem8) || + (PrevAddrMode & atMem16) != (AddrMode & atMem16)) { + OutputMFlag(!!(AddrMode & atMem8)); + } + if ((PrevAddrMode & atIdx8) != (AddrMode & atIdx8) || + (PrevAddrMode & atIdx16) != (AddrMode & atIdx16)) { + OutputXFlag(!!(AddrMode & atIdx8)); + } + + PrevAddrMode = AddrMode; + } + } + /* Output labels within the next insn */ for (I = 1; I < D->Size; ++I) { ForwardLabel (I); @@ -517,6 +535,8 @@ static void OnePass (void) { unsigned Count; + PrevAddrMode = 0; + /* Disassemble until nothing left */ while ((Count = GetRemainingBytes()) > 0) { OneOpcode (Count); diff --git a/src/da65/output.c b/src/da65/output.c index 5b0b6b79c..8e786e130 100644 --- a/src/da65/output.c +++ b/src/da65/output.c @@ -401,3 +401,23 @@ void OutputSettings (void) LineFeed (); LineFeed (); } + + + +void OutputMFlag (unsigned char enabled) +/* Output the 65816 M-flag state */ +{ + Indent (MCol); + Output (enabled ? ".a8" : ".a16"); + LineFeed (); +} + + + +void OutputXFlag (unsigned char enabled) +/* Output the 65816 X-flag state */ +{ + Indent (MCol); + Output (enabled ? ".i8" : ".i16"); + LineFeed (); +} diff --git a/src/da65/output.h b/src/da65/output.h index 13ea0cc85..bc20aace0 100644 --- a/src/da65/output.h +++ b/src/da65/output.h @@ -108,6 +108,12 @@ void LineComment (unsigned PC, unsigned Count); void OutputSettings (void); /* Output CPU and other settings */ +void OutputMFlag (unsigned char enabled); +/* Output the 65816 M-flag state */ + +void OutputXFlag (unsigned char enabled); +/* Output the 65816 X-flag state */ + /* End of output.h */ From db351b42285e9e4cf9997beeabc84cff00e1cb5a Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 15:36:28 +0300 Subject: [PATCH 083/360] Output remaining long labels --- src/da65/labels.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/da65/labels.c b/src/da65/labels.c index 5ca303a33..4cae0316a 100644 --- a/src/da65/labels.c +++ b/src/da65/labels.c @@ -447,6 +447,7 @@ void DefOutOfRangeLabels (void) /* Output any labels that are out of the loaded code range */ { unsigned long Addr; + unsigned i; SeparatorLine (); @@ -469,5 +470,10 @@ void DefOutOfRangeLabels (void) DefOutOfRangeLabel (Addr++); } + /* 65816 long range */ + for (i = 0; i < LongLabelsUsed; i++) { + DefOutOfRangeLabel (LongSymAddr[i]); + } + SeparatorLine (); } From b90bf258e2e27ca0bf592d9fa5de38adc2781e2d Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Wed, 12 Oct 2022 16:02:37 +0300 Subject: [PATCH 084/360] Implement far override --- src/da65/handler.c | 4 +++- src/da65/opc65816.c | 36 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/da65/handler.c b/src/da65/handler.c index 97c79db6d..f2d3ecab3 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -99,7 +99,9 @@ static const char* GetAbsOverride (unsigned Flags, unsigned Addr) ** string, otherwise return the empty string. */ { - if ((Flags & flAbsOverride) != 0 && Addr < 0x100) { + if ((Flags & flFarOverride) != 0 && Addr < 0x10000) { + return "f:"; + } else if ((Flags & flAbsOverride) != 0 && Addr < 0x100) { return "a:"; } else { return ""; diff --git a/src/da65/opc65816.c b/src/da65/opc65816.c index 7457a25c2..64629506c 100644 --- a/src/da65/opc65816.c +++ b/src/da65/opc65816.c @@ -62,7 +62,7 @@ const OpcDesc OpcTable_65816[256] = { { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ - { "ora", 4, flUseLabel, OH_AbsoluteLong }, /* $0f */ + { "ora", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */ @@ -78,10 +78,10 @@ const OpcDesc OpcTable_65816[256] = { { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ - { "ora", 4, flUseLabel, OH_AbsoluteLongX }, /* $1f */ + { "ora", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $1f */ { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ - { "jsl", 4, flLabel, OH_AbsoluteLong }, /* $22 */ + { "jsl", 4, flLabel|flFarOverride, OH_AbsoluteLong }, /* $22 */ { "and", 2, flNone, OH_StackRelative }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ @@ -94,7 +94,7 @@ const OpcDesc OpcTable_65816[256] = { { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ - { "and", 4, flUseLabel, OH_AbsoluteLong }, /* $2f */ + { "and", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "and", 2, flUseLabel, OH_DirectIndirect }, /* $32 */ @@ -110,7 +110,7 @@ const OpcDesc OpcTable_65816[256] = { { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ - { "and", 4, flUseLabel, OH_AbsoluteLongX }, /* $3f */ + { "and", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "wdm", 2, flNone, OH_Implicit }, /* $42 */ @@ -126,7 +126,7 @@ const OpcDesc OpcTable_65816[256] = { { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ - { "eor", 4, flUseLabel, OH_AbsoluteLong }, /* $4f */ + { "eor", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */ @@ -139,10 +139,10 @@ const OpcDesc OpcTable_65816[256] = { { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "phy", 1, flNone, OH_Implicit }, /* $5a */ { "tcd", 1, flNone, OH_Implicit }, /* $5b */ - { "jml", 4, flLabel, OH_AbsoluteLong }, /* $5c */ + { "jml", 4, flLabel|flFarOverride, OH_AbsoluteLong }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ - { "eor", 4, flUseLabel, OH_AbsoluteLongX }, /* $5f */ + { "eor", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "per", 3, flLabel, OH_RelativeLong }, /* $62 */ @@ -158,7 +158,7 @@ const OpcDesc OpcTable_65816[256] = { { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ - { "adc", 4, flUseLabel, OH_AbsoluteLong }, /* $6f */ + { "adc", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "adc", 2, flUseLabel, OH_DirectIndirect }, /* $72 */ @@ -174,7 +174,7 @@ const OpcDesc OpcTable_65816[256] = { { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ - { "adc", 4, flUseLabel, OH_AbsoluteLongX }, /* $7f */ + { "adc", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "brl", 3, flLabel, OH_RelativeLong }, /* $82 */ @@ -190,7 +190,7 @@ const OpcDesc OpcTable_65816[256] = { { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ - { "sta", 4, flUseLabel, OH_AbsoluteLong }, /* $8f */ + { "sta", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */ @@ -206,7 +206,7 @@ const OpcDesc OpcTable_65816[256] = { { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ - { "sta", 4, flUseLabel, OH_AbsoluteLongX }, /* $9f */ + { "sta", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $9f */ { "ldy", 2, flSizeChanges, OH_Immediate65816X }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flSizeChanges, OH_Immediate65816X }, /* $a2 */ @@ -222,7 +222,7 @@ const OpcDesc OpcTable_65816[256] = { { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ - { "lda", 4, flUseLabel, OH_AbsoluteLong }, /* $af */ + { "lda", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */ @@ -238,7 +238,7 @@ const OpcDesc OpcTable_65816[256] = { { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ - { "lda", 4, flUseLabel, OH_AbsoluteLongX }, /* $bf */ + { "lda", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $bf */ { "cpy", 2, flSizeChanges, OH_Immediate65816X }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "rep", 2, flNone, OH_Immediate }, /* $c2 */ @@ -254,7 +254,7 @@ const OpcDesc OpcTable_65816[256] = { { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ - { "cmp", 4, flUseLabel, OH_AbsoluteLong }, /* $cf */ + { "cmp", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */ @@ -270,7 +270,7 @@ const OpcDesc OpcTable_65816[256] = { { "jml", 3, flLabel, OH_AbsoluteIndirect }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ - { "cmp", 4, flUseLabel, OH_AbsoluteLongX }, /* $df */ + { "cmp", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $df */ { "cpx", 2, flSizeChanges, OH_Immediate65816X }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "sep", 2, flNone, OH_Immediate }, /* $e2 */ @@ -286,7 +286,7 @@ const OpcDesc OpcTable_65816[256] = { { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ - { "sbc", 4, flUseLabel, OH_AbsoluteLong }, /* $ef */ + { "sbc", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */ @@ -302,5 +302,5 @@ const OpcDesc OpcTable_65816[256] = { { "jsr", 3, flLabel, OH_AbsoluteXIndirect }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ - { "sbc", 4, flUseLabel, OH_AbsoluteLongX }, /* $ff */ + { "sbc", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $ff */ }; From 3ea999f0349d0e8233e95e94d858d9547a309ec2 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Mon, 17 Oct 2022 12:50:34 +0300 Subject: [PATCH 085/360] Correct mvn, mvp, pei --- src/da65/handler.c | 13 +++++++++++++ src/da65/handler.h | 1 + src/da65/opc65816.c | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/da65/handler.c b/src/da65/handler.c index f2d3ecab3..79b3192de 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -678,6 +678,19 @@ void OH_BlockMove (const OpcDesc* D) +void OH_BlockMove65816 (const OpcDesc* D) +{ + /* Get source operand */ + unsigned Src = GetCodeByte (PC+2); + /* Get destination operand */ + unsigned Dst = GetCodeByte (PC+1); + + /* Output the line */ + OneLine (D, "#$%02X, #$%02X", Src, Dst); +} + + + void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused))) { /* Get the operand */ diff --git a/src/da65/handler.h b/src/da65/handler.h index 2bfaed9c3..ee9b18bbc 100644 --- a/src/da65/handler.h +++ b/src/da65/handler.h @@ -91,6 +91,7 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc*); void OH_DirectIndirectLong (const OpcDesc*); void OH_DirectIndirectLongY (const OpcDesc*); void OH_BlockMove (const OpcDesc*); +void OH_BlockMove65816 (const OpcDesc*); void OH_AbsoluteXIndirect (const OpcDesc*); /* Mitsubishi 740 */ diff --git a/src/da65/opc65816.c b/src/da65/opc65816.c index 64629506c..06272f318 100644 --- a/src/da65/opc65816.c +++ b/src/da65/opc65816.c @@ -115,7 +115,7 @@ const OpcDesc OpcTable_65816[256] = { { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "wdm", 2, flNone, OH_Implicit }, /* $42 */ { "eor", 2, flNone, OH_StackRelative }, /* $43 */ - { "mvp", 3, flNone, OH_BlockMove }, /* $44 */ + { "mvp", 3, flNone, OH_BlockMove65816 }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "eor", 2, flUseLabel, OH_DirectIndirectLong }, /* $47 */ @@ -131,7 +131,7 @@ const OpcDesc OpcTable_65816[256] = { { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */ { "eor", 2, flNone, OH_StackRelativeIndirectY}, /* $53 */ - { "mvn", 3, flNone, OH_BlockMove }, /* $54 */ + { "mvn", 3, flNone, OH_BlockMove65816 }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "eor", 2, flUseLabel, OH_DirectIndirectLongY }, /* $57 */ @@ -259,7 +259,7 @@ const OpcDesc OpcTable_65816[256] = { { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */ { "cmp", 2, flNone, OH_StackRelativeIndirectY}, /* $d3 */ - { "pei", 2, flUseLabel, OH_Direct }, /* $d4 */ + { "pei", 2, flUseLabel, OH_DirectIndirect }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "cmp", 2, flUseLabel, OH_DirectIndirectLongY }, /* $d7 */ From 9aae1efd033fea2252670fcaafad2b6cc370d516 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Mon, 17 Oct 2022 12:50:59 +0300 Subject: [PATCH 086/360] Add a da65 65186 test --- test/dasm/65816.cfg | 7 ++ test/dasm/65816.info | 7 ++ test/dasm/Makefile | 17 ++- test/dasm/test65816.s | 273 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 test/dasm/65816.cfg create mode 100644 test/dasm/65816.info create mode 100644 test/dasm/test65816.s diff --git a/test/dasm/65816.cfg b/test/dasm/65816.cfg new file mode 100644 index 000000000..620439c7b --- /dev/null +++ b/test/dasm/65816.cfg @@ -0,0 +1,7 @@ +MEMORY { + ROM: start = $8000, size = $8000; +} + +SEGMENTS { + CODE: load = ROM; +} diff --git a/test/dasm/65816.info b/test/dasm/65816.info new file mode 100644 index 000000000..2a3394680 --- /dev/null +++ b/test/dasm/65816.info @@ -0,0 +1,7 @@ +GLOBAL { + startaddr $8000; +}; + +RANGE { START $8000; END $8229; ADDRMODE "MX"; TYPE Code;}; +RANGE { START $822a; END $824b; ADDRMODE "mx"; TYPE Code;}; + diff --git a/test/dasm/Makefile b/test/dasm/Makefile index 542ce7d5e..d9ac7ac21 100644 --- a/test/dasm/Makefile +++ b/test/dasm/Makefile @@ -19,6 +19,8 @@ ifdef QUIET endif CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) +CA65 := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65) +LD65 := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65) DA65 := $(if $(wildcard ../../bin/da65*),../../bin/da65,da65) WORKDIR = ../../testwrk/dasm @@ -33,7 +35,7 @@ START = --start-addr 0x8000 .PHONY: all clean SOURCES := $(wildcard *.s) -BINS = $(SOURCES:%disass.s=$(WORKDIR)/%reass.bin) +BINS = $(SOURCES:%disass.s=$(WORKDIR)/%reass.bin) $(WORKDIR)/65816-reass.bin CPUS = $(SOURCES:%-disass.s=%) all: $(BINS) @@ -61,5 +63,18 @@ endef # DISASS_template $(foreach cpu,$(CPUS),$(eval $(call DISASS_template,$(cpu)))) +$(WORKDIR)/test65816.bin: test65816.s | $(WORKDIR) + $(CA65) -o $(WORKDIR)/test65816.o $< + $(LD65) -o $@ -C 65816.cfg $(WORKDIR)/test65816.o + +$(WORKDIR)/65816-reass.s: $(WORKDIR)/test65816.bin + $(DA65) --cpu 65816 -i 65816.info -o $@ $< + +$(WORKDIR)/65816-reass.bin: $(WORKDIR)/65816-reass.s $(ISEQUAL) + $(if $(QUIET),echo dasm/65816-reass.bin) + $(CA65) -o $(WORKDIR)/65816-reass.o $< + $(LD65) -o $@ -C 65816.cfg $(WORKDIR)/65816-reass.o + $(ISEQUAL) --binary $(WORKDIR)/test65816.bin $@ + clean: @$(call RMDIR,$(WORKDIR)) diff --git a/test/dasm/test65816.s b/test/dasm/test65816.s new file mode 100644 index 000000000..3d764fb6e --- /dev/null +++ b/test/dasm/test65816.s @@ -0,0 +1,273 @@ +.setcpu "65816" + +ADC ($10,X) +ADC $32,S +ADC $10 +ADC [$10] +ADC #$54 +ADC $9876 +ADC $FEDBCA +ADC ($10),Y +ADC ($10) +ADC ($32,S),Y +ADC $10,X +ADC [$10],Y +ADC $9876,Y +ADC $9876,X +ADC $FEDCBA,X +SBC ($10,X) +SBC $32,S +SBC $10 +SBC [$10] +SBC #$54 +SBC $9876 +SBC $FEDBCA +SBC ($10),Y +SBC ($10) +SBC ($32,S),Y +SBC $10,X +SBC [$10],Y +SBC $9876,Y +SBC $9876,X +SBC $FEDCBA,X +CMP ($10,X) +CMP $32,S +CMP $10 +CMP [$10] +CMP #$54 +CMP $9876 +CMP $FEDBCA +CMP ($10),Y +CMP ($10) +CMP ($32,S),Y +CMP $10,X +CMP [$10],Y +CMP $9876,Y +CMP $9876,X +CMP $FEDCBA,X +CPX #$54 +CPX $10 +CPX $9876 +CPY #$54 +CPY $10 +CPY $9876 +DEC +DEC $10 +DEC $9876 +DEC $10,X +DEC $9876,X +DEX +DEY +INC +INC $10 +INC $9876 +INC $10,X +INC $9876,X +INX +INY +AND ($10,X) +AND $32,S +AND $10 +AND [$10] +AND #$54 +AND $9876 +AND $FEDBCA +AND ($10),Y +AND ($10) +AND ($32,S),Y +AND $10,X +AND [$10],Y +AND $9876,Y +AND $9876,X +AND $FEDCBA,X +EOR ($10,X) +EOR $32,S +EOR $10 +EOR [$10] +EOR #$54 +EOR $9876 +EOR $FEDBCA +EOR ($10),Y +EOR ($10) +EOR ($32,S),Y +EOR $10,X +EOR [$10],Y +EOR $9876,Y +EOR $9876,X +EOR $FEDCBA,X +ORA ($10,X) +ORA $32,S +ORA $10 +ORA [$10] +ORA #$54 +ORA $9876 +ORA $FEDBCA +ORA ($10),Y +ORA ($10) +ORA ($32,S),Y +ORA $10,X +ORA [$10],Y +ORA $9876,Y +ORA $9876,X +ORA $FEDCBA,X +BIT $10 +BIT $9876 +BIT $10,X +BIT $9876,X +BIT #$54 +TRB $10 +TRB $9876 +TSB $10 +TSB $9876 +ASL $10 +ASL +ASL $9876 +ASL $10,X +ASL $9876,X +LSR $10 +LSR +LSR $9876 +LSR $10,X +LSR $9876,X +ROL $10 +ROL +ROL $9876 +ROL $10,X +ROL $9876,X +ROR $10 +ROR +ROR $9876 +ROR $10,X +ROR $9876,X +LABEL: +BCC LABEL +BCS LABEL +BEQ LABEL +BMI LABEL +BNE LABEL +BPL LABEL +BRA LABEL +BVC LABEL +BVS LABEL +BRL LABEL +JMP $1234 +JMP $FEDCBA +JMP ($1234) +JMP ($1234,X) +JMP [$1234] +JSL $123456 +JSR $1234 +JSR ($1234,X) +RTL +RTS +BRK +RTI +CLC +CLD +CLI +CLV +SEC +SED +SEI +REP #$12 +SEP #$12 +LDA ($10,X) +LDA $32,S +LDA $10 +LDA [$10] +LDA #$54 +LDA $9876 +LDA $FEDBCA +LDA ($10),Y +LDA ($10) +LDA ($32,S),Y +LDA $10,X +LDA [$10],Y +LDA $9876,Y +LDA $9876,X +LDA $FEDCBA,X +LDX #$54 +LDX $10 +LDX $9876 +LDX $10,Y +LDX $9876,Y +LDY #$54 +LDY $10 +LDY $9876 +LDY $10,X +LDY $9876,X +STA ($10,X) +STA $32,S +STA $10 +STA [$10] +STA $9876 +STA $FEDBCA +STA ($10),Y +STA ($10) +STA ($32,S),Y +STA $10,X +STA [$10],Y +STA $9876,Y +STA $9876,X +STA $FEDCBA,X +STX $10 +STX $9876 +STX $10,Y +STY $10 +STY $9876 +STY $10,X +STZ $10 +STZ $10,X +STZ $9876 +STZ $9876,X +MVN #$12,#$34 +MVP #$12,#$34 +NOP +PEA $1234 +PEI ($12) +PER LABEL +PHA +PHX +PHY +PLA +PLX +PLY +PHB +PHD +PHK +PHP +PLB +PLD +PLP +STP +WAI +TAX +TAY +TSX +TXA +TXS +TXY +TYA +TYX +TCD +TCS +TDC +TSC +XBA +XCE + +.a16 +.i16 +longs: +ADC #$5432 +SBC #$5432 +CMP #$5432 +CPX #$5432 +CPY #$5432 +AND #$5432 +EOR #$5432 +ORA #$5432 +BIT #$5432 +LDA #$5432 +LDX #$5432 +LDY #$5432 From 991af3755bd7b8c38ecd15579275bae20e63b919 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 3 Nov 2022 21:46:41 +0800 Subject: [PATCH 087/360] Added support for _Static_assert in unions. --- src/cc65/declare.c | 11 +++++++++-- test/val/staticassert.c | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index b141a15ef..4950dc8f8 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -882,12 +882,19 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) EnterStructLevel (); /* Parse union fields */ - UnionSize = 0; + UnionSize = 0; while (CurTok.Tok != TOK_RCURLY) { /* Get the type of the entry */ DeclSpec Spec; int SignednessSpecified = 0; + + /* Check for a _Static_assert */ + if (CurTok.Tok == TOK_STATIC_ASSERT) { + ParseStaticAssert (); + continue; + } + InitDeclSpec (&Spec); ParseTypeSpec (&Spec, -1, T_QUAL_NONE, &SignednessSpecified); @@ -1030,6 +1037,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) /* Get the type of the entry */ DeclSpec Spec; + int SignednessSpecified = 0; /* Check for a _Static_assert */ if (CurTok.Tok == TOK_STATIC_ASSERT) { @@ -1037,7 +1045,6 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) continue; } - int SignednessSpecified = 0; InitDeclSpec (&Spec); ParseTypeSpec (&Spec, -1, T_QUAL_NONE, &SignednessSpecified); diff --git a/test/val/staticassert.c b/test/val/staticassert.c index e43eeec8d..3338f7a4a 100644 --- a/test/val/staticassert.c +++ b/test/val/staticassert.c @@ -65,6 +65,13 @@ struct S { int b; }; +/* _Static_assert can also appear in unions. */ +union U { + int a; + _Static_assert (1, "1 should still be true."); + int b; +}; + int main (void) { From 8a7f5663876d8ffb5f811480f89a5e6af4efd306 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 3 Nov 2022 21:46:42 +0800 Subject: [PATCH 088/360] Fixed support for storage class specifiers after type specifiers. --- src/cc65/compile.c | 2 +- src/cc65/declare.c | 248 +++++++++++++++++-------------- src/cc65/declare.h | 18 ++- src/cc65/expr.c | 2 +- src/cc65/locals.c | 2 +- test/misc/int-static-1888.c | 10 -- test/val/decl-mixed-specifiers.c | 19 +++ 7 files changed, 178 insertions(+), 123 deletions(-) delete mode 100644 test/misc/int-static-1888.c create mode 100644 test/val/decl-mixed-specifiers.c diff --git a/src/cc65/compile.c b/src/cc65/compile.c index a8ef56af6..f15c5bc54 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -123,7 +123,7 @@ static void Parse (void) } /* Read variable defs and functions */ - ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT); + ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_EXTERN | SC_STATIC); /* Don't accept illegal storage classes */ if ((Spec.StorageClass & SC_TYPEMASK) == 0) { diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 4950dc8f8..f3674d711 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -72,8 +72,7 @@ -static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, - int* SignednessSpecified); +static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpecified); /* Parse a type specifier */ @@ -84,6 +83,75 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, +static unsigned ParseOneStorageClass (void) +/* Parse and return a storage class specifier */ +{ + unsigned StorageClass = 0; + + /* Check the storage class given */ + switch (CurTok.Tok) { + + case TOK_EXTERN: + StorageClass = SC_EXTERN | SC_STATIC; + NextToken (); + break; + + case TOK_STATIC: + StorageClass = SC_STATIC; + NextToken (); + break; + + case TOK_REGISTER: + StorageClass = SC_REGISTER | SC_STATIC; + NextToken (); + break; + + case TOK_AUTO: + StorageClass = SC_AUTO; + NextToken (); + break; + + case TOK_TYPEDEF: + StorageClass = SC_TYPEDEF; + NextToken (); + break; + + default: + break; + } + + return StorageClass; +} + + + +static int ParseStorageClass (DeclSpec* D) +/* Parse storage class specifiers. Return true if a specifier is read even if +** it was duplicated or disallowed. */ +{ + /* Check the storage class given */ + unsigned StorageClass = ParseOneStorageClass (); + + if (StorageClass == 0) { + return 0; + } + + while (StorageClass != 0) { + if (D->StorageClass == 0) { + D->StorageClass = StorageClass; + } else if (D->StorageClass == StorageClass) { + Warning ("Duplicate storage class specifier"); + } else { + Error ("Conflicting storage class specifier"); + } + StorageClass = ParseOneStorageClass (); + } + + return 1; +} + + + static void DuplicateQualifier (const char* Name) /* Print an error message */ { @@ -92,9 +160,9 @@ static void DuplicateQualifier (const char* Name) -static TypeCode OptionalQualifiers (TypeCode Allowed) +static TypeCode OptionalQualifiers (TypeCode Qualifiers, TypeCode Allowed) /* Read type qualifiers if we have any. Allowed specifies the allowed -** qualifiers. +** qualifiers. Return any read qualifiers even if they caused errors. */ { /* We start without any qualifiers */ @@ -107,7 +175,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_CONST: if (Allowed & T_QUAL_CONST) { - if (Q & T_QUAL_CONST) { + if (Qualifiers & T_QUAL_CONST) { DuplicateQualifier ("const"); } Q |= T_QUAL_CONST; @@ -118,7 +186,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_VOLATILE: if (Allowed & T_QUAL_VOLATILE) { - if (Q & T_QUAL_VOLATILE) { + if (Qualifiers & T_QUAL_VOLATILE) { DuplicateQualifier ("volatile"); } Q |= T_QUAL_VOLATILE; @@ -129,7 +197,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_RESTRICT: if (Allowed & T_QUAL_RESTRICT) { - if (Q & T_QUAL_RESTRICT) { + if (Qualifiers & T_QUAL_RESTRICT) { DuplicateQualifier ("restrict"); } Q |= T_QUAL_RESTRICT; @@ -140,7 +208,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_NEAR: if (Allowed & T_QUAL_NEAR) { - if (Q & T_QUAL_NEAR) { + if (Qualifiers & T_QUAL_NEAR) { DuplicateQualifier ("near"); } Q |= T_QUAL_NEAR; @@ -151,7 +219,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_FAR: if (Allowed & T_QUAL_FAR) { - if (Q & T_QUAL_FAR) { + if (Qualifiers & T_QUAL_FAR) { DuplicateQualifier ("far"); } Q |= T_QUAL_FAR; @@ -162,7 +230,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_FASTCALL: if (Allowed & T_QUAL_FASTCALL) { - if (Q & T_QUAL_FASTCALL) { + if (Qualifiers & T_QUAL_FASTCALL) { DuplicateQualifier ("fastcall"); } Q |= T_QUAL_FASTCALL; @@ -173,7 +241,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) case TOK_CDECL: if (Allowed & T_QUAL_CDECL) { - if (Q & T_QUAL_CDECL) { + if (Qualifiers & T_QUAL_CDECL) { DuplicateQualifier ("cdecl"); } Q |= T_QUAL_CDECL; @@ -187,13 +255,16 @@ static TypeCode OptionalQualifiers (TypeCode Allowed) } + /* Combine with newly read qualifiers */ + Qualifiers |= Q; + /* Skip the token */ NextToken (); } Done: /* We cannot have more than one address size far qualifier */ - switch (Q & T_QUAL_ADDRSIZE) { + switch (Qualifiers & T_QUAL_ADDRSIZE) { case T_QUAL_NONE: case T_QUAL_NEAR: @@ -202,11 +273,11 @@ Done: default: Error ("Cannot specify more than one address size qualifier"); - Q &= ~T_QUAL_ADDRSIZE; + Qualifiers &= ~T_QUAL_ADDRSIZE; } /* We cannot have more than one calling convention specifier */ - switch (Q & T_QUAL_CCONV) { + switch (Qualifiers & T_QUAL_CCONV) { case T_QUAL_NONE: case T_QUAL_FASTCALL: @@ -215,15 +286,41 @@ Done: default: Error ("Cannot specify more than one calling convention qualifier"); - Q &= ~T_QUAL_CCONV; + Qualifiers &= ~T_QUAL_CCONV; } - /* Return the qualifiers read */ + /* Return any qualifiers just read */ return Q; } +static void OptionalSpecifiers (DeclSpec* Spec, TypeCode* Qualifiers, typespec_t TSFlags) +/* Read storage specifiers and/or type qualifiers if we have any. Storage class +** specifiers require the corresponding typespec_t flag set to be allowed, and +** only const and volatile type qualifiers are allowed under any circumstance. +** Read storage class specifiers are output in *Spec and type qualifiers are +** output in *Qualifiers with error checking. +*/ +{ + TypeCode Q = T_QUAL_NONE; + int Continue; + + do { + /* There may be type qualifiers *before* any storage class specifiers */ + Q = OptionalQualifiers (*Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE); + *Qualifiers |= Q; + + /* Parse storage class specifiers anyway then check */ + Continue = ParseStorageClass (Spec); + if (Continue && (TSFlags & (TS_STORAGE_CLASS_SPEC | TS_FUNCTION_SPEC)) == 0) { + Error ("Unexpected storage class specified"); + } + } while (Continue || Q != T_QUAL_NONE); +} + + + static void OptionalInt (void) /* Eat an optional "int" token */ { @@ -396,48 +493,6 @@ static void FixQualifiers (Type* DataType) -static unsigned ParseOneStorageClass (void) -/* Parse and return a storage class */ -{ - unsigned StorageClass = 0; - - /* Check the storage class given */ - switch (CurTok.Tok) { - - case TOK_EXTERN: - StorageClass = SC_EXTERN | SC_STATIC; - NextToken (); - break; - - case TOK_STATIC: - StorageClass = SC_STATIC; - NextToken (); - break; - - case TOK_REGISTER: - StorageClass = SC_REGISTER | SC_STATIC; - NextToken (); - break; - - case TOK_AUTO: - StorageClass = SC_AUTO; - NextToken (); - break; - - case TOK_TYPEDEF: - StorageClass = SC_TYPEDEF; - NextToken (); - break; - - default: - break; - } - - return StorageClass; -} - - - static void CheckArrayElementType (Type* DataType) /* Check if data type consists of arrays of incomplete element types */ { @@ -469,33 +524,6 @@ static void CheckArrayElementType (Type* DataType) -static void ParseStorageClass (DeclSpec* D, unsigned DefStorage) -/* Parse a storage class */ -{ - /* Assume we're using an explicit storage class */ - D->Flags &= ~DS_DEF_STORAGE; - - /* Check the storage class given */ - D->StorageClass = ParseOneStorageClass (); - if (D->StorageClass == 0) { - /* No storage class given, use default */ - D->Flags |= DS_DEF_STORAGE; - D->StorageClass = DefStorage; - } else { - unsigned StorageClass = ParseOneStorageClass (); - while (StorageClass != 0) { - if (D->StorageClass == StorageClass) { - Warning ("Duplicate storage class specifier"); - } else { - Error ("Conflicting storage class specifier"); - } - StorageClass = ParseOneStorageClass (); - } - } -} - - - static SymEntry* ESUForwardDecl (const char* Name, unsigned Flags, unsigned* DSFlags) /* Handle an enum, struct or union forward decl */ { @@ -896,7 +924,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) } InitDeclSpec (&Spec); - ParseTypeSpec (&Spec, -1, T_QUAL_NONE, &SignednessSpecified); + ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE, &SignednessSpecified); /* Read fields with this type */ while (1) { @@ -1046,7 +1074,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) } InitDeclSpec (&Spec); - ParseTypeSpec (&Spec, -1, T_QUAL_NONE, &SignednessSpecified); + ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE, &SignednessSpecified); /* Read fields with this type */ while (1) { @@ -1212,8 +1240,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) { -static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, - int* SignednessSpecified) +static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpecified) /* Parse a type specifier. Store whether one of "signed" or "unsigned" was ** specified, so bit-fields of unspecified signedness can be treated as ** unsigned; without special handling, it would be treated as signed. @@ -1221,6 +1248,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, { ident Ident; SymEntry* TagEntry; + TypeCode Qualifiers = T_QUAL_NONE; if (SignednessSpecified != NULL) { *SignednessSpecified = 0; @@ -1229,8 +1257,8 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, /* Assume we have an explicit type */ D->Flags &= ~DS_DEF_TYPE; - /* Read type qualifiers if we have any */ - Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE); + /* Read storage specifiers and/or type qualifiers if we have any */ + OptionalSpecifiers (D, &Qualifiers, TSFlags); /* Look at the data type */ switch (CurTok.Tok) { @@ -1477,20 +1505,21 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, /* FALL THROUGH */ default: - if (Default < 0) { + if ((TSFlags & TS_MASK_DEFAULT_TYPE) != TS_DEFAULT_TYPE_INT) { Error ("Type expected"); D->Type[0].C = T_INT; D->Type[1].C = T_END; } else { D->Flags |= DS_DEF_TYPE; - D->Type[0].C = (TypeCode) Default; + D->Type[0].C = T_INT; D->Type[1].C = T_END; } break; } - /* There may also be qualifiers *after* the initial type */ - D->Type[0].C |= (Qualifiers | OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE)); + /* There may also be specifiers/qualifiers *after* the initial type */ + OptionalSpecifiers (D, &Qualifiers, TSFlags); + D->Type[0].C |= Qualifiers; } @@ -1570,7 +1599,7 @@ static void ParseOldStyleParamList (FuncDesc* F) DeclSpec Spec; /* Read the declaration specifier */ - ParseDeclSpec (&Spec, SC_AUTO, T_INT); + ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO); /* We accept only auto and register as storage class specifiers, but ** we ignore all this, since we use auto anyway. @@ -1649,7 +1678,7 @@ static void ParseAnsiParamList (FuncDesc* F) } /* Read the declaration specifier */ - ParseDeclSpec (&Spec, SC_AUTO, T_INT); + ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO); /* We accept only auto and register as storage class specifiers */ if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) { @@ -1797,7 +1826,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) ** qualifier later will be transfered to the function itself. If it's a ** pointer to something else, it will be flagged as an error. */ - TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV); + TypeCode Qualifiers = OptionalQualifiers (T_QUAL_NONE, T_QUAL_ADDRSIZE | T_QUAL_CCONV); /* Pointer to something */ if (CurTok.Tok == TOK_STAR) { @@ -1806,7 +1835,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) NextToken (); /* Allow const, restrict, and volatile qualifiers */ - Qualifiers |= OptionalQualifiers (T_QUAL_CVR); + Qualifiers |= OptionalQualifiers (Qualifiers, T_QUAL_CVR); /* Parse the type that the pointer points to */ Declarator (Spec, D, Mode); @@ -1951,7 +1980,7 @@ Type* ParseType (Type* T) /* Get a type without a default */ InitDeclSpec (&Spec); - ParseTypeSpec (&Spec, -1, T_QUAL_NONE, NULL); + ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE, NULL); /* Parse additional declarators */ ParseDecl (&Spec, &Decl, DM_NO_IDENT); @@ -2076,22 +2105,23 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode) -void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType) +void ParseDeclSpec (DeclSpec* D, typespec_t TSFlags, unsigned DefStorage) /* Parse a declaration specification */ { - TypeCode Qualifiers; - /* Initialize the DeclSpec struct */ InitDeclSpec (D); - /* There may be qualifiers *before* the storage class specifier */ - Qualifiers = OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE); + /* Assume we're using an explicit storage class */ + D->Flags &= ~DS_DEF_STORAGE; - /* Now get the storage class specifier for this declaration */ - ParseStorageClass (D, DefStorage); + /* Parse the type specifiers */ + ParseTypeSpec (D, TSFlags | TS_STORAGE_CLASS_SPEC | TS_FUNCTION_SPEC, NULL); - /* Parse the type specifiers passing any initial type qualifiers */ - ParseTypeSpec (D, DefType, Qualifiers, NULL); + /* If no explicit storage class is given, use the default */ + if (D->StorageClass == 0) { + D->Flags |= DS_DEF_STORAGE; + D->StorageClass = DefStorage; + } } diff --git a/src/cc65/declare.h b/src/cc65/declare.h index 2b8b36f1c..474a848a9 100644 --- a/src/cc65/declare.h +++ b/src/cc65/declare.h @@ -53,6 +53,22 @@ +/* Type specifier parser flags */ +typedef enum typespec_t typespec_t; +enum typespec_t { + TS_NONE = 0x00, + + /* Default type */ + TS_MASK_DEFAULT_TYPE = 0x03, + TS_DEFAULT_TYPE_NONE = 0x00, /* No default type */ + TS_DEFAULT_TYPE_INT = 0x01, /* Good old int */ + TS_DEFAULT_TYPE_AUTO = 0x02, /* C23 type inference with auto */ + + /* Whether to allow certain kinds of specifiers */ + TS_STORAGE_CLASS_SPEC = 0x04, /* Allow storage storage class specifiers */ + TS_FUNCTION_SPEC = 0x08, /* Allow function specifiers */ +}; + /* Masks for the Flags field in DeclSpec */ #define DS_DEF_STORAGE 0x0001U /* Default storage class used */ #define DS_DEF_TYPE 0x0002U /* Default type used */ @@ -105,7 +121,7 @@ Type* ParseType (Type* Type); void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode); /* Parse a variable, type or function declaration */ -void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType); +void ParseDeclSpec (DeclSpec* D, typespec_t TSFlags, unsigned DefStorage); /* Parse a declaration specification */ void CheckEmptyDecl (const DeclSpec* D); diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 7a22b47b2..c95a5a401 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1301,7 +1301,7 @@ static void Primary (ExprDesc* E) /* Let's see if this is a C99-style declaration */ DeclSpec Spec; InitDeclSpec (&Spec); - ParseDeclSpec (&Spec, -1, T_QUAL_NONE); + ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_AUTO); if (Spec.Type->C != T_END) { diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 5f182f061..fb5bc2563 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -568,7 +568,7 @@ void DeclareLocals (void) continue; } - ParseDeclSpec (&Spec, SC_AUTO, T_INT); + ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_AUTO); if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */ (Spec.Flags & DS_DEF_TYPE) != 0 && /* No type given */ GetQualifier (Spec.Type) == T_QUAL_NONE) { /* No type qualifier */ diff --git a/test/misc/int-static-1888.c b/test/misc/int-static-1888.c deleted file mode 100644 index e5234ab2c..000000000 --- a/test/misc/int-static-1888.c +++ /dev/null @@ -1,10 +0,0 @@ - -/* bug #1888 - The compiler doesn't accept valid data declarations */ - -/* The following is a valid declaration but not accepted by the compiler */ -int static a; - -int main(void) -{ - return 0; -} diff --git a/test/val/decl-mixed-specifiers.c b/test/val/decl-mixed-specifiers.c new file mode 100644 index 000000000..a0fb1596b --- /dev/null +++ b/test/val/decl-mixed-specifiers.c @@ -0,0 +1,19 @@ +/* bug 1888 - cc65 fails with storage class specifiers after type specifiers */ + +#include <stdio.h> + +int const typedef volatile x_type, * const volatile y_type; + +int static failures = 0; + +int extern main(void); + +int main(void) +{ + volatile static x_type const x = 42, * const volatile y[] = { 1 ? &x : (y_type)0 }; + if (**y != 42) { + ++failures; + printf("y = %d, Expected: 42\n", **y); + } + return failures; +} From 44b2e4f3316c34c6b18190af109f120f9eb45cdb Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 3 Nov 2022 17:40:13 +0100 Subject: [PATCH 089/360] added examples for tests that compare the compiler output with a reference --- Contributing.md | 1 + test/readme.txt | 22 +++++++++ test/ref/Makefile | 70 ++++++++++++++++++++++++++-- test/ref/custom-reference-error.c | 21 +++++++++ test/ref/custom-reference-error.cref | 5 ++ test/ref/custom-reference.c | 24 ++++++++++ test/ref/custom-reference.cref | 2 + 7 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 test/ref/custom-reference-error.c create mode 100644 test/ref/custom-reference-error.cref create mode 100644 test/ref/custom-reference.c create mode 100644 test/ref/custom-reference.cref diff --git a/Contributing.md b/Contributing.md index ab1e73508..3541979f6 100644 --- a/Contributing.md +++ b/Contributing.md @@ -8,6 +8,7 @@ This document contains all kinds of information that you should know if you want * You must obey these rules when contributing new code or documentation to cc65. We are well aware that not all existing code may respect all rules outlined here - but this is no reason for you not to respect them. * One commit/patch/PR per issue. Do not mix several things unless they are very closely related. +* Sometimes when you make a PR, it may break completely unrelated tests. However, any PR is expected to merge cleanly with no failures. That means in practise that you are expected to fix/update the failing tests if required - for example this might be needed if you make changes to the compiler that changes the format of error- or warning messages. In that case you might have to update some reference files in the testbench. Obviously still check if that is actually the right thing to do ;) # Codestyle rules diff --git a/test/readme.txt b/test/readme.txt index dd87ea9df..41d19aee3 100644 --- a/test/readme.txt +++ b/test/readme.txt @@ -20,6 +20,28 @@ compiler is working as expected (when the tests behave as described): library. /ref - These tests produce output that must be compared with reference output. + Normally the reference output is produced by compiling the program on the + host (using gcc mostly) and then running them on the host. Tests should + be tweaked to produce the same output as on the host in the cases where + it would be different. + + The Makefile also handles some special cases (add the tests to the + respective list in the makefile): + + - Sometimes we want to check the warnings produced by the compiler. In + that case use the CUSTOMSOURCES list. Whatever output the compiler writes + to stderr will be compared against the matching .cref file. There is an + example in custom-reference.c/.cref + + - Sometimes we want to check what kind of output the compiler produces + for a file that does not compile. In that case use the ERRORSOURCES list. + There is an example in custom-reference-error.c/.cref + + Warning: please understand that comparing the compiler output against + a reference produces a moving target, ie the tests may break randomly + at any time when the compiler output changes for whatever reason. So + only ever use this as a last resort when something can not be tested by + other means. /err - contains tests that MUST NOT compile diff --git a/test/ref/Makefile b/test/ref/Makefile index d9c9817ee..3c275e308 100644 --- a/test/ref/Makefile +++ b/test/ref/Makefile @@ -11,12 +11,14 @@ ifdef CMD_EXE NULLDEV = nul: MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) + CP=copy else S = / EXE = NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 + CP=cp endif ifdef QUIET @@ -42,24 +44,47 @@ CFLAGS = -O2 -Wall -W -Wextra -funsigned-char -fwrapv -fno-strict-overflow .PHONY: all clean -SOURCES := $(wildcard *.c) +# list of sources that produces warnings that we want to check. a .cref file +# containing the exact output is required. +CUSTOMSOURCES = \ + custom-reference.c + +# list of sources that produce a compiler error. a .cref files containing the +# exact error output is required +ERRORSOURCES = \ + custom-reference-error.c + +SOURCES := $(filter-out $(CUSTOMSOURCES) $(ERRORSOURCES),$(wildcard *.c)) + REFS = $(SOURCES:%.c=$(WORKDIR)/%.ref) +CUSTOMREFS = $(CUSTOMSOURCES:%.c=$(WORKDIR)/%.cref) $(ERRORSOURCES:%.c=$(WORKDIR)/%.cref) + TESTS = $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).6502.prg)) TESTS += $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).65c02.prg)) -all: $(REFS) $(TESTS) +CUSTOMTESTS = $(foreach option,$(OPTIONS),$(CUSTOMSOURCES:%.c=$(WORKDIR)/%.$(option).6502.custom.prg)) +CUSTOMTESTS += $(foreach option,$(OPTIONS),$(CUSTOMSOURCES:%.c=$(WORKDIR)/%.$(option).65c02.custom.prg)) + +ERRORTESTS = $(foreach option,$(OPTIONS),$(ERRORSOURCES:%.c=$(WORKDIR)/%.$(option).6502.error.prg)) +ERRORTESTS += $(foreach option,$(OPTIONS),$(ERRORSOURCES:%.c=$(WORKDIR)/%.$(option).65c02.error.prg)) + +all: $(CUSTOMREFS) $(REFS) $(TESTS) $(CUSTOMTESTS) $(ERRORTESTS) $(WORKDIR): $(call MKDIR,$(WORKDIR)) +$(ISEQUAL): ../isequal.c | $(WORKDIR) + $(CC) $(CFLAGS) -o $@ $< + +$(WORKDIR)/%.cref: %.cref | $(WORKDIR) + $(if $(QUIET),echo ref/$*.cref) + $(CP) $*.cref $@ + $(WORKDIR)/%.ref: %.c | $(WORKDIR) $(if $(QUIET),echo ref/$*.host) $(CC) $(CFLAGS) -o $(WORKDIR)/$*.host $< $(NULLERR) $(WORKDIR)$S$*.host > $@ -$(ISEQUAL): ../isequal.c | $(WORKDIR) - $(CC) $(CFLAGS) -o $@ $< - # "yaccdbg.c" includes "yacc.c". # yaccdbg's built files must depend on both of them. # @@ -78,8 +103,43 @@ $(WORKDIR)/%.$1.$2.prg: %.c $(WORKDIR)/%.ref $(ISEQUAL) endef # PRG_template +# extra template for the case when compilation works, but we still want to +# compare the warning output with our custom reference +define PRG_custom_template + +$(WORKDIR)/%.$1.$2.custom.prg: %.c $(WORKDIR)/%.ref %.c $(WORKDIR)/%.cref $(ISEQUAL) + $(if $(QUIET),echo cref/$$*.$1.$2.custom.prg) + -$(CC65) -t sim$2 $$(CC65FLAGS) -$1 -o $$(@:.custom.prg=.s) $$< 2> $(WORKDIR)/$$*.$1.$2.cout + $(CA65) -t sim$2 -o $$(@:.custom.prg=.o) $$(@:.custom.prg=.s) $(NULLERR) + $(LD65) -t sim$2 -o $$@ $$(@:.custom.prg=.o) sim$2.lib $(NULLERR) + $(SIM65) $(SIM65FLAGS) $$@ > $(WORKDIR)/$$*.$1.$2.out + $(ISEQUAL) $(WORKDIR)/$$*.$1.$2.cout $(WORKDIR)/$$*.cref + $(ISEQUAL) $(WORKDIR)/$$*.$1.$2.out $(WORKDIR)/$$*.ref + +endef # PRG_error_template + +# extra template for the case when compilation fails, but we still want to +# compare the error output with our custom reference +define PRG_error_template + +$(WORKDIR)/%.$1.$2.error.prg: %.c $(WORKDIR)/%.cref $(ISEQUAL) + $(if $(QUIET),echo cref/$$*.$1.$2.error.prg) + -$(CC65) -t sim$2 $$(CC65FLAGS) -$1 -o $$(@:.error.prg=.s) $$< 2> $(WORKDIR)/$$*.$1.$2.cout +# $(CA65) -t sim$2 -o $$(@:.error.prg=.o) $$(@:.error.prg=.s) $(NULLERR) +# $(LD65) -t sim$2 -o $$@ $$(@:.error.prg=.o) sim$2.lib $(NULLERR) +# $(SIM65) $(SIM65FLAGS) $$@ > $(WORKDIR)/$$*.$1.$2.out + $(ISEQUAL) $(WORKDIR)/$$*.$1.$2.cout $(WORKDIR)/$$*.cref + +endef # PRG_error_template + $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),6502))) $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),65c02))) +$(foreach option,$(OPTIONS),$(eval $(call PRG_custom_template,$(option),6502))) +$(foreach option,$(OPTIONS),$(eval $(call PRG_custom_template,$(option),65c02))) + +$(foreach option,$(OPTIONS),$(eval $(call PRG_error_template,$(option),6502))) +$(foreach option,$(OPTIONS),$(eval $(call PRG_error_template,$(option),65c02))) + clean: @$(call RMDIR,$(WORKDIR)) diff --git a/test/ref/custom-reference-error.c b/test/ref/custom-reference-error.c new file mode 100644 index 000000000..c86a8b9e9 --- /dev/null +++ b/test/ref/custom-reference-error.c @@ -0,0 +1,21 @@ + +/* + this is an example (not actually a regression test) that shows how to + make a check that compares the compiler (error-) output with a provided + reference. + + to produce a reference file, first make sure your program "works" as intended, + then "make" in this directory once and copy the produced compiler output to + the reference: + + $ cp ../../testwrk/ref/custom-reference-error.g.6502.out custom-reference-error.cref + + and then "make" again to confirm +*/ + +int main(int argc, char* argv[]) +{ + printf("%02x", 0x42); + n = 0; /* produce an error */ + /* another error */ +} diff --git a/test/ref/custom-reference-error.cref b/test/ref/custom-reference-error.cref new file mode 100644 index 000000000..fa584f307 --- /dev/null +++ b/test/ref/custom-reference-error.cref @@ -0,0 +1,5 @@ +custom-reference-error.c:18: Error: Call to undeclared function 'printf' +custom-reference-error.c:19: Error: Undefined symbol: 'n' +custom-reference-error.c:21: Warning: Control reaches end of non-void function [-Wreturn-type] +custom-reference-error.c:21: Warning: Parameter 'argc' is never used +custom-reference-error.c:21: Warning: Parameter 'argv' is never used diff --git a/test/ref/custom-reference.c b/test/ref/custom-reference.c new file mode 100644 index 000000000..5d9c356df --- /dev/null +++ b/test/ref/custom-reference.c @@ -0,0 +1,24 @@ + +/* + this is an example (not actually a regression test) that shows how to + make a check that compares the compiler (error-) output with a provided + reference. + + to produce a reference file, first make sure your program "works" as intended, + then "make" in this directory once and copy the produced compiler output to + the reference: + + $ cp ../../testwrk/ref/custom-reference.g.6502.out custom-reference.cref + + and then "make" again to confirm +*/ + +#include <stdint.h> +#include <stdio.h> + +int main(int argc, char* argv[]) +{ + printf("%02x", 0x42); + /* produce a warning */ + return 0; +} diff --git a/test/ref/custom-reference.cref b/test/ref/custom-reference.cref new file mode 100644 index 000000000..4dba6009b --- /dev/null +++ b/test/ref/custom-reference.cref @@ -0,0 +1,2 @@ +custom-reference.c:24: Warning: Parameter 'argc' is never used +custom-reference.c:24: Warning: Parameter 'argv' is never used From cc450706d13ccde2e6b8d638d1af38edfc292dbf Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 3 Nov 2022 18:03:47 +0100 Subject: [PATCH 090/360] testcase related to bug #1888 --- test/misc/Makefile | 6 ++++++ test/misc/int-static-1888.c | 10 ++++++++++ 2 files changed, 16 insertions(+) create mode 100644 test/misc/int-static-1888.c diff --git a/test/misc/Makefile b/test/misc/Makefile index e77d37b29..f18f40da6 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -58,6 +58,12 @@ $(ISEQUAL): ../isequal.c | $(WORKDIR) define PRG_template +# should compile, but gives an error +$(WORKDIR)/int-static-1888.$1.$2.prg: int-static-1888.c | $(WORKDIR) + @echo "FIXME: " $$@ "currently does not compile." + $(if $(QUIET),echo misc/int-static-1888.$1.$2.prg) + $(NOT) $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) + # should compile, but gives an error $(WORKDIR)/bug1768.$1.$2.prg: bug1768.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." diff --git a/test/misc/int-static-1888.c b/test/misc/int-static-1888.c new file mode 100644 index 000000000..e5234ab2c --- /dev/null +++ b/test/misc/int-static-1888.c @@ -0,0 +1,10 @@ + +/* bug #1888 - The compiler doesn't accept valid data declarations */ + +/* The following is a valid declaration but not accepted by the compiler */ +int static a; + +int main(void) +{ + return 0; +} From 79fd078ae340da74dbc5111ad04e919d0951c5e9 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 3 Nov 2022 18:27:10 +0100 Subject: [PATCH 091/360] add check for line endings containing CR. --- .github/checks/Makefile | 7 +++++-- .github/checks/lineendings.sh | 18 ++++++++++++++++++ Contributing.md | 4 ++++ test/err/bug1890.c | 18 +++++++++--------- 4 files changed, 36 insertions(+), 11 deletions(-) create mode 100755 .github/checks/lineendings.sh diff --git a/.github/checks/Makefile b/.github/checks/Makefile index 18cc153d4..6519eb5b8 100644 --- a/.github/checks/Makefile +++ b/.github/checks/Makefile @@ -1,7 +1,10 @@ -.PHONY: checkstyle tabs lastline spaces noexec +.PHONY: checkstyle lineendings tabs lastline spaces noexec -checkstyle: tabs lastline spaces noexec +checkstyle: lineendings tabs lastline spaces noexec + +lineendings: lineendings.sh + @./lineendings.sh tabs: tabs.sh @./tabs.sh diff --git a/.github/checks/lineendings.sh b/.github/checks/lineendings.sh new file mode 100755 index 000000000..5b445522f --- /dev/null +++ b/.github/checks/lineendings.sh @@ -0,0 +1,18 @@ +#! /bin/bash +OLDCWD=`pwd` +SCRIPT_PATH=`dirname $0` +CHECK_PATH=. + +cd $SCRIPT_PATH/../../ + +FILES=`find $CHECK_PATH -type f \( -name \*.inc -o -name Makefile -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | grep -v "libwrk/" | grep -v "testwrk/" | xargs grep -IUl $'\r'` + +cd $OLDCWD + +if [ x"$FILES"x != xx ]; then + echo "error: found CR in the following files:" >&2 + for n in $FILES; do + echo $n >&2 + done + exit -1 +fi diff --git a/Contributing.md b/Contributing.md index 3541979f6..e316b9c61 100644 --- a/Contributing.md +++ b/Contributing.md @@ -14,6 +14,10 @@ This document contains all kinds of information that you should know if you want ## All Sources +### Line endings + +All files must only contain Unix style 'LF' line endings. Please configure your editors accordingly. + ### TABs and spaces This is an ongoing controversial topic - everyone knows that. However, the following is how we do it :) diff --git a/test/err/bug1890.c b/test/err/bug1890.c index afe04f071..15d857cdb 100644 --- a/test/err/bug1890.c +++ b/test/err/bug1890.c @@ -1,9 +1,9 @@ -/* bug #1890 - Overflow in enumerator value is not detected */ - -#include <limits.h> -enum { a = ULONG_MAX, b } c = b; - -int main(void) -{ - return 0; -} +/* bug #1890 - Overflow in enumerator value is not detected */ + +#include <limits.h> +enum { a = ULONG_MAX, b } c = b; + +int main(void) +{ + return 0; +} From e608f8a94f2a761b4c97e7fdcbea0a4fdebd9e26 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 5 Nov 2022 18:30:02 +0800 Subject: [PATCH 092/360] Renamed several tests. --- test/val/{extern.c => decl-extern-shadow.c} | 0 test/val/{static-1.c => decl-static-extern.c} | 0 test/val/{static-fwd-decl.c => decl-static-fwd.c} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/val/{extern.c => decl-extern-shadow.c} (100%) rename test/val/{static-1.c => decl-static-extern.c} (100%) rename test/val/{static-fwd-decl.c => decl-static-fwd.c} (100%) diff --git a/test/val/extern.c b/test/val/decl-extern-shadow.c similarity index 100% rename from test/val/extern.c rename to test/val/decl-extern-shadow.c diff --git a/test/val/static-1.c b/test/val/decl-static-extern.c similarity index 100% rename from test/val/static-1.c rename to test/val/decl-static-extern.c diff --git a/test/val/static-fwd-decl.c b/test/val/decl-static-fwd.c similarity index 100% rename from test/val/static-fwd-decl.c rename to test/val/decl-static-fwd.c From 699ba1fbd6938cfb81d705fdf1f6304433c7b05c Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 5 Nov 2022 16:42:01 +0100 Subject: [PATCH 093/360] when running on cmd.exe only print a message, the style tests require bash --- .github/checks/Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/checks/Makefile b/.github/checks/Makefile index 6519eb5b8..93eeddd19 100644 --- a/.github/checks/Makefile +++ b/.github/checks/Makefile @@ -1,4 +1,17 @@ +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +ifdef CMD_EXE + +.PHONY: checkstyle + +checkstyle: + $(info INFO: style checks require bash.) + +else + .PHONY: checkstyle lineendings tabs lastline spaces noexec checkstyle: lineendings tabs lastline spaces noexec @@ -17,3 +30,5 @@ spaces: spaces.sh noexec: noexec.sh @./noexec.sh + +endif From bf924395fbd7019c53798a5c7379daa4a071e6e9 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 5 Nov 2022 19:41:02 +0100 Subject: [PATCH 094/360] fix some bashisms, hopefully makes "check" work again in cmd.exe --- samples/Makefile | 1 + targettest/Makefile | 1 + targettest/pce/Makefile | 5 ++++- test/asm/listing/Makefile | 43 +++++++++++++++++++++++---------------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/samples/Makefile b/samples/Makefile index 4007e3522..2aa637844 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -414,6 +414,7 @@ TARGETS := \ define TARGET_recipe +@echo making samples for: $(T) @$(MAKE) -j2 SYS:=$(T) @$(MAKE) --no-print-directory clean SYS:=$(T) diff --git a/targettest/Makefile b/targettest/Makefile index 1475d4eb2..a359c7e7a 100644 --- a/targettest/Makefile +++ b/targettest/Makefile @@ -761,6 +761,7 @@ TARGETS := \ define TARGET_recipe +@echo making targettest for: $(T) @$(MAKE) -j2 SYS:=$(T) @$(MAKE) --no-print-directory clean SYS:=$(T) diff --git a/targettest/pce/Makefile b/targettest/pce/Makefile index f757c3062..89abca6b6 100644 --- a/targettest/pce/Makefile +++ b/targettest/pce/Makefile @@ -73,4 +73,7 @@ endif dd if=$< bs=8K count=${COUNT} >> $@ clean: - @$(DEL) conio.o conio.??? 2>$(NULLDEV) + @$(DEL) conio.o 2>$(NULLDEV) + @$(DEL) conio.pce 2>$(NULLDEV) + @$(DEL) conio.bin 2>$(NULLDEV) + @$(DEL) conio.map 2>$(NULLDEV) diff --git a/test/asm/listing/Makefile b/test/asm/listing/Makefile index d3dc21409..10f5a5a97 100644 --- a/test/asm/listing/Makefile +++ b/test/asm/listing/Makefile @@ -5,25 +5,33 @@ ifneq ($(shell echo),) endif ifdef CMD_EXE + S = $(subst /,\,/) EXE = .exe MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /q /s $(subst /,\,$1) + ERRDIR = 2>&1 + TRUE = exit 0 + CAT = type $(subst /,\,$1) else + S = / EXE = MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 + ERRDIR = 2>&1 + TRUE = true + CAT = cat endif ifdef QUIET # .SILENT: endif -CA65 := $(if $(wildcard ../../../bin/ca65*),../../../bin/ca65,ca65) -LD65 := $(if $(wildcard ../../../bin/ld65*),../../../bin/ld65,ld65) +CA65 := $(if $(wildcard ../../../bin/ca65*),..$S..$S..$Sbin$Sca65,ca65) +LD65 := $(if $(wildcard ../../../bin/ld65*),..$S..$S..$Sbin$Sld65,ld65) WORKDIR = ../../../testwrk/asm/listing -ISEQUAL = ../../../testwrk/isequal$(EXE) +ISEQUAL = ..$S..$S..$Stestwrk$Sisequal$(EXE) CC = gcc CFLAGS = -O2 @@ -50,14 +58,14 @@ $(WORKDIR)/$1.bin: $1.s $(ISEQUAL) # compile without generating listing ifeq ($(wildcard control/$1.err),) - $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2>&1 + $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) $(ERRDIR) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2>&1 + $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) $(ERRDIR) endif else - $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2>&1 || true + $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) $(ERRDIR) || $(TRUE) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2>&1 || true + $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) $(ERRDIR) || $(TRUE) endif endif @@ -71,14 +79,15 @@ ifneq ($(wildcard ref/$1.bin-ref),) $(ISEQUAL) --binary ref/$1.bin-ref $$@ endif +# rem $(indfo $(CAT) $(subst /,$$S,$$$(@:.bin=.ld65-err))) + ifneq ($(wildcard ref/$1.ld65err-ref),) - @echo cat $$(@:.bin=.ld65-err) - cat $$(@:.bin=.ld65-err) - @echo - @echo + @echo $(CAT) $$(@:.bin=.ld65-err) +# FIXME: somehow this refuses to work in cmd.exe +ifndef CMD_EXE + $(call CAT,$$(@:.bin=.ld65-err)) -diff -u ref/$1.ld65err-ref $$(@:.bin=.ld65-err) - @echo - @echo +endif $(ISEQUAL) --wildcards ref/$1.ld65err-ref $$(@:.bin=.ld65-err) else ifneq ($(wildcard $(WORKDIR)/$1.ld65-err),) @@ -88,14 +97,14 @@ endif # compile with listing file ifeq ($(wildcard control/$1.err),) - $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2>&1 + $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) $(ERRDIR) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2>&1 + $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) $(ERRDIR) endif else - $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2>&1 || true + $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) $(ERRDIR) || $(TRUE) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2>&1 || true + $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) $(ERRDIR) || $(TRUE) endif endif From 1452d8164d4bd9e88a507756642fea5e0180f015 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:37:41 +0100 Subject: [PATCH 095/360] add ATTR_UNUSED and ATTR_NORETURN --- src/common/attrib.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/common/attrib.h b/src/common/attrib.h index 07e08b2df..a7935d919 100644 --- a/src/common/attrib.h +++ b/src/common/attrib.h @@ -44,14 +44,20 @@ -#if defined(__GNUC__) -# define attribute(a) __attribute__(a) +#ifdef __clang__ +# define attribute(a) __attribute__(a) +# define ATTR_UNUSED(x) +# define ATTR_NORETURN __attribute__((analyzer_noreturn)) +#elif defined(__GNUC__) +# define attribute(a) __attribute__(a) +# define ATTR_UNUSED(x) __attribute__((__unused__)) x +# define ATTR_NORETURN __attribute__((noreturn)) #else # define attribute(a) +# define ATTR_UNUSED(x) +# define ATTR_NORETURN #endif - - /* End of attrib.h */ #endif From e5777f7ccfdef0869845c4a92d3a8dc602371de9 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:38:07 +0100 Subject: [PATCH 096/360] add ATTR_UNUSED on the flags variable --- src/cc65/codegen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index e521fff73..00a4738e2 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -41,6 +41,7 @@ /* common */ #include "addrsize.h" +#include "attrib.h" #include "check.h" #include "cpu.h" #include "shift.h" @@ -4561,7 +4562,7 @@ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size) -void g_testbitfield (unsigned Flags, unsigned BitOffs, unsigned BitWidth) +void g_testbitfield (ATTR_UNUSED(unsigned Flags), unsigned BitOffs, unsigned BitWidth) /* Test bit-field in primary. */ { /* Since the end is inclusive and cannot be negative here, we subtract 1 from the sum */ From 5d1ad05cb8c6cdf21471f07a1df3e60118869d1c Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:48:53 +0100 Subject: [PATCH 097/360] oops --- src/common/attrib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/attrib.h b/src/common/attrib.h index a7935d919..a16b94a3b 100644 --- a/src/common/attrib.h +++ b/src/common/attrib.h @@ -46,7 +46,7 @@ #ifdef __clang__ # define attribute(a) __attribute__(a) -# define ATTR_UNUSED(x) +# define ATTR_UNUSED(x) x # define ATTR_NORETURN __attribute__((analyzer_noreturn)) #elif defined(__GNUC__) # define attribute(a) __attribute__(a) @@ -54,7 +54,7 @@ # define ATTR_NORETURN __attribute__((noreturn)) #else # define attribute(a) -# define ATTR_UNUSED(x) +# define ATTR_UNUSED(x) x # define ATTR_NORETURN #endif From 2dcccae036f38950be86a16dffd0b6f6a9ac5548 Mon Sep 17 00:00:00 2001 From: Silver Dream ! <silverdr@srebrnysen.com> Date: Sun, 6 Nov 2022 11:27:08 +0000 Subject: [PATCH 098/360] Updated ATTR_UNUSED() for clang --- src/common/attrib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/attrib.h b/src/common/attrib.h index a16b94a3b..3cdacb9d5 100644 --- a/src/common/attrib.h +++ b/src/common/attrib.h @@ -46,7 +46,7 @@ #ifdef __clang__ # define attribute(a) __attribute__(a) -# define ATTR_UNUSED(x) x +# define ATTR_UNUSED(x) __attribute__((__unused__)) x # define ATTR_NORETURN __attribute__((analyzer_noreturn)) #elif defined(__GNUC__) # define attribute(a) __attribute__(a) From e10b5fd79b0fb2194a7949d5d4316df40d8135a4 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Tue, 8 Nov 2022 14:42:52 +0800 Subject: [PATCH 099/360] Renamed a few functions and struct used for declaration parser. --- src/cc65/compile.c | 2 +- src/cc65/declare.c | 102 ++++++++++++++++++++++---------------------- src/cc65/declare.h | 8 ++-- src/cc65/declattr.c | 18 ++++---- src/cc65/declattr.h | 6 +-- src/cc65/expr.c | 2 +- src/cc65/initdata.c | 2 +- src/cc65/locals.c | 18 ++++---- src/cc65/symentry.c | 4 +- src/cc65/symentry.h | 4 +- 10 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/cc65/compile.c b/src/cc65/compile.c index f15c5bc54..73380f3df 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -146,7 +146,7 @@ static void Parse (void) comma = 0; while (1) { - Declaration Decl; + Declarator Decl; /* Read the next declaration */ ParseDecl (&Spec, &Decl, DM_NEED_IDENT); diff --git a/src/cc65/declare.c b/src/cc65/declare.c index f3674d711..f317964ad 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -356,8 +356,8 @@ void InitDeclSpec (DeclSpec* D) -static void InitDeclaration (Declaration* D) -/* Initialize the Declaration struct for use */ +static void InitDeclarator (Declarator* D) +/* Initialize the Declarator struct for use */ { D->Ident[0] = '\0'; D->Type[0].C = T_END; @@ -367,7 +367,7 @@ static void InitDeclaration (Declaration* D) -static void NeedTypeSpace (Declaration* D, unsigned Count) +static void NeedTypeSpace (Declarator* D, unsigned Count) /* Check if there is enough space for Count type specifiers within D */ { if (D->Index + Count >= MAXTYPELEN) { @@ -381,8 +381,8 @@ static void NeedTypeSpace (Declaration* D, unsigned Count) -static void AddTypeToDeclaration (Declaration* D, TypeCode T) -/* Add a type specifier to the type of a declaration */ +static void AddTypeCodeToDeclarator (Declarator* D, TypeCode T) +/* Add a type specifier to the type of a declarator */ { NeedTypeSpace (D, 1); D->Type[D->Index++].C = T; @@ -524,8 +524,8 @@ static void CheckArrayElementType (Type* DataType) -static SymEntry* ESUForwardDecl (const char* Name, unsigned Flags, unsigned* DSFlags) -/* Handle an enum, struct or union forward decl */ +static SymEntry* ForwardESU (const char* Name, unsigned Flags, unsigned* DSFlags) +/* Handle an enum, struct or union forward declaration */ { /* Try to find an enum/struct/union with the given name. If there is none, ** insert a forward declaration into the current lexical level. @@ -584,8 +584,8 @@ static const Type* GetEnumeratorType (long Min, unsigned long Max, int Signed) -static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags) -/* Process an enum declaration */ +static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags) +/* Process an enum specifier */ { SymTable* FieldTab; long EnumVal; @@ -602,7 +602,7 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags) if (CurTok.Tok != TOK_LCURLY) { /* Just a forward definition */ - return ESUForwardDecl (Name, SC_ENUM, DSFlags); + return ForwardESU (Name, SC_ENUM, DSFlags); } /* Add a forward declaration for the enum tag in the current lexical level */ @@ -754,7 +754,7 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags) -static int ParseFieldWidth (Declaration* D) +static int ParseFieldWidth (Declarator* D) /* Parse an optional field width. Returns -1 if no field width is specified, ** otherwise the width of the field. */ @@ -832,7 +832,7 @@ static unsigned PadWithBitField (unsigned StructSize, unsigned BitOffs) -static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon) +static unsigned AliasAnonStructFields (const Declarator* D, SymEntry* Anon) /* Create alias fields from an anon union/struct in the current lexical level. ** The function returns the count of created aliases. */ @@ -879,8 +879,8 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon) -static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) -/* Parse a union declaration. */ +static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags) +/* Parse a union specifier */ { unsigned UnionSize; @@ -895,7 +895,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) if (CurTok.Tok != TOK_LCURLY) { /* Just a forward declaration */ - return ESUForwardDecl (Name, SC_UNION, DSFlags); + return ForwardESU (Name, SC_UNION, DSFlags); } /* Add a forward declaration for the union tag in the current lexical level */ @@ -929,7 +929,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags) /* Read fields with this type */ while (1) { - Declaration Decl; + Declarator Decl; /* Get type and name of the struct field */ ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); @@ -1026,8 +1026,8 @@ NextMember: if (CurTok.Tok != TOK_COMMA) { -static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) -/* Parse a struct declaration. */ +static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags) +/* Parse a struct specifier */ { unsigned StructSize; @@ -1043,7 +1043,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) if (CurTok.Tok != TOK_LCURLY) { /* Just a forward declaration */ - return ESUForwardDecl (Name, SC_STRUCT, DSFlags); + return ForwardESU (Name, SC_STRUCT, DSFlags); } /* Add a forward declaration for the struct tag in the current lexical level */ @@ -1079,7 +1079,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags) /* Read fields with this type */ while (1) { - Declaration Decl; + Declarator Decl; /* If we had a flexible array member before, no other fields can ** follow. @@ -1418,7 +1418,7 @@ static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpeci /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Declare the union in the current scope */ - TagEntry = ParseUnionDecl (Ident, &D->Flags); + TagEntry = ParseUnionSpec (Ident, &D->Flags); /* Encode the union entry into the type */ D->Type[0].C = T_UNION; SetESUTagSym (D->Type, TagEntry); @@ -1437,7 +1437,7 @@ static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpeci /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Declare the struct in the current scope */ - TagEntry = ParseStructDecl (Ident, &D->Flags); + TagEntry = ParseStructSpec (Ident, &D->Flags); /* Encode the struct entry into the type */ D->Type[0].C = T_STRUCT; SetESUTagSym (D->Type, TagEntry); @@ -1460,7 +1460,7 @@ static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpeci /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Parse the enum decl */ - TagEntry = ParseEnumDecl (Ident, &D->Flags); + TagEntry = ParseEnumSpec (Ident, &D->Flags); /* Encode the enum entry into the type */ D->Type[0].C |= T_ENUM; SetESUTagSym (D->Type, TagEntry); @@ -1612,7 +1612,7 @@ static void ParseOldStyleParamList (FuncDesc* F) /* Parse a comma separated variable list */ while (1) { - Declaration Decl; + Declarator Decl; /* Read the parameter */ ParseDecl (&Spec, &Decl, DM_NEED_IDENT); @@ -1667,7 +1667,7 @@ static void ParseAnsiParamList (FuncDesc* F) while (CurTok.Tok != TOK_RPAREN) { DeclSpec Spec; - Declaration Decl; + Declarator Decl; SymEntry* Param; /* Allow an ellipsis as last parameter */ @@ -1748,7 +1748,7 @@ static void ParseAnsiParamList (FuncDesc* F) static FuncDesc* ParseFuncDecl (void) -/* Parse the argument list of a function. */ +/* Parse the argument list of a function with the enclosing parentheses */ { SymEntry* Sym; SymEntry* WrappedCall; @@ -1760,6 +1760,9 @@ static FuncDesc* ParseFuncDecl (void) /* Enter a new lexical level */ EnterFunctionLevel (); + /* Skip the opening paren */ + NextToken (); + /* Check for several special parameter lists */ if (CurTok.Tok == TOK_RPAREN) { /* Parameter list is empty (K&R-style) */ @@ -1817,14 +1820,14 @@ static FuncDesc* ParseFuncDecl (void) -static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) -/* Recursively process declarators. Build a type array in reverse order. */ +static void DirectDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode) +/* Recursively process direct declarators. Build a type array in reverse order. */ { - /* Read optional function or pointer qualifiers. They modify the - ** identifier or token to the right. For convenience, we allow a calling - ** convention also for pointers here. If it's a pointer-to-function, the - ** qualifier later will be transfered to the function itself. If it's a - ** pointer to something else, it will be flagged as an error. + /* Read optional function or pointer qualifiers that modify the identifier + ** or token to the right. For convenience, we allow a calling convention + ** also for pointers here. If it's a pointer-to-function, the qualifier + ** later will be transfered to the function itself. If it's a pointer to + ** something else, it will be flagged as an error. */ TypeCode Qualifiers = OptionalQualifiers (T_QUAL_NONE, T_QUAL_ADDRSIZE | T_QUAL_CCONV); @@ -1838,16 +1841,16 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) Qualifiers |= OptionalQualifiers (Qualifiers, T_QUAL_CVR); /* Parse the type that the pointer points to */ - Declarator (Spec, D, Mode); + DirectDecl (Spec, D, Mode); /* Add the type */ - AddTypeToDeclaration (D, T_PTR | Qualifiers); + AddTypeCodeToDeclarator (D, T_PTR | Qualifiers); return; } if (CurTok.Tok == TOK_LPAREN) { NextToken (); - Declarator (Spec, D, Mode); + DirectDecl (Spec, D, Mode); ConsumeRParen (); } else { /* Things depend on Mode now: @@ -1876,14 +1879,11 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) { if (CurTok.Tok == TOK_LPAREN) { - /* Function declaration */ + /* Function declarator */ FuncDesc* F; SymEntry* PrevEntry; - /* Skip the opening paren */ - NextToken (); - - /* Parse the function declaration */ + /* Parse the function declarator */ F = ParseFuncDecl (); /* We cannot specify fastcall for variadic functions */ @@ -1912,7 +1912,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) Qualifiers = T_QUAL_NONE; } else { - /* Array declaration. */ + /* Array declarator */ long Size = UNSPECIFIED; /* We cannot have any qualifiers for an array */ @@ -1976,7 +1976,7 @@ Type* ParseType (Type* T) /* Parse a complete type specification */ { DeclSpec Spec; - Declaration Decl; + Declarator Decl; /* Get a type without a default */ InitDeclSpec (&Spec); @@ -1994,19 +1994,19 @@ Type* ParseType (Type* T) -void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode) -/* Parse a variable, type or function declaration */ +void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode) +/* Parse a variable, type or function declarator */ { /* Used to check if we have any errors during parsing this */ unsigned PrevErrorCount = ErrorCount; - /* Initialize the Declaration struct */ - InitDeclaration (D); + /* Initialize the Declarator struct */ + InitDeclarator (D); - /* Get additional declarators and the identifier */ - Declarator (Spec, D, Mode); + /* Get additional derivation of the declarator and the identifier */ + DirectDecl (Spec, D, Mode); - /* Add the base type. */ + /* Add the base type */ NeedTypeSpace (D, TypeLen (Spec->Type) + 1); /* Bounds check */ TypeCopy (D->Type + D->Index, Spec->Type); @@ -2024,7 +2024,7 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode) D->StorageClass |= SC_FUNC; } - /* Parse attributes for this declaration */ + /* Parse attributes for this declarator */ ParseAttribute (D); /* Check several things for function or function pointer types */ diff --git a/src/cc65/declare.h b/src/cc65/declare.h index 474a848a9..ee9e1fc63 100644 --- a/src/cc65/declare.h +++ b/src/cc65/declare.h @@ -86,8 +86,8 @@ struct DeclSpec { }; /* Result of ParseDecl */ -typedef struct Declaration Declaration; -struct Declaration { +typedef struct Declarator Declarator; +struct Declarator { unsigned StorageClass; /* A set of SC_xxx flags */ Type Type[MAXTYPELEN]; /* The type */ ident Ident; /* The identifier, if any*/ @@ -118,8 +118,8 @@ void InitDeclSpec (DeclSpec* D); Type* ParseType (Type* Type); /* Parse a complete type specification */ -void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode); -/* Parse a variable, type or function declaration */ +void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode); +/* Parse a variable, type or function declarator */ void ParseDeclSpec (DeclSpec* D, typespec_t TSFlags, unsigned DefStorage); /* Parse a declaration specification */ diff --git a/src/cc65/declattr.c b/src/cc65/declattr.c index 37048e69b..eec89552e 100644 --- a/src/cc65/declattr.c +++ b/src/cc65/declattr.c @@ -2,7 +2,7 @@ /* */ /* declattr.c */ /* */ -/* Declaration attributes */ +/* Declarator attributes */ /* */ /* */ /* */ @@ -55,8 +55,8 @@ /* Forwards for attribute handlers */ -static void NoReturnAttr (Declaration* D); -static void UnusedAttr (Declaration* D); +static void NoReturnAttr (Declarator* D); +static void UnusedAttr (Declarator* D); @@ -64,7 +64,7 @@ static void UnusedAttr (Declaration* D); typedef struct AttrDesc AttrDesc; struct AttrDesc { const char Name[15]; - void (*Handler) (Declaration*); + void (*Handler) (Declarator*); }; static const AttrDesc AttrTable [] = { { "__noreturn__", NoReturnAttr }, @@ -141,8 +141,8 @@ static void ErrorSkip (void) -static void AddAttr (Declaration* D, DeclAttr* A) -/* Add an attribute to a declaration */ +static void AddAttr (Declarator* D, DeclAttr* A) +/* Add an attribute to a declarator */ { /* Allocate the list if necessary, the add the attribute */ if (D->Attributes == 0) { @@ -159,7 +159,7 @@ static void AddAttr (Declaration* D, DeclAttr* A) -static void NoReturnAttr (Declaration* D) +static void NoReturnAttr (Declarator* D) /* Parse the "noreturn" attribute */ { /* Add the noreturn attribute */ @@ -168,7 +168,7 @@ static void NoReturnAttr (Declaration* D) -static void UnusedAttr (Declaration* D) +static void UnusedAttr (Declarator* D) /* Parse the "unused" attribute */ { /* Add the noreturn attribute */ @@ -177,7 +177,7 @@ static void UnusedAttr (Declaration* D) -void ParseAttribute (Declaration* D) +void ParseAttribute (Declarator* D) /* Parse an additional __attribute__ modifier */ { /* Do we have an attribute? */ diff --git a/src/cc65/declattr.h b/src/cc65/declattr.h index 63669cee7..930cd71ff 100644 --- a/src/cc65/declattr.h +++ b/src/cc65/declattr.h @@ -2,7 +2,7 @@ /* */ /* declattr.h */ /* */ -/* Declaration attributes */ +/* Declarator attributes */ /* */ /* */ /* */ @@ -45,7 +45,7 @@ /* Forward */ -struct Declaration; +struct Declarator; /* Supported attribute types */ typedef enum { @@ -67,7 +67,7 @@ struct DeclAttr { -void ParseAttribute (struct Declaration* D); +void ParseAttribute (struct Declarator* D); /* Parse an additional __attribute__ modifier */ diff --git a/src/cc65/expr.c b/src/cc65/expr.c index c95a5a401..7dd19bcad 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1307,7 +1307,7 @@ static void Primary (ExprDesc* E) Error ("Mixed declarations and code are not supported in cc65"); while (CurTok.Tok != TOK_SEMI) { - Declaration Decl; + Declarator Decl; /* Parse one declaration */ ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index 6195e0929..2b151e59e 100644 --- a/src/cc65/initdata.c +++ b/src/cc65/initdata.c @@ -602,7 +602,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) /* Standard member. We should never have stuff from a ** bit-field left because an anonymous member was added - ** for padding by ParseStructDecl. + ** for padding by ParseStructSpec. */ CHECK (SI.ValBits == 0); diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 1d9ca5254..68ac00e62 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -97,8 +97,8 @@ static void AllocStorage (unsigned DataLabel, void (*UseSeg) (), unsigned Size) -static void ParseRegisterDecl (Declaration* Decl, int Reg) -/* Parse the declaration of a register variable. Reg is the offset of the +static void ParseRegisterDecl (Declarator* Decl, int Reg) +/* Parse the declarator of a register variable. Reg is the offset of the ** variable in the register bank. */ { @@ -186,8 +186,8 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg) -static void ParseAutoDecl (Declaration* Decl) -/* Parse the declaration of an auto variable. */ +static void ParseAutoDecl (Declarator* Decl) +/* Parse the declarator of an auto variable. */ { unsigned Flags; SymEntry* Sym; @@ -382,8 +382,8 @@ static void ParseAutoDecl (Declaration* Decl) -static void ParseStaticDecl (Declaration* Decl) -/* Parse the declaration of a static variable. */ +static void ParseStaticDecl (Declarator* Decl) +/* Parse the declarator of a static variable. */ { unsigned Size; @@ -441,12 +441,12 @@ static void ParseStaticDecl (Declaration* Decl) static void ParseOneDecl (const DeclSpec* Spec) -/* Parse one variable declaration */ +/* Parse one variable declarator. */ { - Declaration Decl; /* Declaration data structure */ + Declarator Decl; /* Declarator data structure */ - /* Read the declaration */ + /* Read the declarator */ ParseDecl (Spec, &Decl, DM_NEED_IDENT); /* Check if there are any non-extern storage classes set for function diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index 115d47e3f..30ebe7dd8 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -230,8 +230,8 @@ const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType) -void SymUseAttr (SymEntry* Sym, struct Declaration* D) -/* Use the attributes from the declaration for this symbol */ +void SymUseAttr (SymEntry* Sym, struct Declarator* D) +/* Use the attributes from the declarator for this symbol */ { /* We cannot specify attributes twice */ if ((Sym->Flags & SC_HAVEATTR) != 0) { diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index d973e6586..5ebd30a75 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -298,8 +298,8 @@ INLINE int SymHasAttr (const SymEntry* Sym, DeclAttrType A) # define SymHasAttr(Sym, A) (SymGetAttr (Sym, A) != 0) #endif -void SymUseAttr (SymEntry* Sym, struct Declaration* D); -/* Use the attributes from the declaration for this symbol */ +void SymUseAttr (SymEntry* Sym, struct Declarator* D); +/* Use the attributes from the declarator for this symbol */ void SymSetAsmName (SymEntry* Sym); /* Set the assembler name for an external symbol from the name of the symbol. From a09053ce0b605e82081c10420c9e25fc86e9c1cf Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Wed, 9 Nov 2022 01:07:36 +0100 Subject: [PATCH 100/360] make test work again also on linux. why did this not break the github actions? --- test/asm/listing/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/asm/listing/Makefile b/test/asm/listing/Makefile index 10f5a5a97..d0d045a02 100644 --- a/test/asm/listing/Makefile +++ b/test/asm/listing/Makefile @@ -19,7 +19,7 @@ else RMDIR = $(RM) -r $1 ERRDIR = 2>&1 TRUE = true - CAT = cat + CAT = cat $1 endif ifdef QUIET From 9253f0d6bc70d5385021a7b277999ea315645047 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Thu, 10 Nov 2022 02:11:54 +0800 Subject: [PATCH 101/360] Added testcase for #1889. --- test/misc/Makefile | 5 +++++ test/misc/bug1889-missing-identifier.c | 9 +++++++++ test/misc/bug1889-missing-identifier.ref | 3 +++ 3 files changed, 17 insertions(+) create mode 100644 test/misc/bug1889-missing-identifier.c create mode 100644 test/misc/bug1889-missing-identifier.ref diff --git a/test/misc/Makefile b/test/misc/Makefile index e77d37b29..1a98bd2d1 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -155,6 +155,11 @@ $(WORKDIR)/goto.$1.$2.prg: goto.c $(ISEQUAL) | $(WORKDIR) $(CC65) -t sim$2 -$1 -o $$@ $$< 2>$(WORKDIR)/goto.$1.$2.out $(ISEQUAL) $(WORKDIR)/goto.$1.$2.out goto.ref +$(WORKDIR)/bug1889-missing-identifier.$1.$2.prg: bug1889-missing-identifier.c $(ISEQUAL) | $(WORKDIR) + $(if $(QUIET),echo misc/bug1889-missing-identifier.$1.$2.error.prg) + -$(CC65) -t sim$2 -$1 -o $$(@:.error.prg=.s) $$< 2> $(WORKDIR)/bug1889-missing-identifier.$1.$2.out + $(ISEQUAL) $(WORKDIR)/bug1889-missing-identifier.$1.$2.out bug1889-missing-identifier.ref + # the rest are tests that fail currently for one reason or another $(WORKDIR)/sitest.$1.$2.prg: sitest.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." diff --git a/test/misc/bug1889-missing-identifier.c b/test/misc/bug1889-missing-identifier.c new file mode 100644 index 000000000..d9cf4aa52 --- /dev/null +++ b/test/misc/bug1889-missing-identifier.c @@ -0,0 +1,9 @@ +/* bug 1889 - endless errors due to failure in recovery from missing identifier */ + +int enum { a } x; +inline enum { b }; + +int main(void) +{ + return 0; +} diff --git a/test/misc/bug1889-missing-identifier.ref b/test/misc/bug1889-missing-identifier.ref new file mode 100644 index 000000000..cd3f76849 --- /dev/null +++ b/test/misc/bug1889-missing-identifier.ref @@ -0,0 +1,3 @@ +bug1889-missing-identifier.c:3: Error: Identifier expected +bug1889-missing-identifier.c:4: Error: Identifier expected +bug1889-missing-identifier.c:4: Warning: Implicit 'int' is an obsolete feature From ebb33ee8b445d3531f1b9a787b60c353fecf3f31 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Fri, 11 Nov 2022 20:54:38 +0100 Subject: [PATCH 102/360] fix problem with copy command in cmd.exe --- test/ref/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/ref/Makefile b/test/ref/Makefile index 3c275e308..e30d3324c 100644 --- a/test/ref/Makefile +++ b/test/ref/Makefile @@ -11,14 +11,14 @@ ifdef CMD_EXE NULLDEV = nul: MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) - CP=copy + COPY = copy $(subst /,\,$1) $(subst /,\,$2) else S = / EXE = NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 - CP=cp + COPY = cp $1 $2 endif ifdef QUIET @@ -78,7 +78,7 @@ $(ISEQUAL): ../isequal.c | $(WORKDIR) $(WORKDIR)/%.cref: %.cref | $(WORKDIR) $(if $(QUIET),echo ref/$*.cref) - $(CP) $*.cref $@ + $(call COPY,$*.cref,$@) $(WORKDIR)/%.ref: %.c | $(WORKDIR) $(if $(QUIET),echo ref/$*.host) From ace39197e5b4f75d212f858f764988d327278ee6 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Fri, 11 Nov 2022 21:22:20 +0100 Subject: [PATCH 103/360] move test to test/ref --- test/misc/Makefile | 5 ----- test/ref/Makefile | 3 ++- test/{misc => ref}/bug1889-missing-identifier.c | 0 .../bug1889-missing-identifier.cref} | 0 4 files changed, 2 insertions(+), 6 deletions(-) rename test/{misc => ref}/bug1889-missing-identifier.c (100%) rename test/{misc/bug1889-missing-identifier.ref => ref/bug1889-missing-identifier.cref} (100%) diff --git a/test/misc/Makefile b/test/misc/Makefile index 6b715f221..f18f40da6 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -161,11 +161,6 @@ $(WORKDIR)/goto.$1.$2.prg: goto.c $(ISEQUAL) | $(WORKDIR) $(CC65) -t sim$2 -$1 -o $$@ $$< 2>$(WORKDIR)/goto.$1.$2.out $(ISEQUAL) $(WORKDIR)/goto.$1.$2.out goto.ref -$(WORKDIR)/bug1889-missing-identifier.$1.$2.prg: bug1889-missing-identifier.c $(ISEQUAL) | $(WORKDIR) - $(if $(QUIET),echo misc/bug1889-missing-identifier.$1.$2.error.prg) - -$(CC65) -t sim$2 -$1 -o $$(@:.error.prg=.s) $$< 2> $(WORKDIR)/bug1889-missing-identifier.$1.$2.out - $(ISEQUAL) $(WORKDIR)/bug1889-missing-identifier.$1.$2.out bug1889-missing-identifier.ref - # the rest are tests that fail currently for one reason or another $(WORKDIR)/sitest.$1.$2.prg: sitest.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." diff --git a/test/ref/Makefile b/test/ref/Makefile index e30d3324c..abd3e9bc0 100644 --- a/test/ref/Makefile +++ b/test/ref/Makefile @@ -52,7 +52,8 @@ CUSTOMSOURCES = \ # list of sources that produce a compiler error. a .cref files containing the # exact error output is required ERRORSOURCES = \ - custom-reference-error.c + custom-reference-error.c \ + bug1889-missing-identifier.c SOURCES := $(filter-out $(CUSTOMSOURCES) $(ERRORSOURCES),$(wildcard *.c)) diff --git a/test/misc/bug1889-missing-identifier.c b/test/ref/bug1889-missing-identifier.c similarity index 100% rename from test/misc/bug1889-missing-identifier.c rename to test/ref/bug1889-missing-identifier.c diff --git a/test/misc/bug1889-missing-identifier.ref b/test/ref/bug1889-missing-identifier.cref similarity index 100% rename from test/misc/bug1889-missing-identifier.ref rename to test/ref/bug1889-missing-identifier.cref From 2c3ca15d901f38e7e955903816f0ad298538dcf4 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 12 Nov 2022 12:32:27 +0800 Subject: [PATCH 104/360] Fixed marking unevaluated subexpressions for conditional operator. --- src/cc65/expr.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 932663b18..f7180c020 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3913,17 +3913,6 @@ static void hieQuest (ExprDesc* Expr) ED_Init (&Expr3); Expr3.Flags = Flags; - NextToken (); - - /* Convert non-integer constant to boolean constant, so that we may just - ** check it in the same way. - */ - if (ED_IsConstTrue (Expr)) { - ED_MakeConstBool (Expr, 1); - } else if (ED_IsConstFalse (Expr)) { - ED_MakeConstBool (Expr, 0); - } - if (!ConstantCond) { /* Condition codes not set, request a test */ ED_RequireTest (Expr); @@ -3935,6 +3924,15 @@ static void hieQuest (ExprDesc* Expr) FalseLab = GetLocalLabel (); g_falsejump (CF_NONE, FalseLab); } else { + /* Convert non-integer constant to boolean constant, so that we + ** may just check it in an easier way later. + */ + if (ED_IsConstTrue (Expr)) { + ED_MakeConstBool (Expr, 1); + } else if (ED_IsConstFalse (Expr)) { + ED_MakeConstBool (Expr, 0); + } + /* Constant boolean subexpression could still have deferred inc/dec ** operations, so just flush their side-effects at this sequence point. */ @@ -3943,9 +3941,18 @@ static void hieQuest (ExprDesc* Expr) if (Expr->IVal == 0) { /* Remember the current code position */ GetCodePos (&SkippedBranch); + + /* Expr2 is unevaluated when the condition is false */ + Expr2.Flags |= E_EVAL_UNEVAL; + } else { + /* Expr3 is unevaluated when the condition is true */ + Expr3.Flags |= E_EVAL_UNEVAL; } } + /* Skip the question mark */ + NextToken (); + /* Parse second expression. Remember for later if it is a NULL pointer ** expression, then load it into the primary. */ @@ -3977,26 +3984,22 @@ static void hieQuest (ExprDesc* Expr) /* Jump around the evaluation of the third expression */ TrueLab = GetLocalLabel (); - ConsumeColon (); - g_jump (TrueLab); /* Jump here if the first expression was false */ g_defcodelabel (FalseLab); } else { if (Expr->IVal == 0) { - /* Expr2 is unevaluated when the condition is false */ - Expr2.Flags |= E_EVAL_UNEVAL; - /* Remove the load code of Expr2 */ RemoveCode (&SkippedBranch); } else { /* Remember the current code position */ GetCodePos (&SkippedBranch); } - ConsumeColon(); } + ConsumeColon (); + /* Parse third expression. Remember for later if it is a NULL pointer ** expression, then load it into the primary. */ @@ -4022,9 +4025,6 @@ static void hieQuest (ExprDesc* Expr) Expr3.Type = PtrConversion (Expr3.Type); if (ConstantCond && Expr->IVal != 0) { - /* Expr3 is unevaluated when the condition is true */ - Expr3.Flags |= E_EVAL_UNEVAL; - /* Remove the load code of Expr3 */ RemoveCode (&SkippedBranch); } From d0c9b2de9902be5d0a33b5d14ceaa1a8144a8f9d Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 12 Nov 2022 12:34:16 +0800 Subject: [PATCH 105/360] Added basic shift count check for <<= and >>= operations. --- src/cc65/assignment.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index 9834ae5d1..549e18e95 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -322,6 +322,12 @@ static void OpAssignBitField (const GenDesc* Gen, ExprDesc* Expr, const char* Op } else if (Gen->Func == g_mod) { Error ("Modulo operation with zero"); } + } else if (Gen->Func == g_asl || Gen->Func == g_asr) { + if (Expr2.IVal < 0) { + Warning ("Shift count '%ld' is negative", Expr2.IVal); + } else if (Expr2.IVal >= (long)(SizeOf (Expr->Type) * 8)) { + Warning ("Shift count '%ld' >= width of type", Expr2.IVal); + } } /* Adjust the types of the operands if needed */ @@ -502,6 +508,12 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char* } else if (Gen->Func == g_mod) { Error ("Modulo operation with zero"); } + } else if (Gen->Func == g_asl || Gen->Func == g_asr) { + if (Expr2.IVal < 0) { + Warning ("Shift count '%ld' is negative", Expr2.IVal); + } else if (Expr2.IVal >= (long)(SizeOf (Expr->Type) * 8)) { + Warning ("Shift count '%ld' >= width of type", Expr2.IVal); + } } Gen->Func (Flags | CF_CONST, Expr2.IVal); } From 75be73cc8d4bd24fac6714ef95169555435eeb3e Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 12 Nov 2022 12:32:27 +0800 Subject: [PATCH 106/360] Added utility functions to acquire bit width of types. --- src/cc65/assignment.c | 86 +++++++++++++++++++--------- src/cc65/datatype.c | 19 +++++++ src/cc65/datatype.h | 9 +++ src/cc65/expr.c | 117 ++++++++++++++++---------------------- src/cc65/ppexpr.c | 127 +++++++++++++++--------------------------- src/cc65/shiftexpr.c | 31 ++++++----- 6 files changed, 199 insertions(+), 190 deletions(-) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index 549e18e95..ab501523d 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -315,19 +315,37 @@ static void OpAssignBitField (const GenDesc* Gen, ExprDesc* Expr, const char* Op } else if (Gen->Func == g_sub) { g_dec (Flags | CF_CONST, Expr2.IVal); } else { - if (Expr2.IVal == 0) { - /* Check for div by zero/mod by zero */ - if (Gen->Func == g_div) { - Error ("Division by zero"); - } else if (Gen->Func == g_mod) { - Error ("Modulo operation with zero"); - } - } else if (Gen->Func == g_asl || Gen->Func == g_asr) { - if (Expr2.IVal < 0) { - Warning ("Shift count '%ld' is negative", Expr2.IVal); - } else if (Expr2.IVal >= (long)(SizeOf (Expr->Type) * 8)) { - Warning ("Shift count '%ld' >= width of type", Expr2.IVal); - } + if (!ED_IsUneval (Expr)) { + if (Expr2.IVal == 0) { + /* Check for div by zero/mod by zero */ + if (Gen->Func == g_div) { + Error ("Division by zero"); + } else if (Gen->Func == g_mod) { + Error ("Modulo operation with zero"); + } + } else if (Gen->Func == g_asl || Gen->Func == g_asr) { + const Type* CalType = IntPromotion (Expr->Type); + unsigned ExprBits = BitSizeOf (CalType); + + /* If the shift count is greater than or equal to the width of the + ** promoted left operand, the behaviour is undefined according to + ** the standard. + */ + if (Expr2.IVal < 0) { + Warning ("Negative shift count %ld treated as %u for %s", + Expr2.IVal, + (unsigned)Expr2.IVal & (ExprBits - 1), + GetBasicTypeName (CalType)); + } else if (Expr2.IVal >= (long)ExprBits) { + Warning ("Shift count %ld >= width of %s treated as %u", + Expr2.IVal, + GetBasicTypeName (CalType), + (unsigned)Expr2.IVal & (ExprBits - 1)); + } + + /* Here we simply "wrap" the shift count around the width */ + Expr2.IVal &= ExprBits - 1; + } } /* Adjust the types of the operands if needed */ @@ -501,18 +519,36 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char* } else if (Gen->Func == g_sub) { g_dec (Flags | CF_CONST, Expr2.IVal); } else { - if (Expr2.IVal == 0) { - /* Check for div by zero/mod by zero */ - if (Gen->Func == g_div) { - Error ("Division by zero"); - } else if (Gen->Func == g_mod) { - Error ("Modulo operation with zero"); - } - } else if (Gen->Func == g_asl || Gen->Func == g_asr) { - if (Expr2.IVal < 0) { - Warning ("Shift count '%ld' is negative", Expr2.IVal); - } else if (Expr2.IVal >= (long)(SizeOf (Expr->Type) * 8)) { - Warning ("Shift count '%ld' >= width of type", Expr2.IVal); + if (!ED_IsUneval (Expr)) { + if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) { + /* Check for div by zero/mod by zero */ + if (Gen->Func == g_div) { + Error ("Division by zero"); + } else if (Gen->Func == g_mod) { + Error ("Modulo operation with zero"); + } + } else if (Gen->Func == g_asl || Gen->Func == g_asr) { + const Type* CalType = IntPromotion (Expr->Type); + unsigned ExprBits = BitSizeOf (CalType); + + /* If the shift count is greater than or equal to the width of the + ** promoted left operand, the behaviour is undefined according to + ** the standard. + */ + if (Expr2.IVal < 0) { + Warning ("Negative shift count %ld treated as %u for %s", + Expr2.IVal, + (unsigned)Expr2.IVal & (ExprBits - 1), + GetBasicTypeName (CalType)); + } else if (Expr2.IVal >= (long)ExprBits) { + Warning ("Shift count %ld >= width of %s treated as %u", + Expr2.IVal, + GetBasicTypeName (CalType), + (unsigned)Expr2.IVal & (ExprBits - 1)); + } + + /* Here we simply "wrap" the shift count around the width */ + Expr2.IVal &= ExprBits - 1; } } Gen->Func (Flags | CF_CONST, Expr2.IVal); diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 9a661c037..023aefaf7 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -203,6 +203,14 @@ unsigned long GetIntegerTypeMax (const Type* Type) +unsigned BitSizeOf (const Type* T) +/* Return the size (in bit-width) of a data type */ +{ + return IsTypeBitField (T) ? T->A.B.Width : CHAR_BITS * SizeOf (T); +} + + + unsigned SizeOf (const Type* T) /* Compute size (in bytes) of object represented by type array */ { @@ -288,6 +296,17 @@ unsigned PSizeOf (const Type* T) +unsigned CheckedBitSizeOf (const Type* T) +/* Return the size (in bit-width) of a data type. If the size is zero, emit an +** error and return some valid size instead (so the rest of the compiler +** doesn't have to work with invalid sizes). +*/ +{ + return IsTypeBitField (T) ? T->A.B.Width : CHAR_BITS * CheckedSizeOf (T); +} + + + unsigned CheckedSizeOf (const Type* T) /* Return the size (in bytes) of a data type. If the size is zero, emit an ** error and return some valid size instead (so the rest of the compiler diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 5e4e2e39b..4a20422fb 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -287,12 +287,21 @@ unsigned long GetIntegerTypeMax (const Type* Type); ** The type must have a known size. */ +unsigned BitSizeOf (const Type* T); +/* Return the size (in bit-width) of a data type */ + unsigned SizeOf (const Type* T); /* Compute size (in bytes) of object represented by type array */ unsigned PSizeOf (const Type* T); /* Compute size (in bytes) of pointee object */ +unsigned CheckedBitSizeOf (const Type* T); +/* Return the size (in bit-width) of a data type. If the size is zero, emit an +** error and return some valid size instead (so the rest of the compiler +** doesn't have to work with invalid sizes). +*/ + unsigned CheckedSizeOf (const Type* T); /* Return the size (in bytes) of a data type. If the size is zero, emit an ** error and return some valid size instead (so the rest of the compiler diff --git a/src/cc65/expr.c b/src/cc65/expr.c index f7180c020..45dc9cc37 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -2177,6 +2177,10 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ /* Check for const operands */ if (lconst && rconst) { + /* Evaluate the result for operands */ + unsigned long Val1 = Expr->IVal; + unsigned long Val2 = Expr2.IVal; + /* Both operands are constant, remove the generated code */ RemoveCode (&Mark1); @@ -2184,80 +2188,51 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type); /* Handle the op differently for signed and unsigned types */ - if (IsSignSigned (Expr->Type)) { - - /* Evaluate the result for signed operands */ - signed long Val1 = Expr->IVal; - signed long Val2 = Expr2.IVal; - switch (Tok) { - case TOK_OR: - Expr->IVal = (Val1 | Val2); - break; - case TOK_XOR: - Expr->IVal = (Val1 ^ Val2); - break; - case TOK_AND: - Expr->IVal = (Val1 & Val2); - break; - case TOK_STAR: - Expr->IVal = (Val1 * Val2); - break; - case TOK_DIV: - if (Val2 == 0) { + switch (Tok) { + case TOK_OR: + Expr->IVal = (Val1 | Val2); + break; + case TOK_XOR: + Expr->IVal = (Val1 ^ Val2); + break; + case TOK_AND: + Expr->IVal = (Val1 & Val2); + break; + case TOK_STAR: + Expr->IVal = (Val1 * Val2); + break; + case TOK_DIV: + if (Val2 == 0) { + if (!ED_IsUneval (Expr)) { Error ("Division by zero"); - Expr->IVal = 0x7FFFFFFF; + } + Expr->IVal = 0xFFFFFFFF; + } else { + /* Handle signed and unsigned operands differently */ + if (IsSignSigned (Expr->Type)) { + Expr->IVal = ((long)Val1 / (long)Val2); } else { Expr->IVal = (Val1 / Val2); } - break; - case TOK_MOD: - if (Val2 == 0) { + } + break; + case TOK_MOD: + if (Val2 == 0) { + if (!ED_IsUneval (Expr)) { Error ("Modulo operation with zero"); - Expr->IVal = 0; + } + Expr->IVal = 0; + } else { + /* Handle signed and unsigned operands differently */ + if (IsSignSigned (Expr->Type)) { + Expr->IVal = ((long)Val1 % (long)Val2); } else { Expr->IVal = (Val1 % Val2); } - break; - default: - Internal ("hie_internal: got token 0x%X\n", Tok); - } - } else { - - /* Evaluate the result for unsigned operands */ - unsigned long Val1 = Expr->IVal; - unsigned long Val2 = Expr2.IVal; - switch (Tok) { - case TOK_OR: - Expr->IVal = (Val1 | Val2); - break; - case TOK_XOR: - Expr->IVal = (Val1 ^ Val2); - break; - case TOK_AND: - Expr->IVal = (Val1 & Val2); - break; - case TOK_STAR: - Expr->IVal = (Val1 * Val2); - break; - case TOK_DIV: - if (Val2 == 0) { - Error ("Division by zero"); - Expr->IVal = 0xFFFFFFFF; - } else { - Expr->IVal = (Val1 / Val2); - } - break; - case TOK_MOD: - if (Val2 == 0) { - Error ("Modulo operation with zero"); - Expr->IVal = 0; - } else { - Expr->IVal = (Val1 % Val2); - } - break; - default: - Internal ("hie_internal: got token 0x%X\n", Tok); - } + } + break; + default: + Internal ("hie_internal: got token 0x%X\n", Tok); } /* Limit the calculated value to the range of its type */ @@ -2314,10 +2289,12 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ /* Second value is constant - check for div */ type |= CF_CONST; rtype |= CF_CONST; - if (Tok == TOK_DIV && Expr2.IVal == 0) { - Error ("Division by zero"); - } else if (Tok == TOK_MOD && Expr2.IVal == 0) { - Error ("Modulo operation with zero"); + if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) { + if (Tok == TOK_DIV) { + Error ("Division by zero"); + } else if (Tok == TOK_MOD) { + Error ("Modulo operation with zero"); + } } if ((Gen->Flags & GEN_NOPUSH) != 0) { RemoveCode (&Mark2); diff --git a/src/cc65/ppexpr.c b/src/cc65/ppexpr.c index 0942dc8f8..73ec69de8 100644 --- a/src/cc65/ppexpr.c +++ b/src/cc65/ppexpr.c @@ -305,97 +305,60 @@ static void PPhie_internal (const token_t* Ops, /* List of generators */ if (PPEvaluationEnabled && !PPEvaluationFailed) { + /* Evaluate the result for operands */ + unsigned long Val1 = Expr->IVal; + unsigned long Val2 = Rhs.IVal; + /* If either side is unsigned, the result is unsigned */ Expr->Flags |= Rhs.Flags & PPEXPR_UNSIGNED; - /* Handle the op differently for signed and unsigned integers */ - if ((Expr->Flags & PPEXPR_UNSIGNED) == 0) { - - /* Evaluate the result for signed operands */ - signed long Val1 = Expr->IVal; - signed long Val2 = Rhs.IVal; - switch (Tok) { - case TOK_OR: - Expr->IVal = (Val1 | Val2); - break; - case TOK_XOR: - Expr->IVal = (Val1 ^ Val2); - break; - case TOK_AND: - Expr->IVal = (Val1 & Val2); - break; - case TOK_PLUS: - Expr->IVal = (Val1 + Val2); - break; - case TOK_MINUS: - Expr->IVal = (Val1 - Val2); - break; - case TOK_MUL: - Expr->IVal = (Val1 * Val2); - break; - case TOK_DIV: - if (Val2 == 0) { - PPError ("Division by zero"); - Expr->IVal = 0; + switch (Tok) { + case TOK_OR: + Expr->IVal = (Val1 | Val2); + break; + case TOK_XOR: + Expr->IVal = (Val1 ^ Val2); + break; + case TOK_AND: + Expr->IVal = (Val1 & Val2); + break; + case TOK_PLUS: + Expr->IVal = (Val1 + Val2); + break; + case TOK_MINUS: + Expr->IVal = (Val1 - Val2); + break; + case TOK_MUL: + Expr->IVal = (Val1 * Val2); + break; + case TOK_DIV: + if (Val2 == 0) { + PPError ("Division by zero"); + Expr->IVal = 0; + } else { + /* Handle signed and unsigned operands differently */ + if ((Expr->Flags & PPEXPR_UNSIGNED) == 0) { + Expr->IVal = ((long)Val1 / (long)Val2); } else { Expr->IVal = (Val1 / Val2); } - break; - case TOK_MOD: - if (Val2 == 0) { - PPError ("Modulo operation with zero"); - Expr->IVal = 0; + } + break; + case TOK_MOD: + if (Val2 == 0) { + PPError ("Modulo operation with zero"); + Expr->IVal = 0; + } else { + /* Handle signed and unsigned operands differently */ + if ((Expr->Flags & PPEXPR_UNSIGNED) == 0) { + Expr->IVal = ((long)Val1 % (long)Val2); } else { Expr->IVal = (Val1 % Val2); } - break; - default: - Internal ("PPhie_internal: got token 0x%X\n", Tok); - } - - } else { - - /* Evaluate the result for unsigned operands */ - unsigned long Val1 = Expr->IVal; - unsigned long Val2 = Rhs.IVal; - switch (Tok) { - case TOK_OR: - Expr->IVal = (Val1 | Val2); - break; - case TOK_XOR: - Expr->IVal = (Val1 ^ Val2); - break; - case TOK_AND: - Expr->IVal = (Val1 & Val2); - break; - case TOK_PLUS: - Expr->IVal = (Val1 + Val2); - break; - case TOK_MINUS: - Expr->IVal = (Val1 - Val2); - break; - case TOK_MUL: - Expr->IVal = (Val1 * Val2); - break; - case TOK_DIV: - if (Val2 == 0) { - PPError ("Division by zero"); - Expr->IVal = 0; - } else { - Expr->IVal = (Val1 / Val2); - } - break; - case TOK_MOD: - if (Val2 == 0) { - PPError ("Modulo operation with zero"); - Expr->IVal = 0; - } else { - Expr->IVal = (Val1 % Val2); - } - break; - default: - Internal ("PPhie_internal: got token 0x%X\n", Tok); - } + } + break; + default: + Internal ("PPhie_internal: got token 0x%X\n", Tok); } } } diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c index 312086f3c..48426f1f2 100644 --- a/src/cc65/shiftexpr.c +++ b/src/cc65/shiftexpr.c @@ -139,22 +139,27 @@ void ShiftExpr (struct ExprDesc* Expr) /* Remove the code that pushes the rhs onto the stack. */ RemoveCode (&Mark2); - /* If the shift count is greater or equal than the bit count of - ** the operand, the behaviour is undefined according to the - ** standard. + /* If the shift count is greater than or equal to the width of the + ** promoted left operand, the behaviour is undefined according to + ** the standard. */ - if (Expr2.IVal < 0) { - - Warning ("Shift count '%ld' is negative", Expr2.IVal); - Expr2.IVal &= ExprBits - 1; - - } else if (Expr2.IVal >= (long) ExprBits) { - - Warning ("Shift count '%ld' >= width of type", Expr2.IVal); - Expr2.IVal &= ExprBits - 1; - + if (!ED_IsUneval (Expr)) { + if (Expr2.IVal < 0) { + Warning ("Negative shift count %ld treated as %u for %s", + Expr2.IVal, + (unsigned)Expr2.IVal & (ExprBits - 1), + GetBasicTypeName (ResultType)); + } else if (Expr2.IVal >= (long) ExprBits) { + Warning ("Shift count %ld >= width of %s treated as %u", + Expr2.IVal, + GetBasicTypeName (ResultType), + (unsigned)Expr2.IVal & (ExprBits - 1)); + } } + /* Here we simply "wrap" the shift count around the width */ + Expr2.IVal &= ExprBits - 1; + /* If the shift count is zero, nothing happens. If the left hand ** side is a constant, the result is constant. */ From 73897afacea77ef59c4d7c906f021c8dd6a7ca6b Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 12 Nov 2022 12:36:22 +0800 Subject: [PATCH 107/360] Additional check for out of ranges of bit-fields in bitwise-shifts. --- src/cc65/assignment.c | 13 ++++++++++++- src/cc65/shiftexpr.c | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index ab501523d..2adb1c20e 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -345,7 +345,12 @@ static void OpAssignBitField (const GenDesc* Gen, ExprDesc* Expr, const char* Op /* Here we simply "wrap" the shift count around the width */ Expr2.IVal &= ExprBits - 1; - } + + /* Additional check for bit-fields */ + if (Expr2.IVal >= (long)Expr->Type->A.B.Width) { + Warning ("Shift count %ld >= width of bit-field", Expr2.IVal); + } + } } /* Adjust the types of the operands if needed */ @@ -549,6 +554,12 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char* /* Here we simply "wrap" the shift count around the width */ Expr2.IVal &= ExprBits - 1; + + /* Additional check for bit width */ + if (Expr2.IVal >= (long)BitSizeOf (Expr->Type)) { + Warning ("Shift count %ld >= width of %s", + Expr2.IVal, GetBasicTypeName (Expr->Type)); + } } } Gen->Func (Flags | CF_CONST, Expr2.IVal); diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c index 48426f1f2..b8fb70434 100644 --- a/src/cc65/shiftexpr.c +++ b/src/cc65/shiftexpr.c @@ -160,6 +160,15 @@ void ShiftExpr (struct ExprDesc* Expr) /* Here we simply "wrap" the shift count around the width */ Expr2.IVal &= ExprBits - 1; + /* Additional check for bit-fields */ + if (IsTypeBitField (Expr->Type) && + Tok == TOK_SHR && + Expr2.IVal >= (long) Expr->Type->A.B.Width) { + if (!ED_IsUneval (Expr)) { + Warning ("Right-shift count %ld >= width of bit-field", Expr2.IVal); + } + } + /* If the shift count is zero, nothing happens. If the left hand ** side is a constant, the result is constant. */ From cc177208b465cd24dfd1f1a198a26913b571086f Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 12 Nov 2022 21:05:01 +0800 Subject: [PATCH 108/360] Added tests for diagnostics in unevaluated context. --- test/misc/Makefile | 14 +++-- test/misc/bug1768.c | 149 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 149 insertions(+), 14 deletions(-) diff --git a/test/misc/Makefile b/test/misc/Makefile index f18f40da6..d0b8979b0 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -64,12 +64,6 @@ $(WORKDIR)/int-static-1888.$1.$2.prg: int-static-1888.c | $(WORKDIR) $(if $(QUIET),echo misc/int-static-1888.$1.$2.prg) $(NOT) $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) -# should compile, but gives an error -$(WORKDIR)/bug1768.$1.$2.prg: bug1768.c | $(WORKDIR) - @echo "FIXME: " $$@ "currently does not compile." - $(if $(QUIET),echo misc/bug1768.$1.$2.prg) - $(NOT) $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) - # should compile, but gives an error $(WORKDIR)/bug760.$1.$2.prg: bug760.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." @@ -138,6 +132,14 @@ $(WORKDIR)/bug1265.$1.$2.prg: bug1265.c | $(WORKDIR) $(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR) +# this one requires -Werror +$(WORKDIR)/bug1768.$1.$2.prg: bug1768.c | $(WORKDIR) + $(if $(QUIET),echo misc/bug1768.$1.$2.prg) + $(CC65) -Werror -t sim$2 -$1 -o $$(@:.prg=.s) $$< $(NULLERR) + $(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR) + $(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR) + $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR) + # should compile, but then hangs in an endless loop $(WORKDIR)/endless.$1.$2.prg: endless.c | $(WORKDIR) $(if $(QUIET),echo misc/endless.$1.$2.prg) diff --git a/test/misc/bug1768.c b/test/misc/bug1768.c index 916aa64bc..35cee1049 100644 --- a/test/misc/bug1768.c +++ b/test/misc/bug1768.c @@ -1,14 +1,147 @@ +/* + Copyright 2021-2022, The cc65 Authors -#include <stdlib.h> + This software is provided "as-is", without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. -int a = 1 || (8 / 0); -int b = 0 && (8 % 0); -int c = 1 ? 42 : (0 % 0); -int d = 1 || a / 0; -int e = 0 && b % 0; -int f = 1 ? 42 : (a %= 0, b /= 0); + Permission is granted to anyone to use this software for any purpose, + including commercial applications; and, to alter it and redistribute it + freely, subject to the following restrictions: + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated, but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + Test of operations in unevaluated context resulted from 'sizeof' and + short-circuited code-paths in AND, OR and conditional operations. + + See also: + https://github.com/cc65/cc65/issues/1768#issuecomment-1175221466 +*/ + +#include <stdio.h> + +static int failures; + +#define TEST(EXPR)\ + {\ + int acc = 0;\ + acc += sizeof((EXPR), 0);\ + acc += (0 && (EXPR));\ + acc += (1 || (EXPR));\ + acc += (0 ? (EXPR) : 0);\ + acc += (1 ? 0 : (EXPR));\ + if (acc == 0) {\ + printf("acc = %d\n", acc);\ + ++failures;\ + }\ + } + +/* Division by zero/modulo with zero */ +void test_1(void) +{ + int i; + int j; + TEST((i / 0) | (j % 0)) +} + +/* Division by zero/modulo with zero */ +void test_2(void) +{ + int i; + int j; + TEST((i /= 0) | (j %= 0)) +} + +/* Shift by too wide counts */ +void test_3(void) +{ + int i; + int j; + TEST((i << 32) | (j >> 32)) +} + +/* Shift by too wide counts */ +void test_4(void) +{ + int i; + int j; + TEST((i <<= 32) | (j >>= 32)) +} + +/* Shift by negative counts */ +void test_5(void) +{ + int i; + int j; + TEST((i << -1) | (j >> -1)) +} + +/* Shift by negative counts */ +void test_6(void) +{ + int i; + int j; + TEST((i <<= -1) | (j >>= -1)) +} + +/* Shift bit-fields */ +void test_7(void) +{ + struct S { + long i : 24; /* Will be promoted to 32-bit integer in calculation */ + long j : 8; /* Will be promoted to 16-bit integer in calculation */ + } s; + long k; + + s.i = 1; + printf("%u\n", sizeof(s.i << 24)); + s.i = 2; + k = s.i << 16; + if (k != 0x00020000L) { + printf("k = %ld, expected: %ld\n", k, 0x00020000L); + } + TEST(s.j >> 16) +} + +/* Shift bit-fields */ +void test_8(void) +{ + struct S { + long i : 24; /* Will be promoted to 32-bit integer in calculation */ + long j : 8; /* Will be promoted to 16-bit integer in calculation */ + } s; + long k; + + s.i = 3; + printf("%u\n", sizeof(s.i << 24)); + s.i = 4; + k = s.i <<= 16; + if (k != 0x00040000L) { + printf("k = %ld, expected: %ld\n", k, 0x00040000L); + } + TEST(s.j >>= 8) +} + +/* Do all tests */ int main(void) { - return EXIT_SUCCESS; + test_1(); + test_2(); + test_3(); + test_4(); + test_5(); + test_6(); + test_7(); + test_8(); + + printf("Failures: %d\n", failures); + return failures; } From 9d693d2c80029461e7650c5d17bcd22f19db268a Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sat, 12 Nov 2022 22:13:56 +0800 Subject: [PATCH 109/360] Warnings instead of errors for division-by-zero/modulo-with-zero in evaluation. --- src/cc65/assignment.c | 8 ++++---- src/cc65/expr.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index 2adb1c20e..54ab28d4e 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -319,9 +319,9 @@ static void OpAssignBitField (const GenDesc* Gen, ExprDesc* Expr, const char* Op if (Expr2.IVal == 0) { /* Check for div by zero/mod by zero */ if (Gen->Func == g_div) { - Error ("Division by zero"); + Warning ("Division by zero"); } else if (Gen->Func == g_mod) { - Error ("Modulo operation with zero"); + Warning ("Modulo operation with zero"); } } else if (Gen->Func == g_asl || Gen->Func == g_asr) { const Type* CalType = IntPromotion (Expr->Type); @@ -528,9 +528,9 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char* if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) { /* Check for div by zero/mod by zero */ if (Gen->Func == g_div) { - Error ("Division by zero"); + Warning ("Division by zero"); } else if (Gen->Func == g_mod) { - Error ("Modulo operation with zero"); + Warning ("Modulo operation with zero"); } } else if (Gen->Func == g_asl || Gen->Func == g_asr) { const Type* CalType = IntPromotion (Expr->Type); diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 45dc9cc37..78a4c516a 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -2204,7 +2204,7 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ case TOK_DIV: if (Val2 == 0) { if (!ED_IsUneval (Expr)) { - Error ("Division by zero"); + Warning ("Division by zero"); } Expr->IVal = 0xFFFFFFFF; } else { @@ -2219,7 +2219,7 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ case TOK_MOD: if (Val2 == 0) { if (!ED_IsUneval (Expr)) { - Error ("Modulo operation with zero"); + Warning ("Modulo operation with zero"); } Expr->IVal = 0; } else { @@ -2291,9 +2291,9 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ rtype |= CF_CONST; if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) { if (Tok == TOK_DIV) { - Error ("Division by zero"); + Warning ("Division by zero"); } else if (Tok == TOK_MOD) { - Error ("Modulo operation with zero"); + Warning ("Modulo operation with zero"); } } if ((Gen->Flags & GEN_NOPUSH) != 0) { From 7b436e982322d09c4ee51bf377165fb1716fe83b Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sun, 13 Nov 2022 01:01:24 +0800 Subject: [PATCH 110/360] Added tests for #1895 fix. --- test/err/bug1895-assign1a.c | 5 + test/err/bug1895-assign1b.c | 5 + test/err/bug1895-assign2a.c | 5 + test/err/bug1895-assign2b.c | 5 + test/err/bug1895-assign4a.c | 5 + test/err/bug1895-assign4b.c | 5 + test/err/bug1895-assign5a.c | 5 + test/err/bug1895-assign5b.c | 5 + test/err/bug1895-common.h | 196 ++++++++++++++++++++++++++++++++++ test/err/bug1895-cond1.c | 5 + test/err/bug1895-cond2.c | 5 + test/err/bug1895-cond3.c | 5 + test/err/bug1895-cond4.c | 5 + test/err/bug1895-cond5.c | 5 + test/err/bug1895-prototype1.c | 5 + test/err/bug1895-prototype2.c | 5 + test/err/bug1895-prototype3.c | 5 + test/err/bug1895-prototype4.c | 5 + test/err/bug1895-prototype5.c | 5 + 19 files changed, 286 insertions(+) create mode 100644 test/err/bug1895-assign1a.c create mode 100644 test/err/bug1895-assign1b.c create mode 100644 test/err/bug1895-assign2a.c create mode 100644 test/err/bug1895-assign2b.c create mode 100644 test/err/bug1895-assign4a.c create mode 100644 test/err/bug1895-assign4b.c create mode 100644 test/err/bug1895-assign5a.c create mode 100644 test/err/bug1895-assign5b.c create mode 100644 test/err/bug1895-common.h create mode 100644 test/err/bug1895-cond1.c create mode 100644 test/err/bug1895-cond2.c create mode 100644 test/err/bug1895-cond3.c create mode 100644 test/err/bug1895-cond4.c create mode 100644 test/err/bug1895-cond5.c create mode 100644 test/err/bug1895-prototype1.c create mode 100644 test/err/bug1895-prototype2.c create mode 100644 test/err/bug1895-prototype3.c create mode 100644 test/err/bug1895-prototype4.c create mode 100644 test/err/bug1895-prototype5.c diff --git a/test/err/bug1895-assign1a.c b/test/err/bug1895-assign1a.c new file mode 100644 index 000000000..223964104 --- /dev/null +++ b/test/err/bug1895-assign1a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_1_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign1b.c b/test/err/bug1895-assign1b.c new file mode 100644 index 000000000..cccc0a318 --- /dev/null +++ b/test/err/bug1895-assign1b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_1_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign2a.c b/test/err/bug1895-assign2a.c new file mode 100644 index 000000000..512b658a9 --- /dev/null +++ b/test/err/bug1895-assign2a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_2_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign2b.c b/test/err/bug1895-assign2b.c new file mode 100644 index 000000000..d07191206 --- /dev/null +++ b/test/err/bug1895-assign2b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_2_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign4a.c b/test/err/bug1895-assign4a.c new file mode 100644 index 000000000..c2a6f25de --- /dev/null +++ b/test/err/bug1895-assign4a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_4_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign4b.c b/test/err/bug1895-assign4b.c new file mode 100644 index 000000000..740e10b04 --- /dev/null +++ b/test/err/bug1895-assign4b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_4_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign5a.c b/test/err/bug1895-assign5a.c new file mode 100644 index 000000000..fed4e07d9 --- /dev/null +++ b/test/err/bug1895-assign5a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_5_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign5b.c b/test/err/bug1895-assign5b.c new file mode 100644 index 000000000..ed8498e34 --- /dev/null +++ b/test/err/bug1895-assign5b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_5_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-common.h b/test/err/bug1895-common.h new file mode 100644 index 000000000..03f02e2de --- /dev/null +++ b/test/err/bug1895-common.h @@ -0,0 +1,196 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types + + Test of incompatible pointer/array types in assignment ans conditional + expressions, as well as function prototypes. + + In each source file, define a single macro and include this file to perform + a coresponding test individually. + + https://github.com/cc65/cc65/issues/1895 +*/ + +/* Test 1 suite */ +#ifdef DO_TEST_1_SUB_1_A +#define TEST_1_SUB_1_A CMP_TYPES_1 +#else +#define TEST_1_SUB_1_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_1_B +#define TEST_1_SUB_1_B CMP_TYPES_1 +#else +#define TEST_1_SUB_1_B BLANK +#endif + +#ifdef DO_TEST_1_SUB_2_A +#define TEST_1_SUB_2_A CMP_TYPES_1 +#else +#define TEST_1_SUB_2_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_2_B +#define TEST_1_SUB_2_B CMP_TYPES_1 +#else +#define TEST_1_SUB_2_B BLANK +#endif + +#ifdef DO_TEST_1_SUB_4_A +#define TEST_1_SUB_4_A CMP_TYPES_1 +#else +#define TEST_1_SUB_4_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_4_B +#define TEST_1_SUB_4_B CMP_TYPES_1 +#else +#define TEST_1_SUB_4_B BLANK +#endif + +#ifdef DO_TEST_1_SUB_5_A +#define TEST_1_SUB_5_A CMP_TYPES_1 +#else +#define TEST_1_SUB_5_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_5_B +#define TEST_1_SUB_5_B CMP_TYPES_1 +#else +#define TEST_1_SUB_5_B BLANK +#endif + +/* Test 2 suite */ +#ifdef DO_TEST_2_SUB_1 +#define TEST_2_SUB_1 CMP_TYPES_2 +#else +#define TEST_2_SUB_1 BLANK +#endif + +#ifdef DO_TEST_2_SUB_2 +#define TEST_2_SUB_2 CMP_TYPES_2 +#else +#define TEST_2_SUB_2 BLANK +#endif + +#ifdef DO_TEST_2_SUB_3 +#define TEST_2_SUB_3 CMP_TYPES_2 +#else +#define TEST_2_SUB_3 BLANK +#endif + +#ifdef DO_TEST_2_SUB_4 +#define TEST_2_SUB_4 CMP_TYPES_2 +#else +#define TEST_2_SUB_4 BLANK +#endif + +#ifdef DO_TEST_2_SUB_5 +#define TEST_2_SUB_5 CMP_TYPES_2 +#else +#define TEST_2_SUB_5 BLANK +#endif + +/* Test 3 suite */ +#ifdef DO_TEST_3_SUB_1 +#define TEST_3_SUB_1 CMP_TYPES_3 +#else +#define TEST_3_SUB_1 BLANK +#endif + +#ifdef DO_TEST_3_SUB_2 +#define TEST_3_SUB_2 CMP_TYPES_3 +#else +#define TEST_3_SUB_2 BLANK +#endif + +#ifdef DO_TEST_3_SUB_3 +#define TEST_3_SUB_3 CMP_TYPES_3 +#else +#define TEST_3_SUB_3 BLANK +#endif + +#ifdef DO_TEST_3_SUB_4 +#define TEST_3_SUB_4 CMP_TYPES_3 +#else +#define TEST_3_SUB_4 BLANK +#endif + +#ifdef DO_TEST_3_SUB_5 +#define TEST_3_SUB_5 CMP_TYPES_3 +#else +#define TEST_3_SUB_5 BLANK +#endif + +/* Implementation */ +#define CONCAT(a, b) CONCAT_impl_(a, b) +#define CONCAT_impl_(a, b) a##b +#define BLANK(...) +#define DECL_FUNCS(A, B)\ + void CONCAT(foo_,__LINE__)(A); void CONCAT(foo_,__LINE__)(B); + +/* Test with assignment */ +#define CMP_TYPES_1(A, B)\ + do {\ + A p; B q;\ +_Pragma("warn(error, on)")\ + p = q;\ +_Pragma("warn(error, off)")\ + } while (0) + +/* Test with conditional expression */ +#define CMP_TYPES_2(A, B)\ + do {\ + A p; B q;\ +_Pragma("warn(error, on)")\ + v = v ? p : q;\ +_Pragma("warn(error, off)")\ + } while (0) + +/* Test with function prototype */ +#define CMP_TYPES_3(A, B)\ + do {\ + DECL_FUNCS(A,B);\ + } while (0) + +static void *v; + +typedef int (*p1)[3]; /* pointer to array */ +typedef int **q1; /* pointer to pointer */ +typedef int (**p2)[3]; /* pointer to pointer to array */ +typedef int ***q2; /* pointer to pointer to pointer */ +typedef int p3[1][3]; /* array of array */ +typedef int *q3[1]; /* array of pointer */ +typedef int const **p4; /* pointer to pointer to const */ +typedef int **q4; /* pointer to pointer to non-const */ +typedef int (*p5)(int (*)(p3)); /* pointer to function taking pointer to function taking pointer to array */ +typedef int (*q5)(int (*)(q3)); /* pointer to function taking pointer to function taking pointer to pointer */ + +int main(void) +{ + /* Warnings */ + TEST_1_SUB_1_A(p1, q1); + TEST_1_SUB_1_B(q1, p1); + TEST_1_SUB_2_A(p2, q2); + TEST_1_SUB_2_B(q2, p2); + /* TEST_1_SUB_3_A(p3, q3); */ + /* TEST_1_SUB_3_B(q3, p3); */ + TEST_1_SUB_4_A(p4, q4); + TEST_1_SUB_4_B(q4, p4); + TEST_1_SUB_5_A(p5, q5); + TEST_1_SUB_5_B(q5, p5); + + /* GCC and clang give warnings while cc65 gives errors */ + TEST_2_SUB_1(p1, q1); + TEST_2_SUB_2(p2, q2); + TEST_2_SUB_3(p3, q3); + TEST_2_SUB_4(p4, q4); + TEST_2_SUB_5(p5, q5); + + /* Errors */ + TEST_3_SUB_1(p1, q1); + TEST_3_SUB_2(p2, q2); + TEST_3_SUB_3(p3, q3); + TEST_3_SUB_4(p4, q4); + TEST_3_SUB_5(p5, q5); + + return 0; +} diff --git a/test/err/bug1895-cond1.c b/test/err/bug1895-cond1.c new file mode 100644 index 000000000..ac6a301c9 --- /dev/null +++ b/test/err/bug1895-cond1.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_1 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond2.c b/test/err/bug1895-cond2.c new file mode 100644 index 000000000..81b8b2912 --- /dev/null +++ b/test/err/bug1895-cond2.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_2 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond3.c b/test/err/bug1895-cond3.c new file mode 100644 index 000000000..f1571acbf --- /dev/null +++ b/test/err/bug1895-cond3.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_3 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond4.c b/test/err/bug1895-cond4.c new file mode 100644 index 000000000..e7ef77964 --- /dev/null +++ b/test/err/bug1895-cond4.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_4 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond5.c b/test/err/bug1895-cond5.c new file mode 100644 index 000000000..1625c599b --- /dev/null +++ b/test/err/bug1895-cond5.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_5 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype1.c b/test/err/bug1895-prototype1.c new file mode 100644 index 000000000..30331e757 --- /dev/null +++ b/test/err/bug1895-prototype1.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_1 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype2.c b/test/err/bug1895-prototype2.c new file mode 100644 index 000000000..c8fe213f4 --- /dev/null +++ b/test/err/bug1895-prototype2.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_2 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype3.c b/test/err/bug1895-prototype3.c new file mode 100644 index 000000000..f7d2b79e4 --- /dev/null +++ b/test/err/bug1895-prototype3.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_3 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype4.c b/test/err/bug1895-prototype4.c new file mode 100644 index 000000000..3d0fe2c05 --- /dev/null +++ b/test/err/bug1895-prototype4.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_4 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype5.c b/test/err/bug1895-prototype5.c new file mode 100644 index 000000000..ba9b997c9 --- /dev/null +++ b/test/err/bug1895-prototype5.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_5 + +#include "bug1895-common.h" From d7a804d120812401b389163996af28551cc2013b Mon Sep 17 00:00:00 2001 From: Spiro Trikaliotis <spiro.trikaliotis@gmx.de> Date: Sat, 12 Nov 2022 23:12:25 +0100 Subject: [PATCH 111/360] Split stdin and stdout in test/asm/ Some tests pipe the stdout and stderr of the compiler or assembler into a file and compare the result with a reference. This has the subtle problem that both stdout and stderr and buffered i/o streams that may or may not work the same on different OSs or even shells. That means the order of the lines in the resulting file is not guaranteed. In practise it is "mostly" not an issue, but "we" still stumbled about one test where different behaviour can be triggered depending on running it in cmd.exe or bash (msys): test/asm/listing output of 010-paramcount.bin differs from the reference output when running the test from cmd.exe. The solution is most likely to have two reference files and not redirect into one file. This patch fixes the issue (cf. #1912) for the directory test/asm/. --- test/asm/listing/Makefile | 54 +++++++++++++++---- test/asm/listing/ref/010-paramcount.err-ref | 9 ---- test/asm/listing/ref/010-paramcount.err2-ref | 9 ++++ ...ss.err-ref => 030-assert-success.err2-ref} | 0 ...rr-ref => 030-assert-success.ld65err2-ref} | 0 ...rror.err-ref => 031-assert-error.err2-ref} | 0 ...err-ref => 032-assert-error2.ld65err2-ref} | 0 ...err-ref => 032-assert-error3.ld65err2-ref} | 0 ...err-ref => 032-assert-error4.ld65err2-ref} | 0 ...err-ref => 032-assert-error5.ld65err2-ref} | 0 ...err-ref => 032-assert-error6.ld65err2-ref} | 0 ...err-ref => 032-assert-error7.ld65err2-ref} | 0 ...err-ref => 032-assert-error8.ld65err2-ref} | 0 ...033-assert-ldwarning-success.ld65err2-ref} | 0 ...1.err-ref => 034-assert-lderror1.err2-ref} | 0 ...r-ref => 034-assert-lderror2.ld65err2-ref} | 0 ...r-ref => 034-assert-lderror3.ld65err2-ref} | 0 ...r-ref => 034-assert-lderror4.ld65err2-ref} | 0 ...r-ref => 034-assert-lderror6.ld65err2-ref} | 0 ...r-ref => 034-assert-lderror7.ld65err2-ref} | 0 ...r-ref => 034-assert-lderror8.ld65err2-ref} | 0 ...ign.ld65err-ref => 040-align.ld65err2-ref} | 0 ...se-on-1.err-ref => 050-case-on-1.err2-ref} | 0 ...se-on-2.err-ref => 050-case-on-2.err2-ref} | 0 ...se-on-3.err-ref => 050-case-on-3.err2-ref} | 0 ...se-on-4.err-ref => 050-case-on-4.err2-ref} | 0 ...se-on-5.err-ref => 050-case-on-5.err2-ref} | 0 27 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 test/asm/listing/ref/010-paramcount.err2-ref rename test/asm/listing/ref/{030-assert-success.err-ref => 030-assert-success.err2-ref} (100%) rename test/asm/listing/ref/{030-assert-success.ld65err-ref => 030-assert-success.ld65err2-ref} (100%) rename test/asm/listing/ref/{031-assert-error.err-ref => 031-assert-error.err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error2.ld65err-ref => 032-assert-error2.ld65err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error3.ld65err-ref => 032-assert-error3.ld65err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error4.ld65err-ref => 032-assert-error4.ld65err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error5.ld65err-ref => 032-assert-error5.ld65err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error6.ld65err-ref => 032-assert-error6.ld65err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error7.ld65err-ref => 032-assert-error7.ld65err2-ref} (100%) rename test/asm/listing/ref/{032-assert-error8.ld65err-ref => 032-assert-error8.ld65err2-ref} (100%) rename test/asm/listing/ref/{033-assert-ldwarning-success.ld65err-ref => 033-assert-ldwarning-success.ld65err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror1.err-ref => 034-assert-lderror1.err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror2.ld65err-ref => 034-assert-lderror2.ld65err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror3.ld65err-ref => 034-assert-lderror3.ld65err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror4.ld65err-ref => 034-assert-lderror4.ld65err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror6.ld65err-ref => 034-assert-lderror6.ld65err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror7.ld65err-ref => 034-assert-lderror7.ld65err2-ref} (100%) rename test/asm/listing/ref/{034-assert-lderror8.ld65err-ref => 034-assert-lderror8.ld65err2-ref} (100%) rename test/asm/listing/ref/{040-align.ld65err-ref => 040-align.ld65err2-ref} (100%) rename test/asm/listing/ref/{050-case-on-1.err-ref => 050-case-on-1.err2-ref} (100%) rename test/asm/listing/ref/{050-case-on-2.err-ref => 050-case-on-2.err2-ref} (100%) rename test/asm/listing/ref/{050-case-on-3.err-ref => 050-case-on-3.err2-ref} (100%) rename test/asm/listing/ref/{050-case-on-4.err-ref => 050-case-on-4.err2-ref} (100%) rename test/asm/listing/ref/{050-case-on-5.err-ref => 050-case-on-5.err2-ref} (100%) diff --git a/test/asm/listing/Makefile b/test/asm/listing/Makefile index d0d045a02..3c4c404af 100644 --- a/test/asm/listing/Makefile +++ b/test/asm/listing/Makefile @@ -9,7 +9,6 @@ ifdef CMD_EXE EXE = .exe MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /q /s $(subst /,\,$1) - ERRDIR = 2>&1 TRUE = exit 0 CAT = type $(subst /,\,$1) else @@ -17,7 +16,6 @@ else EXE = MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 - ERRDIR = 2>&1 TRUE = true CAT = cat $1 endif @@ -58,14 +56,14 @@ $(WORKDIR)/$1.bin: $1.s $(ISEQUAL) # compile without generating listing ifeq ($(wildcard control/$1.err),) - $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) $(ERRDIR) + $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) $(ERRDIR) + $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) endif else - $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) $(ERRDIR) || $(TRUE) + $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2) || $(TRUE) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) $(ERRDIR) || $(TRUE) + $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE) endif endif @@ -75,6 +73,12 @@ else $(ISEQUAL) --empty $$(@:.bin=.err) endif +ifneq ($(wildcard ref/$1.err2-ref),) + $(ISEQUAL) ref/$1.err2-ref $$(@:.bin=.err2) +else + $(ISEQUAL) --empty $$(@:.bin=.err2) +endif + ifneq ($(wildcard ref/$1.bin-ref),) $(ISEQUAL) --binary ref/$1.bin-ref $$@ endif @@ -95,16 +99,30 @@ ifneq ($(wildcard $(WORKDIR)/$1.ld65-err),) endif endif +ifneq ($(wildcard ref/$1.ld65err2-ref),) + @echo $(CAT) $$(@:.bin=.ld65-err2) +# FIXME: somehow this refuses to work in cmd.exe +ifndef CMD_EXE + $(call CAT,$$(@:.bin=.ld65-err2)) + -diff -u ref/$1.ld65err2-ref $$(@:.bin=.ld65-err2) +endif + $(ISEQUAL) --wildcards ref/$1.ld65err2-ref $$(@:.bin=.ld65-err2) +else +ifneq ($(wildcard $(WORKDIR)/$1.ld65-err2),) + $(ISEQUAL) --empty $$(@:.bin=.ld65-err2) +endif +endif + # compile with listing file ifeq ($(wildcard control/$1.err),) - $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) $(ERRDIR) + $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) $(ERRDIR) + $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) endif else - $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) $(ERRDIR) || $(TRUE) + $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2) || $(TRUE) ifeq ($(wildcard control/$1.no-ld65),) - $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) $(ERRDIR) || $(TRUE) + $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE) endif endif @@ -122,10 +140,26 @@ ifneq ($(wildcard $(WORKDIR)/$1.list-ld65-err),) endif endif +ifneq ($(wildcard ref/$1.err2-ref),) + $(ISEQUAL) ref/$1.err2-ref $$(@:.bin=.list-err2) +else + $(ISEQUAL) --empty $$(@:.bin=.list-err2) +endif + +ifneq ($(wildcard ref/$1.ld65err2-ref),) + $(ISEQUAL) --wildcards ref/$1.ld65err2-ref $$(@:.bin=.list-ld65-err2) +else +ifneq ($(wildcard $(WORKDIR)/$1.list-ld65-err2),) + $(ISEQUAL) --empty $$(@:.bin=.list-ld65-err2) +endif +endif + # check if the result bin is the same as without listing file ifeq ($(wildcard control/$1.err),) +ifeq ($(wildcard control/$1.err2),) $(ISEQUAL) $$@ $$(@:.bin=.list-bin) endif +endif ifneq ($(wildcard ref/$1.list-ref),) # we have a reference file, compare that, too diff --git a/test/asm/listing/ref/010-paramcount.err-ref b/test/asm/listing/ref/010-paramcount.err-ref index a66162eb5..baf73f50f 100644 --- a/test/asm/listing/ref/010-paramcount.err-ref +++ b/test/asm/listing/ref/010-paramcount.err-ref @@ -1,15 +1,6 @@ .paramcount = 3 .paramcount = 5 -010-paramcount.s:18: Warning: User warning: r1 is blank! -010-paramcount.s:14: Note: Macro was defined here -010-paramcount.s:8: Note: Macro was defined here .paramcount = 3 .paramcount = 5 -010-paramcount.s:19: Warning: User warning: r1 is blank! -010-paramcount.s:14: Note: Macro was defined here -010-paramcount.s:8: Note: Macro was defined here .paramcount = 1 .paramcount = 5 -010-paramcount.s:20: Warning: User warning: r1 is blank! -010-paramcount.s:14: Note: Macro was defined here -010-paramcount.s:8: Note: Macro was defined here diff --git a/test/asm/listing/ref/010-paramcount.err2-ref b/test/asm/listing/ref/010-paramcount.err2-ref new file mode 100644 index 000000000..304c9de61 --- /dev/null +++ b/test/asm/listing/ref/010-paramcount.err2-ref @@ -0,0 +1,9 @@ +010-paramcount.s:18: Warning: User warning: r1 is blank! +010-paramcount.s:14: Note: Macro was defined here +010-paramcount.s:8: Note: Macro was defined here +010-paramcount.s:19: Warning: User warning: r1 is blank! +010-paramcount.s:14: Note: Macro was defined here +010-paramcount.s:8: Note: Macro was defined here +010-paramcount.s:20: Warning: User warning: r1 is blank! +010-paramcount.s:14: Note: Macro was defined here +010-paramcount.s:8: Note: Macro was defined here diff --git a/test/asm/listing/ref/030-assert-success.err-ref b/test/asm/listing/ref/030-assert-success.err2-ref similarity index 100% rename from test/asm/listing/ref/030-assert-success.err-ref rename to test/asm/listing/ref/030-assert-success.err2-ref diff --git a/test/asm/listing/ref/030-assert-success.ld65err-ref b/test/asm/listing/ref/030-assert-success.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/030-assert-success.ld65err-ref rename to test/asm/listing/ref/030-assert-success.ld65err2-ref diff --git a/test/asm/listing/ref/031-assert-error.err-ref b/test/asm/listing/ref/031-assert-error.err2-ref similarity index 100% rename from test/asm/listing/ref/031-assert-error.err-ref rename to test/asm/listing/ref/031-assert-error.err2-ref diff --git a/test/asm/listing/ref/032-assert-error2.ld65err-ref b/test/asm/listing/ref/032-assert-error2.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error2.ld65err-ref rename to test/asm/listing/ref/032-assert-error2.ld65err2-ref diff --git a/test/asm/listing/ref/032-assert-error3.ld65err-ref b/test/asm/listing/ref/032-assert-error3.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error3.ld65err-ref rename to test/asm/listing/ref/032-assert-error3.ld65err2-ref diff --git a/test/asm/listing/ref/032-assert-error4.ld65err-ref b/test/asm/listing/ref/032-assert-error4.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error4.ld65err-ref rename to test/asm/listing/ref/032-assert-error4.ld65err2-ref diff --git a/test/asm/listing/ref/032-assert-error5.ld65err-ref b/test/asm/listing/ref/032-assert-error5.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error5.ld65err-ref rename to test/asm/listing/ref/032-assert-error5.ld65err2-ref diff --git a/test/asm/listing/ref/032-assert-error6.ld65err-ref b/test/asm/listing/ref/032-assert-error6.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error6.ld65err-ref rename to test/asm/listing/ref/032-assert-error6.ld65err2-ref diff --git a/test/asm/listing/ref/032-assert-error7.ld65err-ref b/test/asm/listing/ref/032-assert-error7.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error7.ld65err-ref rename to test/asm/listing/ref/032-assert-error7.ld65err2-ref diff --git a/test/asm/listing/ref/032-assert-error8.ld65err-ref b/test/asm/listing/ref/032-assert-error8.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/032-assert-error8.ld65err-ref rename to test/asm/listing/ref/032-assert-error8.ld65err2-ref diff --git a/test/asm/listing/ref/033-assert-ldwarning-success.ld65err-ref b/test/asm/listing/ref/033-assert-ldwarning-success.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/033-assert-ldwarning-success.ld65err-ref rename to test/asm/listing/ref/033-assert-ldwarning-success.ld65err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror1.err-ref b/test/asm/listing/ref/034-assert-lderror1.err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror1.err-ref rename to test/asm/listing/ref/034-assert-lderror1.err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror2.ld65err-ref b/test/asm/listing/ref/034-assert-lderror2.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror2.ld65err-ref rename to test/asm/listing/ref/034-assert-lderror2.ld65err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror3.ld65err-ref b/test/asm/listing/ref/034-assert-lderror3.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror3.ld65err-ref rename to test/asm/listing/ref/034-assert-lderror3.ld65err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror4.ld65err-ref b/test/asm/listing/ref/034-assert-lderror4.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror4.ld65err-ref rename to test/asm/listing/ref/034-assert-lderror4.ld65err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror6.ld65err-ref b/test/asm/listing/ref/034-assert-lderror6.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror6.ld65err-ref rename to test/asm/listing/ref/034-assert-lderror6.ld65err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror7.ld65err-ref b/test/asm/listing/ref/034-assert-lderror7.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror7.ld65err-ref rename to test/asm/listing/ref/034-assert-lderror7.ld65err2-ref diff --git a/test/asm/listing/ref/034-assert-lderror8.ld65err-ref b/test/asm/listing/ref/034-assert-lderror8.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/034-assert-lderror8.ld65err-ref rename to test/asm/listing/ref/034-assert-lderror8.ld65err2-ref diff --git a/test/asm/listing/ref/040-align.ld65err-ref b/test/asm/listing/ref/040-align.ld65err2-ref similarity index 100% rename from test/asm/listing/ref/040-align.ld65err-ref rename to test/asm/listing/ref/040-align.ld65err2-ref diff --git a/test/asm/listing/ref/050-case-on-1.err-ref b/test/asm/listing/ref/050-case-on-1.err2-ref similarity index 100% rename from test/asm/listing/ref/050-case-on-1.err-ref rename to test/asm/listing/ref/050-case-on-1.err2-ref diff --git a/test/asm/listing/ref/050-case-on-2.err-ref b/test/asm/listing/ref/050-case-on-2.err2-ref similarity index 100% rename from test/asm/listing/ref/050-case-on-2.err-ref rename to test/asm/listing/ref/050-case-on-2.err2-ref diff --git a/test/asm/listing/ref/050-case-on-3.err-ref b/test/asm/listing/ref/050-case-on-3.err2-ref similarity index 100% rename from test/asm/listing/ref/050-case-on-3.err-ref rename to test/asm/listing/ref/050-case-on-3.err2-ref diff --git a/test/asm/listing/ref/050-case-on-4.err-ref b/test/asm/listing/ref/050-case-on-4.err2-ref similarity index 100% rename from test/asm/listing/ref/050-case-on-4.err-ref rename to test/asm/listing/ref/050-case-on-4.err2-ref diff --git a/test/asm/listing/ref/050-case-on-5.err-ref b/test/asm/listing/ref/050-case-on-5.err2-ref similarity index 100% rename from test/asm/listing/ref/050-case-on-5.err-ref rename to test/asm/listing/ref/050-case-on-5.err2-ref From 3bcfa735cb0f8d78a56dd88d3370d4dfea02f652 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sun, 13 Nov 2022 14:57:48 +0800 Subject: [PATCH 112/360] clearer comments on and usage of code generator flags with type conversions in the primary register. --- src/cc65/codegen.c | 117 +++++++++++++++++++++++++++------------------ src/cc65/codegen.h | 18 ++++--- 2 files changed, 81 insertions(+), 54 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 00a4738e2..c9e71de64 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -1283,34 +1283,49 @@ void g_tosint (unsigned flags) -static void g_regchar (unsigned Flags) -/* Make sure, the value in the primary register is in the range of char. Truncate if necessary */ +static void g_regchar (unsigned to) +/* Treat the value in the primary register as a char with specified signedness +** and convert it to an int (whose representation is irrelevent of signedness). +*/ { - unsigned L; - - AddCodeLine ("ldx #$00"); - - if ((Flags & CF_UNSIGNED) == 0) { - /* Sign extend */ - L = GetLocalLabel(); - AddCodeLine ("cmp #$80"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } + /* Since char is the smallest type supported here, we never need any info + ** about the original type to "promote from it". However, we have to make + ** sure the entire AX contains the correct char value as an int, since we + ** will almost always use the char value as an int in AX directly in code + ** generation (unless CF_FORCECHAR is specified). That is to say, we don't + ** need the original "from" flags for the first conversion to char, but do + ** need the original "to" flags as the new "from" flags for the conversion + ** to int. + */ + g_regint (to | CF_FORCECHAR); } -void g_regint (unsigned Flags) -/* Make sure, the value in the primary register an int. Convert if necessary */ +void g_regint (unsigned from) +/* Convert the value in the primary register to an int (whose representation +** is irrelevent of signedness). +*/ { - switch (Flags & CF_TYPEMASK) { + switch (from & CF_TYPEMASK) { case CF_CHAR: - if (Flags & CF_FORCECHAR) { - /* Conversion is from char */ - g_regchar (Flags); + /* If the original value was forced to use only A, it must be + ** extended from char to fill AX. Otherwise nothing to do here + ** since AX would already have the correct int value. + */ + if (from & CF_FORCECHAR) { + AddCodeLine ("ldx #$00"); + + if ((from & CF_UNSIGNED) == 0) { + /* Sign extend */ + unsigned L = GetLocalLabel(); + AddCodeLine ("cmp #$80"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + break; } /* FALLTHROUGH */ @@ -1319,21 +1334,27 @@ void g_regint (unsigned Flags) break; default: - typeerror (Flags); + typeerror (from); } } -void g_reglong (unsigned Flags) -/* Make sure, the value in the primary register a long. Convert if necessary */ +void g_reglong (unsigned from) +/* Convert the value in the primary register to a long (whose representation +** is irrelevent of signedness). +*/ { - switch (Flags & CF_TYPEMASK) { + switch (from & CF_TYPEMASK) { case CF_CHAR: - if (Flags & CF_FORCECHAR) { + /* If the original value was forced to use only A, it must be + ** extended from char to long. Otherwise AX would already have + ** the correct int value to be extened to long. + */ + if (from & CF_FORCECHAR) { /* Conversion is from char */ - if (Flags & CF_UNSIGNED) { + if (from & CF_UNSIGNED) { if (IS_Get (&CodeSizeFactor) >= 200) { AddCodeLine ("ldx #$00"); AddCodeLine ("stx sreg"); @@ -1343,18 +1364,19 @@ void g_reglong (unsigned Flags) } } else { if (IS_Get (&CodeSizeFactor) >= 366) { - g_regchar (Flags); + g_regint (from); AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); } else { AddCodeLine ("jsr along"); } } + break; } /* FALLTHROUGH */ case CF_INT: - if (Flags & CF_UNSIGNED) { + if (from & CF_UNSIGNED) { if (IS_Get (&CodeSizeFactor) >= 200) { AddCodeLine ("ldy #$00"); AddCodeLine ("sty sreg"); @@ -1371,7 +1393,7 @@ void g_reglong (unsigned Flags) break; default: - typeerror (Flags); + typeerror (from); } } @@ -1508,48 +1530,49 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs) -unsigned g_typecast (unsigned lhs, unsigned rhs) -/* Cast the value in the primary register to the operand size that is flagged -** by the lhs value. Return the result value. +unsigned g_typecast (unsigned to, unsigned from) +/* Cast the value in the primary register to the specified operand size and +** signedness. Return the result flags. */ { /* Check if a conversion is needed */ - if ((rhs & CF_CONST) == 0) { - switch (lhs & CF_TYPEMASK) { + if ((from & CF_CONST) == 0) { + switch (to & CF_TYPEMASK) { case CF_LONG: - /* We must promote the primary register to long */ - g_reglong (rhs); + /* We must promote the primary register to long in EAX */ + g_reglong (from); break; case CF_INT: - /* We must promote the primary register to int */ - g_regint (rhs); + /* We must promote the primary register to int in AX */ + g_regint (from); break; case CF_CHAR: - /* We must truncate the primary register to char */ - g_regchar (lhs); + /* We must truncate the primary register to char and then + ** sign-extend it to signed int in AX. + */ + g_regchar (to); break; default: - typeerror (lhs); + /* Since we are switching on "to", report an error on it */ + typeerror (to); } } - /* Do not need any other action. If the left type is int, and the primary + /* Do not need any other action. If the "to" type is int, and the primary ** register is long, it will be automagically truncated. If the right hand ** side is const, it is not located in the primary register and handled by ** the expression parser code. */ /* Result is const if the right hand side was const */ - lhs |= (rhs & CF_CONST); + to |= (from & CF_CONST); - /* The resulting type is that of the left hand side (that's why you called - ** this function :-) - */ - return lhs; + /* The resulting type is "to" (that's why you called this function :-) */ + return to; } diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index cb62d78bd..8e04b45e4 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -208,11 +208,15 @@ void g_toslong (unsigned flags); void g_tosint (unsigned flags); /* Make sure, the value on TOS is an int. Convert if necessary */ -void g_regint (unsigned Flags); -/* Make sure, the value in the primary register an int. Convert if necessary */ +void g_regint (unsigned from); +/* Convert the value in the primary register to an int (whose representation +** is irrelevent of signedness). +*/ -void g_reglong (unsigned Flags); -/* Make sure, the value in the primary register a long. Convert if necessary */ +void g_reglong (unsigned from); +/* Convert the value in the primary register to a long (whose representation +** is irrelevent of signedness). +*/ unsigned g_typeadjust (unsigned lhs, unsigned rhs); /* Adjust the integer operands before doing a binary operation. lhs is a flags @@ -220,9 +224,9 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs); ** in (e)ax. The return value is the flags value for the resulting type. */ -unsigned g_typecast (unsigned lhs, unsigned rhs); -/* Cast the value in the primary register to the operand size that is flagged -** by the lhs value. Return the result value. +unsigned g_typecast (unsigned to, unsigned from); +/* Cast the value in the primary register to the specified operand size and +** signedness. Return the result flags. */ void g_scale (unsigned flags, long val); From dadca9e033383ccf1609015f4106e7d05686ada9 Mon Sep 17 00:00:00 2001 From: acqn <acqn163@outlook.com> Date: Sun, 13 Nov 2022 16:32:41 +0800 Subject: [PATCH 113/360] Fixed bitwise-shift in PP. --- src/cc65/ppexpr.c | 28 +++++++---- test/val/ppshift.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 test/val/ppshift.c diff --git a/src/cc65/ppexpr.c b/src/cc65/ppexpr.c index 0942dc8f8..1610e9b92 100644 --- a/src/cc65/ppexpr.c +++ b/src/cc65/ppexpr.c @@ -519,12 +519,21 @@ static void PPhie7 (PPExpr* Expr) /* Evaluate */ if (PPEvaluationEnabled && !PPEvaluationFailed) { - /* To shift by a negative value is equivalent to shift to the - ** opposite direction. - */ - if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0 && Rhs.IVal > (long)LONG_BITS) { + /* For now we use 32-bit integer types for PP integer constants */ + if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0) { + if ((unsigned long)Rhs.IVal > LONG_BITS) { + Rhs.IVal = (long)LONG_BITS; + } + } else if (Rhs.IVal > (long)LONG_BITS) { Rhs.IVal = (long)LONG_BITS; + } else if (Rhs.IVal < -(long)LONG_BITS) { + Rhs.IVal = -(long)LONG_BITS; } + + /* Positive count for left-shift and negative for right-shift. So + ** to shift by a count is equivalent to shift to the opposite + ** direction by the negated count. + */ if (Op == TOK_SHR) { Rhs.IVal = -Rhs.IVal; } @@ -532,27 +541,26 @@ static void PPhie7 (PPExpr* Expr) /* Evaluate the result */ if ((Expr->Flags & PPEXPR_UNSIGNED) != 0) { if (Rhs.IVal >= (long)LONG_BITS) { - /* For now we use (unsigned) long types for integer constants */ PPWarning ("Integer overflow in preprocessor expression"); Expr->IVal = 0; } else if (Rhs.IVal > 0) { Expr->IVal <<= Rhs.IVal; - } else if (Rhs.IVal < -(long)LONG_BITS) { + } else if (Rhs.IVal <= -(long)LONG_BITS) { Expr->IVal = 0; } else if (Rhs.IVal < 0) { Expr->IVal = (unsigned long)Expr->IVal >> -Rhs.IVal; } } else { + /* -1 for sign bit */ if (Rhs.IVal >= (long)(LONG_BITS - 1)) { - /* For now we use (unsigned) long types for integer constants */ PPWarning ("Integer overflow in preprocessor expression"); Expr->IVal = 0; } else if (Rhs.IVal > 0) { Expr->IVal <<= Rhs.IVal; - } else if (Rhs.IVal < -(long)LONG_BITS) { - Expr->IVal = -1; + } else if (Rhs.IVal <= -(long)LONG_BITS) { + Expr->IVal = Expr->IVal >= 0 ? 0 : -1; } else if (Rhs.IVal < 0) { - Expr->IVal >>= Expr->IVal >> -Rhs.IVal; + Expr->IVal = (long)Expr->IVal >> -Rhs.IVal; } } } diff --git a/test/val/ppshift.c b/test/val/ppshift.c new file mode 100644 index 000000000..466b15926 --- /dev/null +++ b/test/val/ppshift.c @@ -0,0 +1,120 @@ +/* + Test of bitwise-shift in preprocessor expressions. + + Note: Keep in mind that integer constants are always 32-bit in PP for cc65. +*/ + +/* Signed lhs */ +#if 1 << 16 != 0x00010000 +#error 1 << 16 != 0x00010000 +#endif + +#if 0x00010000 << -16 != 1 +#error 0x00010000 << -16 != 1 +#endif + +#if 0x10000 >> 16 != 1 +#error 0x10000 >> 16 != 1 +#endif + +#if 1 >> -16 != 0x10000 +#error 1 >> -16 != 0x10000 +#endif + +#if 1 << 32 != 0 +#error 1 << 32 != 0 +#endif + +#if 1 << -32 != 0 +#error 1 << -32 != 0 +#endif + +#if 1 >> 32 != 0 +#error 1 >> 32 != 0 +#endif + +#if 1 >> -32 != 0 +#error 1 >> -32 != 0 +#endif + +#if -1 << 32 != 0 +#error -1 << 32 != 0 +#endif + +#if -1 << -32 != -1 +#error -1 << -32 != -1 +#endif + +#if -1 >> 32 != -1 +#error -1 >> 32 != -1 +#endif + +#if -1 >> -32 != 0 +#error -1 >> -32 != 0 +#endif + +/* NOTE: 2147483648 is an UNSIGNED integer! */ +#if -1 << 2147483648 != 0 +#error -1 << 2147483648 != 0 +#endif + +/* NOTE: -2147483648 is also an UNSIGNED integer! */ +#if -1 << -2147483648 != 0 +#error -1 << -2147483648 != 0 +#endif + +#if -1 << (-2147483647 - 1) != -1 +#error -1 << (-2147483647 - 1) != -1 +#endif + +/* NOTE: 2147483648 is an UNSIGNED integer! */ +#if -1 >> 2147483648 != -1 +#error -1 >> 2147483648 != -1 +#endif + +/* NOTE: -2147483648 is also an UNSIGNED integer! */ +#if -1 >> -2147483648 != -1 +#error -1 >> -2147483648 != 0 +#endif + +#if -1 >> (-2147483647 - 1) != 0 +#error -1 >> (-2147483647 - 1) != 0 +#endif + +/* Unsigned lhs */ +#if 1U << 16 != 0x00010000 +#error 1U << 16 != 0x00010000 +#endif + +#if 0x80000000U << -16 != 0x8000 +#error 0x80000000U << -16 != 0x8000 +#endif + +#if 0x80000000U >> 16 != 0x8000 +#error 0x80000000U >> 16 != 0x8000 +#endif + +#if 1U >> -16 != 0x10000 +#error 1U >> -16 != 0x10000 +#endif + +#if -1U << 32 != 0 +#error -1U << 32 != 0 +#endif + +#if -1U << -32 != 0 +#error -1U << -32 != 0 +#endif + +#if -1U >> 32 != 0 +#error -1U >> 32 != 0 +#endif + +#if -1U >> -32 != 0 +#error -1U >> -32 != 0 +#endif + +int main(void) +{ + return 0; +} From 0408d71cc577f5529238fc79846c4f2fc6976e9e Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 16:28:25 +0100 Subject: [PATCH 114/360] fixes so "make clean" will work without failing on cmd.exe --- util/atari/Makefile | 12 +++++++++++- util/gamate/Makefile | 12 +++++++++++- util/zlib/Makefile | 12 +++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/util/atari/Makefile b/util/atari/Makefile index db4226f69..e53c837aa 100644 --- a/util/atari/Makefile +++ b/util/atari/Makefile @@ -5,6 +5,16 @@ ifdef CROSS_COMPILE $(info CC: $(CC)) endif +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +ifdef CMD_EXE + DEL = -del /f +else + DEL = $(RM) +endif + CFLAGS += -O3 -Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) .PHONY: mostlyclean clean @@ -15,6 +25,6 @@ ataricvt: ataricvt.c $(CC) $(CFLAGS) -o ataricvt ataricvt.c mostlyclean clean: - $(RM) ataricvt + $(DEL) ataricvt install zip: diff --git a/util/gamate/Makefile b/util/gamate/Makefile index db2a1f059..54fa74191 100644 --- a/util/gamate/Makefile +++ b/util/gamate/Makefile @@ -5,6 +5,16 @@ ifdef CROSS_COMPILE $(info CC: $(CC)) endif +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +ifdef CMD_EXE + DEL = -del /f +else + DEL = $(RM) +endif + CFLAGS += -O3 -Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) .PHONY: mostlyclean clean @@ -15,6 +25,6 @@ gamate-fixcart: gamate-fixcart.c $(CC) $(CFLAGS) -o gamate-fixcart gamate-fixcart.c mostlyclean clean: - $(RM) gamate-fixcart + $(DEL) gamate-fixcart install zip: diff --git a/util/zlib/Makefile b/util/zlib/Makefile index 3b2c7c816..f276ddaf2 100644 --- a/util/zlib/Makefile +++ b/util/zlib/Makefile @@ -5,6 +5,16 @@ ifdef CROSS_COMPILE $(info CC: $(CC)) endif +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +ifdef CMD_EXE + DEL = -del /f +else + DEL = $(RM) +endif + CFLAGS += -O3 -Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) .PHONY: mostlyclean clean @@ -22,6 +32,6 @@ deflater: deflater.c $(CC) $(CFLAGS) -o deflater deflater.c -lz mostlyclean clean: - $(RM) deflater + $(DEL) deflater install zip: From fdcc683997998610baf9c6bc3462f16395862db5 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:13:37 +0100 Subject: [PATCH 115/360] shoot in the dark, try to fix ming build issue --- .github/workflows/snapshot-on-push-master.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 769d778d5..192468079 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -75,13 +75,13 @@ jobs: - name: Build and package 64-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=x86_64-w64-mingw32- + make -j2 bin USER_CFLAGS="-D __STDC_FORMAT_MACROS -Werror" CROSS_COMPILE=x86_64-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win64.zip - name: Build and package 32-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32- + make -j2 bin USER_CFLAGS="-D __STDC_FORMAT_MACROS -Werror" CROSS_COMPILE=i686-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win32.zip From d459b5da8732bd44d3d1d2ef3bbf95346622f848 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:20:44 +0100 Subject: [PATCH 116/360] another try --- .github/workflows/snapshot-on-push-master.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 192468079..45f76b96b 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -46,6 +46,13 @@ jobs: - name: Checkout Source uses: actions/checkout@v2 + - name: Build and package 64-bit Windows versions of the tools. + run: | + make -C src clean + make -j2 bin USER_CFLAGS="-D __USE_MINGW_ANSI_STDIO 1 -Werror" CROSS_COMPILE=x86_64-w64-mingw32- + make zip + mv cc65.zip cc65-snapshot-win64.zip + - name: Do some simple style checks shell: bash run: make -j2 checkstyle @@ -75,13 +82,13 @@ jobs: - name: Build and package 64-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS="-D __STDC_FORMAT_MACROS -Werror" CROSS_COMPILE=x86_64-w64-mingw32- + make -j2 bin USER_CFLAGS="-D __USE_MINGW_ANSI_STDIO 1 -Werror" CROSS_COMPILE=x86_64-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win64.zip - name: Build and package 32-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS="-D __STDC_FORMAT_MACROS -Werror" CROSS_COMPILE=i686-w64-mingw32- + make -j2 bin USER_CFLAGS="-D __USE_MINGW_ANSI_STDIO 1 -Werror" CROSS_COMPILE=i686-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win32.zip From d68598165c1eade5bfdf79a6f960fc95eaac33fd Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:24:05 +0100 Subject: [PATCH 117/360] and another --- .github/workflows/snapshot-on-push-master.yml | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 45f76b96b..5aa2999ac 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -46,13 +46,6 @@ jobs: - name: Checkout Source uses: actions/checkout@v2 - - name: Build and package 64-bit Windows versions of the tools. - run: | - make -C src clean - make -j2 bin USER_CFLAGS="-D __USE_MINGW_ANSI_STDIO 1 -Werror" CROSS_COMPILE=x86_64-w64-mingw32- - make zip - mv cc65.zip cc65-snapshot-win64.zip - - name: Do some simple style checks shell: bash run: make -j2 checkstyle @@ -64,21 +57,21 @@ jobs: - name: Build the platform libraries. shell: bash run: make -j2 lib QUIET=1 - - name: Run the regression tests. - shell: bash - run: make test QUIET=1 - - name: Test that the samples can be built. - shell: bash - run: make -j2 samples - - name: Remove the output from the samples tests. - shell: bash - run: make -C samples clean - - name: Remove programs in util directory - shell: bash - run: make -C util clean - - name: Build the document files. - shell: bash - run: make -j2 doc +# - name: Run the regression tests. +# shell: bash +# run: make test QUIET=1 +# - name: Test that the samples can be built. +# shell: bash +# run: make -j2 samples +# - name: Remove the output from the samples tests. +# shell: bash +# run: make -C samples clean +# - name: Remove programs in util directory +# shell: bash +# run: make -C util clean +# - name: Build the document files. +# shell: bash +# run: make -j2 doc - name: Build and package 64-bit Windows versions of the tools. run: | make -C src clean From d1b7768064ecb46ba3eeb3b1ac9b1162c1c09d6b Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:27:51 +0100 Subject: [PATCH 118/360] yeah! --- .github/workflows/snapshot-on-push-master.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 5aa2999ac..674a2cddf 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -75,13 +75,13 @@ jobs: - name: Build and package 64-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS="-D __USE_MINGW_ANSI_STDIO 1 -Werror" CROSS_COMPILE=x86_64-w64-mingw32- + make -j2 bin USER_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 -Werror" CROSS_COMPILE=x86_64-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win64.zip - name: Build and package 32-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS="-D __USE_MINGW_ANSI_STDIO 1 -Werror" CROSS_COMPILE=i686-w64-mingw32- + make -j2 bin USER_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 -Werror" CROSS_COMPILE=i686-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win32.zip From 5638e0916ac301c36c7eb4d499c18e464ed2d30d Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:39:35 +0100 Subject: [PATCH 119/360] =?UTF-8?q?sp=C3=BCl=20es=20noch=20einmal,=20Sam?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/snapshot-on-push-master.yml | 4 ++-- src/cc65/codegen.c | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 674a2cddf..fcefa10d8 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -75,13 +75,13 @@ jobs: - name: Build and package 64-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 -Werror" CROSS_COMPILE=x86_64-w64-mingw32- + make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=x86_64-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win64.zip - name: Build and package 32-bit Windows versions of the tools. run: | make -C src clean - make -j2 bin USER_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 -Werror" CROSS_COMPILE=i686-w64-mingw32- + make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32- make zip mv cc65.zip cc65-snapshot-win32.zip diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index c9e71de64..b149b7dda 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -65,7 +65,12 @@ #include "util.h" #include "codegen.h" - +/* this is a terrible hack that tries to combat the ever reoccuring issue with + mingw and PRIXPTR */ +#defined(__MINGW64__) +#undef PRIXPTR +#define PRIXPTR "%p" +#endif /*****************************************************************************/ /* Helpers */ From 5fb20dec9153d94c7c514bdba5d0caaf7c28bda1 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:41:22 +0100 Subject: [PATCH 120/360] commit message --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index b149b7dda..c1c6756c1 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -67,7 +67,7 @@ /* this is a terrible hack that tries to combat the ever reoccuring issue with mingw and PRIXPTR */ -#defined(__MINGW64__) +#if defined(__MINGW64__) #undef PRIXPTR #define PRIXPTR "%p" #endif From c6ecee074888fb63d13e5230da6d679e3f58d592 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:45:21 +0100 Subject: [PATCH 121/360] Babydino sagt: nochmal! --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index c1c6756c1..eb0edfdbb 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "%p" +#define PRIXPTR "p" #endif /*****************************************************************************/ From 8a9029d39331b84c2d28b174d73db3aa2e1e8293 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:50:32 +0100 Subject: [PATCH 122/360] hnnngg --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index eb0edfdbb..60b9589f0 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "p" +#define PRIXPTR "ul" #endif /*****************************************************************************/ From feb839e7f03849f28b2ca3ecbd121610b561005c Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:55:22 +0100 Subject: [PATCH 123/360] narrisch werd i! --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 60b9589f0..f4dfd5d5b 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "ul" +#define PRIXPTR "l" #endif /*****************************************************************************/ From 4c6fddd3000efb4aa1d105232cdeebd1b122b4ca Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:58:12 +0100 Subject: [PATCH 124/360] i want a cookie each time i do this --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index f4dfd5d5b..95735a195 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "l" +#define PRIXPTR "lu" #endif /*****************************************************************************/ From ca94cfcbacbe9b50183d9c820599fb1bef541b0a Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 18:03:40 +0100 Subject: [PATCH 125/360] that perhaps? --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 95735a195..be90bb8e2 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "lu" +#define PRIXPTR "zu" #endif /*****************************************************************************/ From a6feeac5ed1115ffcf5910215699907a24bd8980 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 18:10:07 +0100 Subject: [PATCH 126/360] or msvc I64u ? --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index be90bb8e2..0f276dbbd 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "zu" +#define PRIXPTR "%I64u" #endif /*****************************************************************************/ From bbe8c62e9dbc48d89ea0db4dd02b2e40fd4c0629 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 18:13:15 +0100 Subject: [PATCH 127/360] coffee --- src/cc65/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 0f276dbbd..ad3a4d99b 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -69,7 +69,7 @@ mingw and PRIXPTR */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "%I64u" +#define PRIXPTR "I64u" #endif /*****************************************************************************/ From 4c047bf11eb2eb2ab4e42bf6db5ebc8bcbc9fe0e Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 18:13:54 +0100 Subject: [PATCH 128/360] yawn --- .github/workflows/snapshot-on-push-master.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index fcefa10d8..717ad348b 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -49,14 +49,14 @@ jobs: - name: Do some simple style checks shell: bash run: make -j2 checkstyle - - name: Build the tools. - shell: bash - run: | - make -j2 bin USER_CFLAGS=-Werror - make -j2 util - - name: Build the platform libraries. - shell: bash - run: make -j2 lib QUIET=1 +# - name: Build the tools. +# shell: bash +# run: | +# make -j2 bin USER_CFLAGS=-Werror +# make -j2 util +# - name: Build the platform libraries. +# shell: bash +# run: make -j2 lib QUIET=1 # - name: Run the regression tests. # shell: bash # run: make test QUIET=1 From b166dc4261fee8dd7dab7be743dcaca6948831f4 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 18:19:31 +0100 Subject: [PATCH 129/360] hopefully thats it --- .github/workflows/snapshot-on-push-master.yml | 46 +++++++++---------- src/cc65/codegen.c | 8 +++- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 717ad348b..769d778d5 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -49,29 +49,29 @@ jobs: - name: Do some simple style checks shell: bash run: make -j2 checkstyle -# - name: Build the tools. -# shell: bash -# run: | -# make -j2 bin USER_CFLAGS=-Werror -# make -j2 util -# - name: Build the platform libraries. -# shell: bash -# run: make -j2 lib QUIET=1 -# - name: Run the regression tests. -# shell: bash -# run: make test QUIET=1 -# - name: Test that the samples can be built. -# shell: bash -# run: make -j2 samples -# - name: Remove the output from the samples tests. -# shell: bash -# run: make -C samples clean -# - name: Remove programs in util directory -# shell: bash -# run: make -C util clean -# - name: Build the document files. -# shell: bash -# run: make -j2 doc + - name: Build the tools. + shell: bash + run: | + make -j2 bin USER_CFLAGS=-Werror + make -j2 util + - name: Build the platform libraries. + shell: bash + run: make -j2 lib QUIET=1 + - name: Run the regression tests. + shell: bash + run: make test QUIET=1 + - name: Test that the samples can be built. + shell: bash + run: make -j2 samples + - name: Remove the output from the samples tests. + shell: bash + run: make -C samples clean + - name: Remove programs in util directory + shell: bash + run: make -C util clean + - name: Build the document files. + shell: bash + run: make -j2 doc - name: Build and package 64-bit Windows versions of the tools. run: | make -C src clean diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index ad3a4d99b..251c973ee 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -65,8 +65,12 @@ #include "util.h" #include "codegen.h" -/* this is a terrible hack that tries to combat the ever reoccuring issue with - mingw and PRIXPTR */ +/* This is a terrible hack that tries to combat the ever reoccuring issue with + Mingw and PRIXPTR - the macro should have been defined like this for us in + the first place. + NOTE: "I64u" works in the github actions now, so if your local mingw64 fails, + you probably have to update. +*/ #if defined(__MINGW64__) #undef PRIXPTR #define PRIXPTR "I64u" From 9d78e10d4b06d965d6fe149943f1c9865308d350 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 18:39:58 +0100 Subject: [PATCH 130/360] update actions to use node16 instead of node12 --- .github/workflows/build-on-pull-request.yml | 2 +- .github/workflows/snapshot-on-push-master.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 0ba0c6a1f..4e442107d 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -19,7 +19,7 @@ jobs: - shell: bash run: git config --global core.autocrlf input - name: Checkout Source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Do some simple style checks shell: bash diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 769d778d5..eb2a5019c 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -44,7 +44,7 @@ jobs: - shell: bash run: git config --global core.autocrlf input - name: Checkout Source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Do some simple style checks shell: bash From eb8dbcd04dc8765611c31e758ee5539a3289c945 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Fri, 18 Nov 2022 19:00:35 +0100 Subject: [PATCH 131/360] really update all jobs --- .github/workflows/build-on-pull-request.yml | 2 +- .github/workflows/snapshot-on-push-master.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 4e442107d..05d6a4a39 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -57,7 +57,7 @@ jobs: run: git config --global core.autocrlf input - name: Checkout Source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v1.1 diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index eb2a5019c..e8be4400e 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -18,7 +18,7 @@ jobs: run: git config --global core.autocrlf input - name: Checkout Source - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v1.1 @@ -97,7 +97,7 @@ jobs: path: cc65-snapshot-win64.zip - name: Get the online documents repo. - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: cc65/doc path: doc.git From 9a9bf9f2eacdc5ad6cb1029b6e5bc174d0ee0a34 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 19 Nov 2022 18:38:00 +0100 Subject: [PATCH 132/360] update note on identifiers --- Contributing.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/Contributing.md b/Contributing.md index e316b9c61..6fa5ba7c2 100644 --- a/Contributing.md +++ b/Contributing.md @@ -29,9 +29,22 @@ This is an ongoing controversial topic - everyone knows that. However, the follo The (bash) scripts used to check the above rules can be found in ```.github/check```. You can also run all checks using ```make check```. -### identifiers and symbol names +### Identifiers and Symbol names -* any symbols that are exported from source files and/or appear in header files should not be in the "_symbol" form in C, or "__symbol" form in assembly. This way we evade the problem that "_symbol" may or may not be reserved by that standard. +The C Standard defines certain identifiers and symbol names, which we can not use +in our code. Since it is not always obvious which parts of the library code will +actually end up in a linked program, the following applies to ALL of the library. + +Any non standard identifier/symbol/function that is exported from source files, +or appears in header files: + +* must not be in the "_symbol" form in C, or "__symbol" form in assembly. +* must start with (at least) two (C Code) or three (assembly code) underscores, unless the symbol appears in a non standard header file. + +This is likely more than the standard dictates us to do - but it is certainly +standard compliant - and easy to remember. + +Also see the discussion in https://github.com/cc65/cc65/issues/1796 ### misc @@ -173,7 +186,88 @@ The only exception to the above are actions that are exclusive to the github act The first step is implementing the datatype "float" as IEEE488 floats. Help welcomed! * WIP compiler/library changes are here: https://github.com/cc65/cc65/pull/1777 -* free software library with testbench is here: http://www.jhauser.us/arithmetic/ + +## Library + +### name clashes in the library + +see "Identifiers and Symbol names" above - not all identifiers have been checked +and renamed yet. The following is a list of those that still might need to be +fixed: + +``` +common + +__argc libsrc/runtime/callmain.s libsrc/cbm610/mainargs.s libsrc/cx16/mainargs.s libsrc/plus4/mainargs.s libsrc/lynx/mainargs.s libsrc/c16/mainargs.s libsrc/geos-common/system/mainargs.s libsrc/sim6502/mainargs.s libsrc/c128/mainargs.s libsrc/vic20/mainargs.s libsrc/nes/mainargs.s libsrc/atari/getargs.s libsrc/apple2/mainargs.s libsrc/cbm510/mainargs.s libsrc/telestrat/mainargs.s libsrc/c64/mainargs.s libsrc/pet/mainargs.s libsrc/atmos/mainargs.s +__argv libsrc/runtime/callmain.s libsrc/cbm610/mainargs.s libsrc/cx16/mainargs.s libsrc/plus4/mainargs.s libsrc/lynx/mainargs.s libsrc/c16/mainargs.s libsrc/geos-common/system/mainargs.s libsrc/sim6502/mainargs.s libsrc/c128/mainargs.s libsrc/vic20/mainargs.s libsrc/nes/mainargs.s libsrc/atari/getargs.s libsrc/apple2/mainargs.s libsrc/cbm510/mainargs.s libsrc/telestrat/mainargs.s libsrc/c64/mainargs.s libsrc/pet/mainargs.s libsrc/atmos/mainargs.s +__cos libsrc/common/sincos.s +__ctypeidx libsrc/common/ctype.s libsrc/common/ctypemask.s libsrc/geos-common/system/ctype.s libsrc/atari/ctype.s libsrc/cbm/ctype.s libsrc/atmos/ctype.s asminc/ctype_common.inc +__cwd libsrc/common/getcwd.s libsrc/common/_cwd.s libsrc/atari/initcwd.s libsrc/apple2/initcwd.s libsrc/apple2/initcwd.s libsrc/telestrat/initcwd.s libsrc/cbm/initcwd.s +__cwd_buf_size libsrc/common/_cwd.s +__envcount libsrc/common/searchenv.s libsrc/common/_environ.s libsrc/common/putenv.s libsrc/common/getenv.s +__environ libsrc/common/searchenv.s libsrc/common/_environ.s libsrc/common/putenv.s libsrc/common/getenv.s +__envsize libsrc/common/_environ.s libsrc/common/putenv.s +__fdesc libsrc/common/_fdesc.s libsrc/common/fopen.s +__filetab libsrc/common/_fdesc.s libsrc/common/_file.s asminc/_file.inc +__fopen libsrc/common/fopen.s libsrc/common/_fopen.s +__printf libsrc/common/vsnprintf.s libsrc/common/_printf.s libsrc/common/vfprintf.s libsrc/conio/vcprintf.s libsrc/pce/_printf.s +__scanf libsrc/common/_scanf.inc libsrc/common/vsscanf.s libsrc/conio/vcscanf.s +__sin libsrc/common/sincos.s +__sys libsrc/common/_sys.s libsrc/apple2/_sys.s +__sys_oserrlist libsrc/common/stroserr.s libsrc/geos-common/system/oserrlist.s libsrc/atari/oserrlist.s libsrc/apple2/oserrlist.s libsrc/cbm/oserrlist.s libsrc/atmos/oserrlist.s +__syschdir libsrc/common/chdir.s libsrc/atari/syschdir.s libsrc/apple2/syschdir.s libsrc/telestrat/syschdir.s libsrc/cbm/syschdir.s +__sysmkdir libsrc/common/mkdir.s libsrc/atari/sysmkdir.s libsrc/apple2/sysmkdir.s libsrc/telestrat/sysmkdir.s +__sysremove libsrc/common/remove.s libsrc/geos-common/file/sysremove.s libsrc/atari/sysremove.s libsrc/atari/sysrmdir.s libsrc/apple2/sysremove.s libsrc/apple2/sysrmdir.s libsrc/telestrat/sysremove.s libsrc/cbm/sysremove.s +__sysrename libsrc/common/rename.s libsrc/geos-common/file/sysrename.s libsrc/atari/sysrename.s libsrc/apple2/sysrename.s libsrc/cbm/sysrename.s +__sysrmdir libsrc/common/rmdir.s libsrc/atari/sysrmdir.s libsrc/apple2/sysrmdir.s +__sysuname libsrc/common/uname.s libsrc/cbm610/sysuname.s libsrc/cx16/sysuname.s libsrc/plus4/sysuname.s libsrc/lynx/sysuname.s libsrc/c16/sysuname.s libsrc/geos-common/system/sysuname.s libsrc/c128/sysuname.s libsrc/creativision/sysuname.s libsrc/vic20/sysuname.s libsrc/nes/sysuname.s libsrc/atari/sysuname.s libsrc/apple2/sysuname.s libsrc/cbm510/sysuname.s libsrc/telestrat/sysuname.s libsrc/c64/sysuname.s libsrc/pet/sysuname.s libsrc/atari5200/sysuname.s libsrc/atmos/sysuname.s + +apple2 + +__auxtype libsrc/apple2/open.s +__datetime libsrc/apple2/open.s +__dos_type libsrc/apple2/dioopen.s libsrc/apple2/curdevice.s libsrc/apple2/mainargs.s libsrc/apple2/settime.s libsrc/apple2/getdevice.s libsrc/apple2/dosdetect.s libsrc/apple2/irq.s libsrc/apple2/open.s libsrc/apple2/mli.s libsrc/apple2/getres.s +__filetype libsrc/apple2/open.s libsrc/apple2/exehdr.s + + +atari + +__defdev libsrc/atari/posixdirent.s libsrc/atari/ucase_fn.s libsrc/atari/getdefdev.s +__dos_type libsrc/atari/getargs.s libsrc/atari/exec.s libsrc/atari/settime.s libsrc/atari/syschdir.s libsrc/atari/dosdetect.s libsrc/atari/is_cmdline_dos.s libsrc/atari/sysrmdir.s libsrc/atari/gettime.s libsrc/atari/lseek.s libsrc/atari/getres.s libsrc/atari/getdefdev.s +__do_oserror libsrc/atari/posixdirent.s libsrc/atari/do_oserr.s libsrc/atari/serref.s libsrc/atari/read.s libsrc/atari/write.s libsrc/atari/close.s +__getcolor libsrc/atari/setcolor.s +__getdefdev libsrc/atari/getdefdev.s +__graphics libsrc/atari/graphics.s +__inviocb libsrc/atari/serref.s libsrc/atari/ser/atrrdev.s libsrc/atari/inviocb.s libsrc/atari/read.s libsrc/atari/write.s libsrc/atari/lseek.s libsrc/atari/close.s +__is_cmdline_dos libsrc/atari/is_cmdline_dos.s libsrc/atari/doesclrscr.s +__rest_vecs libsrc/atari/savevec.s +__rwsetup libsrc/atari/rwcommon.s libsrc/atari/read.s libsrc/atari/write.s +__save_vecs libsrc/atari/savevec.s +__scroll libsrc/atari/scroll.s +__setcolor libsrc/atari/setcolor.s +__setcolor_low libsrc/atari/setcolor.s +__sio_call libsrc/atari/diowritev.s libsrc/atari/diopncls.s libsrc/atari/siocall.s libsrc/atari/diowrite.s libsrc/atari/dioread.s + + +cbm + +__cbm_filetype libsrc/cbm/cbm_filetype.s asminc/cbm_filetype.in +__dirread libsrc/cbm/dir.inc libsrc/cbm/dir.s +__dirread1 libsrc/cbm/dir.inc libsrc/cbm/dir.s + + +lynx + +__iodat libsrc/lynx/lynx-cart.s libsrc/lynx/bootldr.s libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc +__iodir libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc +__sprsys libsrc/lynx/tgi/lynx-160-102-16.s libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc +__viddma libsrc/lynx/tgi/lynx-160-102-16.s libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc + + +pce + +__nmi libsrc/pce/irq.s libsrc/pce/crt0.s +``` ## Test suite From ec652367d0857217b270b59f7e9d225756c91edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChlstrasser?= <stephan.muehlstrasser@web.de> Date: Sun, 20 Nov 2022 13:28:45 +0100 Subject: [PATCH 133/360] Support targets without cursor keys Not all targets to have cursor keys on their keyboard. Add corresponding #ifdefs to the conio test program. --- targettest/conio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/targettest/conio.c b/targettest/conio.c index 49434595b..efe82d7c6 100644 --- a/targettest/conio.c +++ b/targettest/conio.c @@ -130,9 +130,11 @@ void main(void) case CH_ENTER: clrscr(); return; +#ifdef CH_CURS_LEFT case CH_CURS_LEFT: inpos = (inpos - 1) % 8; break; +#endif case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': (void)textcolor(i - '0'); @@ -164,7 +166,9 @@ void main(void) default: cputc(i); /* fallthrough */ +#ifdef CH_CURS_RIGHT case CH_CURS_RIGHT: +#endif inpos = (inpos + 1) % 8; } #endif From 484e1dc9fde4c8407f05ab7f5f6374a4b9c33cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChlstrasser?= <stephan.muehlstrasser@web.de> Date: Sun, 20 Nov 2022 13:30:57 +0100 Subject: [PATCH 134/360] Character defines for osic1p target Added character definitions for line graphics and enter character for osic1p target. --- include/osic1p.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/osic1p.h b/include/osic1p.h index d6ab5fee1..3a5b4723e 100644 --- a/include/osic1p.h +++ b/include/osic1p.h @@ -44,4 +44,22 @@ #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK +/* Colors are not functional, display is black and white only. */ +#define COLOR_BLACK 0x00 +#define COLOR_WHITE 0x01 + +#define CH_ULCORNER 0xCC +#define CH_URCORNER 0xCD +#define CH_LLCORNER 0xCB +#define CH_LRCORNER 0xCE +#define CH_TTEE 0xD9 +#define CH_BTEE 0xD7 +#define CH_LTEE 0xD8 +#define CH_RTEE 0xDA +#define CH_CROSS 0xDB +#define CH_HLINE 0x94 +#define CH_VLINE 0x95 + +#define CH_ENTER 0x0D + #endif From a46de2f6d447409878f6cb560e28cf6cec6e33df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChlstrasser?= <stephan.muehlstrasser@web.de> Date: Sun, 20 Nov 2022 15:22:37 +0100 Subject: [PATCH 135/360] Fix macro order --- include/osic1p.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/osic1p.h b/include/osic1p.h index 3a5b4723e..479d9fd52 100644 --- a/include/osic1p.h +++ b/include/osic1p.h @@ -36,14 +36,6 @@ # error "This module may only be used when compiling for the Challenger 1P!" #endif -/* The following #defines will cause the matching functions calls in conio.h -** to be overlaid by macros with the same names, saving the function call -** overhead. -*/ -#define _textcolor(color) COLOR_WHITE -#define _bgcolor(color) COLOR_BLACK -#define _bordercolor(color) COLOR_BLACK - /* Colors are not functional, display is black and white only. */ #define COLOR_BLACK 0x00 #define COLOR_WHITE 0x01 @@ -62,4 +54,13 @@ #define CH_ENTER 0x0D +/* The following #defines will cause the matching functions calls in conio.h +** to be overlaid by macros with the same names, saving the function call +** overhead. +*/ +#define _textcolor(color) COLOR_WHITE +#define _bgcolor(color) COLOR_BLACK +#define _bordercolor(color) COLOR_BLACK +#define _cpeekcolor(color) COLOR_WHITE + #endif From 05c2530243e2644ccd798e985ce71c705c75d7ef Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 28 Nov 2022 06:25:45 +0100 Subject: [PATCH 136/360] it should have been I64x, not I64u --- src/cc65/codegen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 251c973ee..480cc32ea 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -68,12 +68,12 @@ /* This is a terrible hack that tries to combat the ever reoccuring issue with Mingw and PRIXPTR - the macro should have been defined like this for us in the first place. - NOTE: "I64u" works in the github actions now, so if your local mingw64 fails, + NOTE: "I64x" works in the github actions now, so if your local mingw64 fails, you probably have to update. */ #if defined(__MINGW64__) #undef PRIXPTR -#define PRIXPTR "I64u" +#define PRIXPTR "I64x" #endif /*****************************************************************************/ From 15eb1c5f5edfe161bf083745bbf5f261aa8073d2 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 28 Nov 2022 06:26:14 +0100 Subject: [PATCH 137/360] support the msvc specific I64 specifier in our sprintf --- src/common/xsprintf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/xsprintf.c b/src/common/xsprintf.c index a3fbc676b..556e4f359 100644 --- a/src/common/xsprintf.c +++ b/src/common/xsprintf.c @@ -486,6 +486,18 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) } break; + /* support the MSVC specific I64 for long long */ + case 'I': + F = *Format++; + if (F == '6') { + F = *Format++; + if (F == '4') { + F = *Format++; + P.LengthMod = lmLongLong; + } + } + break; + case 'l': F = *Format++; if (F == 'l') { From 61ee5fe1d5ef9a9355f0f42dc20351514ec28da3 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 28 Nov 2022 06:26:47 +0100 Subject: [PATCH 138/360] test for bug #1933 --- test/val/bug1933.c | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test/val/bug1933.c diff --git a/test/val/bug1933.c b/test/val/bug1933.c new file mode 100644 index 000000000..9302f565a --- /dev/null +++ b/test/val/bug1933.c @@ -0,0 +1,9 @@ + +/* bug #1933 - wrong printf specifier breaks data lines */ + +unsigned char info_signature[3] = {3, 21, 63 | 0x80}; + +int main(void) +{ + return 0; +} \ No newline at end of file From bad961b36f16452dd81ee5ac6c8aca0ad15c9bc4 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 28 Nov 2022 06:34:05 +0100 Subject: [PATCH 139/360] add missing newline --- test/val/bug1933.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/val/bug1933.c b/test/val/bug1933.c index 9302f565a..4715f38fe 100644 --- a/test/val/bug1933.c +++ b/test/val/bug1933.c @@ -6,4 +6,4 @@ unsigned char info_signature[3] = {3, 21, 63 | 0x80}; int main(void) { return 0; -} \ No newline at end of file +} From dae4b2d9b0e9b45e5ff633592aecfc8eead30313 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Tue, 6 Dec 2022 14:47:03 +0100 Subject: [PATCH 140/360] add note on optimizer --- Contributing.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index 6fa5ba7c2..9fe0e0dee 100644 --- a/Contributing.md +++ b/Contributing.md @@ -181,7 +181,11 @@ The only exception to the above are actions that are exclusive to the github act * the printf family of function does not completely implement all printf modifiers and does not behave as expected in some cases - all this should be documented in detail -## Floating point support +## Compiler + +* We need a way that makes it possible to feed arbitrary assembler code into the optimzer, so we can have proper tests for it + +### Floating point support The first step is implementing the datatype "float" as IEEE488 floats. Help welcomed! From 78e6bcf6435809126fac2c702fdb51d16823d044 Mon Sep 17 00:00:00 2001 From: Irgendwer <C.Krueger.B@web.de> Date: Wed, 7 Dec 2022 00:20:20 +0100 Subject: [PATCH 141/360] Update Contributing.md --- Contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index 9fe0e0dee..74e6ead17 100644 --- a/Contributing.md +++ b/Contributing.md @@ -187,7 +187,7 @@ The only exception to the above are actions that are exclusive to the github act ### Floating point support -The first step is implementing the datatype "float" as IEEE488 floats. Help welcomed! +The first step is implementing the datatype "float" as IEEE 754 floats. Help welcomed! * WIP compiler/library changes are here: https://github.com/cc65/cc65/pull/1777 From ddab16007a23c0b489ac63b9d25dac67d5390229 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sun, 11 Dec 2022 12:08:30 +0100 Subject: [PATCH 142/360] run branch fixer again after replacing BRA by JMP. should fix #1936 --- src/cc65/codeopt.c | 4 ++ test/misc/bug1936.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 test/misc/bug1936.c diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 440b10751..208ada134 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -850,6 +850,10 @@ static unsigned RunOptGroup7 (CodeSeg* S) C += RunOptFunc (S, &DOptJumpCascades, 1); C += RunOptFunc (S, &DOptBranchDist2, 1); + /* Adjust branch distances again, since the previous step may change code + between branches */ + C += RunOptFunc (S, &DOptBranchDist, 3); + Changes += C; /* If we had changes, we must run dead code elimination again, ** since the changes may have introduced dead code. diff --git a/test/misc/bug1936.c b/test/misc/bug1936.c new file mode 100644 index 000000000..788313bd2 --- /dev/null +++ b/test/misc/bug1936.c @@ -0,0 +1,93 @@ + +/* bug #1936 - Compiler produces broken Assembly (129 operand for bne) */ + +#include <stdint.h> + +static uint8_t item_counter; + + +static uint8_t freeze; +static uint8_t powerUp; + +static uint8_t wall_appeared; +static uint8_t freeze_locked; +static uint8_t zombie_locked; + + +struct ItemStruct +{ + uint8_t _active; + void(*_effect)(void); +} ; +typedef struct ItemStruct Item; + +static Item freezeItem; +static Item powerUpItem; +static Item wallItem; +static Item zombieItem; + + +static Item extraPointsItem[1]; + + +uint8_t find_inactive(Item* itemArray) +{ +} + + +void drop_item(register Item *item, uint8_t max_counter) +{ +} + + +void handle_item_drop(void) +{ + { + if(item_counter==1) + { + if(!powerUpItem._active) + { + drop_item(&powerUpItem,35); + } + } + else if((!freeze_locked)&&(!freeze)) + { + if(!freezeItem._active) + { + drop_item(&freezeItem,45); + } + } + else if(!wall_appeared&&(powerUp>=9)) + { + if(!wallItem._active) + { + drop_item(&wallItem,35); + } + } + else if(!zombie_locked && !zombieItem._active) + { + drop_item(&zombieItem,50); + } + else + { + uint8_t index; + + index = find_inactive(extraPointsItem); + if(index!=1) // REMARK: compilation does not fail with 0 + { + drop_item(&extraPointsItem[index],90); + } + } + } +} + +int main(void) +{ + + while(1) // Game (re-)start + { + } + + return 0; +} + From 2b941e255a45ad30db26f0ce0fef3492ca5f0812 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sun, 11 Dec 2022 12:22:41 +0100 Subject: [PATCH 143/360] move test. oops --- test/{misc => val}/bug1936.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{misc => val}/bug1936.c (100%) diff --git a/test/misc/bug1936.c b/test/val/bug1936.c similarity index 100% rename from test/misc/bug1936.c rename to test/val/bug1936.c From d9ebfa7192b9d161ead58db45300ffd363233495 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sun, 11 Dec 2022 12:29:11 +0100 Subject: [PATCH 144/360] all good things are three --- test/val/bug1936.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/val/bug1936.c b/test/val/bug1936.c index 788313bd2..e97231797 100644 --- a/test/val/bug1936.c +++ b/test/val/bug1936.c @@ -83,11 +83,6 @@ void handle_item_drop(void) int main(void) { - - while(1) // Game (re-)start - { - } - return 0; } From d90c7e9853c43f6d2dbf241127006e5bb4fc3830 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt <ol.sc@web.de> Date: Thu, 22 Dec 2022 18:06:16 +0100 Subject: [PATCH 145/360] Introduced the notion of a standard serial driver. There's no target with more than one serial driver (and I don't see that change anytime soon) so it's a no-brainer to apply the standard driver concept to serial drivers. --- include/apple2.h | 2 +- include/apple2enh.h | 2 +- include/atari.h | 4 ++-- include/atmos.h | 2 +- include/c128.h | 2 +- include/c64.h | 2 +- include/cbm510.h | 2 +- include/cbm610.h | 2 +- include/lynx.h | 2 +- include/plus4.h | 2 +- include/serial.h | 7 +++++++ libsrc/apple2/ser_stat_stddrv.s | 22 ++++++++++++++++++++++ libsrc/apple2/ser_stddrv.s | 18 ++++++++++++++++++ libsrc/atari/ser_stat_stddrv.s | 22 ++++++++++++++++++++++ libsrc/atari/ser_stddrv.s | 18 ++++++++++++++++++ libsrc/atmos/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/atmos/ser_stddrv.s | 13 +++++++++++++ libsrc/c128/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/c128/ser_stddrv.s | 13 +++++++++++++ libsrc/c64/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/c64/ser_stddrv.s | 13 +++++++++++++ libsrc/cbm510/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/cbm510/ser_stddrv.s | 13 +++++++++++++ libsrc/cbm610/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/cbm610/ser_stddrv.s | 13 +++++++++++++ libsrc/lynx/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/plus4/ser_stat_stddrv.s | 14 ++++++++++++++ libsrc/plus4/ser_stddrv.s | 13 +++++++++++++ 28 files changed, 274 insertions(+), 11 deletions(-) create mode 100644 libsrc/apple2/ser_stat_stddrv.s create mode 100644 libsrc/apple2/ser_stddrv.s create mode 100644 libsrc/atari/ser_stat_stddrv.s create mode 100644 libsrc/atari/ser_stddrv.s create mode 100644 libsrc/atmos/ser_stat_stddrv.s create mode 100644 libsrc/atmos/ser_stddrv.s create mode 100644 libsrc/c128/ser_stat_stddrv.s create mode 100644 libsrc/c128/ser_stddrv.s create mode 100644 libsrc/c64/ser_stat_stddrv.s create mode 100644 libsrc/c64/ser_stddrv.s create mode 100644 libsrc/cbm510/ser_stat_stddrv.s create mode 100644 libsrc/cbm510/ser_stddrv.s create mode 100644 libsrc/cbm610/ser_stat_stddrv.s create mode 100644 libsrc/cbm610/ser_stddrv.s create mode 100644 libsrc/lynx/ser_stat_stddrv.s create mode 100644 libsrc/plus4/ser_stat_stddrv.s create mode 100644 libsrc/plus4/ser_stddrv.s diff --git a/include/apple2.h b/include/apple2.h index cb15cab97..9f644bc97 100644 --- a/include/apple2.h +++ b/include/apple2.h @@ -171,7 +171,7 @@ extern struct { extern void a2_auxmem_emd[]; extern void a2_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void a2_stdmou_mou[]; /* Referred to by mouse_static_stddrv[] */ -extern void a2_ssc_ser[]; +extern void a2_ssc_ser[]; /* Referred to by ser_static_stddrv[] */ extern void a2_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ extern void a2_lo_tgi[]; #endif diff --git a/include/apple2enh.h b/include/apple2enh.h index 58e0b397f..bfe5cdb18 100644 --- a/include/apple2enh.h +++ b/include/apple2enh.h @@ -99,7 +99,7 @@ extern void a2e_auxmem_emd[]; extern void a2e_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void a2e_stdmou_mou[]; /* Referred to by mouse_static_stddrv[] */ -extern void a2e_ssc_ser[]; +extern void a2e_ssc_ser[]; /* Referred to by ser_static_stddrv[] */ extern void a2e_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ extern void a2e_lo_tgi[]; diff --git a/include/atari.h b/include/atari.h index 781ee7a80..deae8fdf5 100644 --- a/include/atari.h +++ b/include/atari.h @@ -261,7 +261,7 @@ extern void atrst_mou[]; /* referred to by mouse_static_stddrv[] extern void atrami_mou[]; extern void atrtrk_mou[]; extern void atrtt_mou[]; -extern void atrrdev_ser[]; +extern void atrrdev_ser[]; /* referred to by ser_static_stddrv[] */ extern void atr3_tgi[]; extern void atr4_tgi[]; extern void atr5_tgi[]; @@ -286,7 +286,7 @@ extern void atrxst_mou[]; /* referred to by mouse_static_stddrv[] extern void atrxami_mou[]; extern void atrxtrk_mou[]; extern void atrxtt_mou[]; -extern void atrxrdev_ser[]; +extern void atrxrdev_ser[]; /* referred to by ser_static_stddrv[] */ extern void atrx3_tgi[]; extern void atrx4_tgi[]; extern void atrx5_tgi[]; diff --git a/include/atmos.h b/include/atmos.h index 227c387aa..38d423c46 100644 --- a/include/atmos.h +++ b/include/atmos.h @@ -133,7 +133,7 @@ /* The addresses of the static drivers */ extern void atmos_pase_joy[]; /* Referred to by joy_static_stddrv[] */ extern void atmos_ijk_joy[]; -extern void atmos_acia_ser[]; +extern void atmos_acia_ser[]; /* Referred to by ser_static_stddrv[] */ extern void atmos_228_200_3_tgi[]; extern void atmos_240_200_2_tgi[]; /* Referred to by tgi_static_stddrv[] */ diff --git a/include/c128.h b/include/c128.h index ee1dce99e..5a34904e0 100644 --- a/include/c128.h +++ b/include/c128.h @@ -140,7 +140,7 @@ extern void c128_1351_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void c128_joy_mou[]; extern void c128_inkwell_mou[]; extern void c128_pot_mou[]; -extern void c128_swlink_ser[]; +extern void c128_swlink_ser[]; /* Referred to by ser_static_stddrv[] */ extern void c128_hi_tgi[]; extern void c128_vdc_tgi[]; /* Referred to by tgi_static_stddrv[] */ extern void c128_vdc2_tgi[]; diff --git a/include/c64.h b/include/c64.h index 13d252dcb..ffac801ef 100644 --- a/include/c64.h +++ b/include/c64.h @@ -155,7 +155,7 @@ extern void c64_1351_mou[]; /* Referred to by mouse_static_stddrv[] extern void c64_joy_mou[]; extern void c64_inkwell_mou[]; extern void c64_pot_mou[]; -extern void c64_swlink_ser[]; +extern void c64_swlink_ser[]; /* Referred to by ser_static_stddrv[] */ extern void c64_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ diff --git a/include/cbm510.h b/include/cbm510.h index 20b334ed9..8ebbdf3c1 100644 --- a/include/cbm510.h +++ b/include/cbm510.h @@ -128,7 +128,7 @@ extern void cbm510_inkwl_mou[]; extern void cbm510_joy_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void cbm510_ram_emd[]; extern void cbm510_std_joy[]; /* Referred to by joy_static_stddrv[] */ -extern void cbm510_std_ser[]; +extern void cbm510_std_ser[]; /* Referred to by ser_static_stddrv[] */ diff --git a/include/cbm610.h b/include/cbm610.h index de7aa50f8..64beab9e6 100644 --- a/include/cbm610.h +++ b/include/cbm610.h @@ -105,7 +105,7 @@ /* The addresses of the static drivers */ extern void cbm610_ram_emd[]; -extern void cbm610_std_ser[]; +extern void cbm610_std_ser[]; /* Referred to by ser_static_stddrv[] */ diff --git a/include/lynx.h b/include/lynx.h index 1b4828a72..41dc5acb3 100644 --- a/include/lynx.h +++ b/include/lynx.h @@ -115,7 +115,7 @@ /* The addresses of the static drivers */ extern void lynx_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ -extern void lynx_comlynx_ser[]; +extern void lynx_comlynx_ser[]; /* Referred to by ser_static_stddrv[] */ extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */ diff --git a/include/plus4.h b/include/plus4.h index 325ba7d89..7730938e8 100644 --- a/include/plus4.h +++ b/include/plus4.h @@ -56,7 +56,7 @@ /* The addresses of the static drivers */ extern void plus4_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ -extern void plus4_stdser_ser[]; +extern void plus4_stdser_ser[]; /* Referred to by ser_static_stddrv[] */ diff --git a/include/serial.h b/include/serial.h index 35d7b8f66..0510cd219 100644 --- a/include/serial.h +++ b/include/serial.h @@ -123,6 +123,13 @@ struct ser_params { unsigned char handshake; /* Type of handshake to use */ }; +/* The name of the standard serial driver for a platform */ +extern const char ser_stddrv[]; + +/* The address of the static standard serial driver for a platform */ +extern const void ser_static_stddrv[]; + + /*****************************************************************************/ /* Code */ diff --git a/libsrc/apple2/ser_stat_stddrv.s b/libsrc/apple2/ser_stat_stddrv.s new file mode 100644 index 000000000..690fe4853 --- /dev/null +++ b/libsrc/apple2/ser_stat_stddrv.s @@ -0,0 +1,22 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .ifdef __APPLE2ENH__ + .import _a2e_ssc_ser + .else + .import _a2_ssc_ser + .endif + +.rodata + + .ifdef __APPLE2ENH__ +_ser_static_stddrv := _a2e_ssc_ser + .else +_ser_static_stddrv := _a2_ssc_ser + .endif diff --git a/libsrc/apple2/ser_stddrv.s b/libsrc/apple2/ser_stddrv.s new file mode 100644 index 000000000..2e8361865 --- /dev/null +++ b/libsrc/apple2/ser_stddrv.s @@ -0,0 +1,18 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: + .ifdef __APPLE2ENH__ + .asciiz "A2E.SSC.SER" + .else + .asciiz "A2.SSC.SER" + .endif diff --git a/libsrc/atari/ser_stat_stddrv.s b/libsrc/atari/ser_stat_stddrv.s new file mode 100644 index 000000000..b054f7f32 --- /dev/null +++ b/libsrc/atari/ser_stat_stddrv.s @@ -0,0 +1,22 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .ifdef __ATARIXL__ + .import _atrxrdev_ser + .else + .import _atrrdev_ser + .endif + +.rodata + + .ifdef __ATARIXL__ +_ser_static_stddrv := _atrxrdev_ser + .else +_ser_static_stddrv := _atrrdev_ser + .endif diff --git a/libsrc/atari/ser_stddrv.s b/libsrc/atari/ser_stddrv.s new file mode 100644 index 000000000..e6f4ccd48 --- /dev/null +++ b/libsrc/atari/ser_stddrv.s @@ -0,0 +1,18 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: + .ifdef __ATARIXL__ + .asciiz "atrxrdev.ser" + .else + .asciiz "atrrdev.ser" + .endif diff --git a/libsrc/atmos/ser_stat_stddrv.s b/libsrc/atmos/ser_stat_stddrv.s new file mode 100644 index 000000000..2b4373695 --- /dev/null +++ b/libsrc/atmos/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _atmos_acia_ser + +.rodata + +_ser_static_stddrv := _atmos_acia_ser diff --git a/libsrc/atmos/ser_stddrv.s b/libsrc/atmos/ser_stddrv.s new file mode 100644 index 000000000..71e33115a --- /dev/null +++ b/libsrc/atmos/ser_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: .asciiz "atmos-acia.ser" diff --git a/libsrc/c128/ser_stat_stddrv.s b/libsrc/c128/ser_stat_stddrv.s new file mode 100644 index 000000000..8b0732703 --- /dev/null +++ b/libsrc/c128/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _c128_swlink_ser + +.rodata + +_ser_static_stddrv := _c128_swlink_ser diff --git a/libsrc/c128/ser_stddrv.s b/libsrc/c128/ser_stddrv.s new file mode 100644 index 000000000..63f73cadd --- /dev/null +++ b/libsrc/c128/ser_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: .asciiz "c128_swlink.ser" diff --git a/libsrc/c64/ser_stat_stddrv.s b/libsrc/c64/ser_stat_stddrv.s new file mode 100644 index 000000000..327abbe5f --- /dev/null +++ b/libsrc/c64/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _c64_swlink_ser + +.rodata + +_ser_static_stddrv := _c64_swlink_ser diff --git a/libsrc/c64/ser_stddrv.s b/libsrc/c64/ser_stddrv.s new file mode 100644 index 000000000..5b00b7642 --- /dev/null +++ b/libsrc/c64/ser_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: .asciiz "c64_swlink.ser" diff --git a/libsrc/cbm510/ser_stat_stddrv.s b/libsrc/cbm510/ser_stat_stddrv.s new file mode 100644 index 000000000..a872f19b9 --- /dev/null +++ b/libsrc/cbm510/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _cbm510_std_ser + +.rodata + +_ser_static_stddrv := _cbm510_std_ser diff --git a/libsrc/cbm510/ser_stddrv.s b/libsrc/cbm510/ser_stddrv.s new file mode 100644 index 000000000..ed785f914 --- /dev/null +++ b/libsrc/cbm510/ser_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: .asciiz "cbm510-std.ser" diff --git a/libsrc/cbm610/ser_stat_stddrv.s b/libsrc/cbm610/ser_stat_stddrv.s new file mode 100644 index 000000000..643a74c7d --- /dev/null +++ b/libsrc/cbm610/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _cbm610_std_ser + +.rodata + +_ser_static_stddrv := _cbm610_std_ser diff --git a/libsrc/cbm610/ser_stddrv.s b/libsrc/cbm610/ser_stddrv.s new file mode 100644 index 000000000..83702c1ef --- /dev/null +++ b/libsrc/cbm610/ser_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: .asciiz "cbm610-std.ser" diff --git a/libsrc/lynx/ser_stat_stddrv.s b/libsrc/lynx/ser_stat_stddrv.s new file mode 100644 index 000000000..37f481c47 --- /dev/null +++ b/libsrc/lynx/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _lynx_comlynx_ser + +.rodata + +_ser_static_stddrv := _lynx_comlynx_ser diff --git a/libsrc/plus4/ser_stat_stddrv.s b/libsrc/plus4/ser_stat_stddrv.s new file mode 100644 index 000000000..f35b09232 --- /dev/null +++ b/libsrc/plus4/ser_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const void ser_static_stddrv[]; +; + + .export _ser_static_stddrv + .import _plus4_stdser_ser + +.rodata + +_ser_static_stddrv := _plus4_stdser_ser diff --git a/libsrc/plus4/ser_stddrv.s b/libsrc/plus4/ser_stddrv.s new file mode 100644 index 000000000..f308d5f40 --- /dev/null +++ b/libsrc/plus4/ser_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard serial driver +; +; Oliver Schmidt, 2022-12-22 +; +; const char ser_stddrv[]; +; + + .export _ser_stddrv + +.rodata + +_ser_stddrv: .asciiz "plus4-stdser.ser" From 1daa445310a5054a63e4985340f6760111e3e097 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt <ol.sc@web.de> Date: Thu, 22 Dec 2022 21:50:38 +0100 Subject: [PATCH 146/360] Fixed recently introduced addressing mode bug. --- libsrc/apple2/ser/a2.ssc.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/apple2/ser/a2.ssc.s b/libsrc/apple2/ser/a2.ssc.s index e0cd94597..d49bf3526 100644 --- a/libsrc/apple2/ser/a2.ssc.s +++ b/libsrc/apple2/ser/a2.ssc.s @@ -199,7 +199,7 @@ SER_OPEN: asl asl asl - adc Offset ; Assume carry to be clear + adc #Offset ; Assume carry to be clear tax ; Check if the handshake setting is valid From de30a57c0c9e6186049e2659f88ee395bad25b8b Mon Sep 17 00:00:00 2001 From: Oliver Schmidt <ol.sc@web.de> Date: Fri, 23 Dec 2022 15:24:28 +0100 Subject: [PATCH 147/360] Added minimalistic terminal program. So far there was no sample code at all making use of the serial drivers. --- samples/Makefile | 8 +++++ samples/terminal.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 samples/terminal.c diff --git a/samples/Makefile b/samples/Makefile index 2aa637844..114bbdf6a 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -171,6 +171,7 @@ EXELIST_apple2 = \ multdemo \ ovrldemo \ sieve \ + terminal \ tinyshell \ tgidemo @@ -186,6 +187,7 @@ EXELIST_atari = \ multdemo \ ovrldemo \ sieve \ + terminal \ tinyshell \ tgidemo @@ -203,6 +205,7 @@ EXELIST_atmos = \ hello \ mandelbrot \ sieve \ + terminal \ tgidemo EXELIST_bbc = \ @@ -219,6 +222,7 @@ EXELIST_c64 = \ multdemo \ ovrldemo \ sieve \ + terminal \ tinyshell \ tgidemo @@ -231,6 +235,7 @@ EXELIST_c128 = \ mandelbrot \ mousedemo \ sieve \ + terminal \ tinyshell \ tgidemo @@ -247,6 +252,7 @@ EXELIST_cbm510 = \ gunzip65 \ hello \ mousedemo \ + terminal \ tinyshell \ sieve @@ -255,6 +261,7 @@ EXELIST_cbm610 = \ checkversion \ gunzip65 \ hello \ + terminal \ tinyshell \ sieve @@ -314,6 +321,7 @@ EXELIST_plus4 = \ enumdevdir \ gunzip65 \ hello \ + terminal \ tinyshell \ sieve diff --git a/samples/terminal.c b/samples/terminal.c new file mode 100644 index 000000000..51973f7a3 --- /dev/null +++ b/samples/terminal.c @@ -0,0 +1,76 @@ +/* +** Minimalistic terminal program. +** +** Makes use of the serial drivers. +** +** 2022-12-23, Oliver Schmidt (ol.sc@web.de) +** +*/ + + + +#include <cc65.h> +#include <conio.h> +#include <stdio.h> +#include <stdlib.h> +#include <serial.h> + + +static void check (const char* msg, unsigned char err) +{ + if (err == SER_ERR_OK) { + return; + } + + printf ("%s:0x%02x\n", msg, err); + if (doesclrscrafterexit ()) { + cgetc (); + } + exit (1); +} + + +void main (void) +{ + const struct ser_params par = { + SER_BAUD_9600, + SER_BITS_8, + SER_STOP_1, + SER_PAR_NONE, + SER_HS_HW + }; + + check ("ser_install", ser_install (ser_static_stddrv)); + + check ("ser_open", ser_open (&par)); + + atexit ((void (*)) ser_close); + + printf ("Serial Port: 9600-8-1-N RTS/CTS\n" + "Simple Term: Press ESC for exit\n"); + + while (1) + { + char chr; + + if (kbhit ()) + { + chr = cgetc (); + + if (chr == CH_ESC) { + putchar ('\n'); + return; + } + + if (ser_put (chr) == SER_ERR_OK) { + putchar (chr); + } else { + putchar ('\a'); + } + } + + if (ser_get (&chr) == SER_ERR_OK) { + putchar (chr); + } + } +} From a8c6409689d91c35b647bc566b380c6766635cd9 Mon Sep 17 00:00:00 2001 From: Rutger van Bergen <rbergen@xs4all.nl> Date: Mon, 26 Dec 2022 19:54:00 +0100 Subject: [PATCH 148/360] Delete kimHello --- samples/kim1/kimHello | Bin 2789 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 samples/kim1/kimHello diff --git a/samples/kim1/kimHello b/samples/kim1/kimHello deleted file mode 100644 index 5842567557dc9f321409d269970f08832b736d86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2789 zcmbVOTWl2989p<!moqbGW`|^LuiKKGv;}Gss1s;#q)H_X&?OpGQAIB5O9zD|Yicfy zTZvX`id4^PyYa5P4=B(o(lGL@m@VsitJ2o0P$RXt9weHRms}Kq2*Qh942&^glRj+! zGd2QM>PwHj|K(i1^Ur@f{@6caBR^#e^evV4CFt9Pc8bVHbVBy0T$R2rJ0ktL?4Nib zo8J=YZ<8)^P!)bIYN9})f5+@!{>KkCxqxB*K%{?2S`KP<wmO;E>arRkDPJQrCHdD} z0@!q1Hct~T-8U=R>2Yzg!)n|iY!z*Y=9&Z-6I^_pQ(G)ZbVziBX1ZQ%rU7*b56R8W zzS-W9rvhdCYxE5<>*1Q5z-yyl4%@htlkG^!b8X~<mOOr*@3BrTk{gTU_!6=FC6{FO zFOm^q#(ZD)GPQ1C^niF{p0K4Gw+LIXz}^PY#xxBqZs^)riVI-(5T;$23X+G-@8E}& zBF;MTi8MMsO^U{1-cA=f=wFg{XQ7L;OrhIHC##t$_-kg$e<Ym#iFlnh_PT7Ddn;6f zHDPj!-D!2P`D2+}r`<UM?(3Vzw&Hb7%eER<!Zq}G!ijs`RaEpcoXDJDPE<~mDx#+e zeO;_G)s3H-CP&lfj3p~r!@z5tg2U*KMDtgYk6iWLIdabU92PdPcx8@+-NBO}TqmIs zP!MjAFd2M>$(5S~j+uJQr9m%C)In)>Rzec2U&e!Iy&9tvVtJlaZjs>yGJKl==tlO% zXy-%Q-io#@kV>@SXK-OY><E4wt_t>rI55LlFu+v5UA_}tI20RRB<@m$XfCNhAl?vz z*O?A!QC=cGD&HgK$#}2_4)wDQE^2_eqDvcKzUV$#xl8D8#8IhNJ$09aiQy$4dPkw( zl=z_otb=D4E^yChsu-eC#o(0SAX^8=PTeG7SGHipjkp+>v<0Hw1`NNKE{b^vuV5Tv znu{uT$PBp0Kg`wzgN$(7hz7RuOMb#sIwHcIJEJ=fgQ2gno@@ial?cm!4FLHT1GeOY z!%SYuxB&&ugE=eeD@s|{Dk-h8Y)Hr00-4jb#%*%)dP*BlRCH}PrS&!D$#q?;H*OI= z3-PV*Y?p7563}_lm?KQ0-4gw(1Y*cVz%Lsb_;HnHO=UC3a>z!Ia6;a4+Lw-ui%@Ig zkOU<cCjCxVH2(}`^Nx*uV#~l4;Hum7+qU7LnNVxusxrmyw&a$|!j{2qT9**(c(Hy) zB_r_{VPtwz^)raL$m#>rtWm_oNnsLM9_pKo!Oem-DMU)*zQWrOa$|I>LVuZn7Le%? z!UWJnm~h)AlO{pNp$>ErstQ_C2IlG~GW5Lci}Xqo&O<{IsGxu;$pD32=9iL}+H7^u zX5Ac5j#V=pCz8c#<{VdCbOL2z2H8-l$nMUYA0*3<Xg01qszJI4P23|e**7Ro)Xfi* zpvKrdWD#}|H&~`uWhcprOfMv9h~aKMKumGspgW5BNP@ngf)yFCBHiG?jYl=;000d3 zVCHcYzLy?V0Kf4&GB!@kTA~FGYY7&&3|b*-p)d|V$!Z}!D*>*P;ACapa#1FSvZb6* z&s&+D?S3H(nb42wp2(RkdQ!xtyanM{j&+s}CmhL>cq0*kl&UCStRl-ccnebss!a+S zJt%Vx8nZ>ej%(7W@t(q-^TfCu$86Q5BTRGDiQ8&bDH==WUvbG;?Qd{URcR?;zsmbC z4U@d`%(pQB_~2~nBi_H)ifg6yXN{5Aw9&#vHg|I3iVDpgfT0N4Cl1P2l~9^uOCG6d z7E8FOWU<eAh^_Em?;=-2(YP7$*^#Re{}kwY%hpTb#zG2AKQ=0d>mX%~9jU$gh?>da zx+muh+bHcd_U(naBAfN}TFNrF$OU;6*YpA&(j9C*FWWjl@4yFytL@Z|2d7hZs<bz? zkDt9(_jC)EBmj;k?(hj76I+I$+1UJBayYFunq=(v{3-NMO~~v|Yw!+5%?OeJf{XbI zchncuQ)vx?>I>$1-l@<i6yqekzYr8&Jiwrhqb#o>(MIr=3XX6;Y7of>)5}T24^F|l z#REB0Q0p@VWjUUc3X4su;S==xk5T8bo?iq>h60VneFaoFhFh3@+LGBvk?&8ZvrTj~ zod>kj9bD`H(c&56f^khH#8d2EOPyi2k6HY?_zEwPFiratJt9;w?x)ao*&IO5cuGx$ zbhY&;LUdG#9%~=jl4I0T;p03v)~}W7XLV1SPK{t&DoyM47A_Up6<f5T<?+~A9TG?9 ziE{%cp@OdRe>9>}Y<xz>E)&`trCnTRNqAu{5T<!Jv;P7Cv9$jpDPJT|ZdvGuFm;hQ zViT1=BmM>WMvyKOpFlOxSER-TGIo*tPY<r<-w8g89H@W;HBi8Lms+y9OO3qePp@=Q zbkaqk!u{~?mVA!geXlo+b8XSu_0vN+x|<I49{_e>4?Xl|Zg7xp|L(5s-+PK48p!P) z%xzQ@q-1jg0|)7=2j3jn^90wGUHRPyemKbG-lw10wD}v)Zs~jO`ES3lZTpT5&pf?( z%jUjK&u;ERNDzsv7+YU**j^a5Vv)0G$Y^<N;seB&UVeGam+ub|p{?7trB~e_0y?y^ z{r_eUKQBl?f`CNfzro%izb5Yz6QS}Xsr-YK&y&hONpYgxE`PMlJ|x4R5ZZ1#Z8l>e JbXnmD{{hxi-7)|G From 37954dffe78074b9d8c80ef8253fd3f8dcb83f56 Mon Sep 17 00:00:00 2001 From: Rutger van Bergen <rbergen@xs4all.nl> Date: Mon, 26 Dec 2022 20:26:29 +0100 Subject: [PATCH 149/360] Specify supported tests --- targettest/Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/targettest/Makefile b/targettest/Makefile index 7bcbc95f0..4d989d0df 100644 --- a/targettest/Makefile +++ b/targettest/Makefile @@ -693,6 +693,17 @@ EXELIST_bbc = \ EXELIST_lunix = \ notavailable +# omitted: arg-test clock-test clock cpeek-test conio cprintf cursor deb dir-test +# em-test exec-test1 exec-test2 fileio-test ft getopt-test heaptest joy-test +# mouse-test mul-test posixio-test rename-test scanf-test seek ser-test strdup-test +# stroserror-test uname-test +EXELIST_kim1 = \ + minimal \ + div-test \ + moddiv-test \ + strnlen \ + strqtok-test + # Unlisted targets will try to build everything. # That lets us learn what they cannot build, and what settings # we need to use for programs that can be built and run. From 817d129be8a076744a4d2d8d04e0d682f5d99fad Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Thu, 29 Dec 2022 19:18:00 +0200 Subject: [PATCH 150/360] Add support for 4 pixels per plane --- src/sp65/pcx.c | 171 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 141 insertions(+), 30 deletions(-) diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index d721671b3..489c65c5d 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -153,11 +153,12 @@ static PCXHeader* ReadPCXHeader (FILE* F, const char* Name) P->Compressed, Name); } /* We support: - ** - one plane with either 1 or 8 bits per pixel - ** - three planes with 8 bits per pixel - ** - four planes with 8 bits per pixel (does this exist?) - */ + * - one plane with either 1, 4 or 8 bits per pixel + * - three planes with 8 bits per pixel + * - four planes with 8 bits per pixel (does this exist?) + */ if (!((P->BPP == 1 && P->Planes == 1) || + (P->BPP == 4 && P->Planes == 1) || (P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) { /* We could support others, but currently we don't */ Error ("Unsupported PCX format: %u planes, %u bpp in PCX file '%s'", @@ -204,11 +205,14 @@ static void DumpPCXHeader (const PCXHeader* P, const char* Name) static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) /* Read one (possibly compressed) plane from the file */ { - if (P->Compressed) { + unsigned i; + if (P->Compressed) { /* Uncompress RLE data */ - unsigned Remaining = P->Width; - while (Remaining) { + signed Remaining = P->BytesPerPlane; + signed WidthCounter = P->Width; + + while (Remaining > 0) { unsigned char C; @@ -224,21 +228,111 @@ static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) } /* Write the data to the buffer */ - if (C > Remaining) { - C = Remaining; - } - memset (L, B, C); - - /* Bump counters */ - L += C; - Remaining -= C; - + switch (P->BPP) { + default: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = B; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + case 4: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = B >> 4; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = B & 15; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + case 2: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = (B >> 6) & 3; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 4) & 3; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 2) & 3; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = B & 3; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + case 1: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = (B >> 7) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 6) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 5) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 4) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 3) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 2) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 1) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = B & 1; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + } } } else { - /* Just read one line */ - ReadData (F, L, P->Width); - + if (P->BPP == 4) { + printf("Not implemented\n"); + } else { + ReadData (F, L, P->Width); + } } } @@ -309,25 +403,42 @@ Bitmap* ReadPCXFile (const Collection* A) } } else { - /* One plane with 8bpp is indexed */ - for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { + if (P->BPP == 4) { + /* One plane with 8bpp is indexed */ + for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { - /* Read the plane */ - ReadPlane (F, P, L); + /* Read the plane */ + ReadPlane (F, P, L); - /* Create pixels */ - for (X = 0; X < P->Width; ++X, ++Px) { - if (L[X] > MaxIdx) { - MaxIdx = L[X]; + /* Create pixels */ + for (X = 0; X < P->Width; ++X, ++Px) { + if (L[X] > MaxIdx) { + MaxIdx = L[X]; + } + Px->Index = L[X]; + } + } + } else { + /* One plane with 8bpp is indexed */ + for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { + + /* Read the plane */ + ReadPlane (F, P, L); + + /* Create pixels */ + for (X = 0; X < P->Width; ++X, ++Px) { + if (L[X] > MaxIdx) { + MaxIdx = L[X]; + } + Px->Index = L[X]; } - Px->Index = L[X]; } } } /* One plane means we have a palette which is either part of the header - ** or follows. - */ + * or follows. + */ if (P->PalInfo == 0) { /* Create the monochrome palette */ From e953c1aa082a154b991388650bef4a0e46bd76b0 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Thu, 29 Dec 2022 19:28:16 +0200 Subject: [PATCH 151/360] Add support for 4 pixels per plane --- src/sp65/pcx.c | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index 489c65c5d..4beda045c 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -230,109 +230,109 @@ static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) /* Write the data to the buffer */ switch (P->BPP) { default: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = B; + *L = B; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; case 4: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = B >> 4; + *L = B >> 4; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = B & 15; + *L = B & 15; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; case 2: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = (B >> 6) & 3; + *L = (B >> 6) & 3; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 4) & 3; + *L = (B >> 4) & 3; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 2) & 3; + *L = (B >> 2) & 3; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = B & 3; + *L = B & 3; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; case 1: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = (B >> 7) & 1; + *L = (B >> 7) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 6) & 1; + *L = (B >> 6) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 5) & 1; + *L = (B >> 5) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 4) & 1; + *L = (B >> 4) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 3) & 1; + *L = (B >> 3) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 2) & 1; + *L = (B >> 2) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 1) & 1; + *L = (B >> 1) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = B & 1; + *L = B & 1; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; - } + } } } else { /* Just read one line */ if (P->BPP == 4) { - printf("Not implemented\n"); - } else { + printf("Not implemented\n"); + } else { ReadData (F, L, P->Width); - } + } } } From 05766d4bfecddc4e4cd4d468c945ee142a5c163d Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Thu, 29 Dec 2022 19:40:00 +0200 Subject: [PATCH 152/360] Add support for 4 pixels per plane --- src/sp65/pcx.c | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index 4beda045c..519f3bd58 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -230,109 +230,109 @@ static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) /* Write the data to the buffer */ switch (P->BPP) { default: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = B; + *L = B; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; case 4: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = B >> 4; + *L = B >> 4; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = B & 15; + *L = B & 15; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; case 2: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = (B >> 6) & 3; + *L = (B >> 6) & 3; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 4) & 3; + *L = (B >> 4) & 3; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 2) & 3; + *L = (B >> 2) & 3; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = B & 3; + *L = B & 3; L += 1; WidthCounter -= 1; } Remaining -= 1; - } + } break; case 1: - for (i = 0; i < C; i++) { + for (i = 0; i < C; i++) { if (WidthCounter > 0) { - *L = (B >> 7) & 1; + *L = (B >> 7) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 6) & 1; + *L = (B >> 6) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 5) & 1; + *L = (B >> 5) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 4) & 1; + *L = (B >> 4) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 3) & 1; + *L = (B >> 3) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 2) & 1; + *L = (B >> 2) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = (B >> 1) & 1; + *L = (B >> 1) & 1; L += 1; WidthCounter -= 1; } if (WidthCounter > 0) { - *L = B & 1; + *L = B & 1; L += 1; WidthCounter -= 1; } Remaining -= 1; - } - break; } + break; + } } } else { /* Just read one line */ if (P->BPP == 4) { - printf("Not implemented\n"); - } else { + printf("Not implemented\n"); + } else { ReadData (F, L, P->Width); - } + } } } From 5ec5050af2cb6b9e51c3c5482aaf67be3f22c1d4 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Thu, 29 Dec 2022 21:48:28 +0200 Subject: [PATCH 153/360] Remove redundant code --- src/sp65/pcx.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index 519f3bd58..607253c59 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -403,35 +403,18 @@ Bitmap* ReadPCXFile (const Collection* A) } } else { - if (P->BPP == 4) { - /* One plane with 8bpp is indexed */ - for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { + /* One plane with 8bpp is indexed */ + for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { - /* Read the plane */ - ReadPlane (F, P, L); + /* Read the plane */ + ReadPlane (F, P, L); - /* Create pixels */ - for (X = 0; X < P->Width; ++X, ++Px) { - if (L[X] > MaxIdx) { - MaxIdx = L[X]; - } - Px->Index = L[X]; - } - } - } else { - /* One plane with 8bpp is indexed */ - for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { - - /* Read the plane */ - ReadPlane (F, P, L); - - /* Create pixels */ - for (X = 0; X < P->Width; ++X, ++Px) { - if (L[X] > MaxIdx) { - MaxIdx = L[X]; - } - Px->Index = L[X]; + /* Create pixels */ + for (X = 0; X < P->Width; ++X, ++Px) { + if (L[X] > MaxIdx) { + MaxIdx = L[X]; } + Px->Index = L[X]; } } } From 9cb06672602c8d563d021baa7cdc3f871f67668f Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Thu, 29 Dec 2022 21:53:50 +0200 Subject: [PATCH 154/360] Use same style in comments --- src/sp65/pcx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index 607253c59..18a60276d 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -153,10 +153,10 @@ static PCXHeader* ReadPCXHeader (FILE* F, const char* Name) P->Compressed, Name); } /* We support: - * - one plane with either 1, 4 or 8 bits per pixel - * - three planes with 8 bits per pixel - * - four planes with 8 bits per pixel (does this exist?) - */ + ** - one plane with either 1, 4 or 8 bits per pixel + ** - three planes with 8 bits per pixel + ** - four planes with 8 bits per pixel (does this exist?) + **/ if (!((P->BPP == 1 && P->Planes == 1) || (P->BPP == 4 && P->Planes == 1) || (P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) { @@ -420,8 +420,8 @@ Bitmap* ReadPCXFile (const Collection* A) } /* One plane means we have a palette which is either part of the header - * or follows. - */ + ** or follows. + **/ if (P->PalInfo == 0) { /* Create the monochrome palette */ From ebd13810307768b422626d91253018e515d8ba06 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Thu, 29 Dec 2022 21:55:25 +0200 Subject: [PATCH 155/360] Use same style in comments --- src/sp65/pcx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index 18a60276d..e6d99b30b 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -156,7 +156,7 @@ static PCXHeader* ReadPCXHeader (FILE* F, const char* Name) ** - one plane with either 1, 4 or 8 bits per pixel ** - three planes with 8 bits per pixel ** - four planes with 8 bits per pixel (does this exist?) - **/ + */ if (!((P->BPP == 1 && P->Planes == 1) || (P->BPP == 4 && P->Planes == 1) || (P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) { @@ -421,7 +421,7 @@ Bitmap* ReadPCXFile (const Collection* A) /* One plane means we have a palette which is either part of the header ** or follows. - **/ + */ if (P->PalInfo == 0) { /* Create the monochrome palette */ From aed6591b19262c10d13517f7049fad25d03c2d27 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 12:16:46 +0200 Subject: [PATCH 156/360] Add new method GetBitmapBPP as we need it for sprite math --- src/sp65/bitmap.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/sp65/bitmap.h b/src/sp65/bitmap.h index bf5e60559..e94ec71fd 100644 --- a/src/sp65/bitmap.h +++ b/src/sp65/bitmap.h @@ -75,6 +75,9 @@ struct Bitmap { unsigned Width; unsigned Height; + /* Bits per pixels */ + unsigned BPP; + /* Palette for indexed bitmap types, otherwise NULL */ Palette* Pal; @@ -179,6 +182,17 @@ INLINE unsigned GetBitmapColors (const Bitmap* B) # define GetBitmapColors(B) ((B)->Pal? (B)->Pal->Count : (1U << 24)) #endif +#if defined(HAVE_INLINE) +INLINE unsigned GetBitmapBPP (const Bitmap* B) +/* Get the bits per pixel of the converted sprite + */ +{ + return B->BPP; +} +#else +# define GetBitmapBPP(B) ((B)->BPP +#endif + /* End of bitmap.h */ From b4aa853e6fa15835a0f8cf862cd9639bc7e9dfb2 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 12:21:49 +0200 Subject: [PATCH 157/360] Add fixed Lynx sprite generation --- src/sp65/lynxsprite.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sp65/lynxsprite.h b/src/sp65/lynxsprite.h index fe686ec8e..e700b4f46 100644 --- a/src/sp65/lynxsprite.h +++ b/src/sp65/lynxsprite.h @@ -54,9 +54,9 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A); -/* Generate binary output in packed Lynx sprite format for the bitmap B. The output -** is stored in a string buffer (which is actually a dynamic char array) and -** returned. +/* Generate binary output in packed Lynx sprite format for the bitmap B. +** The output is stored in a string buffer (which is actually a dynamic +** char array) and returned. */ From f6b3bdda21f10b8078217a7679c9b36f441581ea Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 12:36:49 +0200 Subject: [PATCH 158/360] Add fixed Lynx sprite generation --- src/sp65/lynxsprite.c | 785 ++++++++++++++++++++++++++++-------------- 1 file changed, 529 insertions(+), 256 deletions(-) diff --git a/src/sp65/lynxsprite.c b/src/sp65/lynxsprite.c index 4d7669faf..dca42b061 100644 --- a/src/sp65/lynxsprite.c +++ b/src/sp65/lynxsprite.c @@ -88,12 +88,18 @@ static enum Mode GetMode (const Collection* A) } -static unsigned GetActionPointX (const Collection* A) +static unsigned GetActionPointX (const Bitmap* B, const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Check for a action point x attribute */ const char* ActionPointX = GetAttrVal (A, "ax"); if (ActionPointX) { + if (strcmp (ActionPointX, "mid") == 0) { + return GetBitmapWidth (B) / 2; + } + if (strcmp (ActionPointX, "max") == 0) { + return GetBitmapWidth (B) - 1; + } return atoi(ActionPointX); } else { return 0; @@ -101,12 +107,18 @@ static unsigned GetActionPointX (const Collection* A) } -static unsigned GetActionPointY (const Collection* A) +static unsigned GetActionPointY (const Bitmap* B, const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Check for a action point y attribute */ const char* ActionPointY = GetAttrVal (A, "ay"); if (ActionPointY) { + if (strcmp (ActionPointY, "mid") == 0) { + return GetBitmapHeight (B) / 2; + } + if (strcmp (ActionPointY, "max") == 0) { + return GetBitmapHeight (B) - 1; + } return atoi(ActionPointY); } else { return 0; @@ -125,6 +137,124 @@ static unsigned GetEdgeIndex (const Collection* A) } } +static unsigned GetQuadrant (const Collection* A) +/* Return the sprite mode from the attribute collection A */ +{ + /* Get index for edge color in shaped mode */ + const char* Quadrant = GetAttrVal (A, "quadrant"); + if (Quadrant) { + return atoi(Quadrant); + } else { + return 0; + } +} + +static void OptimizePenpal (const Bitmap* B, char *PenPal) +/* Create an optimal Penpal */ +{ + char usage[16]; + unsigned I, J, Val; + + memset(usage, 0, sizeof(usage)); + for (J = 0; J < GetBitmapHeight (B); J++) { + for (I = 0; I < GetBitmapWidth (B); I++) { + Val = GetPixel (B, I, J).Index; + if (Val < 16) { + usage[Val] = 1; + } + } + } + J = 0; + for (I = 0; I < 16; I++) { + if (usage[I]) { + switch (I) { + case 0: + PenPal[J] = '0'; + break; + case 1: + PenPal[J] = '1'; + break; + case 2: + PenPal[J] = '2'; + break; + case 3: + PenPal[J] = '3'; + break; + case 4: + PenPal[J] = '4'; + break; + case 5: + PenPal[J] = '5'; + break; + case 6: + PenPal[J] = '6'; + break; + case 7: + PenPal[J] = '7'; + break; + case 8: + PenPal[J] = '8'; + break; + case 9: + PenPal[J] = '9'; + break; + case 10: + PenPal[J] = 'a'; + break; + case 11: + PenPal[J] = 'b'; + break; + case 12: + PenPal[J] = 'c'; + break; + case 13: + PenPal[J] = 'd'; + break; + case 14: + PenPal[J] = 'e'; + break; + case 15: + PenPal[J] = 'f'; + break; + } + J++; + } + } + while (J < 16) { + PenPal[J] = 0; + J++; + } + /* printf("Penpal %s\n", PenPal); */ +} + +static unsigned GetPenpal (const Bitmap* B, const Collection* A, char *PenPal) +/* Return the penpal from the attribute collection A */ +{ + const char* Pen = GetAttrVal (A, "pen"); + if (Pen) { + if (strcmp (Pen, "opt") == 0) { + /* So we need to optimize the penpal and colour depth */ + OptimizePenpal (B, PenPal); + } else { + strncpy(PenPal, Pen, 17); + } + return 1; + } + return 0; +} + +static unsigned GetBPP (const Collection* A) +/* Return the sprite depth from the attribute collection A */ +{ + /* Get index for edge color in shaped mode */ + const char* BPP = GetAttrVal (A, "bpp"); + if (BPP) { + return atoi(BPP); + } else { + return 0; + } +} + static char OutBuffer[512]; /* The maximum size is 508 pixels */ static unsigned char OutIndex; @@ -140,26 +270,16 @@ static void AssembleByte(unsigned bits, char val) return; } /* handle end of line */ - if (bits == 8) { + if (bits == 7) { if (bit_counter != 8) { byte <<= bit_counter; OutBuffer[OutIndex++] = byte; if (!OutIndex) { Error ("Sprite is too large for the Lynx"); } - if (byte & 0x1) { - OutBuffer[OutIndex++] = byte; - if (!OutIndex) { - Error ("Sprite is too large for the Lynx"); - } - } - } - return; - } - /* handle end of line for literal */ - if (bits == 7) { - if (bit_counter != 8) { - byte <<= bit_counter; + } else { + /* Add pad byte */ + byte = 0; OutBuffer[OutIndex++] = byte; if (!OutIndex) { Error ("Sprite is too large for the Lynx"); @@ -189,28 +309,78 @@ static void AssembleByte(unsigned bits, char val) } while (--bits); } -static unsigned char ChoosePackagingMode(signed len, signed index, char ColorBits, char LineBuffer[512]) +static unsigned char AnalyseNextChunks(signed *newlen, signed len, char data[32], char ColorBits) { - --len; - if (!len) { - return 0; + char longest = 1; + char prev = 255; + char count = 0; + char index = 0; + char lindex = 0; + int i; + int literal_cost; + int packed_cost; + + for (i = 0; i < len; i++) { + index = index + 1; + if (data[i] == prev) { + count = count + 1; + if (count >= longest) { + longest = count; + lindex = index - count; + } + } else { + prev = data[i]; + count = 1; + } } - if (LineBuffer[index] != LineBuffer[index + 1]) { - return 0; + if (longest == 1) { + if (len > 16) { + *newlen = 16; + } else { + *newlen = len; + } + return 'L'; } - if (ColorBits > 2) { - return 1; + if ((lindex > 0) && (lindex + longest > 15)) { + /* We cannot pack the stride in this packet */ + *newlen = lindex; + return 'A'; } - if (LineBuffer[index] != LineBuffer[index + 2]) { - return 0; + /* Cost till end of area */ + literal_cost = 5 + lindex * ColorBits + longest * ColorBits; + packed_cost = 5 + lindex * ColorBits + 5 + ColorBits; + if (packed_cost < literal_cost) { + if (lindex == 0) { + /* Use packed data */ + if (longest > 16) { + *newlen = 16; + } else { + *newlen = longest; + } + return 'P'; + } + /* We had a good find, but it was not at the start of the line */ + *newlen = lindex; + return 'A'; } - if (ColorBits > 1) { - return 1; + /* There is no point in packing - use literal */ + if (len > 16) { + *newlen = 16; + } else { + *newlen = len; } - if (LineBuffer[index] != LineBuffer[index + 3]) { - return 0; + return 'L'; +} + +static unsigned char GetNextChunk(signed *newlen, signed len, char data[32], char ColorBits) +{ + char oper = 'A'; + + while (oper == 'A') { + oper = AnalyseNextChunks(newlen, len, data, ColorBits); + len = *newlen; } - return 1; + return oper; /* The packet type is now P or L and the length is in newlen */ } static void WriteOutBuffer(StrBuf *D) @@ -235,27 +405,25 @@ static void WriteOutBuffer(StrBuf *D) static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, char LineBuffer[512], int len, int LastOpaquePixel) { /* -** The data starts with a byte count. It tells the number of bytes on this -** line + 1. -** Special case is a count of 1. It will change to next quadrant. -** Other special case is 0. It will end the sprite. -** -** Ordinary data packet. These are bits in a stream. -** 1=literal 0=packed -** 4 bit count (+1) -** for literal you put "count" values -** for packed you repeat the value "count" times -** Never use packed mode for one pixel -** If the last bit on a line is 1 you need to add a byte of zeroes -** A sequence 00000 ends a scan line -** -** All data is high nybble first -*/ + * The data starts with a byte count. It tells the number of bytes on this + * line + 1. + * Special case is a count of 1. It will change to next quadrant. + * Other special case is 0. It will end the sprite. + * + * Ordinary data packet. These are bits in a stream. + * 1=literal 0=packed + * 4 bit count (+1) + * for literal you put "count" values + * for packed you repeat the value "count" times + * Never use packed mode for one pixel + * If the last bit on a line is in use you need to add a byte of zeroes + * A sequence 00000 ends a scan line + * + * All data is high nybble first + */ unsigned char V = 0; signed i; signed count; - unsigned char differ[16]; - unsigned char *d_ptr; AssembleByte(0, 0); switch (M) { @@ -270,100 +438,46 @@ static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, WriteOutBuffer(D); break; case smPacked: + case smShaped: + if (M == smShaped) { + if (LastOpaquePixel > -1) { + if (LastOpaquePixel < len - 1) { + len = LastOpaquePixel + 1; + } + } else { + len = 0; + } + } i = 0; while (len) { - if (ChoosePackagingMode(len, i, ColorBits, LineBuffer)) { + signed analyselen; + analyselen = len; + if (analyselen > 32) { + analyselen = 32; + } + if (GetNextChunk(&count, analyselen, LineBuffer + i, ColorBits) == 'P') { /* Make runlength packet */ V = LineBuffer[i]; - ++i; - --len; - count = 0; - do { - ++count; - ++i; - --len; - } while (V == LineBuffer[i] && len && count != 15); - - AssembleByte(5, count); - AssembleByte(ColorBits, V); + i += count; + len -= count; + AssembleByte(5, count-1); + AssembleByte(ColorBits, V & ColorMask); } else { /* Make packed literal packet */ - d_ptr = differ; - V = LineBuffer[i++]; - *d_ptr++ = V; - --len; - count = 0; - while (ChoosePackagingMode(len, i, ColorBits, LineBuffer) == 0 && len && count != 15) { - V = LineBuffer[i++]; - *d_ptr++ = V; - ++count; - --len; - } - - AssembleByte(5, count | 0x10); - d_ptr = differ; + AssembleByte(5, (count-1) | 0x10); do { - AssembleByte(ColorBits, *d_ptr++); - } while (--count >= 0); - + AssembleByte(ColorBits, LineBuffer[i]); + i++; + len--; + } while (--count > 0); } } - AssembleByte(8, 0); + /* Force EOL for shaped? AssembleByte(5, 0); */ + AssembleByte(7, 0); /* Write the buffer to file */ WriteOutBuffer(D); break; - - case smShaped: - if (LastOpaquePixel > -1) { - if (LastOpaquePixel < len - 1) { - len = LastOpaquePixel + 1; - } - i = 0; - while (len) { - if (ChoosePackagingMode(len, i, ColorBits, LineBuffer)) { - /* Make runlength packet */ - V = LineBuffer[i]; - ++i; - --len; - count = 0; - do { - ++count; - ++i; - --len; - } while (V == LineBuffer[i] && len && count != 15); - - AssembleByte(5, count); - AssembleByte(ColorBits, V); - - } else { - /* Make packed literal packet */ - d_ptr = differ; - V = LineBuffer[i++]; - *d_ptr++ = V; - --len; - count = 0; - while (ChoosePackagingMode(len, i, ColorBits, LineBuffer) == 0 && len && count != 15) { - V = LineBuffer[i++]; - *d_ptr++ = V; - ++count; - --len; - } - - AssembleByte(5, count | 0x10); - d_ptr = differ; - do { - AssembleByte(ColorBits, *d_ptr++); - } while (--count >= 0); - - } - } - AssembleByte(5, 0); - AssembleByte(8, 0); - /* Write the buffer to file */ - WriteOutBuffer(D); - } - break; } } @@ -373,10 +487,10 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) ** returned. ** ** The Lynx will draw 4 quadrants: -** - Down right -** - Up right -** - Up left -** - Down left +** 0 - Down right +** 1 - Up right +** 2 - Up left +** 3 - Down left ** ** The sprite will end with a byte 0. */ @@ -388,13 +502,24 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) char ColorBits; char ColorMask; char EdgeIndex; + char Quadrant; + char quad; + char BPP; + /* The default mapping is 1:1 plus extra colours become 0 */ + char Map[17] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; + signed PenColors; + char PenPal[18]; + signed Val; /* Get EdgeIndex */ EdgeIndex = GetEdgeIndex (A); + /* Get Quadrant for starting the draw process */ + Quadrant = GetQuadrant (A) & 3; + /* Action point of the sprite */ - OX = GetActionPointX (A); - OY = GetActionPointY (A); + OX = GetActionPointX (B, A); + OY = GetActionPointY (B, A); if (OX >= GetBitmapWidth (B)) { Error ("Action point X cannot be larger than bitmap width"); } @@ -410,145 +535,293 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) /* Get the sprite mode */ M = GetMode (A); - /* Now check if bitmap indexes are ok */ - if (GetBitmapColors (B) > 16) { - Error ("Too many colors for a Lynx sprite"); + /* Now check how to do the mapping */ + if (GetPenpal (B, A, &PenPal[0])) { + signed I; + + /* Modify the map by content of PenPal */ + PenColors = strlen(PenPal); + for (I = 0; I < PenColors; I++) { + switch (PenPal[I]) { + case '0': + Map[0] = I; + break; + case '1': + Map[1] = I; + break; + case '2': + Map[2] = I; + break; + case '3': + Map[3] = I; + break; + case '4': + Map[4] = I; + break; + case '5': + Map[5] = I; + break; + case '6': + Map[6] = I; + break; + case '7': + Map[7] = I; + break; + case '8': + Map[8] = I; + break; + case '9': + Map[9] = I; + break; + case 'a': + case 'A': + Map[10] = I; + break; + case 'b': + case 'B': + Map[11] = I; + break; + case 'c': + case 'C': + Map[12] = I; + break; + case 'd': + case 'D': + Map[13] = I; + break; + case 'e': + case 'E': + Map[14] = I; + break; + case 'f': + case 'F': + Map[15] = I; + break; + /* The X is reserved as transparency. This allows for shaped sprites */ + case 'x': + case 'X': + Map[16] = I; + break; + } + } + } else { + PenColors = GetBitmapColors (B); } ColorBits = 4; - ColorMask = 0x0f; - if (GetBitmapColors (B) < 9) { + if (PenColors < 9) { ColorBits = 3; - ColorMask = 0x07; } - if (GetBitmapColors (B) < 5) { + if (PenColors < 5) { ColorBits = 2; - ColorMask = 0x03; } - if (GetBitmapColors (B) < 3) { + if (PenColors < 3) { ColorBits = 1; - ColorMask = 0x01; } + BPP = GetBPP (A); + if (BPP > 0) { + ColorBits = BPP; + } + switch (ColorBits) { + case 1: + ColorMask = 0x01; + break; + case 2: + ColorMask = 0x03; + break; + case 3: + ColorMask = 0x07; + break; + default: + case 4: + ColorMask = 0x0f; + break; + } + /* B->BPP = ColorBits; */ /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, 63); - /* Convert the image for quadrant bottom right */ - for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ + for (quad = 0; quad < 4; quad++) { + switch ((Quadrant + quad) & 3) { + case 0: + /* Convert the image for quadrant bottom right */ + for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ - /* Fill the LineBuffer for easier optimisation */ - for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { + /* Fill the LineBuffer for easier optimisation */ + for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; + LineBuffer[i] = Map[Val] & ColorMask; - /* Fetch next bit into byte buffer */ - LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } - if (LineBuffer[i] != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + if ((OY == 0) && (OX == 0)) { + /* Trivial case only one quadrant */ - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OY == 0)) { + /* Special case only two quadrants */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + break; + case 1: + /* Convert the image for quadrant top right */ + for (Y = OY - 1; Y >= 0; --Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ + + /* Fill the LineBuffer for easier optimisation */ + for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; + + LineBuffer[i] = Map[Val] & ColorMask; + + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } + + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + + if ((OY == GetBitmapHeight (B) - 1) && (OX == 0)) { + /* Trivial case only one quadrant */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OX == 0)) { + /* Special case only two quadrants */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + break; + case 2: + /* Convert the image for quadrant top left */ + for (Y = OY - 1; Y >= 0; --Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ + + /* Fill the LineBuffer for easier optimisation */ + for (X = OX - 1; X >= 0; --X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; + + LineBuffer[i] = Map[Val] & ColorMask; + + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } + + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + if ((OY == GetBitmapHeight (B) - 1) && (OX == GetBitmapWidth (B) - 1)) { + /* Trivial case only one quadrant */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OY == GetBitmapHeight (B) - 1)) { + /* Special case only two quadrants */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + break; + case 3: + /* Convert the image for quadrant bottom left */ + for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ + + /* Fill the LineBuffer for easier optimisation */ + for (X = OX - 1; X >= 0; --X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; + + LineBuffer[i] = Map[Val] & ColorMask; + + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } + + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + if ((OY == 0) && (OX == GetBitmapWidth (B) - 1)) { + /* Trivial case only one quadrant */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OX == GetBitmapWidth (B) - 1)) { + /* Special case only two quadrants */ + + /* Mark end of sprite */ + SB_AppendChar (D, 0); + + /* Return the converted bitmap */ + return D; + } + break; + } + if (quad < 3) { + /* Next quadrant */ + SB_AppendChar (D, 1); + } else { + /* End sprite */ + SB_AppendChar (D, 0); + } } - if ((OY == 0) && (OX == 0)) { - /* Trivial case only one quadrant */ - - /* Mark end of sprite */ - SB_AppendChar (D, 0); - - /* Return the converted bitmap */ - return D; - } - - /* Next quadrant */ - SB_AppendChar (D, 1); - - /* Convert the image for quadrant top right */ - for (Y = OY - 1; Y >= 0; --Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ - - /* Fill the LineBuffer for easier optimisation */ - for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { - - /* Fetch next bit into byte buffer */ - LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; - - if (LineBuffer[i] != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } - - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } - - if (OX == 0) { - /* Special case only two quadrants */ - - /* Mark end of sprite */ - SB_AppendChar (D, 0); - - /* Return the converted bitmap */ - return D; - } - - /* Next quadrant */ - SB_AppendChar (D, 1); - - /* Convert the image for quadrant top left */ - for (Y = OY - 1; Y >= 0; --Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ - - /* Fill the LineBuffer for easier optimisation */ - for (X = OX - 1; X >= 0; --X) { - - /* Fetch next bit into byte buffer */ - LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; - - if (LineBuffer[i] != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } - - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } - - /* Next quadrant */ - SB_AppendChar (D, 1); - - /* Convert the image for quadrant bottom left */ - for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ - - /* Fill the LineBuffer for easier optimisation */ - for (X = OX - 1; X >= 0; --X) { - - /* Fetch next bit into byte buffer */ - LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; - - if (LineBuffer[i] != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } - - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } - - /* End sprite */ - SB_AppendChar (D, 0); - /* Return the converted bitmap */ return D; } From c2e9e5961d898e6f0237d40e70853e16d3deac4c Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 12:57:50 +0200 Subject: [PATCH 159/360] Add fixed Lynx sprite generation --- src/sp65/lynxsprite.c | 458 +++++++++++++++++++++--------------------- 1 file changed, 229 insertions(+), 229 deletions(-) diff --git a/src/sp65/lynxsprite.c b/src/sp65/lynxsprite.c index dca42b061..566edacbe 100644 --- a/src/sp65/lynxsprite.c +++ b/src/sp65/lynxsprite.c @@ -96,10 +96,10 @@ static unsigned GetActionPointX (const Bitmap* B, const Collection* A) if (ActionPointX) { if (strcmp (ActionPointX, "mid") == 0) { return GetBitmapWidth (B) / 2; - } + } if (strcmp (ActionPointX, "max") == 0) { return GetBitmapWidth (B) - 1; - } + } return atoi(ActionPointX); } else { return 0; @@ -115,10 +115,10 @@ static unsigned GetActionPointY (const Bitmap* B, const Collection* A) if (ActionPointY) { if (strcmp (ActionPointY, "mid") == 0) { return GetBitmapHeight (B) / 2; - } + } if (strcmp (ActionPointY, "max") == 0) { return GetBitmapHeight (B) - 1; - } + } return atoi(ActionPointY); } else { return 0; @@ -235,10 +235,10 @@ static unsigned GetPenpal (const Bitmap* B, const Collection* A, char *PenPal) if (strcmp (Pen, "opt") == 0) { /* So we need to optimize the penpal and colour depth */ OptimizePenpal (B, PenPal); - } else { - strncpy(PenPal, Pen, 17); + } else { + strncpy(PenPal, Pen, 17); } - return 1; + return 1; } return 0; } @@ -322,52 +322,52 @@ static unsigned char AnalyseNextChunks(signed *newlen, signed len, char data[32] for (i = 0; i < len; i++) { index = index + 1; - if (data[i] == prev) { + if (data[i] == prev) { count = count + 1; - if (count >= longest) { + if (count >= longest) { longest = count; - lindex = index - count; - } - } else { - prev = data[i]; - count = 1; - } + lindex = index - count; + } + } else { + prev = data[i]; + count = 1; + } } if (longest == 1) { - if (len > 16) { - *newlen = 16; - } else { - *newlen = len; - } - return 'L'; + if (len > 16) { + *newlen = 16; + } else { + *newlen = len; + } + return 'L'; } if ((lindex > 0) && (lindex + longest > 15)) { /* We cannot pack the stride in this packet */ *newlen = lindex; - return 'A'; + return 'A'; } /* Cost till end of area */ literal_cost = 5 + lindex * ColorBits + longest * ColorBits; packed_cost = 5 + lindex * ColorBits + 5 + ColorBits; if (packed_cost < literal_cost) { if (lindex == 0) { - /* Use packed data */ - if (longest > 16) { - *newlen = 16; - } else { - *newlen = longest; + /* Use packed data */ + if (longest > 16) { + *newlen = 16; + } else { + *newlen = longest; } - return 'P'; - } - /* We had a good find, but it was not at the start of the line */ - *newlen = lindex; - return 'A'; + return 'P'; + } + /* We had a good find, but it was not at the start of the line */ + *newlen = lindex; + return 'A'; } /* There is no point in packing - use literal */ if (len > 16) { - *newlen = 16; + *newlen = 16; } else { - *newlen = len; + *newlen = len; } return 'L'; } @@ -378,7 +378,7 @@ static unsigned char GetNextChunk(signed *newlen, signed len, char data[32], cha while (oper == 'A') { oper = AnalyseNextChunks(newlen, len, data, ColorBits); - len = *newlen; + len = *newlen; } return oper; /* The packet type is now P or L and the length is in newlen */ } @@ -439,27 +439,27 @@ static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, break; case smPacked: case smShaped: - if (M == smShaped) { + if (M == smShaped) { if (LastOpaquePixel > -1) { if (LastOpaquePixel < len - 1) { len = LastOpaquePixel + 1; - } + } } else { len = 0; } } i = 0; while (len) { - signed analyselen; - analyselen = len; - if (analyselen > 32) { + signed analyselen; + analyselen = len; + if (analyselen > 32) { analyselen = 32; - } + } if (GetNextChunk(&count, analyselen, LineBuffer + i, ColorBits) == 'P') { /* Make runlength packet */ V = LineBuffer[i]; - i += count; - len -= count; + i += count; + len -= count; AssembleByte(5, count-1); AssembleByte(ColorBits, V & ColorMask); @@ -468,8 +468,8 @@ static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, AssembleByte(5, (count-1) | 0x10); do { AssembleByte(ColorBits, LineBuffer[i]); - i++; - len--; + i++; + len--; } while (--count > 0); } } @@ -537,75 +537,75 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) /* Now check how to do the mapping */ if (GetPenpal (B, A, &PenPal[0])) { - signed I; + signed I; - /* Modify the map by content of PenPal */ - PenColors = strlen(PenPal); - for (I = 0; I < PenColors; I++) { - switch (PenPal[I]) { + /* Modify the map by content of PenPal */ + PenColors = strlen(PenPal); + for (I = 0; I < PenColors; I++) { + switch (PenPal[I]) { case '0': - Map[0] = I; - break; + Map[0] = I; + break; case '1': - Map[1] = I; - break; + Map[1] = I; + break; case '2': - Map[2] = I; - break; + Map[2] = I; + break; case '3': - Map[3] = I; - break; + Map[3] = I; + break; case '4': - Map[4] = I; - break; + Map[4] = I; + break; case '5': - Map[5] = I; - break; + Map[5] = I; + break; case '6': - Map[6] = I; - break; + Map[6] = I; + break; case '7': - Map[7] = I; - break; + Map[7] = I; + break; case '8': - Map[8] = I; - break; + Map[8] = I; + break; case '9': - Map[9] = I; - break; + Map[9] = I; + break; case 'a': case 'A': - Map[10] = I; - break; + Map[10] = I; + break; case 'b': case 'B': - Map[11] = I; - break; + Map[11] = I; + break; case 'c': case 'C': - Map[12] = I; - break; + Map[12] = I; + break; case 'd': case 'D': - Map[13] = I; - break; + Map[13] = I; + break; case 'e': case 'E': - Map[14] = I; - break; + Map[14] = I; + break; case 'f': case 'F': - Map[15] = I; - break; - /* The X is reserved as transparency. This allows for shaped sprites */ + Map[15] = I; + break; + /* The X is reserved as transparency. This allows for shaped sprites */ case 'x': case 'X': - Map[16] = I; - break; - } - } + Map[16] = I; + break; + } + } } else { - PenColors = GetBitmapColors (B); + PenColors = GetBitmapColors (B); } ColorBits = 4; if (PenColors < 9) { @@ -643,183 +643,183 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) SB_Realloc (D, 63); for (quad = 0; quad < 4; quad++) { - switch ((Quadrant + quad) & 3) { - case 0: - /* Convert the image for quadrant bottom right */ - for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ + switch ((Quadrant + quad) & 3) { + case 0: + /* Convert the image for quadrant bottom right */ + for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ - /* Fill the LineBuffer for easier optimisation */ - for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { - /* Fetch next bit into byte buffer */ - Val = GetPixel (B, X, Y).Index; - if (Val > 16) Val = 16; - LineBuffer[i] = Map[Val] & ColorMask; + /* Fill the LineBuffer for easier optimisation */ + for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; + LineBuffer[i] = Map[Val] & ColorMask; - if (Val != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } - if ((OY == 0) && (OX == 0)) { - /* Trivial case only one quadrant */ + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + if ((OY == 0) && (OX == 0)) { + /* Trivial case only one quadrant */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - if ((quad == 1) && (OY == 0)) { - /* Special case only two quadrants */ + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OY == 0)) { + /* Special case only two quadrants */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - break; - case 1: - /* Convert the image for quadrant top right */ - for (Y = OY - 1; Y >= 0; --Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ + /* Return the converted bitmap */ + return D; + } + break; + case 1: + /* Convert the image for quadrant top right */ + for (Y = OY - 1; Y >= 0; --Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ - /* Fill the LineBuffer for easier optimisation */ - for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { - /* Fetch next bit into byte buffer */ - Val = GetPixel (B, X, Y).Index; - if (Val > 16) Val = 16; + /* Fill the LineBuffer for easier optimisation */ + for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; - LineBuffer[i] = Map[Val] & ColorMask; + LineBuffer[i] = Map[Val] & ColorMask; - if (Val != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } - if ((OY == GetBitmapHeight (B) - 1) && (OX == 0)) { - /* Trivial case only one quadrant */ + if ((OY == GetBitmapHeight (B) - 1) && (OX == 0)) { + /* Trivial case only one quadrant */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - if ((quad == 1) && (OX == 0)) { - /* Special case only two quadrants */ + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OX == 0)) { + /* Special case only two quadrants */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - break; - case 2: - /* Convert the image for quadrant top left */ - for (Y = OY - 1; Y >= 0; --Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ + /* Return the converted bitmap */ + return D; + } + break; + case 2: + /* Convert the image for quadrant top left */ + for (Y = OY - 1; Y >= 0; --Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ - /* Fill the LineBuffer for easier optimisation */ - for (X = OX - 1; X >= 0; --X) { - /* Fetch next bit into byte buffer */ - Val = GetPixel (B, X, Y).Index; - if (Val > 16) Val = 16; + /* Fill the LineBuffer for easier optimisation */ + for (X = OX - 1; X >= 0; --X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; - LineBuffer[i] = Map[Val] & ColorMask; + LineBuffer[i] = Map[Val] & ColorMask; - if (Val != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } - if ((OY == GetBitmapHeight (B) - 1) && (OX == GetBitmapWidth (B) - 1)) { - /* Trivial case only one quadrant */ + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + if ((OY == GetBitmapHeight (B) - 1) && (OX == GetBitmapWidth (B) - 1)) { + /* Trivial case only one quadrant */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - if ((quad == 1) && (OY == GetBitmapHeight (B) - 1)) { - /* Special case only two quadrants */ + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OY == GetBitmapHeight (B) - 1)) { + /* Special case only two quadrants */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - break; - case 3: - /* Convert the image for quadrant bottom left */ - for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { - signed i = 0; - signed LastOpaquePixel = -1; - char LineBuffer[512]; /* The maximum size is 508 pixels */ + /* Return the converted bitmap */ + return D; + } + break; + case 3: + /* Convert the image for quadrant bottom left */ + for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { + signed i = 0; + signed LastOpaquePixel = -1; + char LineBuffer[512]; /* The maximum size is 508 pixels */ - /* Fill the LineBuffer for easier optimisation */ - for (X = OX - 1; X >= 0; --X) { - /* Fetch next bit into byte buffer */ - Val = GetPixel (B, X, Y).Index; - if (Val > 16) Val = 16; + /* Fill the LineBuffer for easier optimisation */ + for (X = OX - 1; X >= 0; --X) { + /* Fetch next bit into byte buffer */ + Val = GetPixel (B, X, Y).Index; + if (Val > 16) Val = 16; - LineBuffer[i] = Map[Val] & ColorMask; + LineBuffer[i] = Map[Val] & ColorMask; - if (Val != EdgeIndex) { - LastOpaquePixel = i; - } - ++i; - } + if (Val != EdgeIndex) { + LastOpaquePixel = i; + } + ++i; + } - encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); - } - if ((OY == 0) && (OX == GetBitmapWidth (B) - 1)) { - /* Trivial case only one quadrant */ + encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); + } + if ((OY == 0) && (OX == GetBitmapWidth (B) - 1)) { + /* Trivial case only one quadrant */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - if ((quad == 1) && (OX == GetBitmapWidth (B) - 1)) { - /* Special case only two quadrants */ + /* Return the converted bitmap */ + return D; + } + if ((quad == 1) && (OX == GetBitmapWidth (B) - 1)) { + /* Special case only two quadrants */ - /* Mark end of sprite */ - SB_AppendChar (D, 0); + /* Mark end of sprite */ + SB_AppendChar (D, 0); - /* Return the converted bitmap */ - return D; - } - break; - } - if (quad < 3) { + /* Return the converted bitmap */ + return D; + } + break; + } + if (quad < 3) { /* Next quadrant */ SB_AppendChar (D, 1); - } else { + } else { /* End sprite */ SB_AppendChar (D, 0); - } + } } /* Return the converted bitmap */ From 4117e94ed59e9a8c47f05eddad27bd746fba6d42 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 14:44:18 +0200 Subject: [PATCH 160/360] Add palette extraction functions --- src/sp65/lynxpalette.c | 90 +++++++++++++++++++++++++++++++++++ src/sp65/lynxpalette.h | 66 ++++++++++++++++++++++++++ src/sp65/main.c | 64 +++++++++++++++++++++++-- src/sp65/palconv.c | 104 +++++++++++++++++++++++++++++++++++++++++ src/sp65/palconv.h | 72 ++++++++++++++++++++++++++++ 5 files changed, 391 insertions(+), 5 deletions(-) create mode 100644 src/sp65/lynxpalette.c create mode 100644 src/sp65/lynxpalette.h create mode 100644 src/sp65/palconv.c create mode 100644 src/sp65/palconv.h diff --git a/src/sp65/lynxpalette.c b/src/sp65/lynxpalette.c new file mode 100644 index 000000000..e822fa5ee --- /dev/null +++ b/src/sp65/lynxpalette.c @@ -0,0 +1,90 @@ +/*****************************************************************************/ +/* */ +/* lynxpalette.c */ +/* */ +/* Lynx palette backend for the sp65 sprite and bitmap utility */ +/* */ +/* */ +/* */ +/* (C) 2022, Karri Kaksonen */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#include <stdlib.h> + +/* common */ +#include "attrib.h" +#include "print.h" + +/* sp65 */ +#include "attr.h" +#include "error.h" +#include "palette.h" +#include "lynxpalette.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + +StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A) +/* Generate binary output in Lynx palette format for the bitmap B. The output +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +** +*/ +{ + StrBuf* D; + Palette* P; + unsigned I; + + P = GetBitmapPalette (B); + D = NewStrBuf (); + for (I = 0; I < 16; ++I) { + + /* Get the color entry */ + const Color* C = P->Entries + I; + + /* Add the green component */ + SB_AppendChar (D, C->G >> 4); + } + for (I = 0; I < 16; ++I) { + + /* Get the color entry */ + const Color* C = P->Entries + I; + + /* Add the blue,red component */ + SB_AppendChar (D, (C->B & 0xF0) | (C->R >> 4)); + } + + /* Return the converted palette */ + return D; +} + diff --git a/src/sp65/lynxpalette.h b/src/sp65/lynxpalette.h new file mode 100644 index 000000000..3ba4526fb --- /dev/null +++ b/src/sp65/lynxpalette.h @@ -0,0 +1,66 @@ +/*****************************************************************************/ +/* */ +/* lynxpalette.h */ +/* */ +/* Lynx palette format backend for the sp65 sprite and bitmap utility */ +/* */ +/* */ +/* */ +/* (C) 2022, Karri Kaksonen */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef LYNXPALETTE_H +#define LYNXPALETTE_H + + + +/* common */ +#include "coll.h" +#include "strbuf.h" + +/* sp65 */ +#include "bitmap.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A); +/* Generate binary output in Lynx palette format for the bitmap B. The output + * is stored in a string buffer (which is actually a dynamic char array) and + * returned. + */ + + + +/* End of lynxpalette.h */ + +#endif + + + diff --git a/src/sp65/main.c b/src/sp65/main.c index 1dda696d6..62dec0952 100644 --- a/src/sp65/main.c +++ b/src/sp65/main.c @@ -1,6 +1,6 @@ /*****************************************************************************/ /* */ -/* main.c */ +/* main.c */ /* */ /* Main program of the sp65 sprite and bitmap utility */ /* */ @@ -47,6 +47,7 @@ /* sp65 */ #include "attr.h" #include "convert.h" +#include "palconv.h" #include "error.h" #include "input.h" #include "output.h" @@ -68,10 +69,13 @@ static Bitmap* C; /* Output data from convertion */ static StrBuf* D; +/* Output data from palconv */ +static StrBuf* E; + /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -88,11 +92,11 @@ static void Usage (void) " -lc\t\t\t\tList all possible conversions\n" " -r file[,attrlist]\t\tRead an input file\n" " -v\t\t\t\tIncrease verbosity\n" + " -p tgt,file[,attrlist]\t\tWrite the palette to a file\n" " -w file[,attrlist]\t\tWrite the output to a file\n" "\n" "Long options:\n" " --convert-to fmt[,attrlist]\tConvert into target format\n" - " --dump-palette\t\tDump palette as table\n" " --help\t\t\tHelp (this text)\n" " --list-conversions\t\tList all possible conversions\n" " --pop\t\t\t\tRestore the original loaded image\n" @@ -100,6 +104,7 @@ static void Usage (void) " --slice x,y,w,h\t\tGenerate a slice from the loaded bitmap\n" " --verbose\t\t\tIncrease verbosity\n" " --version\t\t\tPrint the version number and exit\n" + " --palette tgt,file[,attrlist]\tWrite the palette to a file\n" " --write file[,attrlist]\tWrite the output to a file\n", ProgName); } @@ -137,6 +142,21 @@ static void SetOutputData (StrBuf* N) } +static void SetPalOutputData (StrBuf* N) +/* Delete the old output data and replace it by the given one. The new one +** may be NULL to clear it. +*/ +{ + /* Delete the old output data */ + if (E != 0) { + FreeStrBuf (E); + } + + /* Set the new one */ + E = N; +} + + static void OptConvertTo (const char* Opt attribute ((unused)), const char* Arg) /* Convert the bitmap into a target format */ @@ -282,15 +302,45 @@ static void OptVerbose (const char* Opt attribute ((unused)), static void OptVersion (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); - exit(EXIT_SUCCESS); } +static void OptPalette (const char* Opt attribute ((unused)), const char* Arg) +/* Write an output file */ +{ + static const char* const NameList[] = { + "target", "name", "format" + }; + + + /* Parse the argument */ + Collection* A = ParseAttrList (Arg, NameList, 2); + + /* We must have a bitmap ... */ + if (C == 0) { + Error ("No bitmap"); + } + + /* ... which must be indexed */ + if (!BitmapIsIndexed (C)) { + Error ("Current bitmap is not indexed"); + } + + /* Convert the palette */ + SetPalOutputData (PaletteTo (C, A)); + + /* Write the file */ + WriteOutputFile (E, A, C); + + /* Delete the attribute list */ + FreeAttrList (A); +} + static void OptWrite (const char* Opt attribute ((unused)), const char* Arg) /* Write an output file */ { @@ -381,6 +431,10 @@ int main (int argc, char* argv []) OptVerbose (Arg, 0); break; + case 'p': + OptPalette (Arg, GetArg (&I, 2)); + break; + case 'w': OptWrite (Arg, GetArg (&I, 2)); break; diff --git a/src/sp65/palconv.c b/src/sp65/palconv.c new file mode 100644 index 000000000..e92f3c22e --- /dev/null +++ b/src/sp65/palconv.c @@ -0,0 +1,104 @@ +/*****************************************************************************/ +/* */ +/* palconv.c */ +/* */ +/* Color palette conversions for the sp65 sprite and bitmap utility */ +/* */ +/* */ +/* */ +/* (C) 2022, Karri Kaksonen */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#include <string.h> +#include <stdlib.h> + +/* common */ +#include "check.h" +#include "xmalloc.h" + +/* sp65 */ +#include "attr.h" +#include "error.h" +#include "palette.h" +#include "lynxpalette.h" + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + +/* Type of the entry in the palette table */ +typedef struct PaletteMapEntry PaletteMapEntry; +struct PaletteMapEntry { + const char* Format; + StrBuf* (*PaletteFunc) (const Bitmap*, const Collection*); +}; + +/* Converter table, alphabetically sorted */ +static const PaletteMapEntry PaletteMap[] = { + { "lynx-palette", GenLynxPalette }, +}; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + +static int Compare (const void* Key, const void* MapEntry) +/* Compare function for bsearch */ +{ + return strcmp (Key, ((const PaletteMapEntry*) MapEntry)->Format); +} + + + +StrBuf* PaletteTo (const Bitmap* B, const Collection* A) +/* Convert the palette of bitmap B into some sort of other binary format. +** The output is stored in a string buffer (which is actually a dynamic +** char array) and returned. The actual output format is taken from the +** "format" attribute in the attribute collection A. +*/ +{ + const PaletteMapEntry* E; + + /* Get the format to convert to */ + const char* Format = NeedAttrVal (A, "target", "palette"); + + /* Search for the matching converter */ + E = bsearch (Format, + PaletteMap, + sizeof (PaletteMap) / sizeof (PaletteMap[0]), + sizeof (PaletteMap[0]), + Compare); + if (E == 0) { + Error ("No such target format: '%s'", Format); + } + + /* Do the conversion */ + return E->PaletteFunc (B, A); +} + diff --git a/src/sp65/palconv.h b/src/sp65/palconv.h new file mode 100644 index 000000000..693281c20 --- /dev/null +++ b/src/sp65/palconv.h @@ -0,0 +1,72 @@ +/*****************************************************************************/ +/* */ +/* palconv.h */ +/* */ +/* Color palette conversions for the sp65 sprite and bitmap utility */ +/* */ +/* */ +/* */ +/* (C) 2022, Karri Kaksonen */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef PALCONV_H +#define PALCONV_H + + + +#include <stdio.h> + +/* common */ +#include "coll.h" +#include "strbuf.h" + +/* sp65 */ +#include "bitmap.h" + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + +StrBuf* PaletteTo (const Bitmap* B, const Collection* A); +/* Convert the palette of bitmap B into some sort of other binary format. +** The output is stored in a string buffer (which is actually a dynamic char +** array) and returned. The actual output format is taken from the "target" +** attribute in the attribute collection A. +*/ + +void ListPaletteTargets (FILE* F); +/* Output a list of palette targets */ + +/* End of palette.h */ + +#endif + + + From f85951ab2497dec2bac535ae569382b20e89d9fe Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 15:06:22 +0200 Subject: [PATCH 161/360] Add to build --- src/sp65.vcxproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sp65.vcxproj b/src/sp65.vcxproj index 1b7a18427..a9f0919a3 100644 --- a/src/sp65.vcxproj +++ b/src/sp65.vcxproj @@ -62,9 +62,11 @@ <ClCompile Include="sp65\geosicon.c" /> <ClCompile Include="sp65\input.c" /> <ClCompile Include="sp65\koala.c" /> + <ClCompile Include="sp65\lynxpalette.c" /> <ClCompile Include="sp65\lynxsprite.c" /> <ClCompile Include="sp65\main.c" /> <ClCompile Include="sp65\output.c" /> + <ClCompile Include="sp65\palconv.c" /> <ClCompile Include="sp65\palette.c" /> <ClCompile Include="sp65\pcx.c" /> <ClCompile Include="sp65\raw.c" /> @@ -84,8 +86,10 @@ <ClInclude Include="sp65\geosicon.h" /> <ClInclude Include="sp65\input.h" /> <ClInclude Include="sp65\koala.h" /> + <ClInclude Include="sp65\lynxpalette.h" /> <ClInclude Include="sp65\lynxsprite.h" /> <ClInclude Include="sp65\output.h" /> + <ClInclude Include="sp65\palconv.h" /> <ClInclude Include="sp65\palette.h" /> <ClInclude Include="sp65\pcx.h" /> <ClInclude Include="sp65\pixel.h" /> @@ -95,4 +99,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> From b6d06288e0e918dbad2b724caca5a2b0a4ba1e83 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 15:20:54 +0200 Subject: [PATCH 162/360] Fix warnings --- src/sp65/lynxpalette.c | 7 +++++-- src/sp65/lynxpalette.h | 9 +++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sp65/lynxpalette.c b/src/sp65/lynxpalette.c index e822fa5ee..b084af26e 100644 --- a/src/sp65/lynxpalette.c +++ b/src/sp65/lynxpalette.c @@ -62,10 +62,13 @@ StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A) */ { StrBuf* D; - Palette* P; + const Palette* P = GetBitmapPalette (B); + const char* Format = GetAttrVal(A, "format"); unsigned I; - P = GetBitmapPalette (B); + if (Format == 0) { + /* No format specified */ + } D = NewStrBuf (); for (I = 0; I < 16; ++I) { diff --git a/src/sp65/lynxpalette.h b/src/sp65/lynxpalette.h index 3ba4526fb..805db0d74 100644 --- a/src/sp65/lynxpalette.h +++ b/src/sp65/lynxpalette.h @@ -52,15 +52,12 @@ StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A); /* Generate binary output in Lynx palette format for the bitmap B. The output - * is stored in a string buffer (which is actually a dynamic char array) and - * returned. - */ +** is stored in a string buffer (which is actually a dynamic char array) and +** returned. +*/ /* End of lynxpalette.h */ #endif - - - From 878a20ab59b8ba5104220dc4bcc08927816ae6d4 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Fri, 30 Dec 2022 15:27:17 +0200 Subject: [PATCH 163/360] Fix dangling space --- src/sp65/lynxpalette.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sp65/lynxpalette.h b/src/sp65/lynxpalette.h index 805db0d74..b4e3defe3 100644 --- a/src/sp65/lynxpalette.h +++ b/src/sp65/lynxpalette.h @@ -51,7 +51,7 @@ StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A); -/* Generate binary output in Lynx palette format for the bitmap B. The output +/* Generate binary output in Lynx palette format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. */ From 56a414593aad29ddc2f2cff1ffc9205d297db79c Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <cand@gmx.com> Date: Tue, 8 Nov 2022 19:04:46 +0200 Subject: [PATCH 164/360] Teach da65 about table units --- doc/da65.sgml | 5 +++++ src/da65/attrtab.h | 5 ++++- src/da65/data.c | 2 +- src/da65/infofile.c | 32 ++++++++++++++++++++++++++++++++ src/da65/scanner.h | 1 + 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/doc/da65.sgml b/doc/da65.sgml index aa6ad40bf..3a01ce4f5 100644 --- a/doc/da65.sgml +++ b/doc/da65.sgml @@ -522,6 +522,11 @@ following attributes are recognized: </descrip> + <tag><tt>UNIT</tt></tag> + Split the table into sections of this size. For example, if you have a + ByteTable of size 48, but it has logical groups of size 16, specifying + 16 for UNIT adds newlines after every 16 bytes. UNIT is always in bytes. + <tag><tt>ADDRMODE</tt></tag> When disassembling 65816 code, this specifies the M and X flag states for this range. It's a string argument of the form "mx", capital letters diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index 37143c0d1..4a0ea8225 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -71,6 +71,9 @@ typedef enum attr_t { atSegmentEnd = 0x0200, /* Segment end */ atSegmentStart = 0x0400, /* Segment start */ + /* Table unit separator */ + atTableUnit = 0x0800, + /* 65816 addressing mode */ atMem8 = 0x1000, /* M flag enabled, 8-bit */ atMem16 = 0x2000, /* M flag disabled, 16-bit */ @@ -79,7 +82,7 @@ typedef enum attr_t { atStyleMask = 0x000F, /* Output style */ atLabelMask = 0x00F0, /* Label information */ - atSegmentMask = 0x0F00, /* Segment information */ + atSegmentMask = 0x0700, /* Segment information */ at65816Mask = 0xF000, /* 65816 information */ } attr_t; diff --git a/src/da65/data.c b/src/da65/data.c index 7355e60d1..f85cd327d 100644 --- a/src/da65/data.c +++ b/src/da65/data.c @@ -70,7 +70,7 @@ static unsigned GetSpan (attr_t Style) if ((Attr & atStyleMask) != Style) { break; } - if ((Attr & (atSegmentStart | atSegmentEnd))) { + if ((Attr & (atSegmentStart | atSegmentEnd | atTableUnit))) { break; } ++Count; diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 923cc53c9..fbf367cc9 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -528,6 +528,7 @@ static void RangeSection (void) { "START", INFOTOK_START }, { "TYPE", INFOTOK_TYPE }, { "ADDRMODE", INFOTOK_ADDRMODE }, + { "UNIT", INFOTOK_UNIT }, }; static const IdentTok TypeDefs[] = { @@ -552,6 +553,7 @@ static void RangeSection (void) tName = 0x08, tComment = 0x10, tAddrMode = 0x20, + tUnit = 0x40, tNeeded = (tStart | tEnd | tType) }; unsigned Attributes = tNone; @@ -564,6 +566,7 @@ static void RangeSection (void) char* Name = 0; char* Comment = 0; unsigned MemberSize = 0; + unsigned Unit = 0; /* Skip the token */ @@ -682,6 +685,15 @@ static void RangeSection (void) InfoNextTok (); break; + case INFOTOK_UNIT: + AddAttr ("UNIT", &Attributes, tUnit); + InfoNextTok (); + InfoAssureInt (); + InfoRangeCheck (0x0002, 0xFFFF); + Unit = InfoIVal; + InfoNextTok (); + break; + default: Internal ("Unexpected token: %u", InfoTok); } @@ -705,6 +717,26 @@ static void RangeSection (void) } } + /* Only tables support unit sizes */ + if ((Attributes & tUnit) && + Type != atAddrTab && + Type != atByteTab && + Type != atDByteTab && + Type != atDWordTab && + Type != atRtsTab && + Type != atTextTab && + Type != atWordTab) { + InfoError ("Only table types support unit size"); + } + + /* Mark each unit separator */ + if (Attributes & tUnit) { + unsigned i; + for (i = Start; i < End; i += Unit) { + MarkAddr(i, atTableUnit); + } + } + /* Start must be less than end */ if (Start > End) { InfoError ("Start value must not be greater than end value"); diff --git a/src/da65/scanner.h b/src/da65/scanner.h index 60648a40c..ce76d4a98 100644 --- a/src/da65/scanner.h +++ b/src/da65/scanner.h @@ -91,6 +91,7 @@ typedef enum token_t { INFOTOK_END, INFOTOK_TYPE, INFOTOK_ADDRMODE, + INFOTOK_UNIT, INFOTOK_CODE, INFOTOK_BYTETAB, From e2c6d06b0d5be4f77deb3994c601f362ae1326f1 Mon Sep 17 00:00:00 2001 From: karri <karri@sipo.fi> Date: Wed, 4 Jan 2023 12:14:37 +0200 Subject: [PATCH 165/360] Update dosc --- doc/sp65.sgml | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/doc/sp65.sgml b/doc/sp65.sgml index 255d7a552..e1bcdd558 100644 --- a/doc/sp65.sgml +++ b/doc/sp65.sgml @@ -44,6 +44,7 @@ Short options: -lc List all possible conversions -r file[,attrlist] Read an input file -v Increase verbosity + -p tgt,file[,attrlist] Write the palette to a file -w file[,attrlist] Write the output to a file Long options: @@ -56,6 +57,7 @@ Long options: --slice x,y,w,h Generate a slice from the loaded bitmap --verbose Increase verbosity --version Print the version number and exit + --palette tgt,file{,attrlist] Write the palette to a file --write file[,attrlist] Write the output to a file --------------------------------------------------------------------------- </verb></tscreen> @@ -124,6 +126,13 @@ attribute lists see <ref id="attr-lists" name="below">. bugfixes, please include the version number. + <label id="option--palette"> + <tag><tt>-p, --palette target,filename[,attrlist]</tt></tag> + + Write the palette of the input bitmap to a file in a format suitable of + the target. + + <label id="option--write"> <tag><tt>-w, --write filename[,attrlist]</tt></tag> @@ -265,6 +274,7 @@ of a sprite is roughly 508 pixels but in reality the Lynx screen is only 160 by 102 pixels which makes very large sprites useless. The number per pixels is taken from the number of colors of the input bitmap. +You can also force the number of pens used in the conversion. There are a few attributes that you can give to the conversion software. @@ -273,7 +283,7 @@ There are a few attributes that you can give to the conversion software. <tag/mode/ The first is what kind of encoding to use for the sprite. The attribute for this is called "mode" and the possible values are "literal", "packed" or - "transparent". The default is "packed" if no mode is specified. + "shaped". The default is "packed" if no mode is specified. The "literal" is a totally literal mode with no packing. In this mode the number of pixels per scanline will be a multiple of 8 both right and left from @@ -290,10 +300,26 @@ There are a few attributes that you can give to the conversion software. using run-length encoding and literal coding mixed for optimisation to produce a small sprite. - The last encoding mode "transparent" is like packed. But here we know that - the index 0 will be transparent so we can clip off all 0 pixels from the left - and right edge of the sprite. This will produce the smallest sprite possible - on the Lynx. The sprite is not rectangular anymore. + The last encoding mode "shaped" is like packed. But we can stop the conversion + to the right abd left edge when we get the first "edge" colour. If no edge + colour is specified we stop at the first index 0 colour. + If your edge index is outside the range 0..15 then your sprite can use all + the colours in the defined palette. + This will also produce the smallest sprite possible on the Lynx. The sprite + is not rectangular anymore. + + <tag/edge/ + This keyword is only meaningful for shaped sprites. By default it is 0. + The shaped sprite outer edge is defined by the colour index "edge". + + <tag/pen/ + This keyword defines the order the colours in the original bitmap is + mapped to the Lynx sprite. The length of the pen also defines the depth + of the generated sprite. + If you want to create a 1 BPP sprite you can define the two indices used + in the sprite like pen=34. Now areas in colour index 3 will be mapped as 0. + Areas in colour index 4 will be mapped as 1. + The default pen=0123456789abcdef. <tag/ax/ The sprite is painted around the Anchor point. The anchor point x can be @@ -301,7 +327,9 @@ There are a few attributes that you can give to the conversion software. painting the sprite in location 10,20 will set the left edge of the sprite 10 pixels from the left of the Lynx screen. When the sprite is scaled by hardware the anchor point stays in place and the sprite grows or shrinks - around the anchor point. The default value is 0 (left). + around the anchor point. You can also define the location using the words + "mid" for the center or "max" for the right edge. + The default value is 0 (left). <tag/ay/ The sprite is painted around the Anchor point. The anchor point y can be @@ -309,7 +337,8 @@ There are a few attributes that you can give to the conversion software. painting the sprite in location 10,20 will set the top of the sprite 20 pixels from the top of the Lynx screen. When the sprite is scaled by hardware the anchor point stays in place and the sprite grows or shrinks - around the anchor point. The default value is 0 (top). + around the anchor point. You can also define the location using the words + "mid" for the center or "max" for the bottom. The default value is 0 (top). </descrip> From 7ea2d8ab180ba38ba05952862034acc5aaccf109 Mon Sep 17 00:00:00 2001 From: Rutger van Bergen <rbergen@xs4all.nl> Date: Wed, 4 Jan 2023 19:05:08 +0100 Subject: [PATCH 166/360] Address review comment --- include/kim1.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/kim1.h b/include/kim1.h index bb616f7a0..dae246944 100644 --- a/include/kim1.h +++ b/include/kim1.h @@ -46,13 +46,6 @@ /* Hardware */ /*****************************************************************************/ - -// Todo (davepl) -// -// #include <_6530.h> -// #define RIOT3 (*(struct __6530*)0x1700) // U25 -// #define RIOT2 (*(struct __6530*)0x1740) // U28 - /*****************************************************************************/ /* Code */ /*****************************************************************************/ From f9024d132a33ffb62257fbb2bb84b63436eb8996 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:12:58 -0800 Subject: [PATCH 167/360] add sound command this behives the same as BASIC sound(voice, pitch, distortion, volume) --- include/atari.h | 6 ++++++ libsrc/atari/sound.s | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 libsrc/atari/sound.s diff --git a/include/atari.h b/include/atari.h index deae8fdf5..e31463991 100644 --- a/include/atari.h +++ b/include/atari.h @@ -235,6 +235,12 @@ extern void __fastcall__ _scroll (signed char numlines); /* numlines < 0 scrolls down */ +/*****************************************************************************/ +/* Sound function */ +/*****************************************************************************/ + +extern void __fastcall__ sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume); /* plays a sound in the specidied voice, to silence call with in other params*/ + /*****************************************************************************/ /* Misc. functions */ /*****************************************************************************/ diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s new file mode 100644 index 000000000..53cb717ff --- /dev/null +++ b/libsrc/atari/sound.s @@ -0,0 +1,43 @@ +; +; Mariano Domínguez +; 2022-12-4 +; +; atari lib +; + .include "atari.inc" + + .export _sound + .import popa +; play sound, arguments: voice, pitch, distortion, volume. same as BASIC +.proc _sound + sta STORE2 ;save volume + jsr popa ;get distortion + sta STORE1 ;save distortion + jsr popa ;get pitch + pha ;save in stack + jsr popa ;get voice + + asl a ;adjust voice *2 for offset in x + tax + pla ;get pitch from stack + sta AUDF1,x ; store pitch + + lda #0 + sta AUDCTL + lda #3 + stx SKCTL ; init sound + + lda STORE1 ;get distortion + asl a ;ignore the high nibble + asl a + asl a + asl a + clc ; setup for adding volume + adc STORE2 ; add volume + sta AUDC1,x ; volume + distortion in control channel + rts +.endproc +; reserve 2 bytes for temp storage + .bss +STORE1: .res 1 +STORE2: .res 1 \ No newline at end of file From fa05294054a441be49d247d1a72a9cf53d2de9d6 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:16:58 -0800 Subject: [PATCH 168/360] add newline for style --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 53cb717ff..94b7a2d8a 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -40,4 +40,4 @@ ; reserve 2 bytes for temp storage .bss STORE1: .res 1 -STORE2: .res 1 \ No newline at end of file +STORE2: .res 1 From 30df733c3156893e8f3b113718ed393750cb8daa Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:20:16 -0800 Subject: [PATCH 169/360] remove dangling spaces --- libsrc/atari/sound.s | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 94b7a2d8a..eb90662ad 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -5,7 +5,6 @@ ; atari lib ; .include "atari.inc" - .export _sound .import popa ; play sound, arguments: voice, pitch, distortion, volume. same as BASIC @@ -15,18 +14,15 @@ sta STORE1 ;save distortion jsr popa ;get pitch pha ;save in stack - jsr popa ;get voice - - asl a ;adjust voice *2 for offset in x + jsr popa ;get voice + asl a ;adjust voice *2 for offset in x tax - pla ;get pitch from stack - sta AUDF1,x ; store pitch - + pla ;get pitch from stack + sta AUDF1,x ; store pitch lda #0 sta AUDCTL lda #3 - stx SKCTL ; init sound - + stx SKCTL ;init sound lda STORE1 ;get distortion asl a ;ignore the high nibble asl a From 29a80065cca2e36639d773f773ddf799f5808969 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:27:54 -0800 Subject: [PATCH 170/360] fix tab indentation --- libsrc/atari/sound.s | 52 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index eb90662ad..756d0e02d 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -9,31 +9,31 @@ .import popa ; play sound, arguments: voice, pitch, distortion, volume. same as BASIC .proc _sound - sta STORE2 ;save volume - jsr popa ;get distortion - sta STORE1 ;save distortion - jsr popa ;get pitch - pha ;save in stack - jsr popa ;get voice - asl a ;adjust voice *2 for offset in x - tax - pla ;get pitch from stack - sta AUDF1,x ; store pitch - lda #0 - sta AUDCTL - lda #3 - stx SKCTL ;init sound - lda STORE1 ;get distortion - asl a ;ignore the high nibble - asl a - asl a - asl a - clc ; setup for adding volume - adc STORE2 ; add volume - sta AUDC1,x ; volume + distortion in control channel - rts + sta STORE2 ;save volume + jsr popa ;get distortion + sta STORE1 ;save distortion + jsr popa ;get pitch + pha ;save in stack + jsr popa ;get voice + asl a ;adjust voice *2 for offset in x + tax + pla ;get pitch from stack + sta AUDF1,x ;store pitch + lda #0 + sta AUDCTL + lda #3 + stx SKCTL ;init sound + lda STORE1 ;get distortion + asl a ;ignore the high nibble + asl a + asl a + asl a + clc ;setup for adding volume + adc STORE2 ;add volume + sta AUDC1,x ;volume + distortion in control channel + rts .endproc -; reserve 2 bytes for temp storage + ;reserve 2 bytes for temp storage .bss -STORE1: .res 1 -STORE2: .res 1 +STORE1: .res 1 +STORE2: .res 1 From 4e8b18c035775344519fde47b2571027abe2944c Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:29:33 -0800 Subject: [PATCH 171/360] missing tab --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 756d0e02d..880af3ee7 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -34,6 +34,6 @@ rts .endproc ;reserve 2 bytes for temp storage - .bss + .bss STORE1: .res 1 STORE2: .res 1 From 85f657b35e2c141ebccc1d99445c4f2ca4a50e56 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:30:31 -0800 Subject: [PATCH 172/360] missing space --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 880af3ee7..0fc1dad07 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -16,7 +16,7 @@ pha ;save in stack jsr popa ;get voice asl a ;adjust voice *2 for offset in x - tax + tax pla ;get pitch from stack sta AUDF1,x ;store pitch lda #0 From 658c1ad71195e7cfd5544dabfa2dc7408454f30b Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:33:40 -0800 Subject: [PATCH 173/360] only missing space --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 0fc1dad07..90fed6f70 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -8,7 +8,7 @@ .export _sound .import popa ; play sound, arguments: voice, pitch, distortion, volume. same as BASIC -.proc _sound +.proc _sound sta STORE2 ;save volume jsr popa ;get distortion sta STORE1 ;save distortion From 8c97b54f5d5391322692436bb854913bbf02c957 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:34:43 -0800 Subject: [PATCH 174/360] more trailing spaces :( --- libsrc/atari/sound.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 90fed6f70..80f89a0c4 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -25,8 +25,8 @@ stx SKCTL ;init sound lda STORE1 ;get distortion asl a ;ignore the high nibble - asl a - asl a + asl a + asl a asl a clc ;setup for adding volume adc STORE2 ;add volume From c3e1ae3478bc848a9ab16219aee4e8fd1c9d3424 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Thu, 5 Jan 2023 21:36:44 -0800 Subject: [PATCH 175/360] last trailing space --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 80f89a0c4..9b0984ad7 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -28,7 +28,7 @@ asl a asl a asl a - clc ;setup for adding volume + clc ;setup for adding volume adc STORE2 ;add volume sta AUDC1,x ;volume + distortion in control channel rts From 2a961a870b2486bf1a4edd2eb4e00faf57fe1064 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Fri, 6 Jan 2023 09:56:15 -0800 Subject: [PATCH 176/360] add target test --- targettest/atari/Makefile | 5 ++++- targettest/atari/sound.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 targettest/atari/sound.c diff --git a/targettest/atari/Makefile b/targettest/atari/Makefile index dd4f6078f..d5b4d9593 100644 --- a/targettest/atari/Makefile +++ b/targettest/atari/Makefile @@ -39,6 +39,7 @@ EXELIST_atari = \ multi.xex \ ostype.xex \ scrcode.com \ + sound.xex \ sys.xex ifneq ($(EXELIST_$(SYS)),) @@ -74,7 +75,8 @@ scrcode.com: scrcode.s $(CL) -t atari -C atari-asm.cfg -o scrcode.com scrcode.s sys.xex: sys.c $(CL) -t atari -o sys.xex sys.c - +sound.xex: sound.c + $(CL) -t atari -o sound.xex sound.c clean: @$(DEL) charmapping.xex 2>$(NULLDEV) @$(DEL) defdev.xex 2>$(NULLDEV) @@ -85,3 +87,4 @@ clean: @$(DEL) scrcode.o 2>$(NULLDEV) @$(DEL) scrcode.com 2>$(NULLDEV) @$(DEL) sys.xex 2>$(NULLDEV) + @$(DEL) sound.xex 2>$(NULLDEV) diff --git a/targettest/atari/sound.c b/targettest/atari/sound.c new file mode 100644 index 000000000..e0cec7f3b --- /dev/null +++ b/targettest/atari/sound.c @@ -0,0 +1,20 @@ +/* +** testprogram printing the default device +** +** January 6 2023 Mariano Domínguez +*/ + +#include <stdio.h> +#include <conio.h> +#include <atari.h> +#include <cc65.h> + +int main(void) +{ + int i=0; + printf("playing sound \n"); + sound(1,121,10,15); + for(i=0;i<90;i++); + sound(1,0,0,0); + return 0; +} From 196962adac43b17a4df99da6f27bc801ae0e2fa7 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Fri, 6 Jan 2023 10:54:16 -0800 Subject: [PATCH 177/360] remove lasy pesky space --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 9b0984ad7..95431bbb4 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -11,7 +11,7 @@ .proc _sound sta STORE2 ;save volume jsr popa ;get distortion - sta STORE1 ;save distortion + sta STORE1 ;save distortion jsr popa ;get pitch pha ;save in stack jsr popa ;get voice From bf9fb6dcdb3717abb25dbd0dad6935f5a6d0e30d Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Fri, 6 Jan 2023 11:23:33 -0800 Subject: [PATCH 178/360] increase delay in sound test --- targettest/atari/sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targettest/atari/sound.c b/targettest/atari/sound.c index e0cec7f3b..66d0ee3e3 100644 --- a/targettest/atari/sound.c +++ b/targettest/atari/sound.c @@ -14,7 +14,7 @@ int main(void) int i=0; printf("playing sound \n"); sound(1,121,10,15); - for(i=0;i<90;i++); + for(i=0;i<9000;i++); sound(1,0,0,0); return 0; } From e4d9dbf0c005951d39e8013659772aa8ba3b69be Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 8 Jan 2023 17:47:04 +0100 Subject: [PATCH 179/360] Wrong file "geover.cvt" See line 106 --- samples/geos/Makefile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/samples/geos/Makefile b/samples/geos/Makefile index 1fc49a873..7b78b1064 100644 --- a/samples/geos/Makefile +++ b/samples/geos/Makefile @@ -94,37 +94,37 @@ bitmap.c: logo.pcx $(SP) -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap bitmap-demo.cvt: bitmap.c bitmap-demores.grc bitmap-demo.c - $(CL) -t $(SYS) -O -o bitmap-demo.cvt -m bitmap-demo.map bitmap-demores.grc bitmap-demo.c + $(CL) -t $(SYS) -O -o $@ -m bitmap-demo.map bitmap-demores.grc bitmap-demo.c filesel.cvt: fileselres.grc filesel.c - $(CL) -t $(SYS) -O -o filesel.cvt -m filesel.map fileselres.grc filesel.c + $(CL) -t $(SYS) -O -o $@ -m filesel.map fileselres.grc filesel.c geosconio.cvt: geosconiores.grc geosconio.c - $(CL) -t $(SYS) -O -o geosconio.cvt -m geosconio.map geosconiores.grc geosconio.c + $(CL) -t $(SYS) -O -o $@ -m geosconio.map geosconiores.grc geosconio.c geosver.cvt: geosverres.grc geosver.c - $(CL) -t $(SYS) -O -o geover.cvt -m geosver.map geosverres.grc geosver.c + $(CL) -t $(SYS) -O -o $@ -m geosver.map geosverres.grc geosver.c getid.cvt: getidres.grc getid.c - $(CL) -t $(SYS) -O -o getid.cvt -m getid.map getidres.grc getid.c + $(CL) -t $(SYS) -O -o $@ -m getid.map getidres.grc getid.c hello1.cvt: hello1res.grc hello1.c - $(CL) -t $(SYS) -O -o hello1.cvt -m hello1.map hello1res.grc hello1.c + $(CL) -t $(SYS) -O -o $@ -m hello1.map hello1res.grc hello1.c hello2.cvt: hello2res.grc hello2.c - $(CL) -t $(SYS) -O -o hello2.cvt -m hello2.map hello2res.grc hello2.c + $(CL) -t $(SYS) -O -o $@ -m hello2.map hello2res.grc hello2.c overlay-demo.cvt: overlay-demores.grc overlay-demo.c - $(CL) -t $(SYS) -O -o overlay-demo.cvt -m overlay-demo.map overlay-demores.grc overlay-demo.c + $(CL) -t $(SYS) -O -o $@ -m overlay-demo.map overlay-demores.grc overlay-demo.c rmvprot.cvt: rmvprotres.grc rmvprot.c - $(CL) -t $(SYS) -O -o rmvprot.cvt -m rmvprot.map rmvprotres.grc rmvprot.c + $(CL) -t $(SYS) -O -o $@ -m rmvprot.map rmvprotres.grc rmvprot.c vector-demo.cvt: vector-demores.grc vector-demo.c - $(CL) -t $(SYS) -O -o vector-demo.cvt -m vector-demo.map vector-demores.grc vector-demo.c + $(CL) -t $(SYS) -O -o $@ -m vector-demo.map vector-demores.grc vector-demo.c yesno.cvt: yesnores.grc yesno.c - $(CL) -t $(SYS) -O -o yesno.cvt -m yesno.map yesnores.grc yesno.c + $(CL) -t $(SYS) -O -o $@ -m yesno.map yesnores.grc yesno.c clean: From 27ecb555eab378f9c7aacabd5d1a302a042becca Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <marianod@wepay.com> Date: Tue, 10 Jan 2023 11:16:36 -0800 Subject: [PATCH 180/360] Rename sound to _sound. remove extra comments. --- include/atari.h | 2 +- libsrc/atari/sound.s | 4 ++-- targettest/atari/sound.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/atari.h b/include/atari.h index e31463991..08b671ff4 100644 --- a/include/atari.h +++ b/include/atari.h @@ -239,7 +239,7 @@ extern void __fastcall__ _scroll (signed char numlines); /* Sound function */ /*****************************************************************************/ -extern void __fastcall__ sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume); /* plays a sound in the specidied voice, to silence call with in other params*/ +extern void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume); /*****************************************************************************/ /* Misc. functions */ diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 95431bbb4..a8b712770 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -5,10 +5,10 @@ ; atari lib ; .include "atari.inc" - .export _sound + .export __sound .import popa ; play sound, arguments: voice, pitch, distortion, volume. same as BASIC -.proc _sound +.proc __sound sta STORE2 ;save volume jsr popa ;get distortion sta STORE1 ;save distortion diff --git a/targettest/atari/sound.c b/targettest/atari/sound.c index 66d0ee3e3..d1c50e1b4 100644 --- a/targettest/atari/sound.c +++ b/targettest/atari/sound.c @@ -1,5 +1,5 @@ /* -** testprogram printing the default device +** Test program for _sound for atari ** ** January 6 2023 Mariano Domínguez */ @@ -13,8 +13,8 @@ int main(void) { int i=0; printf("playing sound \n"); - sound(1,121,10,15); + _sound(1,121,10,15); //voice, pitch, distortion, volume for(i=0;i<9000;i++); - sound(1,0,0,0); + _sound(1,0,0,0); //silencing, same as Atari Basic return 0; } From 42c39c6bfcdc111b927c0f82895f11071e0ed6d0 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Tue, 10 Jan 2023 11:26:12 -0800 Subject: [PATCH 181/360] remove trailing spacew, use correct user --- include/atari.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/atari.h b/include/atari.h index 08b671ff4..04cacab33 100644 --- a/include/atari.h +++ b/include/atari.h @@ -239,7 +239,7 @@ extern void __fastcall__ _scroll (signed char numlines); /* Sound function */ /*****************************************************************************/ -extern void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume); +extern void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume); /*****************************************************************************/ /* Misc. functions */ From 8ea0dfe45395f9357eb7e523044344d09db490e5 Mon Sep 17 00:00:00 2001 From: Matt Seabold <matt.seabold@gmail.com> Date: Wed, 11 Jan 2023 20:18:51 -0500 Subject: [PATCH 182/360] Allow line_bynumber to return more than one result --- src/dbginfo/dbginfo.c | 54 +++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index fdebe6910..c8db5bea6 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -4736,14 +4736,18 @@ static SpanInfoListEntry* FindSpanInfoByAddr (const SpanInfoList* L, cc65_addr A -static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line) -/* Find the LineInfo for a given line number. The function returns the line -** info or NULL if none was found. +static int FindLineInfoByLine (const Collection* LineInfos, cc65_line Line, + unsigned *Index) +/* Find the LineInfo for a given line number. The function returns true if the +** name was found. In this case, Index contains the index of the first item +** that matches. If the item wasn't found, the function returns false and +** Index contains the insert position for Name. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (LineInfos) - 1; + int Found = 0; while (Lo <= Hi) { /* Mid of range */ @@ -4755,16 +4759,20 @@ static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line /* Found? */ if (Line > CurItem->Line) { Lo = Cur + 1; - } else if (Line < CurItem->Line) { - Hi = Cur - 1; } else { - /* Found */ - return CurItem; + Hi = Cur - 1; + /* Since we may have duplicates, repeat the search until we've + ** the first item that has a match. + */ + if(Line == CurItem->Line) { + Found = 1; + } } } - /* Not found */ - return 0; + /* Pass back the index. This is also the insert position */ + *Index = Lo; + return Found; } @@ -6134,6 +6142,9 @@ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId, const FileInfo* F; cc65_lineinfo* D; LineInfo* L = 0; + unsigned I; + unsigned Index; + unsigned Count; /* Check the parameter */ assert (Handle != 0); @@ -6150,18 +6161,31 @@ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId, F = CollAt (&Info->FileInfoById, FileId); /* Search in the file for the given line */ - L = FindLineInfoByLine (&F->LineInfoByLine, Line); - - /* Bail out if we didn't find the line */ - if (L == 0) { + if(!FindLineInfoByLine (&F->LineInfoByLine, Line, &Index)) { + /* Not found */ return 0; } + /* Index contains the first position. Count how many lines with this number + ** we have. Skip the first one, since we have at least one. + */ + Count = 1; + + while ((unsigned) Index + Count < CollCount( &F->LineInfoByLine)) { + L = CollAt (&F->LineInfoByLine, (unsigned) Index + Count); + if (L->Line != Line) { + break; + } + ++Count; + } + /* Prepare the struct we will return to the caller */ - D = new_cc65_lineinfo (1); + D = new_cc65_lineinfo (Count); /* Copy the data */ - CopyLineInfo (D->data, L); + for (I = 0; I < Count; ++I) { + CopyLineInfo (D->data + I, CollAt (&F->LineInfoByLine, Index++)); + } /* Return the allocated struct */ return D; From a5a8225a58addbd8e1532d378163786cb2ebafa7 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sat, 14 Jan 2023 13:49:16 +0100 Subject: [PATCH 183/360] Create disk of GEOS samples You don't need to convert anymore. --- samples/geos/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/samples/geos/Makefile b/samples/geos/Makefile index 7b78b1064..03f6b8cdc 100644 --- a/samples/geos/Makefile +++ b/samples/geos/Makefile @@ -80,6 +80,14 @@ EXELIST_geos-apple = \ ifneq ($(EXELIST_$(SYS)),) samples: $(EXELIST_$(SYS)) $(foreach dir,$(DIRLIST),$(SUBDIR_recipe)) + +define samples-geos +c1541 -attach $(0).d64 -geoswrite $(1); +endef + +samples-geos: $(EXELIST_$(SYS)) + c1541 -format "$@,01" d64 $@.d64 + $(foreach tool,$(EXELIST_$(SYS)),$(call samples-geos,$(tool))) else samples: ifeq ($(MAKELEVEL),0) From 6236e828504bde60b0206fe6e710dfa34bcd7feb Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Sun, 15 Jan 2023 17:00:05 -0800 Subject: [PATCH 184/360] change storage to pager zero fix bug that kills keyboard. --- libsrc/atari/sound.s | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index a8b712770..746ebc2bb 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -7,11 +7,13 @@ .include "atari.inc" .export __sound .import popa + .importzp tmp1,tmp2 + ; play sound, arguments: voice, pitch, distortion, volume. same as BASIC .proc __sound - sta STORE2 ;save volume + sta tmp2 ;save volume jsr popa ;get distortion - sta STORE1 ;save distortion + sta tmp1 ;save distortion jsr popa ;get pitch pha ;save in stack jsr popa ;get voice @@ -22,18 +24,14 @@ lda #0 sta AUDCTL lda #3 - stx SKCTL ;init sound - lda STORE1 ;get distortion + sta SKCTL ;init sound + lda tmp1 ;get distortion asl a ;ignore the high nibble asl a asl a asl a clc ;setup for adding volume - adc STORE2 ;add volume + adc tmp2 ;add volume sta AUDC1,x ;volume + distortion in control channel rts .endproc - ;reserve 2 bytes for temp storage - .bss -STORE1: .res 1 -STORE2: .res 1 From 40656ffb6e829da3abace9503020de5e8754a6d3 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Sun, 15 Jan 2023 17:05:24 -0800 Subject: [PATCH 185/360] more style --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 746ebc2bb..0c1e80db5 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -7,7 +7,7 @@ .include "atari.inc" .export __sound .import popa - .importzp tmp1,tmp2 + .importzp tmp1,tmp2 ; play sound, arguments: voice, pitch, distortion, volume. same as BASIC .proc __sound From 67564d83c8a549be4ad963037dd2e1038c023ce6 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Mon, 16 Jan 2023 18:01:11 +0100 Subject: [PATCH 186/360] libsrc/atari/sound.s: fix indentation --- libsrc/atari/sound.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 0c1e80db5..0d2362318 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -31,7 +31,7 @@ asl a asl a clc ;setup for adding volume - adc tmp2 ;add volume + adc tmp2 ;add volume sta AUDC1,x ;volume + distortion in control channel rts .endproc From c6d183c31b72dd710adaf35d4d6773165be077f1 Mon Sep 17 00:00:00 2001 From: Mariano Dominguez <mariano.dm@gmail.com> Date: Mon, 16 Jan 2023 19:09:01 -0800 Subject: [PATCH 187/360] add documentation for _sound. --- doc/atari.sgml | 1 + doc/funcref.sgml | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/atari.sgml b/doc/atari.sgml index 2e2db0402..3057cd8a6 100644 --- a/doc/atari.sgml +++ b/doc/atari.sgml @@ -332,6 +332,7 @@ See the <url url="funcref.html" name="function reference"> for declaration and u <item>_scroll <item>_setcolor <item>_setcolor_low +<item>_sound <item>waitvsync </itemize> diff --git a/doc/funcref.sgml b/doc/funcref.sgml index a8593ebb5..2df86289e 100644 --- a/doc/funcref.sgml +++ b/doc/funcref.sgml @@ -126,6 +126,7 @@ function. <!-- <item><ref id="_scroll" name="_scroll"> --> <!-- <item><ref id="_setcolor" name="_setcolor"> --> <!-- <item><ref id="_setcolor_low" name="_setcolor_low"> --> +<item><ref id="_sound" name="_sound"> <item><ref id="get_ostype" name="get_ostype"> <!-- <item><ref id="get_tv" name="get_tv"> --> </itemize> @@ -1108,6 +1109,43 @@ considered random to a certain degree. </descrip> </quote> +<sect1>_sound<label id="_sound"><p> +<quote> +<descrip> +<tag/Function/Use the speaker to produce sound in a specified voice. (Atari only) +<tag/Header/<tt/<ref id="atari.h" name="atari.h">/ +<tag/Declaration/<tt/void _sound (unsigned char voice, unsigned char pitch, unsigned char distortion, unsigned char volume);/ +<tag/Description/The function produces a sound with the specified parameters. using any of the 4 availble oscillators (voices) controlled by POKEY chip. Sound is non cpu-blocking and it keeps oscillating until program sends 0 in all the other parameters. + +<tag/Notes/<itemize> +<item>The function is specific to the Atari 8 bit. +<item> Voice can be any of 0-3 different sound channels. +<item> Pitch goes from 0-255 (about 125 Hz to 32 Khz). +<item> Distortion (0-14) uses poly dividers to reshape wave in order to create a noise effect. Use 10 for a "pure" square-wave sound. +<item>Volume (0-15) is the intensity for the wave. +<item>Extra bits in those parameters will be ignored. +</itemize> +<tag/Availability/cc65 (not all platforms) +<tag/Example/ +<verb> + +#include <stdio.h> +int main(void) +{ + int i=0; + unsigned char j; + printf("playing sound \n"); + for (j=0; j<144; j++) { + _sound(1,144-j,10,8); //change the pitch for voice 1 + for (i=0; i<50; i++); //pause for sound duration + } + _sound(1,0,0,0); //use zero in other parameters to stop the sound + return 0; +} + +</verb> +</descrip> +</quote> <sect1>_stroserror<label id="_stroserror"><p> @@ -6908,7 +6946,6 @@ switching the CPU into single clock mode. </descrip> </quote> - <sect1>srand<label id="srand"><p> <quote> From 9ee0c835e5f7698f1376b58d38a6cfd5f1514bfc Mon Sep 17 00:00:00 2001 From: Matt Seabold <matt.seabold@gmail.com> Date: Tue, 17 Jan 2023 22:15:27 -0500 Subject: [PATCH 188/360] Update documentation for line_bynumber --- src/dbginfo/dbginfo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index 38d891e7c..95aae837c 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -258,7 +258,8 @@ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo handle, unsigned source_id, cc65_line line); /* Return line information for a source file/line number combination. The -** function returns NULL if no line information was found. +** function returns NULL if no line information was found, otherwise a list +** of line infos. */ const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned source_id); From 3360734487a08e32e473476b29c5ea4c6207c752 Mon Sep 17 00:00:00 2001 From: Matt Seabold <matt.seabold@gmail.com> Date: Tue, 17 Jan 2023 22:17:23 -0500 Subject: [PATCH 189/360] Update comment to match in source file --- src/dbginfo/dbginfo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index c8db5bea6..fee41012c 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -6135,7 +6135,8 @@ const cc65_lineinfo* cc65_line_byid (cc65_dbginfo Handle, unsigned Id) const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId, cc65_line Line) /* Return line information for a source file/line number combination. The -** function returns NULL if no line information was found. +** function returns NULL if no line information was found, otherwise a list +** of line infos. */ { const DbgInfo* Info; From 60f56c43c769f39089f5005f736a06aacd393224 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Wed, 18 Jan 2023 11:55:52 +0100 Subject: [PATCH 190/360] some documentation fixes --- doc/funcref.sgml | 11 +++++++---- libsrc/atari/sound.s | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/funcref.sgml b/doc/funcref.sgml index 2df86289e..6418723b5 100644 --- a/doc/funcref.sgml +++ b/doc/funcref.sgml @@ -1114,18 +1114,21 @@ considered random to a certain degree. <descrip> <tag/Function/Use the speaker to produce sound in a specified voice. (Atari only) <tag/Header/<tt/<ref id="atari.h" name="atari.h">/ -<tag/Declaration/<tt/void _sound (unsigned char voice, unsigned char pitch, unsigned char distortion, unsigned char volume);/ -<tag/Description/The function produces a sound with the specified parameters. using any of the 4 availble oscillators (voices) controlled by POKEY chip. Sound is non cpu-blocking and it keeps oscillating until program sends 0 in all the other parameters. +<tag/Declaration/<tt/void __fastcall__ _sound (unsigned char voice, unsigned char pitch, unsigned char distortion, unsigned char volume);/ +<tag/Description/The function produces a sound with the specified parameters using any of the 4 available oscillators (voices) controlled by the POKEY chip. Sound is non cpu-blocking and it keeps oscillating until program sends 0 in all the other parameters. <tag/Notes/<itemize> +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. <item>The function is specific to the Atari 8 bit. <item> Voice can be any of 0-3 different sound channels. <item> Pitch goes from 0-255 (about 125 Hz to 32 Khz). <item> Distortion (0-14) uses poly dividers to reshape wave in order to create a noise effect. Use 10 for a "pure" square-wave sound. <item>Volume (0-15) is the intensity for the wave. <item>Extra bits in those parameters will be ignored. +<item>Parameters are the same as for the AtariBASIC SOUND statement. </itemize> -<tag/Availability/cc65 (not all platforms) +<tag/Availability/cc65 (<tt/atari/ and <tt/atarixl/ platforms) <tag/Example/ <verb> @@ -4186,7 +4189,7 @@ be used in presence of a prototype. <tag/Example/<verb> chdir (getdevicedir (device, buf, sizeof buf)); </verb> -cf. <tt/samples/enumdevdir.c/ +cf. <tt/samples/enumdevdir.c/ </descrip> </quote> diff --git a/libsrc/atari/sound.s b/libsrc/atari/sound.s index 0d2362318..a8d11fd82 100644 --- a/libsrc/atari/sound.s +++ b/libsrc/atari/sound.s @@ -2,14 +2,16 @@ ; Mariano Domínguez ; 2022-12-4 ; -; atari lib +; this file provides an equivalent to the BASIC SOUND function +; +; void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume); ; .include "atari.inc" .export __sound .import popa .importzp tmp1,tmp2 -; play sound, arguments: voice, pitch, distortion, volume. same as BASIC +; play sound, arguments: voice, pitch, distortion, volume .proc __sound sta tmp2 ;save volume jsr popa ;get distortion From ed909dba1d819f324f2cf77eb9862946b64474f2 Mon Sep 17 00:00:00 2001 From: tomas <93524600+TommiRommi@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:52:20 +0000 Subject: [PATCH 191/360] fixed spelling mistake there was a spelling mistake in one of pointer warnings --- src/cc65/typeconv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 18a9f4dfa..683cb2356 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -238,10 +238,10 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) ** void pointers, just with warnings. */ if (Result.C == TC_PTR_SIGN_DIFF) { - /* Specific warning for pointee signedness difference */ + /* Specific warning for pointer signess difference */ if (IS_Get (&WarnPointerSign)) { TypeCompatibilityDiagnostic (NewType, Expr->Type, - 0, "Pointer conversion to '%s' from '%s' changes pointee signedness"); + 0, "Pointer conversion to '%s' from '%s' changes pointer signess"); } } else if ((Result.C <= TC_PTR_INCOMPATIBLE || (Result.F & TCF_INCOMPATIBLE_QUAL) != 0)) { From 1d73c8d2592f0153138f3c5706d24abd293f70b5 Mon Sep 17 00:00:00 2001 From: tomas <93524600+TommiRommi@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:53:36 +0000 Subject: [PATCH 192/360] Update typeconv.c --- src/cc65/typeconv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 683cb2356..f77ec3951 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -238,10 +238,10 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) ** void pointers, just with warnings. */ if (Result.C == TC_PTR_SIGN_DIFF) { - /* Specific warning for pointer signess difference */ + /* Specific warning for pointer signedness difference */ if (IS_Get (&WarnPointerSign)) { TypeCompatibilityDiagnostic (NewType, Expr->Type, - 0, "Pointer conversion to '%s' from '%s' changes pointer signess"); + 0, "Pointer conversion to '%s' from '%s' changes pointer signedness"); } } else if ((Result.C <= TC_PTR_INCOMPATIBLE || (Result.F & TCF_INCOMPATIBLE_QUAL) != 0)) { From 1764b7aca9cbcf822649e5c69694c1f4158dab64 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 28 Jan 2023 12:29:05 +0100 Subject: [PATCH 193/360] fix for #1941, taken from https://github.com/acqn/cc65/commit/22d435b68966b86929d3c393f3bbc1593b261cee --- src/cc65/shiftexpr.c | 37 +++++++++++++++++--------------- test/val/bug1941-shift-by-zero.c | 28 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 test/val/bug1941-shift-by-zero.c diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c index b8fb70434..1224bfecb 100644 --- a/src/cc65/shiftexpr.c +++ b/src/cc65/shiftexpr.c @@ -169,27 +169,21 @@ void ShiftExpr (struct ExprDesc* Expr) } } - /* If the shift count is zero, nothing happens. If the left hand - ** side is a constant, the result is constant. - */ - if (Expr2.IVal == 0 || lconst) { - - /* Set the type */ + /* If the left hand side is a constant, the result is constant */ + if (lconst) { + /* Set the result type */ Expr->Type = ResultType; - if (lconst) { - - /* Evaluate the result */ - switch (Tok) { - case TOK_SHL: Expr->IVal <<= Expr2.IVal; break; - case TOK_SHR: Expr->IVal >>= Expr2.IVal; break; - default: /* Shutup gcc */ break; - } - - /* Limit the calculated value to the range of its type */ - LimitExprValue (Expr, 1); + /* Evaluate the result */ + switch (Tok) { + case TOK_SHL: Expr->IVal <<= Expr2.IVal; break; + case TOK_SHR: Expr->IVal >>= Expr2.IVal; break; + default: /* Shutup gcc */ break; } + /* Limit the calculated value to the range of its type */ + LimitExprValue (Expr, 1); + /* Result is already got, remove the generated code */ RemoveCode (&Mark1); @@ -197,6 +191,15 @@ void ShiftExpr (struct ExprDesc* Expr) continue; } + /* If the shift count is zero, nothing happens */ + if (Expr2.IVal == 0) { + /* Result is already got, remove the pushing code */ + RemoveCode (&Mark2); + + /* Be sure to mark the value as in the primary */ + goto MakeRVal; + } + /* If we're shifting an integer or unsigned to the right, the lhs ** has a quasi-const address, and the shift count is larger than 8, ** we can load just the high byte as a char with the correct diff --git a/test/val/bug1941-shift-by-zero.c b/test/val/bug1941-shift-by-zero.c new file mode 100644 index 000000000..eaeba814f --- /dev/null +++ b/test/val/bug1941-shift-by-zero.c @@ -0,0 +1,28 @@ +/* Bug 1941 - Bitwise shift char types by 0 count results in out-of-range access */ + +#include <stdio.h> +#include <stdint.h> + +uint8_t foo = 42U; /* "Low byte" */ +uint8_t goo = 1U; /* "High byte" - you need it to reproduce the issue */ +int16_t bar = 256; /* ...or just do it with this */ + +_Static_assert (sizeof (foo >> 0) == sizeof (int), "Shift result should be int-promoted"); +_Static_assert (sizeof ((int8_t)bar << 0) == sizeof (int), "Shift result should be int-promoted"); + +unsigned failures; + +int main(void) +{ + if (foo >> 0 != foo) { + ++failures; + printf("foo failed\n"); + } + + if ((int8_t)bar << 0 != (int8_t)bar) { + ++failures; + printf("bar failed\n"); + } + + return failures; +} From 8ac5e2f7b6292b594cdde0bcfe66b426eb8c5741 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 28 Jan 2023 15:08:00 +0100 Subject: [PATCH 194/360] fix devicestr call, so related posix function work on cbm targets --- libsrc/cbm/initcwd.s | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libsrc/cbm/initcwd.s b/libsrc/cbm/initcwd.s index d5e5b9296..7064c16e1 100644 --- a/libsrc/cbm/initcwd.s +++ b/libsrc/cbm/initcwd.s @@ -9,8 +9,6 @@ .import pusha0, tosudiva0 .importzp sreg, ptr1, ptr2 - .macpack generic - initcwd: lda #<__cwd ldx #>__cwd @@ -27,15 +25,20 @@ devicestr: lda #10 jsr tosudiva0 ldy #0 - lda sreg - beq @L0 ; >=10 - add #'0' + tax ; result of the division (lsb) + beq @L0 ; < 10 + + clc + adc #'0' sta (ptr2),y iny -@L0: lda ptr1 ; rem - add #'0' +@L0: + lda sreg ; reminder of the division + clc + adc #'0' sta (ptr2),y iny - lda #0 + + lda #0 ; terminating 0 sta (ptr2),y rts From 727b3288d67ffc0642f2ef5b424a3e4cd4b39c00 Mon Sep 17 00:00:00 2001 From: Spiro Trikaliotis <spiro.trikaliotis@gmx.de> Date: Fri, 17 Feb 2023 17:22:55 +0100 Subject: [PATCH 195/360] Remove .exe from file output Whenever a tool like ld65 wants to output its name into a log file, it uses the name of command-line parameter 0. However, this parameter also includes the .exe suffix if it is on Windows. This patch removes the .exe suffix, so that the output is clean and consistent across platforms. This fixes #1990. --- src/common/cmdline.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/common/cmdline.c b/src/common/cmdline.c index 4de79a419..6b24a75fb 100644 --- a/src/common/cmdline.c +++ b/src/common/cmdline.c @@ -181,6 +181,17 @@ void InitCmdLine (int* aArgCount, char*** aArgVec, const char* aProgName) /* Use the default */ ProgName = aProgName; } + else { + /* remove .exe extension, if there is any + ** + ** Note: This creates a new string that is + ** never free()d. + ** As this is exactly only string, and it + ** lives for the whole lifetime of the tool, + ** this is not an issue. + */ + ProgName = MakeFilename (ProgName, ""); + } } /* Make a CmdLine struct */ From 78263cd24b301406f9567f3e0a4fa03488445656 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 17 Feb 2023 23:48:32 -0500 Subject: [PATCH 196/360] Fix OptStackOps label migration case for toscmpbool, add test case --- src/cc65/coptstop.c | 2 ++ test/val/bug1989.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/val/bug1989.c diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 4d0151c55..8b2821dcd 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1153,6 +1153,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) /* Save lhs into zeropage */ AddStoreLhsA (D); + /* AddStoreLhsA may have moved the OpIndex, recalculate insertion point to prevent label migration. */ + D->IP = D->OpIndex + 1; /* cmp */ X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); diff --git a/test/val/bug1989.c b/test/val/bug1989.c new file mode 100644 index 000000000..b3e3d4c8d --- /dev/null +++ b/test/val/bug1989.c @@ -0,0 +1,40 @@ + +/* bug #1989 - OptStackOps Opt_a_toscmpbool bypassed a comparison, discovered in 544a49c */ + +#include <stdlib.h> + +unsigned char i,r,j; + +void fail() // for the r=0 case, the == comparison was getting jumped over by OptStackOps +{ + if ((i & 0x1f) == (r ? 0 : 16)) j -=8; +} + +void pass() +{ + if ((i & 0x1f) == (unsigned char)(r ? 0 : 16)) j -= 8; +} + +void test(unsigned char ti, unsigned char tr, unsigned char tj) +{ + unsigned char rj; + i = ti; + r = tr; + j = tj; + pass(); + rj = j; + i = ti; + r = tr; + j = tj; + fail(); + if (j != rj) exit(1); +} + +int main(void) +{ + test( 1,0,33); + test( 0,0,33); + test( 1,1,33); + test(16,1,33); + return 0; +} From 4e411e8526df0c627c5ab0e6338853a82a51c0b2 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sat, 18 Feb 2023 00:13:34 -0500 Subject: [PATCH 197/360] Opt_a_tosicmp likely has a bug which will incorrectly migrate a label on a replaced op in one case. --- src/cc65/coptstop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 8b2821dcd..ae40a55e9 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1208,6 +1208,8 @@ static unsigned Opt_a_tosicmp (StackOpData* D) /* RHS src is not directly comparable */ X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); InsertEntry (D, X, D->Rhs.A.ChgIndex + 1); + /* RHS insertion may have moved the OpIndex, recalculate insertion point to prevent label migration. */ + D->IP = D->OpIndex + 1; /* Cmp with stored RHS */ X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); From 4d30333099d84dc9266bd6cc3febbdb559e7a5e6 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 19 Feb 2023 05:31:46 -0500 Subject: [PATCH 198/360] sim65 path length safety for PVOpen --- src/sim65/paravirt.c | 13 ++++++++++--- src/sim65/paravirt.h | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index db4120326..9e5c28432 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -63,6 +63,7 @@ /* sim65 */ #include "6502.h" +#include "error.h" #include "memory.h" #include "paravirt.h" @@ -166,7 +167,7 @@ static void PVArgs (CPURegs* Regs) static void PVOpen (CPURegs* Regs) { - char Path[1024]; + char Path[PVOPEN_PATH_SIZE]; int OFlag = O_INITIAL; int OMode = 0; unsigned RetVal, I = 0; @@ -183,9 +184,15 @@ static void PVOpen (CPURegs* Regs) } do { - Path[I] = MemReadByte (Name++); + if (!(Path[I] = MemReadByte ((Name + I) & 0xFFFF))) { + break; + } + ++I; + if (I >= PVOPEN_PATH_SIZE) { + Error("PVOpen path too long at address $%04X",Name); + } } - while (Path[I++]); + while (1); Print (stderr, 2, "PVOpen (\"%s\", $%04X)\n", Path, Flags); diff --git a/src/sim65/paravirt.h b/src/sim65/paravirt.h index bfa38e047..3badb50ea 100644 --- a/src/sim65/paravirt.h +++ b/src/sim65/paravirt.h @@ -47,6 +47,9 @@ #define PARAVIRT_BASE 0xFFF4 /* Lowest address used by a paravirtualization hook */ +#define PVOPEN_PATH_SIZE 1024 +/* Maximum path size supported by PVOpen */ + /*****************************************************************************/ From 5c12659cf499343deff1d81c0c4ac235a74192c3 Mon Sep 17 00:00:00 2001 From: compyx <b.wassink@ziggo.nl> Date: Sun, 19 Feb 2023 14:01:14 +0100 Subject: [PATCH 199/360] make avail: check for presence of binaries before creating symbolic links To avoid creating broken symlinks, first check if the binaries exists in bin/ and exit when they don't, with a message to first run `make`. --- src/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Makefile b/src/Makefile index 8356d0001..a37fa5811 100644 --- a/src/Makefile +++ b/src/Makefile @@ -110,11 +110,21 @@ $(RM) /usr/local/bin/$(prog) endef # UNAVAIL_recipe +define AVAIL_check_prog + +@if [ ! -e ../bin/$(prog) ]; then \ + echo "failed to locate $(prog), please run make first"; \ + false; \ +fi + +endef # AVAIL_check_prog + install: $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: + $(foreach prog,$(PROGS),$(AVAIL_check_prog)) $(foreach prog,$(PROGS),$(AVAIL_recipe)) unavail: From 2ac055383f4619cea09988aa79c2b4324c1bfb40 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 19 Feb 2023 08:14:04 -0500 Subject: [PATCH 200/360] ld65 fix overwrite segments adding wrong padding or causing internal errors --- src/ld65/config.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ld65/config.c b/src/ld65/config.c index c22ced1ef..c101bd1c6 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1945,6 +1945,10 @@ unsigned CfgProcess (void) /* Remember the start address before handling this segment */ unsigned long StartAddr = Addr; + /* For computing FillLevel */ + unsigned long FillLevel; + unsigned long FillAdded = 0; + /* Take note of "overwrite" segments and make sure there are no ** other segment types following them in current memory region. */ @@ -2081,14 +2085,19 @@ unsigned CfgProcess (void) /* Increment the fill level of the memory area; and, check for an ** overflow. */ - M->FillLevel = Addr + S->Seg->Size - M->Start; - if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { + FillLevel = Addr + S->Seg->Size - M->Start; + 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%c", GetString (S->Name), GetString (M->Name), - M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's'); + FillLevel - M->Size, (FillLevel - M->Size == 1) ? ' ' : 's'); + } + if (FillLevel > M->FillLevel) { + /* Regular segments increase FillLevel. Overwrite segments may increase but not decrease FillLevel. */ + FillAdded = FillLevel - M->FillLevel; + M->FillLevel = FillLevel; } /* If requested, define symbols for the start and size of the @@ -2107,13 +2116,14 @@ unsigned CfgProcess (void) Addr += S->Seg->Size; /* If this segment will go out to the file, or its place - ** in the file will be filled, then increase the file size, - ** unless it's an OVERWRITE segment. + ** in the file will be filled, then increase the file size. + ** An OVERWRITE segment will only increase the size if it overlapped some of the fill area. */ if (S->Load == M && - ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0) && - (S->Flags & SF_OVERWRITE) == 0) { - M->F->Size += Addr - StartAddr; + ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) { + M->F->Size += (!(S->Flags & SF_OVERWRITE)) ? + (Addr - StartAddr) : + FillAdded; } } From 4fc19a3d4c27d193297e928171f85ab361ac2ae7 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 19 Feb 2023 08:37:07 -0500 Subject: [PATCH 201/360] ld65 overwrite segment should pad with fill value if the desired seek position is beyond the end of the file so far --- src/ld65/bin.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ld65/bin.c b/src/ld65/bin.c index bd822cc23..15b534f66 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -193,8 +193,16 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M) NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { - /* Seek in "overwrite" segments */ if (S->Flags & SF_OVERWRITE) { + /* Seek in "overwrite" segments. Fill if the seek position has not been reached yet. */ + unsigned long FileLength; + unsigned long SeekTarget = NewAddr - M->Start + M->FileOffs; + fseek (D->F, 0, SEEK_END); + FileLength = ftell (D->F); + if (SeekTarget > FileLength) { + WriteMult (D->F, M->FillVal, SeekTarget - FileLength); + PrintNumVal ("SF_OVERWRITE", SeekTarget - FileLength); + } fseek (D->F, NewAddr - M->Start + M->FileOffs, SEEK_SET); } else { WriteMult (D->F, M->FillVal, NewAddr-Addr); From 5bc8ff98de9e7d942b7920645ce1a162d93af3ab Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 19 Feb 2023 09:01:17 -0500 Subject: [PATCH 202/360] error if computed memory size is negative --- src/ld65/config.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ld65/config.c b/src/ld65/config.c index c22ced1ef..6606df7e3 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1936,6 +1936,11 @@ unsigned CfgProcess (void) 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); + } /* Walk through the segments in this memory area */ for (J = 0; J < CollCount (&M->SegList); ++J) { From 3df5b9f41faabcbff982713db485d91cc8ac9a6c Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 19 Feb 2023 09:30:07 -0500 Subject: [PATCH 203/360] relocate dasm test start-addr to avoid producing negative memory area size with none.cfg (conflicted with stack position at $8000) --- test/dasm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dasm/Makefile b/test/dasm/Makefile index d9ac7ac21..e84560ad2 100644 --- a/test/dasm/Makefile +++ b/test/dasm/Makefile @@ -30,7 +30,7 @@ ISEQUAL = ../../testwrk/isequal$(EXE) CC = gcc CFLAGS = -O2 -START = --start-addr 0x8000 +START = --start-addr 0x7000 .PHONY: all clean From 68ce335f59b9d6d69b6d348ec1e764162021bdbe Mon Sep 17 00:00:00 2001 From: compyx <b.wassink@ziggo.nl> Date: Sun, 19 Feb 2023 19:17:45 +0100 Subject: [PATCH 204/360] Replace shell code with GNU Make conditionals and functions Use `ifeq` to provide two rules for the `avail` target: one that reports an error if any of the symlink targets are missing and one that installs the symlinks for the targets if they're all present. --- src/Makefile | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Makefile b/src/Makefile index a37fa5811..034a2230f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -110,22 +110,16 @@ $(RM) /usr/local/bin/$(prog) endef # UNAVAIL_recipe -define AVAIL_check_prog - -@if [ ! -e ../bin/$(prog) ]; then \ - echo "failed to locate $(prog), please run make first"; \ - false; \ -fi - -endef # AVAIL_check_prog - install: $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: - $(foreach prog,$(PROGS),$(AVAIL_check_prog)) +ifneq ($(patsubst %,../bin/%,$(PROGS)),$(wildcard $(patsubst %,../bin/%,$(PROGS)))) + $(error executables are missing, please run make first) +else $(foreach prog,$(PROGS),$(AVAIL_recipe)) +endif unavail: $(foreach prog,$(PROGS),$(UNAVAIL_recipe)) From 864eecf7c3764741855801de3228f4363b4d69fa Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:08:58 -0500 Subject: [PATCH 205/360] ca16 doc for A8/A18/I8/I16: use "assume" instead of "switch" to avoid implying that a hardware state is changed. See: #1759 --- doc/ca65.sgml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 19fd3aa2a..c84c57353 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2019,7 +2019,7 @@ Here's a list of all control commands and a description, what they do: <sect1><tt>.A16</tt><label id=".A16"><p> - Valid only in 65816 mode. Switch the accumulator to 16 bit. + Valid only in 65816 mode. Assume the accumulator is 16 bit. Note: This command will not emit any code, it will tell the assembler to create 16 bit operands for immediate accumulator addressing mode. @@ -2029,7 +2029,7 @@ Here's a list of all control commands and a description, what they do: <sect1><tt>.A8</tt><label id=".A8"><p> - Valid only in 65816 mode. Switch the accumulator to 8 bit. + Valid only in 65816 mode. Assume the accumulator is 8 bit. Note: This command will not emit any code, it will tell the assembler to create 8 bit operands for immediate accu addressing mode. @@ -3036,7 +3036,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH <sect1><tt>.I16</tt><label id=".I16"><p> - Valid only in 65816 mode. Switch the index registers to 16 bit. + Valid only in 65816 mode. Assume the index registers are 16 bit. Note: This command will not emit any code, it will tell the assembler to create 16 bit operands for immediate operands. @@ -3047,7 +3047,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH <sect1><tt>.I8</tt><label id=".I8"><p> - Valid only in 65816 mode. Switch the index registers to 8 bit. + Valid only in 65816 mode. Assume the index registers are 8 bit. Note: This command will not emit any code, it will tell the assembler to create 8 bit operands for immediate operands. From f1134cc5f18aef555e3c8573d0fa62b17f3908a0 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:42:09 -0500 Subject: [PATCH 206/360] ca65 improve error for unclosed scopes See: #1779 --- src/ca65/symtab.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index afe7b3ad6..a01d14bd8 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -570,7 +570,18 @@ void SymCheck (void) /* Check for open scopes */ if (CurrentScope->Parent != 0) { - Error ("Local scope was not closed"); + if (CurrentScope->Label) { + /* proc has a label indicating the line it was opened. */ + LIError (&CurrentScope->Label->DefLines, + "Local proc '%s' was not closed", + GetString (CurrentScope->Name)); + } else { + /* scope has no label to track a line number, uses end-of-document line instead. + ** Anonymous scopes will reveal their internal automatic name. + */ + Error ("Local scope '%s' was not closed", + GetString (CurrentScope->Name)); + } } /* First pass: Walk through all symbols, checking for undefined's and From 45d0d603495b7f2181301ed4db4acdc98d7a4e6b Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 20 Feb 2023 22:24:26 -0500 Subject: [PATCH 207/360] --warnings-as-errors for ca65 and ld65 --- doc/ca65.sgml | 8 +++++++ doc/ld65.sgml | 8 +++++++ src/ca65/global.c | 1 + src/ca65/global.h | 1 + src/ca65/main.c | 56 +++++++++++++++++++++++++++++----------------- src/ld65/error.c | 14 ++++++++++++ src/ld65/error.h | 11 +++++++++ src/ld65/global.c | 23 ++++++++++--------- src/ld65/global.h | 23 ++++++++++--------- src/ld65/main.c | 14 ++++++++++++ src/ld65/scanner.c | 3 +++ 11 files changed, 119 insertions(+), 43 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 19fd3aa2a..da094359c 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -125,6 +125,7 @@ Long options: --target sys Set the target system --verbose Increase verbosity --version Print the assembler version + --warnings-as-errors Treat warnings as errors --------------------------------------------------------------------------- </verb></tscreen> @@ -359,6 +360,13 @@ Here is a description of all the command line options: warning level is 1, and it would probably be silly to set it to something lower. + + <label id="option--warnings-as-errors"> + <tag><tt>--warnings-as-errors</tt></tag> + + An error will be generated if any warnings were produced. + + </descrip> <p> diff --git a/doc/ld65.sgml b/doc/ld65.sgml index 307caeaa4..1ad04b395 100644 --- a/doc/ld65.sgml +++ b/doc/ld65.sgml @@ -90,6 +90,7 @@ Long options: --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> @@ -330,6 +331,13 @@ Here is a description of all of the command-line options: directory, in the list of directories specified using <tt/--obj-path/, in directories given by environment variables, and in a built-in default directory. + + <label id="option--warnings-as-errors"> + <tag><tt>--warnings-as-errors</tt></tag> + + An error will be generated if any warnings were produced. + + </descrip> diff --git a/src/ca65/global.c b/src/ca65/global.c index a216fc406..81ff68a79 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -67,6 +67,7 @@ unsigned char LineCont = 0; /* Allow line continuation */ unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */ unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */ +unsigned char WarningsAsErrors = 0; /* Error if any warnings */ /* Emulation features */ unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */ diff --git a/src/ca65/global.h b/src/ca65/global.h index 77d90beca..26877032e 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -69,6 +69,7 @@ extern unsigned char LineCont; /* Allow line continuation */ extern unsigned char LargeAlignment; /* Don't warn about large alignments */ extern unsigned char RelaxChecks; /* Relax a few assembler checks */ extern unsigned char StringEscapes; /* Allow C-style escapes in strings */ +extern unsigned char WarningsAsErrors; /* Error if any warnings */ /* Emulation features */ extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */ diff --git a/src/ca65/main.c b/src/ca65/main.c index 4146aaf11..9710924bf 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -656,6 +656,15 @@ static void OptVersion (const char* Opt attribute ((unused)), +static void OptWarningsAsErrors (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Generate an error if any warnings occur */ +{ + WarningsAsErrors = 1; +} + + + static void DoPCAssign (void) /* Start absolute code */ { @@ -919,27 +928,28 @@ int main (int argc, char* argv []) { /* Program long options */ static const LongOpt OptTab[] = { - { "--auto-import", 0, OptAutoImport }, - { "--bin-include-dir", 1, OptBinIncludeDir }, - { "--cpu", 1, OptCPU }, - { "--create-dep", 1, OptCreateDep }, - { "--create-full-dep", 1, OptCreateFullDep }, - { "--debug", 0, OptDebug }, - { "--debug-info", 0, OptDebugInfo }, - { "--feature", 1, OptFeature }, - { "--help", 0, OptHelp }, - { "--ignore-case", 0, OptIgnoreCase }, - { "--include-dir", 1, OptIncludeDir }, - { "--large-alignment", 0, OptLargeAlignment }, - { "--list-bytes", 1, OptListBytes }, - { "--listing", 1, OptListing }, - { "--memory-model", 1, OptMemoryModel }, - { "--pagelength", 1, OptPageLength }, - { "--relax-checks", 0, OptRelaxChecks }, - { "--smart", 0, OptSmart }, - { "--target", 1, OptTarget }, - { "--verbose", 0, OptVerbose }, - { "--version", 0, OptVersion }, + { "--auto-import", 0, OptAutoImport }, + { "--bin-include-dir", 1, OptBinIncludeDir }, + { "--cpu", 1, OptCPU }, + { "--create-dep", 1, OptCreateDep }, + { "--create-full-dep", 1, OptCreateFullDep }, + { "--debug", 0, OptDebug }, + { "--debug-info", 0, OptDebugInfo }, + { "--feature", 1, OptFeature }, + { "--help", 0, OptHelp }, + { "--ignore-case", 0, OptIgnoreCase }, + { "--include-dir", 1, OptIncludeDir }, + { "--large-alignment", 0, OptLargeAlignment }, + { "--list-bytes", 1, OptListBytes }, + { "--listing", 1, OptListing }, + { "--memory-model", 1, OptMemoryModel }, + { "--pagelength", 1, OptPageLength }, + { "--relax-checks", 0, OptRelaxChecks }, + { "--smart", 0, OptSmart }, + { "--target", 1, OptTarget }, + { "--verbose", 0, OptVerbose }, + { "--version", 0, OptVersion }, + { "--warnings-as-errors", 0, OptWarningsAsErrors }, }; /* Name of the global name space */ @@ -1144,6 +1154,10 @@ int main (int argc, char* argv []) SegDump (); } + if (WarningCount > 0 && WarningsAsErrors) { + Error("Warnings as errors"); + } + /* If we didn't have an errors, finish off the line infos */ DoneLineInfo (); diff --git a/src/ld65/error.c b/src/ld65/error.c index 20dfd4537..344e4c1b3 100644 --- a/src/ld65/error.c +++ b/src/ld65/error.c @@ -46,6 +46,17 @@ +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Statistics */ +unsigned WarningCount = 0; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -66,6 +77,9 @@ void Warning (const char* Format, ...) fprintf (stderr, "%s: Warning: %s\n", ProgName, SB_GetConstBuf (&S)); SB_Done (&S); + + /* Count warnings */ + ++WarningCount; } diff --git a/src/ld65/error.h b/src/ld65/error.h index 75b8e0bc1..1285ca725 100644 --- a/src/ld65/error.h +++ b/src/ld65/error.h @@ -43,6 +43,17 @@ +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Statistics */ +extern unsigned WarningCount; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ diff --git a/src/ld65/global.c b/src/ld65/global.c index 8f43232fe..93dd65958 100644 --- a/src/ld65/global.c +++ b/src/ld65/global.c @@ -43,19 +43,20 @@ -const char* OutputName = "a.out"; /* Name of output file */ -unsigned OutputNameUsed = 0; /* Output name was used by %O */ +const char* OutputName = "a.out"; /* Name of output file */ +unsigned OutputNameUsed = 0; /* Output name was used by %O */ -unsigned ModuleId = 0; /* Id for o65 module */ +unsigned ModuleId = 0; /* Id for o65 module */ /* Start address */ -unsigned char HaveStartAddr = 0; /* Start address not given */ -unsigned long StartAddr = 0x200; /* Start address */ +unsigned char HaveStartAddr = 0; /* Start address not given */ +unsigned long StartAddr = 0x200; /* Start address */ -unsigned char VerboseMap = 0; /* Verbose map file */ -unsigned char AllowMultDef = 0; /* Allow multiple definitions */ -unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ +unsigned char VerboseMap = 0; /* Verbose map file */ +unsigned char AllowMultDef = 0; /* Allow multiple definitions */ +unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ +unsigned char WarningsAsErrors = 0; /* Error if any warnings */ -const char* MapFileName = 0; /* Name of the map file */ -const char* LabelFileName = 0; /* Name of the label file */ -const char* DbgFileName = 0; /* Name of the debug file */ +const char* MapFileName = 0; /* Name of the map file */ +const char* LabelFileName = 0; /* Name of the label file */ +const char* DbgFileName = 0; /* Name of the debug file */ diff --git a/src/ld65/global.h b/src/ld65/global.h index a923f6de5..ad85daf0a 100644 --- a/src/ld65/global.h +++ b/src/ld65/global.h @@ -44,21 +44,22 @@ -extern const char* OutputName; /* Name of output file */ -extern unsigned OutputNameUsed; /* Output name was used by %O */ +extern const char* OutputName; /* Name of output file */ +extern unsigned OutputNameUsed; /* Output name was used by %O */ -extern unsigned ModuleId; /* Id for o65 module */ +extern unsigned ModuleId; /* Id for o65 module */ -extern unsigned char HaveStartAddr; /* True if start address was given */ -extern unsigned long StartAddr; /* Start address */ +extern unsigned char HaveStartAddr; /* True if start address was given */ +extern unsigned long StartAddr; /* Start address */ -extern unsigned char VerboseMap; /* Verbose map file */ -extern unsigned char AllowMultDef; /* Allow multiple definitions */ -extern unsigned char LargeAlignment; /* Don't warn about large alignments */ +extern unsigned char VerboseMap; /* Verbose map file */ +extern unsigned char AllowMultDef; /* Allow multiple definitions */ +extern unsigned char LargeAlignment; /* Don't warn about large alignments */ +extern unsigned char WarningsAsErrors; /* Error if any warnings */ -extern const char* MapFileName; /* Name of the map file */ -extern const char* LabelFileName; /* Name of the label file */ -extern const char* DbgFileName; /* Name of the debug file */ +extern const char* MapFileName; /* Name of the map file */ +extern const char* LabelFileName; /* Name of the label file */ +extern const char* DbgFileName; /* Name of the debug file */ diff --git a/src/ld65/main.c b/src/ld65/main.c index f2415a914..70e9c84d1 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -559,6 +559,15 @@ static void OptVersion (const char* Opt attribute ((unused)), +static void OptWarningsAsErrors (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Generate an error if any warnings occur */ +{ + WarningsAsErrors = 1; +} + + + static void OptMultDef (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Set flag to allow multiple definitions of a global symbol */ @@ -637,6 +646,7 @@ static void ParseCommandLine(void) { "--start-group", 0, CmdlOptStartGroup }, { "--target", 1, CmdlOptTarget }, { "--version", 0, OptVersion }, + { "--warnings-as-errors", 0, OptWarningsAsErrors }, }; unsigned I; @@ -845,6 +855,10 @@ int main (int argc, char* argv []) (MemoryAreaOverflows > 1) ? 's' : ' '); } + if (WarningCount > 0 && WarningsAsErrors) { + Error("Warnings as errors"); + } + /* Create the output file */ CfgWriteTarget (); diff --git a/src/ld65/scanner.c b/src/ld65/scanner.c index 718951aa5..5f53e5765 100644 --- a/src/ld65/scanner.c +++ b/src/ld65/scanner.c @@ -95,6 +95,9 @@ void CfgWarning (const FilePos* Pos, const char* Format, ...) Warning ("%s:%u: %s", GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf)); SB_Done (&Buf); + + /* Count warnings */ + ++WarningCount; } From 99ecd9b69d698ad555d01bae5e3622ec1ca07f7b Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 21 Feb 2023 00:53:55 -0500 Subject: [PATCH 208/360] Document expected linker configuration and special segments used by cc65 --- doc/cc65-intern.sgml | 73 +++++++++++++++++++++++++++++++++++++++++++- doc/index.sgml | 2 +- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/doc/cc65-intern.sgml b/doc/cc65-intern.sgml index 8e36578b5..904cee070 100644 --- a/doc/cc65-intern.sgml +++ b/doc/cc65-intern.sgml @@ -6,7 +6,8 @@ <abstract> Internal details of cc65 code generation, -such as calling assembly functions from C. +such as the expected linker configuration, +and calling assembly functions from C. </abstract> <!-- Table of contents --> @@ -16,6 +17,76 @@ such as calling assembly functions from C. +<sect>Linker configuration<p> + +The C libraries and code generation depend directly on a suitable linker configuration. +There are premade configuration files in the <tt/cfg// directory, normally chosen by the +linker's selected target. These can be used as a template for customization. + +The C libraries depend on several special segments to be defined in your linker configuration. +Generated code will also use some of them by default. +Some platform libraries have additional special segments. + +Memory areas are free to be defined in a way that is appropriate to each platform, +and the segments they contain are used as a layer of semantics and abstraction, +to allow much of the reorganization to be done with the linker config, +rather than requiring platform-specific code source changes. + +<sect1><tt/ZEROPAGE/ segment<p> + +Used by the C library and generated code for efficient internal and temporary state storage, +also called "pseudo-registers". + +<sect1><tt/STARTUP/ segment<p> + +Used by each platform instance of the C library in <tt/crt0.s/ to contain the entry point +of the program. + +The startup module will export <tt/__STARTUP__ : absolute = 1/ to force the linker to +always include <tt/crt0.s/ from the library. + +<sect1><tt/CODE/ segment<p> + +The default segment for generated code, and most C library code will be located here. + +Use <tt/#pragma code-name/ to redirect generated code to another segment. + +<sect1><tt/BSS/ segment<p> + +Used for uninitialized variables. +Originally an acronym for "Block Started by Symbol", but the meaning of this is now obscure. + +Use <tt/#pragma bss-name/ to redirect uninitialized variables to another segment. + +<sect1><tt/DATA/ segment<p> + +Used for initialized variables. + +On some platforms, this may be initialized as part of the program loading process, +but on others it may have a separate <tt/LOAD/ and <tt/RUN/ address, +allowing <tt/copydata/ to copy the initialization from the loaded location +into their run destination in RAM. + +Use <tt/#pragma data-name/ to redirect initialized variables to another segment. + +<sect1><tt/RODATA/ segment<p> + +Used for read-only (constant) data. + +Use <tt/#pragma rodata-name/ to redirect constant data to another segment. + +<sect1><tt/FEATURES/ table<p> + +This currently defines table locations for the <tt/CONDES/ +constructor, destructor, and interruptor features. +Some platform libraries use these. + +The constructors will be called with <tt/initlib/ at startup, +and the destructors with <tt/donelib/ at program exit. +Interruptors are called with <tt/callirq/. + + + <sect>Calling assembly functions from C<p> <sect1>Calling conventions<p> diff --git a/doc/index.sgml b/doc/index.sgml index bfce63486..727364028 100644 --- a/doc/index.sgml +++ b/doc/index.sgml @@ -59,7 +59,7 @@ Contains hints on creating the most effective code with cc65. <tag><htmlurl url="cc65-intern.html" name="cc65-intern.html"></tag> - Describes internal details of cc65, such as calling conventions. + Describes internal details of cc65: linker configuration, calling conventions, etc. <tag><htmlurl url="using-make.html" name="using-make.html"></tag> Build programs, using the GNU Make utility. From ccf3994e3b6f669d18ce83329adc1998a04923fe Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 21 Feb 2023 04:00:34 -0500 Subject: [PATCH 209/360] ca65 jsr/jmp/rts will not promote to jsl/jml/rtl by default, but can still be enabled with new feature long_jsr_jmp_rts --- doc/ca65.sgml | 23 ++++++++++++++++-- src/ca65/feature.c | 2 ++ src/ca65/feature.h | 1 + src/ca65/global.c | 1 + src/ca65/global.h | 1 + src/ca65/instr.c | 60 ++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 79 insertions(+), 9 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 19fd3aa2a..276a2b697 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -183,7 +183,7 @@ Here is a description of all the command line options: Enable an emulation feature. This is identical as using <tt/.FEATURE/ in the source with two exceptions: Feature names must be lower case, and - each feature must be specified by using an extra <tt/--feature/ option, + each feature must be specified by using a separate <tt/--feature/ option, comma separated lists are not allowed. See the discussion of the <tt><ref id=".FEATURE" name=".FEATURE"></tt> @@ -2825,6 +2825,23 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH overridden. When using this feature, you may also get into trouble if later versions of the assembler define new keywords starting with a dot. + <tag><tt>long_jsr_jmp_rts</tt><label id="long_jsr_jmp_rts"></tag> + + Affects 65816 mode only. + + Allows <tt>jsr</tt> and <tt>jmp</tt> to produce long jumps if the target + address has been previously declared in a <tt>far</tt> segment, + or imported as <tt>far</tt>. + Otherwise <tt>jsl</tt> and <tt>jml</tt> must be used instead. + + Also allows <tt><ref id=".SMART" name=".SMART"></tt> to convert <tt>rts</tt> + to a long return <tt>rtl</tt> when the enclosing scope or memory model + indicates returning from a <tt>far</tt> procedure. + + This permits compatibility with the old behavior of this assembler, or other + assemblers which similarly allowed <tt>jsr</tt> and <tt>jmp</tt> to be used + this way. + <tag><tt>loose_char_term</tt><label id="loose_char_term"></tag> Accept single quotes as well as double quotes as terminators for char @@ -3994,7 +4011,9 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE" the assembler cannot trace the execution flow this may lead to false results in some cases. If in doubt, use the <tt/.Inn/ and <tt/.Ann/ instructions to tell the assembler about the current settings. - <item>In 65816 mode, replace a <tt/RTS/ instruction by <tt/RTL/ if it is + <item>In 65816 mode, if the <tt><ref id="long_jsr_jmp_rts" + name="long_jsr_jmp_rts"></tt> feature is enabled, + smart mode will replace a <tt/RTS/ instruction by <tt/RTL/ if it is used within a procedure declared as <tt/far/, or if the procedure has no explicit address specification, but it is <tt/far/ because of the memory model used. diff --git a/src/ca65/feature.c b/src/ca65/feature.c index b11345338..754b645cf 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -66,6 +66,7 @@ static const char* const FeatureKeys[FEAT_COUNT] = { "addrsize", "bracket_as_indirect", "string_escapes", + "long_jsr_jmp_rts", }; @@ -125,6 +126,7 @@ feature_t SetFeature (const StrBuf* Key) case FEAT_ADDRSIZE: AddrSize = 1; break; case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break; case FEAT_STRING_ESCAPES: StringEscapes = 1; break; + case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = 1; break; default: /* Keep gcc silent */ break; } diff --git a/src/ca65/feature.h b/src/ca65/feature.h index 876f3c4a8..a29ee0172 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -68,6 +68,7 @@ typedef enum { FEAT_ADDRSIZE, FEAT_BRACKET_AS_INDIRECT, FEAT_STRING_ESCAPES, + FEAT_LONG_JSR_JMP_RTS, /* Special value: Number of features available */ FEAT_COUNT diff --git a/src/ca65/global.c b/src/ca65/global.c index a216fc406..962f368db 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -67,6 +67,7 @@ unsigned char LineCont = 0; /* Allow line continuation */ unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */ unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */ +unsigned char LongJsrJmpRts = 0; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */ /* Emulation features */ unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */ diff --git a/src/ca65/global.h b/src/ca65/global.h index 77d90beca..c92291ad3 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -69,6 +69,7 @@ extern unsigned char LineCont; /* Allow line continuation */ extern unsigned char LargeAlignment; /* Don't warn about large alignments */ extern unsigned char RelaxChecks; /* Relax a few assembler checks */ extern unsigned char StringEscapes; /* Allow C-style escapes in strings */ +extern unsigned char LongJsrJmpRts; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */ /* Emulation features */ extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */ diff --git a/src/ca65/instr.c b/src/ca65/instr.c index d0d7ce64c..745072a09 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -120,9 +120,21 @@ static void PutJMP (const InsDesc* Ins); ** to check for this case and is otherwise identical to PutAll. */ +static void PutJMP816 (const InsDesc* Ins); +/* Handle the JMP instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JMP. +** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC, +** because the [] notation for long indirection makes the generated instruction unambiguous. +*/ + +static void PutJSR816 (const InsDesc* Ins); +/* Handle the JSR instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JSR. +*/ + static void PutRTS (const InsDesc* Ins attribute ((unused))); /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if -** the enclosing scope is FAR. +** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies. */ static void PutAll (const InsDesc* Ins); @@ -758,9 +770,9 @@ static const struct { { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JML", 0x4000010, 0x5c, 1, PutAll }, - { "JMP", 0x4010818, 0x4c, 6, PutAll }, + { "JMP", 0x4010818, 0x4c, 6, PutJMP816 }, { "JSL", 0x0000010, 0x20, 7, PutAll }, - { "JSR", 0x0010018, 0x20, 7, PutAll }, + { "JSR", 0x0010018, 0x20, 7, PutJSR816 }, { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll }, { "LDX", 0x0c0030c, 0xa2, 1, PutAll }, { "LDY", 0x0c0006c, 0xa0, 1, PutAll }, @@ -1627,12 +1639,46 @@ static void PutJMP (const InsDesc* Ins) -static void PutRTS (const InsDesc* Ins attribute ((unused))) -/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if -** the enclosing scope is FAR. +static void PutJMP816 (const InsDesc* Ins) +/* Handle the JMP instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JMP. +** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC, +** because the [] notation for long indirection makes the generated instruction unambiguous. */ { - if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { + if (LongJsrJmpRts) { + PutJMP (Ins); + } else { + InsDesc InsAbs = *Ins; + InsAbs.AddrMode &= ~(AM65_ABS_LONG); + PutJMP (&InsAbs); + } +} + + + +static void PutJSR816 (const InsDesc* Ins) +/* Handle the JSR instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JSR. +*/ +{ + if (LongJsrJmpRts) { + PutAll (Ins); + } else { + InsDesc InsAbs = *Ins; + InsAbs.AddrMode &= ~(AM65_ABS_LONG); + PutJMP (&InsAbs); + } +} + + + +static void PutRTS (const InsDesc* Ins attribute ((unused))) +/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if +** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies. +*/ +{ + if (LongJsrJmpRts && SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { Emit0 (0x6B); /* RTL */ } else { Emit0 (0x60); /* RTS */ From 4b29d257d9c1aaa256b5bf1537daf9eb1e18a8ee Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 21 Feb 2023 04:38:17 -0500 Subject: [PATCH 210/360] fix dasm test65816 which relied on JMP automatic promotion, add test of new long_jsr_jmp_rts and smart --- test/dasm/test65816.s | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/dasm/test65816.s b/test/dasm/test65816.s index 3d764fb6e..1b447d0fe 100644 --- a/test/dasm/test65816.s +++ b/test/dasm/test65816.s @@ -151,10 +151,11 @@ BVC LABEL BVS LABEL BRL LABEL JMP $1234 -JMP $FEDCBA +JML $FEDCBA JMP ($1234) JMP ($1234,X) JMP [$1234] +JML [$1234] ; alternative to JMP [] JSL $123456 JSR $1234 JSR ($1234,X) @@ -271,3 +272,15 @@ BIT #$5432 LDA #$5432 LDX #$5432 LDY #$5432 + +; test of smart and long_jsr_jmp_rts +.smart +.proc short_rts : far +RTS ; not promoted to RTL +.endproc +.feature long_jsr_jmp_rts +JSR $FEDCBA ; promoted to JSL +JMP $FEDCBA ; promoted to JML +.proc long_rts : far +RTS ; promoted to RTL +.endproc From 2cdab999f54a8c6047657507e2e8a5f0a9242c0e Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 21 Feb 2023 05:22:28 -0500 Subject: [PATCH 211/360] dasm test extend 65816.info to include added code --- test/dasm/65816.info | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dasm/65816.info b/test/dasm/65816.info index 2a3394680..a6d836688 100644 --- a/test/dasm/65816.info +++ b/test/dasm/65816.info @@ -3,5 +3,5 @@ GLOBAL { }; RANGE { START $8000; END $8229; ADDRMODE "MX"; TYPE Code;}; -RANGE { START $822a; END $824b; ADDRMODE "mx"; TYPE Code;}; +RANGE { START $822a; END $825b; ADDRMODE "mx"; TYPE Code;}; From 13f1d37403017a3b399eb9bc2c61e6613a1ebdfa Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 21 Feb 2023 06:48:46 -0500 Subject: [PATCH 212/360] suppress spurious "large alignment" warning when the combined alignment is not larger than any of the explictly requested ones --- doc/ca65.sgml | 13 +++++++------ src/ca65/segment.c | 2 +- src/ld65/segments.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 19fd3aa2a..f2f7e94c0 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2112,14 +2112,15 @@ Here's a list of all control commands and a description, what they do: </verb></tscreen> the assembler will force a segment alignment to the least common multiple of - 15, 18 and 251 - which is 22590. To protect the user against errors, the - assembler will issue a warning when the combined alignment exceeds 256. The - command line option <tt><ref id="option--large-alignment" - name="--large-alignment"></tt> will disable this warning. + 15, 18 and 251 - which is 22590. To protect the user against errors, when the + combined alignment is larger than the explicitly requested alignments, + and also exceeds 256, the assembler will issue a warning. The command line + option <tt><ref id="option--large-alignment" name="--large-alignment"></tt> + will disable this warning. Please note that with alignments that are a power of two (which were the - only alignments possible in older versions of the assembler), the problem is - less severe, because the least common multiple of powers to the same base is + only alignments possible in older versions of the assembler) will not cause + a warning, because the least common multiple of powers to the same base is always the larger one. diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 26b568711..aadc35009 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -306,7 +306,7 @@ void SegAlign (unsigned long Alignment, int FillVal) ActiveSeg->Align = CombinedAlignment; /* Output a warning for larger alignments if not suppressed */ - if (CombinedAlignment >= LARGE_ALIGNMENT && !LargeAlignment) { + if (CombinedAlignment >= LARGE_ALIGNMENT && CombinedAlignment > ActiveSeg->Align && CombinedAlignment > Alignment && !LargeAlignment) { Warning (0, "Combined alignment is suspiciously large (%lu)", CombinedAlignment); } diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 10d2cda2c..255b8ccd1 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -230,7 +230,7 @@ Section* ReadSection (FILE* F, ObjData* O) "%lu. Last module requiring alignment was '%s'.", GetString (Name), Alignment, MAX_ALIGNMENT, GetObjFileName (O)); - } else if (Alignment >= LARGE_ALIGNMENT && !LargeAlignment) { + } 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'.", GetString (Name), Alignment, GetObjFileName (O)); From 23cc295b08661bab604237582acd5bf5773dd6d3 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 21 Feb 2023 07:32:38 -0500 Subject: [PATCH 213/360] improve description of large-alignment warning --- doc/ca65.sgml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index f2f7e94c0..062b6d0c7 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2114,14 +2114,13 @@ Here's a list of all control commands and a description, what they do: the assembler will force a segment alignment to the least common multiple of 15, 18 and 251 - which is 22590. To protect the user against errors, when the combined alignment is larger than the explicitly requested alignments, - and also exceeds 256, the assembler will issue a warning. The command line + the assembler will issue a warning if it also exceeds 256. The command line option <tt><ref id="option--large-alignment" name="--large-alignment"></tt> will disable this warning. - Please note that with alignments that are a power of two (which were the - only alignments possible in older versions of the assembler) will not cause - a warning, because the least common multiple of powers to the same base is - always the larger one. + Please note that with only alignments that are a power of two, a warning will + never occur, because the least common multiple of powers to the same base is + always simply the larger one. From fedfc3443de7adacb290cc33adb4b8fb63739e41 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Fri, 24 Feb 2023 02:12:19 +0100 Subject: [PATCH 214/360] fix for issue #1973 (printf("%c", '\0') doesn't _write '\0' to fd 0) --- libsrc/common/_printf.s | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libsrc/common/_printf.s b/libsrc/common/_printf.s index 840d42127..a0074583e 100644 --- a/libsrc/common/_printf.s +++ b/libsrc/common/_printf.s @@ -502,10 +502,10 @@ DoFormat: ; It is a character jsr GetIntArg ; Get the argument (promoted to int) - sta Buf ; Place it as zero terminated string... - lda #0 - sta Buf+1 ; ...into the buffer - jmp HaveArg ; Done + sta Buf ; Place it into the buffer + ldx #0 + lda #1 ; Buffer length is 1 + jmp HaveArg1 ; Is it an integer? @@ -671,6 +671,7 @@ HaveArg: lda Str ldx Str+1 jsr _strlen ; Get length of argument +HaveArg1: ; Jumped into here from %c handling sta ArgLen stx ArgLen+1 From da150aeeac5e030d34a208bf3efabdaaac23e81b Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 24 Feb 2023 18:00:58 -0500 Subject: [PATCH 215/360] allow .feature to both enable and disable --- doc/ca65.sgml | 14 ++++++++----- src/ca65/feature.c | 50 +++++++++++++++++++--------------------------- src/ca65/feature.h | 6 ++---- src/ca65/main.c | 11 ++++++---- src/ca65/pseudo.c | 25 +++++++++++++++-------- 5 files changed, 56 insertions(+), 50 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b65d337bb..02ed5ad8a 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2746,15 +2746,19 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH This directive may be used to enable one or more compatibility features of the assembler. While the use of <tt/.FEATURE/ should be avoided when possible, it may be useful when porting sources written for other - assemblers. There is no way to switch a feature off, once you have - enabled it, so using + assemblers. After the feature name an optional '+' or '-' may specify whether + to enable or disable the feature (enable if omitted). Multiple features may be + enabled, separated by commas. Examples: <tscreen><verb> - .FEATURE xxx + ; enable c_comments + .feature c_comments + .feature c_comments + + ; enable force_range, disable underline_in_numbers, enable labels_without_colons + .feature force_range, underline_in_numbers -, labels_without_colons + + .feature force_range +, underline_in_numbers off, labels_without_colons on </verb></tscreen> - will enable the feature until end of assembly is reached. - The following features are available: <descrip> diff --git a/src/ca65/feature.c b/src/ca65/feature.c index 754b645cf..41177d66b 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -98,38 +98,30 @@ feature_t FindFeature (const StrBuf* Key) -feature_t SetFeature (const StrBuf* Key) -/* Find the feature and set the corresponding flag if the feature is known. -** In any case, return the feature found. An invalid Key will return -** FEAT_UNKNOWN. +void SetFeature (feature_t Feature, unsigned char On) +/* Set the corresponding feature flag if Feature is valid. */ { - /* Map the string to an enum value */ - feature_t Feature = FindFeature (Key); - /* Set the flags */ switch (Feature) { - case FEAT_DOLLAR_IS_PC: DollarIsPC = 1; break; - case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = 1; break; - case FEAT_LOOSE_STRING_TERM: LooseStringTerm = 1; break; - case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = 1; break; - case FEAT_AT_IN_IDENTIFIERS: AtInIdents = 1; break; - case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = 1; break; - case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= 1; break; - case FEAT_ORG_PER_SEG: OrgPerSeg = 1; break; - case FEAT_PC_ASSIGNMENT: PCAssignment = 1; break; - case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break; - case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break; - case FEAT_C_COMMENTS: CComments = 1; break; - case FEAT_FORCE_RANGE: ForceRange = 1; break; - case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break; - case FEAT_ADDRSIZE: AddrSize = 1; break; - case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break; - case FEAT_STRING_ESCAPES: StringEscapes = 1; break; - case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = 1; break; - default: /* Keep gcc silent */ break; + case FEAT_DOLLAR_IS_PC: DollarIsPC = On; break; + case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = On; break; + case FEAT_LOOSE_STRING_TERM: LooseStringTerm = On; break; + case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = On; break; + case FEAT_AT_IN_IDENTIFIERS: AtInIdents = On; break; + case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = On; break; + case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= On; break; + case FEAT_ORG_PER_SEG: OrgPerSeg = On; break; + case FEAT_PC_ASSIGNMENT: PCAssignment = On; break; + case FEAT_MISSING_CHAR_TERM: MissingCharTerm = On; break; + case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = On; break; + case FEAT_C_COMMENTS: CComments = On; break; + case FEAT_FORCE_RANGE: ForceRange = On; break; + case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= On; break; + case FEAT_ADDRSIZE: AddrSize = On; break; + case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = On; break; + case FEAT_STRING_ESCAPES: StringEscapes = On; break; + case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = On; break; + default: break; } - - /* Return the value found */ - return Feature; } diff --git a/src/ca65/feature.h b/src/ca65/feature.h index a29ee0172..8eeb62e6f 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -87,10 +87,8 @@ feature_t FindFeature (const StrBuf* Key); ** feature is invalid, return FEAT_UNKNOWN. */ -feature_t SetFeature (const StrBuf* Key); -/* Find the feature and set the corresponding flag if the feature is known. -** In any case, return the feature found. An invalid Key will return -** FEAT_UNKNOWN. +void SetFeature (feature_t Feature, unsigned char On); +/* Set the corresponding feature flag if Feature is valid. */ diff --git a/src/ca65/main.c b/src/ca65/main.c index 9710924bf..7183ff046 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -489,12 +489,15 @@ static void OptDebugInfo (const char* Opt attribute ((unused)), static void OptFeature (const char* Opt attribute ((unused)), const char* Arg) /* Set an emulation feature */ { - /* Make a string buffer from Arg */ - StrBuf Feature; + /* Make a string buffer from Arg and use it to find the feature. */ + StrBuf StrFeature; + feature_t Feature = FindFeature (SB_InitFromString (&StrFeature, Arg)); - /* Set the feature, check for errors */ - if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) { + /* Enable the feature, check for errors */ + if (Feature == FEAT_UNKNOWN) { AbEnd ("Illegal emulation feature: '%s'", Arg); + } else { + SetFeature (Feature, 1); } } diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 843f5b9d2..1877512d5 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1023,7 +1023,10 @@ static void DoFatal (void) static void DoFeature (void) /* Switch the Feature option */ { - /* Allow a list of comma separated keywords */ + feature_t Feature; + unsigned char On; + + /* Allow a list of comma separated feature keywords with optional +/- or ON/OFF */ while (1) { /* We expect an identifier */ @@ -1034,18 +1037,24 @@ static void DoFeature (void) /* Make the string attribute lower case */ LocaseSVal (); - - /* Set the feature and check for errors */ - if (SetFeature (&CurTok.SVal) == FEAT_UNKNOWN) { + Feature = FindFeature(&CurTok.SVal); + if (Feature == FEAT_UNKNOWN) { /* Not found */ ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal); return; - } else { - /* Skip the keyword */ - NextTok (); + } + NextTok (); + + /* Optional +/- or ON/OFF */ + On = 1; + if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) { + SetBoolOption(&On); } - /* Allow more than one keyword */ + /* Apply feature setting. */ + SetFeature (Feature, On); + + /* Allow more than one feature separated by commas. */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { From 230230819eb8a10be5eda01ee646acd8ce57c796 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 24 Feb 2023 19:35:38 -0500 Subject: [PATCH 216/360] document the undocumented test/asm/listing behaviours --- test/asm/listing/readme.txt | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/test/asm/listing/readme.txt b/test/asm/listing/readme.txt index e43f2008a..d6280b954 100644 --- a/test/asm/listing/readme.txt +++ b/test/asm/listing/readme.txt @@ -6,22 +6,38 @@ The name of a test is everything in the form <test>.s. The following reference files can be added: -- <test>.bin-ref: +- ref/<test>.bin-ref: This is a reference for the resulting binary. The binary as binary tested against this file. If they are not equal, the test fails. -- <test>.list-ref +- ref/<test>.list-ref This is a reference for the resulting listing output This file *must* have the first line of the listing removed, as that contains a ca65 version string, and almost always this will be changed! +- ref/<test>.err-ref + This is a reference for the resulting ca65 stdout (>) output. + +- ref/<test>.err2-ref + This is a reference for the resulting ca65 stderr (2>) output. + +- ref/<test>.ld65err-ref + This is a reference for the resutling ld65 stdout (>) output. + +- ref/<test>.ld65err2-ref + This is a reference for the resulting ld65 stderr (2>) output. + +The following control files can be added to control the tests. +These files are empty (contents ignored), and only the filename is used: + +- control/<test>.err + Test is expected to produce an error. + +- control/<test>.no-ld65 + Skip the ld65 step. + Note that the resulting .bin file is generated twice: Once with no listing file, and once with listing file. This way, one can find out if the listing file generation changes anything with the resulting binary output. - - -TODO: -- add the possibility to test for specific error output that are to be - expected From c2bc40f2138152c333021cff7d60931d24380f18 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 24 Feb 2023 20:00:56 -0500 Subject: [PATCH 217/360] test for all ca65 .feature options --- test/asm/listing/108-long-rts.s | 8 ++ test/asm/listing/ref/108-long-rts.bin-ref | 1 + test/asm/val/feature.s | 147 ++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 test/asm/listing/108-long-rts.s create mode 100644 test/asm/listing/ref/108-long-rts.bin-ref create mode 100644 test/asm/val/feature.s diff --git a/test/asm/listing/108-long-rts.s b/test/asm/listing/108-long-rts.s new file mode 100644 index 000000000..a8bf860cd --- /dev/null +++ b/test/asm/listing/108-long-rts.s @@ -0,0 +1,8 @@ +; test of long-rts promotion + +.p816 +.feature long_jsr_jmp_rts +.smart + +.proc farproc : far + rts ; should be $6B (RTL) and not $60 (RTS) +.endproc diff --git a/test/asm/listing/ref/108-long-rts.bin-ref b/test/asm/listing/ref/108-long-rts.bin-ref new file mode 100644 index 000000000..23fa7d31a --- /dev/null +++ b/test/asm/listing/ref/108-long-rts.bin-ref @@ -0,0 +1 @@ +k \ No newline at end of file diff --git a/test/asm/val/feature.s b/test/asm/val/feature.s new file mode 100644 index 000000000..4428cf4c2 --- /dev/null +++ b/test/asm/val/feature.s @@ -0,0 +1,147 @@ +; a simple test of every .feature + +.export _main + +.segment "ZEROPAGE" +zplabel: + +.segment "CODE" +abslabel: + +; exit with 0 + +_main: + ; if any feature needs a runtime test, + ; it can be added here. + lda #0 + tax + rts + + +.feature addrsize + +.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" +.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" +.feature addrsize - + + +.feature at_in_identifiers on +ident@with@at: + rts +.feature at_in_identifiers off + + +.feature bracket_as_indirect + lda [$82],y +.feature bracket_as_indirect- + + +.feature c_comments + lda zplabel /* comment */ + /* comment */ +/* multiline +** comment +*/ +.feature c_comments - + + +.feature dollar_in_identifiers +ident$with$dollar: + rts +.feature dollar_in_identifiers - + + +.feature dollar_is_pc +.assert $ = *, error, "dollar_is_pc failure" +.feature dollar_is_pc - + + +.feature force_range + lda #-1 +.feature force_range - + + +.feature labels_without_colons +labelwithoutcolon + jmp labelwithoutcolon +.feature labels_without_colons - + + +.feature leading_dot_in_identifiers +.identifierwithdot: + rts +.feature leading_dot_in_identifiers - + + +.feature long_jsr_jmp_rts +.p816 + ; long addresses require alternate instruction names JSL, JML without this feature + jsr $123456 + jmp $123456 +; smart + far + long_jsr_jmp_rts will promote rts to rtl +.smart + +.proc long_rts : far + rts ; should become RTL ($6B) instead of RTS ($60) + ; the emitted opcode is not verified by this test, + ; see test/asm/listing/108-long-rts +.endproc +.smart - +.p02 +.feature long_jsr_jmp_rts - + + +.feature loose_char_term +.byte 'a' +.byte "a" +.feature loose_char_term - + + +.feature loose_string_term +.asciiz "string" +.asciiz 'string' +.feature loose_string_term - + + +.feature missing_char_term + lda #'a +.feature missing_char_term - + + +.feature org_per_seg +.segment "RODATA" +.org $5678 +.assert * = $5678, error, "org_per_seg failed" +.segment "CODE" +.org $9ABC +.assert * = $9ABC, error, "org_per_seg failed" +.segment "RODATA" +.assert * = $5678, error, "org_per_seg failed" +.reloc +.segment "CODE" +.assert * = $9ABC, error, "org_per_seg failed" +.reloc +.feature org_per_seg - + + +.feature pc_assignment +* = $1234 +.assert * = $1234, error, "pc_assignment failed" +.reloc +.feature pc_assignment - + + +.feature string_escapes +.asciiz "quote:\"" +.feature string_escapes - + + +.feature ubiquitous_idents +.macro bit + brk +.endmacro + bit +.feature ubiquitous_idents - + + +.feature underline_in_numbers +.byte %10_10_10_10 +.feature underline_in_numbers - From cd8fa3906631c6ba4dda3f37077eb0770daf769a Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 24 Feb 2023 22:40:29 -0500 Subject: [PATCH 218/360] optional BRK signature on all 6502 CPUs, not just 65816 (also COP) --- src/ca65/instr.c | 16 ++++---- test/asm/listing/109-brk-signature.s | 36 ++++++++++++++++++ .../asm/listing/ref/109-brk-signature.bin-ref | Bin 0 -> 28 bytes 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 test/asm/listing/109-brk-signature.s create mode 100644 test/asm/listing/ref/109-brk-signature.bin-ref diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 745072a09..2ed5ba734 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -181,7 +181,7 @@ static const struct { { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -252,7 +252,7 @@ static const struct { { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -342,7 +342,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x12, 0, PutPCRel8 }, /* DTV */ - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -418,7 +418,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -510,7 +510,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -622,7 +622,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BSR", 0x0040000, 0x63, 0, PutPCRel4510 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, @@ -756,7 +756,7 @@ static const struct { { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll }, - { "COP", 0x0000004, 0x02, 6, PutAll }, + { "COP", 0x0000005, 0x02, 6, PutAll }, { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */ { "CPX", 0x0c0000c, 0xe0, 1, PutAll }, { "CPY", 0x0c0000c, 0xc0, 1, PutAll }, @@ -909,7 +909,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BSR", 0x0020000, 0x44, 0, PutPCRel8 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, diff --git a/test/asm/listing/109-brk-signature.s b/test/asm/listing/109-brk-signature.s new file mode 100644 index 000000000..b150e088a --- /dev/null +++ b/test/asm/listing/109-brk-signature.s @@ -0,0 +1,36 @@ +; test of optional signature byte for BRK on all 6502-derived CPUs +; and also COP on 65C816 + +.setcpu "6502" +brk ; 1 byte +brk 0 ; 2 bytes +brk $60 ; 2 bytes + +.setcpu "6502X" +brk +brk $60 + +.setcpu "6502DTV" +brk +brk $60 + +.setcpu "65SC02" +brk +brk $60 + +.setcpu "65816" +brk +brk $60 +cop +cop $60 +; WDM is a NOP that gives +2 PC, probably not useful to make its signature byte optional +;wdm +wdm $60 + +.setcpu "4510" +brk +brk $60 + +.setcpu "HuC6280" +brk +brk $60 diff --git a/test/asm/listing/ref/109-brk-signature.bin-ref b/test/asm/listing/ref/109-brk-signature.bin-ref new file mode 100644 index 0000000000000000000000000000000000000000..0f46d29fd39f8d79bd403ca35bd6eb6aa7ced41c GIT binary patch literal 28 TcmZQzU|>i<ModfzPEY{=EA|7Y literal 0 HcmV?d00001 From 3f8252311efaae97cae48b6acb2e76d1a4dcf14f Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 24 Feb 2023 23:00:30 -0500 Subject: [PATCH 219/360] 65C816 document brk optional signature, and mvn/mvp syntax --- doc/ca65.sgml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b65d337bb..d4c002408 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -439,6 +439,14 @@ The assembler accepts <tt><ref id=".P4510" name=".P4510"></tt> command was given). </itemize> +On 6502-derived platforms the <tt/BRK/ instruction has an optional signature +byte. If omitted, the assembler will only produce only 1 byte. + +<tscreen><verb> + brk ; 1-byte: $00 + brk $34 ; 2-bytes: $00 $34 +</verb></tscreen> + <sect1>65816 mode<p> @@ -456,6 +464,17 @@ mnemonics: <item><tt>TSA</tt> is an alias for <tt>TSC</tt> </itemize> +The <tt/MVN/ and <tt/MVP/ instructions accept two different argument forms. +Either two bank bytes may be given with a <tt/#/ prefix, +or two far addresses whose high byte will be used. + +<tscreen><verb> + mvn #^src, #^dst ; bank of src to bank of dst + mvn src, dst ; bank of src to bank of dst + mvp #$12, #$78 ; bank $12 to $78 + mvp $123456, $789ABC ; bank $12 to $78 +</verb></tscreen> + <sect1>6502X mode<label id="6502X-mode"><p> From 3d41a5b51647fbc1c840d2d8167c76456faa3dec Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sat, 25 Feb 2023 08:23:47 -0500 Subject: [PATCH 220/360] allow immedite style syntax variation for BRK signature byte --- doc/ca65.sgml | 1 + src/ca65/instr.c | 20 +++++++++--------- test/asm/listing/109-brk-signature.s | 9 ++++++++ .../asm/listing/ref/109-brk-signature.bin-ref | Bin 28 -> 46 bytes 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index d4c002408..1bef0b551 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -445,6 +445,7 @@ byte. If omitted, the assembler will only produce only 1 byte. <tscreen><verb> brk ; 1-byte: $00 brk $34 ; 2-bytes: $00 $34 + brk #$34 ; 2-bytes: $00 $34 </verb></tscreen> diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 2ed5ba734..b72be6711 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -181,7 +181,7 @@ static const struct { { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -252,7 +252,7 @@ static const struct { { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -342,7 +342,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x12, 0, PutPCRel8 }, /* DTV */ - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -418,7 +418,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -510,7 +510,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -622,7 +622,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BSR", 0x0040000, 0x63, 0, PutPCRel4510 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, @@ -747,7 +747,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BRL", 0x0040000, 0x82, 0, PutPCRel16 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, @@ -756,7 +756,7 @@ static const struct { { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll }, - { "COP", 0x0000005, 0x02, 6, PutAll }, + { "COP", 0x0800005, 0x02, 6, PutAll }, { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */ { "CPX", 0x0c0000c, 0xe0, 1, PutAll }, { "CPY", 0x0c0000c, 0xc0, 1, PutAll }, @@ -833,7 +833,7 @@ static const struct { { "TYA", 0x0000001, 0x98, 0, PutAll }, { "TYX", 0x0000001, 0xbb, 0, PutAll }, { "WAI", 0x0000001, 0xcb, 0, PutAll }, - { "WDM", 0x0000004, 0x42, 6, PutAll }, + { "WDM", 0x0800004, 0x42, 6, PutAll }, { "XBA", 0x0000001, 0xeb, 0, PutAll }, { "XCE", 0x0000001, 0xfb, 0, PutAll } } @@ -909,7 +909,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BSR", 0x0020000, 0x44, 0, PutPCRel8 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, diff --git a/test/asm/listing/109-brk-signature.s b/test/asm/listing/109-brk-signature.s index b150e088a..e9c23dd63 100644 --- a/test/asm/listing/109-brk-signature.s +++ b/test/asm/listing/109-brk-signature.s @@ -5,32 +5,41 @@ brk ; 1 byte brk 0 ; 2 bytes brk $60 ; 2 bytes +brk #$60 ; 2 bytes .setcpu "6502X" brk brk $60 +brk #$60 .setcpu "6502DTV" brk brk $60 +brk #$60 .setcpu "65SC02" brk brk $60 +brk #$60 .setcpu "65816" brk brk $60 +brk #$60 cop cop $60 +cop #$60 ; WDM is a NOP that gives +2 PC, probably not useful to make its signature byte optional ;wdm wdm $60 +wdm #$60 .setcpu "4510" brk brk $60 +brk #$60 .setcpu "HuC6280" brk brk $60 +brk #$60 diff --git a/test/asm/listing/ref/109-brk-signature.bin-ref b/test/asm/listing/ref/109-brk-signature.bin-ref index 0f46d29fd39f8d79bd403ca35bd6eb6aa7ced41c..0eaa09faa5e113f3fe15fcb8e23837523fe04edc 100644 GIT binary patch literal 46 YcmZQzU|>i9LM#LmQvy?h6A&UK0hde%O8@`> literal 28 TcmZQzU|>i<ModfzPEY{=EA|7Y From e87325033d04955ea871e367f015b7ec508ae481 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 25 Feb 2023 12:39:36 -0500 Subject: [PATCH 221/360] Fix .endmacro in a .define in a macro body --- src/ca65/macro.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 4812b12c4..16d916c88 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -391,6 +391,7 @@ void MacDef (unsigned Style) Macro* M; TokNode* N; int HaveParams; + int DefineActive = 0; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { @@ -491,8 +492,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed */ - if (CurTok.Tok == TOK_ENDMACRO) { + /* In classic macros, only .endmacro is allowed, but ignore it if it is in a .define */ + if (CurTok.Tok == TOK_ENDMACRO && !DefineActive) { /* Done */ break; } @@ -573,6 +574,13 @@ void MacDef (unsigned Style) } ++M->TokCount; + /* Mark if .define has been read until end of line has been reached */ + if (CurTok.Tok == TOK_DEFINE) { + DefineActive = 1; + } else if (TokIsSep(CurTok.Tok)) { + DefineActive = 0; + } + /* Read the next token */ NextTok (); } @@ -582,7 +590,7 @@ void MacDef (unsigned Style) NextTok (); } - /* Reset the Incomplete flag now that parsing is done */ +/* Reset the Incomplete flag now that parsing is done */ M->Incomplete = 0; Done: From 429e90dffdc326bbb23a332ea3b7b11dc67f8c67 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 25 Feb 2023 12:42:26 -0500 Subject: [PATCH 222/360] Fix .endmacro in a .define in a macro body --- src/ca65/macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 16d916c88..24cdcad38 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -590,7 +590,7 @@ void MacDef (unsigned Style) NextTok (); } -/* Reset the Incomplete flag now that parsing is done */ + /* Reset the Incomplete flag now that parsing is done */ M->Incomplete = 0; Done: From 0a05f78d47c8a6ea20b97fd570d0f5db054aa387 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 25 Feb 2023 13:38:02 -0500 Subject: [PATCH 223/360] Fix .endmacro not at the start of the line. --- src/ca65/macro.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 24cdcad38..c09b2412f 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -391,7 +391,7 @@ void MacDef (unsigned Style) Macro* M; TokNode* N; int HaveParams; - int DefineActive = 0; + int LastTokWasSep = 0; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { @@ -493,7 +493,7 @@ void MacDef (unsigned Style) /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { /* In classic macros, only .endmacro is allowed, but ignore it if it is in a .define */ - if (CurTok.Tok == TOK_ENDMACRO && !DefineActive) { + if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } @@ -574,12 +574,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Mark if .define has been read until end of line has been reached */ - if (CurTok.Tok == TOK_DEFINE) { - DefineActive = 1; - } else if (TokIsSep(CurTok.Tok)) { - DefineActive = 0; - } + /* Save if last token was a separator to know if .endmacro is valid */ + LastTokWasSep = TokIsSep(CurTok.Tok); /* Read the next token */ NextTok (); From 4b29615f2bad008cc5a7b015616883a4e837972b Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 25 Feb 2023 13:49:19 -0500 Subject: [PATCH 224/360] Fix .endmacro not at the start of the line. Allow empty macro --- src/ca65/macro.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index c09b2412f..fa90009b5 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -480,6 +480,7 @@ void MacDef (unsigned Style) */ if (Style == MAC_STYLE_CLASSIC) { ConsumeSep (); + LastTokWasSep = 1; } else if (HaveParams) { ConsumeRParen (); } From 7d894fbe04f64aa0917404412cc5b14a1c970818 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 25 Feb 2023 13:52:13 -0500 Subject: [PATCH 225/360] Fix .endmacro not at the start of the line. Fix comment --- src/ca65/macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index fa90009b5..92a0f6e9a 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -493,7 +493,7 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed, but ignore it if it is in a .define */ + /* In classic macros, only .endmacro is allowed, but ignore it if it is not at the start of the line */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; From ffa83c32a4d4cb2f7bd7749aa3e2766c370e60a7 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sun, 26 Feb 2023 20:03:41 +0100 Subject: [PATCH 226/360] clean-up of driver return codes --- Contributing.md | 17 +++++++- libsrc/apple2/emd/a2.auxmem.s | 3 +- libsrc/apple2/joy/a2.stdjoy.s | 5 ++- libsrc/apple2/mou/a2.stdmou.s | 4 +- libsrc/apple2/ser/a2.ssc.s | 43 +++++++++++-------- libsrc/atari/joy/atrmj8.s | 3 +- libsrc/atari/joy/atrstd.s | 3 +- libsrc/atari/mou/atrjoy.s | 5 ++- libsrc/atari/mou/atrst.s | 5 ++- libsrc/atari/mou/atrtt.s | 5 ++- libsrc/atari/ser/atrrdev.s | 35 ++++++++------- libsrc/atari5200/joy/atr5200std.s | 3 +- libsrc/atari7800/joy/atari7800-stdjoy.s | 5 ++- libsrc/atmos/joy/atmos-ijk.s | 7 +-- libsrc/atmos/joy/atmos-pase.s | 3 +- libsrc/atmos/ser/atmos-acia.s | 28 ++++++------ libsrc/atmos/tgi/atmos-228-200-3.s | 3 +- libsrc/c128/emd/c128-efnram.s | 7 +-- libsrc/c128/emd/c128-georam.s | 8 ++-- libsrc/c128/emd/c128-ifnram.s | 7 +-- libsrc/c128/emd/c128-ram.s | 3 +- libsrc/c128/emd/c128-ram2.s | 3 +- libsrc/c128/emd/c128-ramcart.s | 9 ++-- libsrc/c128/emd/c128-reu.s | 5 ++- libsrc/c128/emd/c128-vdc.s | 5 ++- libsrc/c128/joy/c128-ptvjoy.s | 5 ++- libsrc/c128/joy/c128-stdjoy.s | 5 ++- libsrc/c128/mou/c128-1351.s | 5 ++- libsrc/c128/mou/c128-inkwell.s | 3 +- libsrc/c128/mou/c128-joy.s | 5 ++- libsrc/c128/mou/c128-pot.s | 5 ++- libsrc/c128/ser/c128-swlink.s | 39 +++++++++-------- libsrc/c16/emd/c16-ram.s | 9 ++-- libsrc/c64/emd/c64-65816.s | 9 ++-- libsrc/c64/emd/c64-c256k.s | 9 ++-- libsrc/c64/emd/c64-dqbb.s | 9 ++-- libsrc/c64/emd/c64-georam.s | 9 ++-- libsrc/c64/emd/c64-isepic.s | 9 ++-- libsrc/c64/emd/c64-kerberos.s | 9 ++-- libsrc/c64/emd/c64-ram.s | 5 ++- libsrc/c64/emd/c64-ramcart.s | 8 ++-- libsrc/c64/emd/c64-reu.s | 6 ++- libsrc/c64/emd/c64-vdc.s | 9 ++-- libsrc/c64/emd/dtv-himem.s | 9 ++-- libsrc/c64/joy/c64-hitjoy.s | 5 ++- libsrc/c64/joy/c64-numpad.s | 10 +++-- libsrc/c64/joy/c64-ptvjoy.s | 5 ++- libsrc/c64/joy/c64-stdjoy.s | 5 ++- libsrc/c64/mou/c64-1351.s | 9 ++-- libsrc/c64/mou/c64-inkwell.s | 5 ++- libsrc/c64/mou/c64-joy.s | 9 ++-- libsrc/c64/mou/c64-pot.s | 9 ++-- libsrc/c64/ser/c64-swlink.s | 39 +++++++++-------- libsrc/cbm510/emd/cbm510-ram.s | 5 ++- libsrc/cbm510/joy/cbm510-std.s | 5 ++- libsrc/cbm510/mou/cbm510-inkwl.s | 5 ++- libsrc/cbm510/mou/cbm510-joy.s | 7 +-- libsrc/cbm510/ser/cbm510-std.s | 34 ++++++++------- libsrc/cbm610/emd/cbm610-ram.s | 5 ++- libsrc/cbm610/ser/cbm610-std.s | 31 +++++++------ libsrc/creativision/joy/creativision-stdjoy.s | 3 +- libsrc/cx16/joy/cx16-std.s | 5 ++- libsrc/cx16/mou/cx16-std.s | 7 +-- libsrc/gamate/joy/gamate-stdjoy.s | 5 ++- libsrc/geos-cbm/emd/geos-vdc.s | 5 ++- libsrc/geos-cbm/joy/geos-stdjoy.s | 5 ++- libsrc/joystick/joy_unload.s | 7 ++- libsrc/lynx/joy/lynx-stdjoy.s | 5 ++- libsrc/lynx/ser/lynx-comlynx.s | 33 +++++++------- libsrc/mouse/mouse_unload.s | 7 ++- libsrc/nes/joy/nes-stdjoy.s | 3 +- libsrc/pce/joy/pce-stdjoy.s | 5 ++- libsrc/pet/joy/pet-ptvjoy.s | 5 ++- libsrc/plus4/joy/plus4-stdjoy.s | 5 ++- libsrc/plus4/ser/plus4-stdser.s | 34 ++++++++------- libsrc/serial/ser_unload.s | 10 ++--- libsrc/supervision/joy/supervision-stdjoy.s | 5 ++- libsrc/telestrat/joy/telestrat.s | 5 ++- libsrc/vic20/emd/vic20-georam.s | 8 ++-- libsrc/vic20/emd/vic20-rama.s | 9 ++-- libsrc/vic20/joy/vic20-ptvjoy.s | 5 ++- libsrc/vic20/joy/vic20-stdjoy.s | 5 ++- 82 files changed, 438 insertions(+), 322 deletions(-) diff --git a/Contributing.md b/Contributing.md index 74e6ead17..eb26e920b 100644 --- a/Contributing.md +++ b/Contributing.md @@ -134,7 +134,22 @@ You can refer to Annex B of the ISO C99 standard ([here](https://www.open-std.or * Hexadecimal number constants should be used except where decimal or binary numbers make much more sense in that constant's context. * Hexadecimal letters should be upper-case. * When you set two registers or two memory locations to an immediate 16-bit zero, you should use the expressions ```#<$0000``` and ```#>$0000``` (they make it obvious where you are putting the lower and upper bytes). -* If a function is declared to return a char-sized value, it actually must return an integer-sized value. (When cc65 promotes a returned value, it sometimes assumes that the value already is an integer.) +* If a function is declared to return a char-sized value, it actually must return an integer-sized value. (When cc65 promotes a returned value, it sometimes assumes that the value already is an integer.) This must be done in one of the following ways: +<pre> + lda #RETURN_VALUE + ldx #0 ; return value is char +</pre> +or, if the value is 0, you can use: +<pre> + lda #RETURN_VALUE + .assert RETURN_VALUE = 0 + tax +</pre> +sometimes jumping to return0 could save a byte: +<pre> + .assert RETURN_VALUE = 0 + jmp return 0 +</pre> * Functions, that are intended for a platform's system library, should be optimized as much as possible. * Sometimes, there must be a trade-off between size and speed. If you think that a library function won't be used often, then you should make it small. Otherwise, you should make it fast. * Comments that are put on the right side of instructions must be aligned (start in the same character columns). diff --git a/libsrc/apple2/emd/a2.auxmem.s b/libsrc/apple2/emd/a2.auxmem.s index 5ef2564b1..c582e9eec 100644 --- a/libsrc/apple2/emd/a2.auxmem.s +++ b/libsrc/apple2/emd/a2.auxmem.s @@ -73,7 +73,8 @@ INSTALL: and #$f0 cmp #$80 bne @L1 - lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + txa rts @L1: lda #EM_ERR_NO_DEVICE ; rts diff --git a/libsrc/apple2/joy/a2.stdjoy.s b/libsrc/apple2/joy/a2.stdjoy.s index 558013910..11be52eb4 100644 --- a/libsrc/apple2/joy/a2.stdjoy.s +++ b/libsrc/apple2/joy/a2.stdjoy.s @@ -71,8 +71,9 @@ INSTALL: stx gettype+2 gettype:jsr $0000 sta ostype - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; Fall through ; UNINSTALL routine. Is called before the driver is removed from memory. diff --git a/libsrc/apple2/mou/a2.stdmou.s b/libsrc/apple2/mou/a2.stdmou.s index dfc69a942..c54c09d34 100644 --- a/libsrc/apple2/mou/a2.stdmou.s +++ b/libsrc/apple2/mou/a2.stdmou.s @@ -133,8 +133,8 @@ next: inc ptr1+1 bcc :+ ; Mouse firmware not found - lda #<MOUSE_ERR_NO_DEVICE - ldx #>MOUSE_ERR_NO_DEVICE + lda #MOUSE_ERR_NO_DEVICE + ldx #0 ; return value is char rts ; Check Pascal 1.1 Firmware Protocol ID bytes diff --git a/libsrc/apple2/ser/a2.ssc.s b/libsrc/apple2/ser/a2.ssc.s index d49bf3526..6ad9c3825 100644 --- a/libsrc/apple2/ser/a2.ssc.s +++ b/libsrc/apple2/ser/a2.ssc.s @@ -168,8 +168,9 @@ SER_CLOSE: sta ACIA_CMD,x ; Done, return an error code -: lda #<SER_ERR_OK - tax ; A is zero +: lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax stx Index ; Mark port as closed rts @@ -256,23 +257,24 @@ SER_OPEN: ; Done stx Index ; Mark port as open - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Device (hardware) not found -NoDevice:lda #<SER_ERR_NO_DEVICE - ldx #>SER_ERR_NO_DEVICE +NoDevice:lda #SER_ERR_NO_DEVICE + ldx #0 ; return value is char rts ; Invalid parameter -InvParam:lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED +InvParam:lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available -InvBaud:lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL +InvBaud:lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -292,8 +294,8 @@ SER_GET: : lda RecvFreeCnt ; (25) cmp #$FF bne :+ - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -336,8 +338,8 @@ SER_PUT: ; Put byte into send buffer & send : ldy SendFreeCnt bne :+ - lda #<SER_ERR_OVERFLOW - ldx #>SER_ERR_OVERFLOW + lda #SER_ERR_OVERFLOW + ldx #0 ; return value is char rts : ldy SendTail @@ -346,7 +348,8 @@ SER_PUT: dec SendFreeCnt lda #$FF ; TryHard = true jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -359,7 +362,8 @@ SER_STATUS: lda ACIA_STATUS,x ldx #$00 sta (ptr1,x) - txa ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + txa rts ;---------------------------------------------------------------------------- @@ -379,11 +383,12 @@ SER_IOCTL: bcs :+ stx Slot - tax ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts -: lda #<SER_ERR_INV_IOCTL - ldx #>SER_ERR_INV_IOCTL +: lda #SER_ERR_INV_IOCTL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/atari/joy/atrmj8.s b/libsrc/atari/joy/atrmj8.s index 3a26c381d..daf11651d 100644 --- a/libsrc/atari/joy/atrmj8.s +++ b/libsrc/atari/joy/atrmj8.s @@ -69,7 +69,8 @@ INSTALL: lda #$34 sta PACTL lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/joy/atrstd.s b/libsrc/atari/joy/atrstd.s index fd1d99d31..1a124192f 100644 --- a/libsrc/atari/joy/atrstd.s +++ b/libsrc/atari/joy/atrstd.s @@ -62,7 +62,8 @@ JOY_COUNT = 4 ; Number of joysticks we support INSTALL: lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s index 3ea428576..a93c7de13 100644 --- a/libsrc/atari/mou/atrjoy.s +++ b/libsrc/atari/mou/atrjoy.s @@ -137,9 +137,10 @@ INSTALL: ldx YPos+1 jsr CMOVEY -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s index 5d8a5cd12..626b7a8f7 100644 --- a/libsrc/atari/mou/atrst.s +++ b/libsrc/atari/mou/atrst.s @@ -268,9 +268,10 @@ INSTALL: and #$0f sta old_porta_vbi -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index 61963aa61..b1e53935e 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -132,9 +132,10 @@ INSTALL: ldx YPos+1 jsr CMOVEY -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/atari/ser/atrrdev.s b/libsrc/atari/ser/atrrdev.s index 3a7bc21c2..1d2b98e8d 100644 --- a/libsrc/atari/ser/atrrdev.s +++ b/libsrc/atari/ser/atrrdev.s @@ -135,8 +135,8 @@ my_CIOV: .code invbaud: - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char openerr: rts @@ -229,8 +229,9 @@ SER_OPEN: jsr my_CIOV bmi cioerr - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts inverr: jmp my___inviocb @@ -240,8 +241,8 @@ cioerr: jsr my_fddecusage ; decrement usage counter of fd as open failed init_err: - ldx #0 lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ;---- open the device @@ -313,8 +314,9 @@ SER_CLOSE: stx rshand+1 inx stx cm_run -@done: lda #<SER_ERR_OK - ldx #>SER_ERR_OK +@done: lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -365,16 +367,16 @@ SER_GET: rts @nix_da:lda #SER_ERR_NO_DATA - ldx #0 + ldx #0 ; return value is char rts ser_error: lda #SER_ERR_OVERFLOW ; there is no large selection of serial error codes... :-/ - ldx #0 + ldx #0 ; return value is char rts ni_err: lda #SER_ERR_NOT_OPEN - ldx #0 + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -427,8 +429,8 @@ SER_STATUS: ; SER_IOCTL: - lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -456,8 +458,8 @@ search: lda HATABS,y ; get device name ; R: device not found, return error - lda #<SER_ERR_NO_DEVICE - ldx #0 + lda #SER_ERR_NO_DEVICE + ldx #0 ; return value is char rts ; R: device found, initialize jump table into main program @@ -554,8 +556,9 @@ found: lda ptr3 pla sta ptr3 - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts diff --git a/libsrc/atari5200/joy/atr5200std.s b/libsrc/atari5200/joy/atr5200std.s index fb7946bea..980428d13 100644 --- a/libsrc/atari5200/joy/atr5200std.s +++ b/libsrc/atari5200/joy/atr5200std.s @@ -47,7 +47,8 @@ INSTALL: lda #$04 ; enable POT input from the joystick ports, see section "GTIA" in sta CONSOL ; http://www.atarimuseum.com/videogames/consoles/5200/conv_to_5200.html lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atari7800/joy/atari7800-stdjoy.s b/libsrc/atari7800/joy/atari7800-stdjoy.s index d76e1d105..59f656ada 100644 --- a/libsrc/atari7800/joy/atari7800-stdjoy.s +++ b/libsrc/atari7800/joy/atari7800-stdjoy.s @@ -62,8 +62,9 @@ INSTALL: sty SWCHB ; enable 2-button 7800 controller 2: pull pin 6 (INPT4) high reset: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/joy/atmos-ijk.s b/libsrc/atmos/joy/atmos-ijk.s index 6e75a3e0b..c2bdd67ab 100644 --- a/libsrc/atmos/joy/atmos-ijk.s +++ b/libsrc/atmos/joy/atmos-ijk.s @@ -55,11 +55,12 @@ INSTALL: lda VIA::PRA and #%00100000 bne ijkPresent - lda #<JOY_ERR_NO_DEVICE + lda #JOY_ERR_NO_DEVICE .byte $2C ; Skip next opcode ijkPresent: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/joy/atmos-pase.s b/libsrc/atmos/joy/atmos-pase.s index fd64901c9..d9982cafe 100644 --- a/libsrc/atmos/joy/atmos-pase.s +++ b/libsrc/atmos/joy/atmos-pase.s @@ -58,7 +58,8 @@ temp2: .byte $00 INSTALL: lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/ser/atmos-acia.s b/libsrc/atmos/ser/atmos-acia.s index f84b66a0a..f679125d1 100644 --- a/libsrc/atmos/ser/atmos-acia.s +++ b/libsrc/atmos/ser/atmos-acia.s @@ -141,8 +141,9 @@ SER_CLOSE: sta ACIA::CMD,x ; Done, return an error code -: lda #<SER_ERR_OK - tax ; A is zero +: lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax stx Index ; Mark port as closed rts @@ -205,8 +206,9 @@ SER_OPEN: ; Done stx Index ; Mark port as open - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Invalid parameter @@ -235,8 +237,8 @@ SER_GET: : lda RecvFreeCnt ; (25) cmp #$FF bne :+ - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -277,8 +279,8 @@ SER_PUT: ; Put byte into send buffer & send : ldy SendFreeCnt bne :+ - lda #<SER_ERR_OVERFLOW - ldx #>SER_ERR_OVERFLOW + lda #SER_ERR_OVERFLOW + ldx #0 ; return value is char rts : ldy SendTail @@ -287,7 +289,8 @@ SER_PUT: dec SendFreeCnt lda #$FF ; TryHard = true jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -299,7 +302,8 @@ SER_STATUS: lda ACIA::STATUS ldx #$00 sta (ptr1,x) - txa ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + txa rts ;---------------------------------------------------------------------------- @@ -308,8 +312,8 @@ SER_STATUS: ; Must return an SER_ERR_xx code in a/x. SER_IOCTL: - lda #<SER_ERR_INV_IOCTL - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/atmos/tgi/atmos-228-200-3.s b/libsrc/atmos/tgi/atmos-228-200-3.s index 98d2cef96..466f6922a 100644 --- a/libsrc/atmos/tgi/atmos-228-200-3.s +++ b/libsrc/atmos/tgi/atmos-228-200-3.s @@ -215,7 +215,8 @@ SETPALETTE: jsr PAPER ldy #1 jsr flipcolor - dey ; TGI_ERR_OK + .assert TGI_ERR_OK = 0, error + dey sty ERROR sty PARAM1+1 jmp INK diff --git a/libsrc/c128/emd/c128-efnram.s b/libsrc/c128/emd/c128-efnram.s index 788c73e0f..909c90048 100644 --- a/libsrc/c128/emd/c128-efnram.s +++ b/libsrc/c128/emd/c128-efnram.s @@ -87,16 +87,17 @@ INSTALL: cli cmp tmp1 beq @ram_present - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @ram_present: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-georam.s b/libsrc/c128/emd/c128-georam.s index 7511c6841..ecf12f6cd 100644 --- a/libsrc/c128/emd/c128-georam.s +++ b/libsrc/c128/emd/c128-georam.s @@ -120,16 +120,16 @@ INSTALL: bne @setok @notpresent: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @setok: lda #0 sta pagecount stx pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts check: diff --git a/libsrc/c128/emd/c128-ifnram.s b/libsrc/c128/emd/c128-ifnram.s index 01a4fdf8e..c51b775b2 100644 --- a/libsrc/c128/emd/c128-ifnram.s +++ b/libsrc/c128/emd/c128-ifnram.s @@ -87,16 +87,17 @@ INSTALL: cli cmp tmp1 beq @ram_present - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @ram_present: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-ram.s b/libsrc/c128/emd/c128-ram.s index 3fc52c9cc..0ae504b84 100644 --- a/libsrc/c128/emd/c128-ram.s +++ b/libsrc/c128/emd/c128-ram.s @@ -68,8 +68,9 @@ INSTALL: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-ram2.s b/libsrc/c128/emd/c128-ram2.s index 7d2703fa5..92e72700a 100644 --- a/libsrc/c128/emd/c128-ram2.s +++ b/libsrc/c128/emd/c128-ram2.s @@ -107,8 +107,9 @@ INSTALL: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-ramcart.s b/libsrc/c128/emd/c128-ramcart.s index e72d053ac..c58c1cd1b 100644 --- a/libsrc/c128/emd/c128-ramcart.s +++ b/libsrc/c128/emd/c128-ramcart.s @@ -97,13 +97,14 @@ INSTALL: lda #0 sta pagecount stx pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @notpresent: @readonly: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-reu.s b/libsrc/c128/emd/c128-reu.s index 84e7cb695..8228a0517 100644 --- a/libsrc/c128/emd/c128-reu.s +++ b/libsrc/c128/emd/c128-reu.s @@ -126,8 +126,9 @@ size_found: pagecount_ok: stx pagecount sty pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts ; common REU setup for size check diff --git a/libsrc/c128/emd/c128-vdc.s b/libsrc/c128/emd/c128-vdc.s index accb82154..8d0b77fd2 100644 --- a/libsrc/c128/emd/c128-vdc.s +++ b/libsrc/c128/emd/c128-vdc.s @@ -121,8 +121,9 @@ INSTALL: lda vdc_cset_save jsr vdcputreg @keep64kBit: - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts test64k: diff --git a/libsrc/c128/joy/c128-ptvjoy.s b/libsrc/c128/joy/c128-ptvjoy.s index 180f7667d..0a1c53587 100644 --- a/libsrc/c128/joy/c128-ptvjoy.s +++ b/libsrc/c128/joy/c128-ptvjoy.s @@ -53,8 +53,9 @@ JOY_COUNT = 4 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/joy/c128-stdjoy.s b/libsrc/c128/joy/c128-stdjoy.s index bf2e2fea7..ee04374ee 100644 --- a/libsrc/c128/joy/c128-stdjoy.s +++ b/libsrc/c128/joy/c128-stdjoy.s @@ -57,8 +57,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/mou/c128-1351.s b/libsrc/c128/mou/c128-1351.s index 79ccbe0de..76e28d9f7 100644 --- a/libsrc/c128/mou/c128-1351.s +++ b/libsrc/c128/mou/c128-1351.s @@ -194,9 +194,10 @@ INSTALL: sta (ptr3),y cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/c128/mou/c128-inkwell.s b/libsrc/c128/mou/c128-inkwell.s index b8e71bbb1..2aac7d32d 100644 --- a/libsrc/c128/mou/c128-inkwell.s +++ b/libsrc/c128/mou/c128-inkwell.s @@ -228,9 +228,10 @@ INSTALL: jsr MoveX cli -; Done, return zero. +; Done lda #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error tax rts diff --git a/libsrc/c128/mou/c128-joy.s b/libsrc/c128/mou/c128-joy.s index 065674dc0..d809db526 100644 --- a/libsrc/c128/mou/c128-joy.s +++ b/libsrc/c128/mou/c128-joy.s @@ -195,9 +195,10 @@ INSTALL: sta (ptr3),y cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/c128/mou/c128-pot.s b/libsrc/c128/mou/c128-pot.s index e582d64fb..1cbe4aa18 100644 --- a/libsrc/c128/mou/c128-pot.s +++ b/libsrc/c128/mou/c128-pot.s @@ -195,9 +195,10 @@ INSTALL: sta (ptr3),y cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/c128/ser/c128-swlink.s b/libsrc/c128/ser/c128-swlink.s index 3337e2668..7d36eb5bc 100644 --- a/libsrc/c128/ser/c128-swlink.s +++ b/libsrc/c128/ser/c128-swlink.s @@ -187,8 +187,9 @@ SetNMI: sta NMIVec ; Done, return an error code - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -264,22 +265,23 @@ SER_OPEN: ; Done - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Invalid parameter InvParam: - lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -300,8 +302,9 @@ SER_CLOSE: ; Return OK - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -322,8 +325,8 @@ SER_GET: @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -370,7 +373,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #<SER_ERR_OVERFLOW ; X is already zero + lda #SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail @@ -379,7 +382,8 @@ SER_PUT: dec SendFreeCnt lda #$ff jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -392,7 +396,8 @@ SER_STATUS: lda ACIA_STATUS ldx #0 sta (ptr1,x) - txa ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + txa rts ;---------------------------------------------------------------------------- @@ -402,8 +407,8 @@ SER_STATUS: ; SER_IOCTL: - lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c16/emd/c16-ram.s b/libsrc/c16/emd/c16-ram.s index a8083aca4..937019974 100644 --- a/libsrc/c16/emd/c16-ram.s +++ b/libsrc/c16/emd/c16-ram.s @@ -77,12 +77,13 @@ INSTALL: ldx #$FF stx curpage ; Invalidate the current page - inx ; X = 0 - txa ; A = X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa rts -nomem: ldx #>EM_ERR_NO_DEVICE - lda #<EM_ERR_NO_DEVICE +nomem: ldx #EM_ERR_NO_DEVICE + lda #0 ; return value is char ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-65816.s b/libsrc/c64/emd/c64-65816.s index 39f323d28..ce9491fbe 100644 --- a/libsrc/c64/emd/c64-65816.s +++ b/libsrc/c64/emd/c64-65816.s @@ -120,13 +120,14 @@ INSTALL: dex @noextradex: stx bankcount - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @not_present: cli - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/emd/c64-c256k.s b/libsrc/c64/emd/c64-c256k.s index 79706e8fb..5a4bc54c3 100644 --- a/libsrc/c64/emd/c64-c256k.s +++ b/libsrc/c64/emd/c64-c256k.s @@ -158,13 +158,14 @@ INSTALL: jsr restore_data cpy #$01 beq @present - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @present: - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-dqbb.s b/libsrc/c64/emd/c64-dqbb.s index 986c5939d..6a63b3baa 100644 --- a/libsrc/c64/emd/c64-dqbb.s +++ b/libsrc/c64/emd/c64-dqbb.s @@ -147,13 +147,14 @@ INSTALL: jsr restore_data cpy #$01 beq @present - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @present: - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-georam.s b/libsrc/c64/emd/c64-georam.s index 97f1a7cc4..0116fe8ea 100644 --- a/libsrc/c64/emd/c64-georam.s +++ b/libsrc/c64/emd/c64-georam.s @@ -121,16 +121,17 @@ INSTALL: bne @setok @notpresent: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + .assert EM_ERR_OK = 0, error + tax rts @setok: lda #0 sta pagecount stx pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts check: diff --git a/libsrc/c64/emd/c64-isepic.s b/libsrc/c64/emd/c64-isepic.s index 3764443e2..2b7949757 100644 --- a/libsrc/c64/emd/c64-isepic.s +++ b/libsrc/c64/emd/c64-isepic.s @@ -76,13 +76,14 @@ INSTALL: beq @setok @notpresent: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @setok: - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-kerberos.s b/libsrc/c64/emd/c64-kerberos.s index 30183362f..20be4e409 100644 --- a/libsrc/c64/emd/c64-kerberos.s +++ b/libsrc/c64/emd/c64-kerberos.s @@ -82,13 +82,14 @@ INSTALL: cmp #$AA bne @notpresent - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @notpresent: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; use rts from UNINSTALL below ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-ram.s b/libsrc/c64/emd/c64-ram.s index 5355b552d..cdd7b8965 100644 --- a/libsrc/c64/emd/c64-ram.s +++ b/libsrc/c64/emd/c64-ram.s @@ -65,8 +65,9 @@ window: .res 256 ; Memory "window" INSTALL: ldx #$FF stx curpage ; Invalidate the current page - inx ; X = 0 - txa ; A = X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-ramcart.s b/libsrc/c64/emd/c64-ramcart.s index 8998bb6d6..a99f25b4f 100644 --- a/libsrc/c64/emd/c64-ramcart.s +++ b/libsrc/c64/emd/c64-ramcart.s @@ -98,13 +98,13 @@ INSTALL: lda #0 sta pagecount stx pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @notpresent: @readonly: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-reu.s b/libsrc/c64/emd/c64-reu.s index 07ac1fbed..832e66f51 100644 --- a/libsrc/c64/emd/c64-reu.s +++ b/libsrc/c64/emd/c64-reu.s @@ -127,8 +127,9 @@ size_found: pagecount_ok: stx pagecount sty pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts ; common REU setup for size check @@ -152,6 +153,7 @@ reu_size_check_common: nodevice: lda #EM_ERR_NO_DEVICE + .assert EM_ERR_OK = 0, error ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-vdc.s b/libsrc/c64/emd/c64-vdc.s index 2448f09d4..60fbccbbf 100644 --- a/libsrc/c64/emd/c64-vdc.s +++ b/libsrc/c64/emd/c64-vdc.s @@ -87,8 +87,8 @@ INSTALL: bne @L0 iny bne @L0 - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE +; ldx #0 ; return value is char rts @present: @@ -131,8 +131,9 @@ INSTALL: sta pagecount stx pagecount+1 @endok: - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts test64k: diff --git a/libsrc/c64/emd/dtv-himem.s b/libsrc/c64/emd/dtv-himem.s index 6dde874f7..4d19b19d5 100644 --- a/libsrc/c64/emd/dtv-himem.s +++ b/libsrc/c64/emd/dtv-himem.s @@ -93,15 +93,16 @@ INSTALL: ; DTV not found - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @present: ldx #$FF stx curpage+1 ; Invalidate curpage - inx ; X = 0 - txa ; A/X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/joy/c64-hitjoy.s b/libsrc/c64/joy/c64-hitjoy.s index 3b4a0b909..a9d454fd0 100644 --- a/libsrc/c64/joy/c64-hitjoy.s +++ b/libsrc/c64/joy/c64-hitjoy.s @@ -59,8 +59,9 @@ temp4: .byte 0 ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/joy/c64-numpad.s b/libsrc/c64/joy/c64-numpad.s index 0ccdc4fcd..f6839d6cf 100644 --- a/libsrc/c64/joy/c64-numpad.s +++ b/libsrc/c64/joy/c64-numpad.s @@ -100,12 +100,14 @@ masktable: ; INSTALL: - lda #JOY_ERR_OK ; Assume we have a joystick - ldx VIC_CLK_128 ; Test for a C128 - cpx #$FF + lda #JOY_ERR_OK ; Assume we have a "joystick" + .assert JOY_ERR_OK = 0, error + tax ; Set high byte + ldy VIC_CLK_128 ; Test for a C128 + cpy #$FF bne @C128 ; Jump if we have one lda #JOY_ERR_NO_DEVICE ; No C128 -> no numpad -@C128: ldx #0 ; Set high byte +@C128: ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/joy/c64-ptvjoy.s b/libsrc/c64/joy/c64-ptvjoy.s index a772fb5f6..30466b2c2 100644 --- a/libsrc/c64/joy/c64-ptvjoy.s +++ b/libsrc/c64/joy/c64-ptvjoy.s @@ -52,8 +52,9 @@ JOY_COUNT = 4 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/joy/c64-stdjoy.s b/libsrc/c64/joy/c64-stdjoy.s index d11093fba..511032507 100644 --- a/libsrc/c64/joy/c64-stdjoy.s +++ b/libsrc/c64/joy/c64-stdjoy.s @@ -56,8 +56,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/mou/c64-1351.s b/libsrc/c64/mou/c64-1351.s index a7d042c7b..ce0f18803 100644 --- a/libsrc/c64/mou/c64-1351.s +++ b/libsrc/c64/mou/c64-1351.s @@ -152,9 +152,10 @@ INSTALL: jsr CMOVEY cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -307,8 +308,8 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/mou/c64-inkwell.s b/libsrc/c64/mou/c64-inkwell.s index 9c876a7c8..d2f14a6f0 100644 --- a/libsrc/c64/mou/c64-inkwell.s +++ b/libsrc/c64/mou/c64-inkwell.s @@ -168,6 +168,7 @@ INSTALL: ; Done, return zero. lda #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error tax rts @@ -319,8 +320,8 @@ INFO: jsr POS ; Must return an error code in .XA. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/mou/c64-joy.s b/libsrc/c64/mou/c64-joy.s index f2a501000..5ee1b4f84 100644 --- a/libsrc/c64/mou/c64-joy.s +++ b/libsrc/c64/mou/c64-joy.s @@ -156,9 +156,10 @@ INSTALL: jsr CMOVEY cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -312,8 +313,8 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/mou/c64-pot.s b/libsrc/c64/mou/c64-pot.s index 102ca351c..9bdf24f62 100644 --- a/libsrc/c64/mou/c64-pot.s +++ b/libsrc/c64/mou/c64-pot.s @@ -139,9 +139,10 @@ INSTALL: jsr CMOVEY cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -297,8 +298,8 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/ser/c64-swlink.s b/libsrc/c64/ser/c64-swlink.s index 597cf1dd6..81c9916a6 100644 --- a/libsrc/c64/ser/c64-swlink.s +++ b/libsrc/c64/ser/c64-swlink.s @@ -161,8 +161,9 @@ SetNMI: sta NMIVec ; Done, return an error code - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -238,22 +239,23 @@ SER_OPEN: ; Done - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Invalid parameter InvParam: - lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -274,8 +276,9 @@ SER_CLOSE: ; Return OK - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -296,8 +299,8 @@ SER_GET: @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -344,7 +347,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #<SER_ERR_OVERFLOW ; X is already zero + lda #SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail @@ -353,7 +356,8 @@ SER_PUT: dec SendFreeCnt lda #$ff jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -366,7 +370,8 @@ SER_STATUS: lda ACIA_STATUS ldx #0 sta (ptr1,x) - txa ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + txa rts ;---------------------------------------------------------------------------- @@ -376,8 +381,8 @@ SER_STATUS: ; SER_IOCTL: - lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm510/emd/cbm510-ram.s b/libsrc/cbm510/emd/cbm510-ram.s index f724c7360..6cc319b7f 100644 --- a/libsrc/cbm510/emd/cbm510-ram.s +++ b/libsrc/cbm510/emd/cbm510-ram.s @@ -81,8 +81,9 @@ INSTALL: sbc #$00 sta pagecount -@L1: lda #<EM_ERR_OK - ldx #>EM_ERR_OK +@L1: lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cbm510/joy/cbm510-std.s b/libsrc/cbm510/joy/cbm510-std.s index 4e47fc1a0..f7cbb2cdc 100644 --- a/libsrc/cbm510/joy/cbm510-std.s +++ b/libsrc/cbm510/joy/cbm510-std.s @@ -57,8 +57,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cbm510/mou/cbm510-inkwl.s b/libsrc/cbm510/mou/cbm510-inkwl.s index 91bc52fcd..ea6d95934 100644 --- a/libsrc/cbm510/mou/cbm510-inkwl.s +++ b/libsrc/cbm510/mou/cbm510-inkwl.s @@ -175,6 +175,7 @@ INSTALL: ; Done, return zero. lda #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error tax rts @@ -331,8 +332,8 @@ INFO: jsr POS ; Must return an error code in .XA. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm510/mou/cbm510-joy.s b/libsrc/cbm510/mou/cbm510-joy.s index 8aa3a778e..4daa49272 100644 --- a/libsrc/cbm510/mou/cbm510-joy.s +++ b/libsrc/cbm510/mou/cbm510-joy.s @@ -140,7 +140,8 @@ INSTALL: ; Done, return zero. - ldx #>MOUSE_ERR_OK + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -315,8 +316,8 @@ POS: ldy #MOUSE_POS::XCOORD ; Structure offset ; Must return an error code in .XA. ; -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm510/ser/cbm510-std.s b/libsrc/cbm510/ser/cbm510-std.s index 64f613cd5..cc58c1233 100644 --- a/libsrc/cbm510/ser/cbm510-std.s +++ b/libsrc/cbm510/ser/cbm510-std.s @@ -148,8 +148,9 @@ SER_CLOSE: ; Done, return an error code - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -217,22 +218,23 @@ SER_OPEN: ; Done - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Invalid parameter InvParam: - lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -253,8 +255,8 @@ SER_GET: @L1: lda RecvFreeCnt cmp #$ff bne @L2 - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -301,7 +303,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #<SER_ERR_OVERFLOW ; X is already zero + lda #SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail @@ -310,7 +312,8 @@ SER_PUT: dec SendFreeCnt lda #$ff jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -328,7 +331,8 @@ SER_STATUS: sta (ptr1,x) lda IndReg sta ExecReg - txa ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + txa rts ;---------------------------------------------------------------------------- @@ -338,8 +342,8 @@ SER_STATUS: ; SER_IOCTL: - lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm610/emd/cbm610-ram.s b/libsrc/cbm610/emd/cbm610-ram.s index 5c67df7a4..5aa43b0c2 100644 --- a/libsrc/cbm610/emd/cbm610-ram.s +++ b/libsrc/cbm610/emd/cbm610-ram.s @@ -81,8 +81,9 @@ INSTALL: sbc #$00 sta pagecount -@L1: lda #<EM_ERR_OK - ldx #>EM_ERR_OK +@L1: lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cbm610/ser/cbm610-std.s b/libsrc/cbm610/ser/cbm610-std.s index 7cdb285bd..f7ddde935 100644 --- a/libsrc/cbm610/ser/cbm610-std.s +++ b/libsrc/cbm610/ser/cbm610-std.s @@ -149,8 +149,9 @@ SER_CLOSE: ; Done, return an error code - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -218,22 +219,23 @@ SER_OPEN: ; Done - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Invalid parameter InvParam: - lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -254,8 +256,8 @@ SER_GET: @L1: lda RecvFreeCnt cmp #$ff bne @L2 - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -302,7 +304,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #<SER_ERR_OVERFLOW ; X is already zero + lda #SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail @@ -311,7 +313,8 @@ SER_PUT: dec SendFreeCnt lda #$ff jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -339,8 +342,8 @@ SER_STATUS: ; SER_IOCTL: - lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/creativision/joy/creativision-stdjoy.s b/libsrc/creativision/joy/creativision-stdjoy.s index 73b0c249f..43f9a2b40 100644 --- a/libsrc/creativision/joy/creativision-stdjoy.s +++ b/libsrc/creativision/joy/creativision-stdjoy.s @@ -59,7 +59,8 @@ JOY_RIGHT = $08 ; INSTALL: lda #JOY_ERR_OK - ldx #>$0000 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Fall through ; ------------------------------------------------------------------------ diff --git a/libsrc/cx16/joy/cx16-std.s b/libsrc/cx16/joy/cx16-std.s index a40fcb061..5def55511 100644 --- a/libsrc/cx16/joy/cx16-std.s +++ b/libsrc/cx16/joy/cx16-std.s @@ -55,8 +55,9 @@ JOY_COUNT = $05 ; Number of joysticks we support ; Must return a JOY_ERR_xx code in .XA . INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cx16/mou/cx16-std.s b/libsrc/cx16/mou/cx16-std.s index 3af7d2eb3..f211815de 100644 --- a/libsrc/cx16/mou/cx16-std.s +++ b/libsrc/cx16/mou/cx16-std.s @@ -139,7 +139,8 @@ INSTALL: ; Done, return zero - ldx #>MOUSE_ERR_OK + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -300,8 +301,8 @@ INFO: jsr BUTTONS ; Will not touch ptr1 ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in .XA . -IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now - ldx #>MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char ; rts ; Fall through ;---------------------------------------------------------------------------- diff --git a/libsrc/gamate/joy/gamate-stdjoy.s b/libsrc/gamate/joy/gamate-stdjoy.s index 8f927cdf5..514f92db4 100644 --- a/libsrc/gamate/joy/gamate-stdjoy.s +++ b/libsrc/gamate/joy/gamate-stdjoy.s @@ -47,8 +47,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/geos-cbm/emd/geos-vdc.s b/libsrc/geos-cbm/emd/geos-vdc.s index 27316e1a0..2e7d19c03 100644 --- a/libsrc/geos-cbm/emd/geos-vdc.s +++ b/libsrc/geos-cbm/emd/geos-vdc.s @@ -125,8 +125,9 @@ INSTALL: pla sta $01 plp - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts test64k: diff --git a/libsrc/geos-cbm/joy/geos-stdjoy.s b/libsrc/geos-cbm/joy/geos-stdjoy.s index 2787cb594..a3fd4ffc8 100644 --- a/libsrc/geos-cbm/joy/geos-stdjoy.s +++ b/libsrc/geos-cbm/joy/geos-stdjoy.s @@ -53,8 +53,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/joystick/joy_unload.s b/libsrc/joystick/joy_unload.s index 25d54ff02..f52b7a2c1 100644 --- a/libsrc/joystick/joy_unload.s +++ b/libsrc/joystick/joy_unload.s @@ -10,7 +10,7 @@ .include "modload.inc" .import joy_clear_ptr - .import return0 + .import return0, return1 @@ -31,7 +31,6 @@ _joy_unload: jmp return0 ; Return JOY_ERR_OK no_driver: - tax ; X = 0 pla ; Remove pushed junk - lda #JOY_ERR_NO_DRIVER - rts + .assert JOY_ERR_NO_DRIVER = 1, error + jmp return1 ; Return JOY_ERR_NO_DRIVER diff --git a/libsrc/lynx/joy/lynx-stdjoy.s b/libsrc/lynx/joy/lynx-stdjoy.s index c81a97dbf..45eb8ab4e 100644 --- a/libsrc/lynx/joy/lynx-stdjoy.s +++ b/libsrc/lynx/joy/lynx-stdjoy.s @@ -58,8 +58,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/lynx/ser/lynx-comlynx.s b/libsrc/lynx/ser/lynx-comlynx.s index ded862eaa..8aa3c838e 100644 --- a/libsrc/lynx/ser/lynx-comlynx.s +++ b/libsrc/lynx/ser/lynx-comlynx.s @@ -75,8 +75,9 @@ SER_UNINSTALL: SER_CLOSE: ; Disable interrupts ; Done, return an error code - lda #<SER_ERR_OK - ldx #>SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -190,8 +191,8 @@ SER_OPEN: cmp #SER_BAUD_134_5 beq setbaudrate - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts setprescaler: stx TIM4CTLA @@ -238,12 +239,13 @@ checkhs: lda contrl ora #RxIntEnable|ResetErr sta SERCTL - lda #<SER_ERR_OK - ldx #>SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts invparameter: - lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -255,8 +257,8 @@ SER_GET: lda RxPtrIn cmp RxPtrOut bne GetByte - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts GetByte: ldy RxPtrOut @@ -277,8 +279,8 @@ SER_PUT: ina cmp TxPtrOut bne PutByte - lda #<SER_ERR_OVERFLOW - ldx #>SER_ERR_OVERFLOW + lda #SER_ERR_OVERFLOW + ldx #0 ; return value is char rts PutByte: ldy TxPtrIn @@ -296,7 +298,8 @@ PutByte: sta TxDone plp @L1: - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -317,8 +320,8 @@ SER_STATUS: ; Must return an SER_ERR_xx code in a/x. SER_IOCTL: - lda #<SER_ERR_INV_IOCTL - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/mouse/mouse_unload.s b/libsrc/mouse/mouse_unload.s index 8c9018484..ecd7846ab 100644 --- a/libsrc/mouse/mouse_unload.s +++ b/libsrc/mouse/mouse_unload.s @@ -8,7 +8,7 @@ .include "mouse-kernel.inc" .include "modload.inc" - .import return0 + .import return0, return1 @@ -29,7 +29,6 @@ _mouse_unload: jmp return0 ; Return MOUSE_ERR_OK no_driver: - tax ; X = 0 pla ; Remove pushed junk - lda #<MOUSE_ERR_NO_DRIVER - rts + .assert MOUSE_ERR_NO_DRIVER = 1, error + jmp return1 ; Return MOUSE_ERR_NO_DRIVER diff --git a/libsrc/nes/joy/nes-stdjoy.s b/libsrc/nes/joy/nes-stdjoy.s index 63caf364b..0d0e7d9ac 100644 --- a/libsrc/nes/joy/nes-stdjoy.s +++ b/libsrc/nes/joy/nes-stdjoy.s @@ -53,7 +53,8 @@ JOY_COUNT = 2 ; Number of joysticks we support INSTALL: lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/pce/joy/pce-stdjoy.s b/libsrc/pce/joy/pce-stdjoy.s index 2de3d0c4c..dc8576c87 100644 --- a/libsrc/pce/joy/pce-stdjoy.s +++ b/libsrc/pce/joy/pce-stdjoy.s @@ -50,8 +50,9 @@ padbuffer: .res JOY_COUNT ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/pet/joy/pet-ptvjoy.s b/libsrc/pet/joy/pet-ptvjoy.s index c098072fb..ee14c95c8 100644 --- a/libsrc/pet/joy/pet-ptvjoy.s +++ b/libsrc/pet/joy/pet-ptvjoy.s @@ -51,8 +51,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/plus4/joy/plus4-stdjoy.s b/libsrc/plus4/joy/plus4-stdjoy.s index e8e85fedc..86f080dae 100644 --- a/libsrc/plus4/joy/plus4-stdjoy.s +++ b/libsrc/plus4/joy/plus4-stdjoy.s @@ -58,8 +58,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/plus4/ser/plus4-stdser.s b/libsrc/plus4/ser/plus4-stdser.s index bb44a4cf9..fbdc61b2e 100644 --- a/libsrc/plus4/ser/plus4-stdser.s +++ b/libsrc/plus4/ser/plus4-stdser.s @@ -157,8 +157,9 @@ SER_CLOSE: ; Done, return an error code - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -225,22 +226,23 @@ SER_OPEN: ; Done - lda #<SER_ERR_OK - tax ; A is zero + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ; Invalid parameter InvParam: - lda #<SER_ERR_INIT_FAILED - ldx #>SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #<SER_ERR_BAUD_UNAVAIL - ldx #>SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -261,8 +263,8 @@ SER_GET: @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 - lda #<SER_ERR_NO_DATA - ldx #>SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -309,7 +311,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #<SER_ERR_OVERFLOW ; X is already zero + lda #SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail @@ -318,7 +320,8 @@ SER_PUT: dec SendFreeCnt lda #$ff jsr TryToSend - lda #<SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error tax rts @@ -331,7 +334,8 @@ SER_STATUS: lda ACIA_STATUS ldx #0 sta (ptr1,x) - txa ; SER_ERR_OK + .assert SER_ERR_OK = 0, error + txa rts ;---------------------------------------------------------------------------- @@ -341,8 +345,8 @@ SER_STATUS: ; SER_IOCTL: - lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now - ldx #>SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ; Run into IRQ instead ;---------------------------------------------------------------------------- diff --git a/libsrc/serial/ser_unload.s b/libsrc/serial/ser_unload.s index bf7201255..7cd0f7125 100644 --- a/libsrc/serial/ser_unload.s +++ b/libsrc/serial/ser_unload.s @@ -10,7 +10,7 @@ .include "modload.inc" .import ser_clear_ptr - .import return0 + .import return0, return1 @@ -28,10 +28,10 @@ _ser_unload: tax pla ; Get pointer to driver jsr _mod_free ; Free the driver - jmp return0 ; Return SER_ERR_OK + .assert SER_ERR_OK = 0, error + jmp return0 no_driver: - tax ; X = 0 pla ; Remove pushed junk - lda #<SER_ERR_NO_DRIVER - rts + .assert SER_ERR_NO_DRIVER = 1, error + jmp return1 diff --git a/libsrc/supervision/joy/supervision-stdjoy.s b/libsrc/supervision/joy/supervision-stdjoy.s index ef790ec0b..2469abf31 100644 --- a/libsrc/supervision/joy/supervision-stdjoy.s +++ b/libsrc/supervision/joy/supervision-stdjoy.s @@ -46,8 +46,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/telestrat/joy/telestrat.s b/libsrc/telestrat/joy/telestrat.s index 0f5d28651..7472ab187 100644 --- a/libsrc/telestrat/joy/telestrat.s +++ b/libsrc/telestrat/joy/telestrat.s @@ -54,8 +54,9 @@ INSTALL: sta VIA2::PRB ; We could detect joysticks because with previous command bit0,1,2,3,4 should be set to 1 after ; But if some one press fire or press direction, we could reach others values which could break joystick detection. - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/vic20/emd/vic20-georam.s b/libsrc/vic20/emd/vic20-georam.s index a960e9a1a..4e3121c05 100644 --- a/libsrc/vic20/emd/vic20-georam.s +++ b/libsrc/vic20/emd/vic20-georam.s @@ -119,16 +119,16 @@ INSTALL: bne @setok @notpresent: - lda #<EM_ERR_NO_DEVICE - ldx #>EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @setok: lda #0 sta pagecount stx pagecount+1 - lda #<EM_ERR_OK - ldx #>EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts check: diff --git a/libsrc/vic20/emd/vic20-rama.s b/libsrc/vic20/emd/vic20-rama.s index 133c3974b..4264e2caf 100644 --- a/libsrc/vic20/emd/vic20-rama.s +++ b/libsrc/vic20/emd/vic20-rama.s @@ -71,12 +71,13 @@ INSTALL: ldx #$FF stx curpage ; Invalidate the current page - inx ; X = 0 - txa ; A = X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa rts -nomem: ldx #>EM_ERR_NO_DEVICE - lda #<EM_ERR_NO_DEVICE +nomem: ldx #0 ; return value is char + lda #EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/vic20/joy/vic20-ptvjoy.s b/libsrc/vic20/joy/vic20-ptvjoy.s index 496653e9d..c29d1d5ed 100644 --- a/libsrc/vic20/joy/vic20-ptvjoy.s +++ b/libsrc/vic20/joy/vic20-ptvjoy.s @@ -53,8 +53,9 @@ JOY_COUNT = 3 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/vic20/joy/vic20-stdjoy.s b/libsrc/vic20/joy/vic20-stdjoy.s index ee8dc93d7..b3de8766c 100644 --- a/libsrc/vic20/joy/vic20-stdjoy.s +++ b/libsrc/vic20/joy/vic20-stdjoy.s @@ -57,8 +57,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #<JOY_ERR_OK - ldx #>JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ From 993054c9d300a222e3a7abbf9d7217fa4e47e4b3 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Wed, 1 Mar 2023 11:58:42 -0500 Subject: [PATCH 227/360] Fix .endmacro not at the start of the line. .ENDMACRO error with line number of macro definition start --- src/ca65/macro.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 92a0f6e9a..84f0e8bcd 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -364,7 +364,7 @@ static void FreeMacExp (MacExp* E) -static void MacSkipDef (unsigned Style) +static void MacSkipDef (unsigned Style, FilePos Pos) /* Skip a macro definition */ { if (Style == MAC_STYLE_CLASSIC) { @@ -375,7 +375,7 @@ static void MacSkipDef (unsigned Style) if (CurTok.Tok != TOK_EOF) { SkipUntilSep (); } else { - Error ("'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected"); } } else { /* Skip until end of line */ @@ -391,19 +391,26 @@ void MacDef (unsigned Style) Macro* M; TokNode* N; int HaveParams; - int LastTokWasSep = 0; + + /* Remember if we are at the beginning of the line. If the macro name + ** and parameters pass then this will be set, so set it now */ + int LastTokWasSep = 1; + + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .ENDMACRO isn't found */ + FilePos Pos = CurTok.Pos; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); - MacSkipDef (Style); + MacSkipDef (Style, Pos); return; } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not ** allowed if not explicitly enabled. */ Error ("Cannot use an instruction as macro name"); - MacSkipDef (Style); + MacSkipDef (Style, Pos); return; } @@ -412,7 +419,7 @@ void MacDef (unsigned Style) /* Macro is already defined */ Error ("A macro named '%m%p' is already defined", &CurTok.SVal); /* Skip tokens until we reach the final .endmacro */ - MacSkipDef (Style); + MacSkipDef (Style, Pos); return; } @@ -480,7 +487,6 @@ void MacDef (unsigned Style) */ if (Style == MAC_STYLE_CLASSIC) { ConsumeSep (); - LastTokWasSep = 1; } else if (HaveParams) { ConsumeRParen (); } @@ -493,14 +499,14 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed, but ignore it if it is not at the start of the line */ + /* In classic macros, only .endmacro is allowed, but do no exit the macro definition if not at the start of a line */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { - Error ("'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected"); goto Done; } } else { From 1c60bc50098ac981f05131eb4e85556f0cd0a5be Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Wed, 1 Mar 2023 21:47:50 -0500 Subject: [PATCH 228/360] Fix .endmacro not at the start of the line. Fix style, add doc., add tests --- doc/ca65.sgml | 14 +++++++++++++- src/ca65/macro.c | 35 ++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b65d337bb..b19a66a2d 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2522,7 +2522,19 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH <sect1><tt>.ENDMAC, .ENDMACRO</tt><label id=".ENDMACRO"><p> - Marks the end of a macro definition. + Marks the end of a macro definition. Note, <tt>.ENDMACRO</tt> should be on + its own line to successfully end the macro definition. It is possible to use + <tt><ref id=".DEFINE" name=".DEFINE"></tt> to create a symbol that references + <tt>.ENDMACRO</tt> without ending the macro definition. + + Example: + + <tscreen><verb> + .macro new_mac + .define startmac .macro + .define endmac .endmacro + .endmacro + </verb></tscreen> See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>, diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 84f0e8bcd..72436fdec 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -364,7 +364,7 @@ static void FreeMacExp (MacExp* E) -static void MacSkipDef (unsigned Style, FilePos Pos) +static void MacSkipDef (unsigned Style) /* Skip a macro definition */ { if (Style == MAC_STYLE_CLASSIC) { @@ -375,7 +375,7 @@ static void MacSkipDef (unsigned Style, FilePos Pos) if (CurTok.Tok != TOK_EOF) { SkipUntilSep (); } else { - PError (&Pos, "'.ENDMACRO' expected"); + Error ("'.ENDMACRO' expected"); } } else { /* Skip until end of line */ @@ -390,27 +390,32 @@ void MacDef (unsigned Style) { Macro* M; TokNode* N; + FilePos Pos; int HaveParams; + int LastTokWasSep; - /* Remember if we are at the beginning of the line. If the macro name - ** and parameters pass then this will be set, so set it now */ - int LastTokWasSep = 1; + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now + */ + LastTokWasSep = 1; /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .ENDMACRO isn't found */ - FilePos Pos = CurTok.Pos; + ** using Perror to display the error if .ENDMACRO isn't found + */ + Pos = CurTok.Pos; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); - MacSkipDef (Style, Pos); + MacSkipDef (Style); return; } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not ** allowed if not explicitly enabled. */ Error ("Cannot use an instruction as macro name"); - MacSkipDef (Style, Pos); + MacSkipDef (Style); return; } @@ -419,7 +424,7 @@ void MacDef (unsigned Style) /* Macro is already defined */ Error ("A macro named '%m%p' is already defined", &CurTok.SVal); /* Skip tokens until we reach the final .endmacro */ - MacSkipDef (Style, Pos); + MacSkipDef (Style); return; } @@ -499,14 +504,16 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed, but do no exit the macro definition if not at the start of a line */ + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. + */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { - PError (&Pos, "'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name); goto Done; } } else { @@ -581,7 +588,9 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is valid */ + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line + */ LastTokWasSep = TokIsSep(CurTok.Tok); /* Read the next token */ From 0b71d1cfff0bf3fd7d329701e231fb9b0bbb818a Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Wed, 1 Mar 2023 21:55:14 -0500 Subject: [PATCH 229/360] Fix .endmacro not at the start of the line. Fix last commit --- doc/ca65.sgml | 2 +- src/ca65/macro.c | 18 +++++++++--------- test/asm/err/bug2013.s | 6 ++++++ test/asm/val/bug2013.s | 30 ++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 test/asm/err/bug2013.s create mode 100644 test/asm/val/bug2013.s diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b19a66a2d..b68acb639 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2522,7 +2522,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH <sect1><tt>.ENDMAC, .ENDMACRO</tt><label id=".ENDMACRO"><p> - Marks the end of a macro definition. Note, <tt>.ENDMACRO</tt> should be on + Marks the end of a macro definition. Note, <tt>.ENDMACRO</tt> should be on its own line to successfully end the macro definition. It is possible to use <tt><ref id=".DEFINE" name=".DEFINE"></tt> to create a symbol that references <tt>.ENDMACRO</tt> without ending the macro definition. diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 72436fdec..6e059f421 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -394,14 +394,14 @@ void MacDef (unsigned Style) int HaveParams; int LastTokWasSep; - /* For classic macros, remember if we are at the beginning of the line. - ** If the macro name and parameters pass our checks then we will be on a - ** new line, so set it now + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now */ LastTokWasSep = 1; - /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .ENDMACRO isn't found + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .ENDMACRO isn't found */ Pos = CurTok.Pos; @@ -504,8 +504,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, if .endmacro is not at the start of the line - ** it will be added to the macro definition instead of closing it. + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ @@ -588,8 +588,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is at - ** the start of a line + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line */ LastTokWasSep = TokIsSep(CurTok.Tok); diff --git a/test/asm/err/bug2013.s b/test/asm/err/bug2013.s new file mode 100644 index 000000000..8907675fb --- /dev/null +++ b/test/asm/err/bug2013.s @@ -0,0 +1,6 @@ +; for PR #2013 +; should produce error output: +; ... Error: '.ENDMACRO' expected for macro 'test' + +.macro test + nop .endmacro diff --git a/test/asm/val/bug2013.s b/test/asm/val/bug2013.s new file mode 100644 index 000000000..b6e9e37e6 --- /dev/null +++ b/test/asm/val/bug2013.s @@ -0,0 +1,30 @@ +; for PR #2013 + .import _exit + .export _main + + ; this macro is invalid, but should not cause an error (if it is never expanded) + .macro invalid + nop .endmacro + .endmacro + + .define temp_endmac .endmacro + .macro new_mac + .define startmac .macro + .define endmac .endmacro + temp_endmac + + .undefine temp_endmac + + new_mac + + startmac dex2 + dex + dex + endmac + +_main: + ldx #$02 + dex2 + ; x should be zero + txa + jmp _exit \ No newline at end of file From 98d2d9ee4e3d86c1d44d9a1d696d631031cdeffe Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Wed, 1 Mar 2023 21:59:00 -0500 Subject: [PATCH 230/360] Fix .endmacro not at the start of the line. Fix style --- test/asm/val/bug2013.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/asm/val/bug2013.s b/test/asm/val/bug2013.s index b6e9e37e6..cfb8efefb 100644 --- a/test/asm/val/bug2013.s +++ b/test/asm/val/bug2013.s @@ -27,4 +27,4 @@ _main: dex2 ; x should be zero txa - jmp _exit \ No newline at end of file + jmp _exit From 3f2129894be43d2840c28c5a33cd39c306984c1e Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Thu, 2 Mar 2023 15:12:30 -0500 Subject: [PATCH 231/360] Fix .endmacro not at the start of the line. Rename test files. --- test/asm/err/{bug2013.s => endmacro.s} | 0 test/asm/val/{bug2013.s => endmacro.s} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/asm/err/{bug2013.s => endmacro.s} (100%) rename test/asm/val/{bug2013.s => endmacro.s} (100%) diff --git a/test/asm/err/bug2013.s b/test/asm/err/endmacro.s similarity index 100% rename from test/asm/err/bug2013.s rename to test/asm/err/endmacro.s diff --git a/test/asm/val/bug2013.s b/test/asm/val/endmacro.s similarity index 100% rename from test/asm/val/bug2013.s rename to test/asm/val/endmacro.s From 90d5f41b377dfe810758c3cfdd0dd42d735a3bc7 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Thu, 2 Mar 2023 17:26:05 -0500 Subject: [PATCH 232/360] Consistent case for .endmacro in comments --- src/ca65/macro.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 6e059f421..d776411be 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -394,14 +394,14 @@ void MacDef (unsigned Style) int HaveParams; int LastTokWasSep; - /* For classic macros, remember if we are at the beginning of the line. - ** If the macro name and parameters pass our checks then we will be on a - ** new line, so set it now + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now */ LastTokWasSep = 1; - /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .ENDMACRO isn't found + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .endmacro isn't found */ Pos = CurTok.Pos; @@ -504,8 +504,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, if .endmacro is not at the start of the line - ** it will be added to the macro definition instead of closing it. + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ @@ -588,8 +588,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is at - ** the start of a line + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line */ LastTokWasSep = TokIsSep(CurTok.Tok); From c092f57b73a92b6db55d43a4b4f649059d77bf2e Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Thu, 2 Mar 2023 17:31:55 -0500 Subject: [PATCH 233/360] Consistent case for .endmacro in comments, remove trailing spaces --- src/ca65/macro.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index d776411be..904c80756 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -394,13 +394,13 @@ void MacDef (unsigned Style) int HaveParams; int LastTokWasSep; - /* For classic macros, remember if we are at the beginning of the line. - ** If the macro name and parameters pass our checks then we will be on a - ** new line, so set it now + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now */ LastTokWasSep = 1; - /* Save the position of the start of the macro definition to allow + /* Save the position of the start of the macro definition to allow ** using Perror to display the error if .endmacro isn't found */ Pos = CurTok.Pos; @@ -504,8 +504,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, if .endmacro is not at the start of the line - ** it will be added to the macro definition instead of closing it. + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ @@ -588,8 +588,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is at - ** the start of a line + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line */ LastTokWasSep = TokIsSep(CurTok.Tok); From 016b03e3562666db24e5364b8034ad07314a96fc Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 7 Mar 2023 17:00:38 -0500 Subject: [PATCH 234/360] ca65 jmp (abs) wrap warning only applies to 6502, later CPUs do not have this bug --- src/ca65/instr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ca65/instr.c b/src/ca65/instr.c index b72be6711..7cbefaecf 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -1617,11 +1617,12 @@ static void PutJMP (const InsDesc* Ins) if (EvalEA (Ins, &A)) { /* Check for indirect addressing */ - if (A.AddrModeBit & AM65_ABS_IND) { + if (A.AddrModeBit & AM65_ABS_IND && CPU < CPU_65SC02) { /* Compare the low byte of the expression to 0xFF to check for ** a page cross. Be sure to use a copy of the expression otherwise - ** things will go weird later. + ** things will go weird later. This only affects the 6502 CPU, + ** and was corrected in 65C02 and later CPUs in this family. */ ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF); From 8b818aac673b186a9a1558f1f6dfd7559f056f1f Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 7 Mar 2023 18:42:20 -0500 Subject: [PATCH 235/360] remove trailing space on segment "bytes" warning plural --- src/ld65/config.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ld65/config.c b/src/ld65/config.c index 38b4f96d0..6c1f6ad4c 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -2043,14 +2043,14 @@ unsigned CfgProcess (void) ++Overflows; if (S->Flags & SF_OFFSET) { CfgWarning (GetSourcePos (S->LI), - "Segment '%s' offset is too small in '%s' by %lu byte%c", + "Segment '%s' offset is too small in '%s' by %lu byte%s", GetString (S->Name), GetString (M->Name), - Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); + Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s"); } else { CfgWarning (GetSourcePos (S->LI), - "Segment '%s' start address is too low in '%s' by %lu byte%c", + "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'); + Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s"); } } else { Addr = NewAddr; @@ -2095,9 +2095,9 @@ unsigned CfgProcess (void) ++Overflows; M->Flags |= MF_OVERFLOW; CfgWarning (GetSourcePos (M->LI), - "Segment '%s' overflows memory area '%s' by %lu byte%c", + "Segment '%s' overflows memory area '%s' by %lu byte%s", GetString (S->Name), GetString (M->Name), - FillLevel - M->Size, (FillLevel - M->Size == 1) ? ' ' : 's'); + FillLevel - M->Size, (FillLevel - M->Size == 1) ? "" : "s"); } if (FillLevel > M->FillLevel) { /* Regular segments increase FillLevel. Overwrite segments may increase but not decrease FillLevel. */ From 4732e937ad0aee2bdc2f693861e67eab263e6880 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 7 Mar 2023 18:44:56 -0500 Subject: [PATCH 236/360] overwrite segment tests asm/listing linker CFG support asm and asm/listing test documentation --- test/asm/listing/200-overwrite.cfg | 20 ++++++++ test/asm/listing/200-overwrite.s | 29 +++++++++++ test/asm/listing/201-overwrite-overflow.cfg | 12 +++++ test/asm/listing/201-overwrite-overflow.s | 13 +++++ test/asm/listing/Makefile | 16 ++++++ .../control/201-overwrite-overflow.err | 0 test/asm/listing/readme.txt | 2 + test/asm/listing/ref/200-overwrite.bin-ref | Bin 0 -> 30 bytes .../ref/201-overwrite-overflow.ld65err2-ref | 3 ++ test/asm/readme.txt | 46 ++++++++++-------- 10 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 test/asm/listing/200-overwrite.cfg create mode 100644 test/asm/listing/200-overwrite.s create mode 100644 test/asm/listing/201-overwrite-overflow.cfg create mode 100644 test/asm/listing/201-overwrite-overflow.s create mode 100644 test/asm/listing/control/201-overwrite-overflow.err create mode 100644 test/asm/listing/ref/200-overwrite.bin-ref create mode 100644 test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref diff --git a/test/asm/listing/200-overwrite.cfg b/test/asm/listing/200-overwrite.cfg new file mode 100644 index 000000000..b7b2fee49 --- /dev/null +++ b/test/asm/listing/200-overwrite.cfg @@ -0,0 +1,20 @@ +MEMORY +{ + A: start = 0, size = 8, file = %O, fill = yes, fillval = $33; + B: start = 8, size = 8, file = %O, fill = yes, fillval = $44; + C: start = 0, size = 8, file = %O, fill = yes, fillval = $55; + D: start = 8, size = 8, file = %O, fill = no, fillval = $66; +} +SEGMENTS +{ + A: load = A, type = ro; + B: load = B, type = ro; + C0: load = C, type = ro; + C1: load = C, type = ro, start = 5; + D: load = D, type = ro; + + AO: load = A, type = overwrite, start = 4; + BO: load = B, type = overwrite, start = 8+5; + CO: load = C, type = overwrite, start = 2; + DO: load = D, type = overwrite, start = 8+4; +} diff --git a/test/asm/listing/200-overwrite.s b/test/asm/listing/200-overwrite.s new file mode 100644 index 000000000..cd2349c6a --- /dev/null +++ b/test/asm/listing/200-overwrite.s @@ -0,0 +1,29 @@ +; verification of overwrite segment feature +; See: https://github.com/cc65/cc65/issues/1366 + +; A: full memory area which is overwritten to the end +.segment "A" +.byte 0,1,2,3,4,5,6,7 +.segment "AO" +.byte $24,$25,$26,$27 + +; B: incomplete memory area overwritten in the fill area +.segment "B" +.byte 0,1,2 +.segment "BO" +.byte $25,$26 + +; C: memory area with gap overwritten across the gap +.segment "C0" +.byte 0,1,2 +.segment "C1" +.byte 5,6,7 +.segment "CO" +.byte $22,$23,$24,$25 + +; D: incomplete memory area without fill, +; but overwrite extends past existing segments +.segment "D" +.byte 0,1,2 +.segment "DO" +.byte $24,$25 diff --git a/test/asm/listing/201-overwrite-overflow.cfg b/test/asm/listing/201-overwrite-overflow.cfg new file mode 100644 index 000000000..cada57d5a --- /dev/null +++ b/test/asm/listing/201-overwrite-overflow.cfg @@ -0,0 +1,12 @@ +MEMORY +{ + A: start = 0, size = 8, file = %O, fill = yes, fillval = $33; + B: start = 8, size = 8, file = %O, fill = yes, fillval = $44; +} +SEGMENTS +{ + A: load = A, type = ro; + B: load = B, type = ro; + AO: load = A, type = overwrite, start = 6; + BO: load = B, type = overwrite, start = 8+6; +} diff --git a/test/asm/listing/201-overwrite-overflow.s b/test/asm/listing/201-overwrite-overflow.s new file mode 100644 index 000000000..156388ab5 --- /dev/null +++ b/test/asm/listing/201-overwrite-overflow.s @@ -0,0 +1,13 @@ +; verification of overwrite segment overflow cases + +; error: overflow past end of A memory area +.segment "A" +.byte 0,1,2,3 +.segment "AO" +.byte $26,$27,$28 + +; error: overflow past end of B memory area +.segment "B" +.byte 0,1,2,3 +.segment "BO" +.byte $26,$27,$28 diff --git a/test/asm/listing/Makefile b/test/asm/listing/Makefile index 3c4c404af..204984b64 100644 --- a/test/asm/listing/Makefile +++ b/test/asm/listing/Makefile @@ -58,12 +58,20 @@ $(WORKDIR)/$1.bin: $1.s $(ISEQUAL) ifeq ($(wildcard control/$1.err),) $(CA65) -t none -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) +else + $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) +endif endif else $(CA65) -t none -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) +else + $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE) +endif endif endif @@ -117,12 +125,20 @@ endif ifeq ($(wildcard control/$1.err),) $(CA65) -t none -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) +else + $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) +endif endif else $(CA65) -t none -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) +else + $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE) +endif endif endif diff --git a/test/asm/listing/control/201-overwrite-overflow.err b/test/asm/listing/control/201-overwrite-overflow.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/readme.txt b/test/asm/listing/readme.txt index d6280b954..5436b234a 100644 --- a/test/asm/listing/readme.txt +++ b/test/asm/listing/readme.txt @@ -4,6 +4,8 @@ Overall test: These testcases can be used to test different aspects of the assembler. The name of a test is everything in the form <test>.s. +If a custom linker configuration is needed, also include <test>.cfg. + The following reference files can be added: - ref/<test>.bin-ref: diff --git a/test/asm/listing/ref/200-overwrite.bin-ref b/test/asm/listing/ref/200-overwrite.bin-ref new file mode 100644 index 0000000000000000000000000000000000000000..b3a6f4f63cbcf5aa6c02e3980227eac3edd378f2 GIT binary patch literal 30 jcmZQzWMWoPRa0kRWO8v)RdZorR8m$^Wn%~O(^OOeDdYnM literal 0 HcmV?d00001 diff --git a/test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref b/test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref new file mode 100644 index 000000000..e372938ef --- /dev/null +++ b/test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref @@ -0,0 +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 +ld65: Error: Cannot generate most of the files due to memory area overflows diff --git a/test/asm/readme.txt b/test/asm/readme.txt index c3198c12a..db7f64504 100644 --- a/test/asm/readme.txt +++ b/test/asm/readme.txt @@ -1,32 +1,38 @@ Assembler Testcases =================== -Opcode Tests: -------------- +cpudetect +--------- -these go into opcodes/. Refer to opcodes/readme.txt +Tests the --cpu command line option of ca65/ld65. +Refer to cpudetect/readme.txt -CPU Detect Tests ----------------- +opcodes +------- -these go into cpudetect/. Refer to cpudetect/readme.txt +Test of assembler opcodes for each CPU. +Refer to opcodes/readme.txt -Overall tests: --------------- - -These go into listing/. Refer to listing/readme.txt - -val: ----- - -Works very much like the /val directory used to test the compiler - individual -tests are run in the simulator and should exit with an exit code of 0 when they -pass, or either -1 or a number indicating what part of the test failed on error. - err: ---- -Works very much like the /err directory used to test the compiler - individual -tests are assembled and MUST NOT assemble without error. +Used to test assembler errors. These tests MUST NOT assemble without error. + + +listing: +-------- + +This is the most versatile assembler test form, allowing control customizations, +reference tests for binary output, stdout and error text ouput, error tests, +listings, custom linker configuration, etc. as needed. +Refer to listing/readme.txt + + +val: +---- + +Runtime assembly tests using sim65 that should exit with an exit code of 0 when +the pass, or either -1 or a number indicating what part of the test failed on +error. From 6be7c160133d4315686d49149029149e7106a958 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 7 Mar 2023 18:48:30 -0500 Subject: [PATCH 237/360] linkter test with custom config should not use none.lib --- test/asm/listing/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/asm/listing/Makefile b/test/asm/listing/Makefile index 204984b64..23aa3969c 100644 --- a/test/asm/listing/Makefile +++ b/test/asm/listing/Makefile @@ -61,7 +61,7 @@ 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) else - $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) + $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) endif endif else @@ -70,7 +70,7 @@ 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) else - $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE) + $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE) endif endif endif @@ -128,7 +128,7 @@ 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) else - $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) + $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) endif endif else @@ -137,7 +137,7 @@ 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) else - $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE) + $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE) endif endif endif From 99220f60af8fca4817bde91a9dce8fb20e83e53f Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 7 Mar 2023 18:53:30 -0500 Subject: [PATCH 238/360] test/asm readme val description revision --- test/asm/readme.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/asm/readme.txt b/test/asm/readme.txt index db7f64504..49b530d1c 100644 --- a/test/asm/readme.txt +++ b/test/asm/readme.txt @@ -33,6 +33,6 @@ Refer to listing/readme.txt val: ---- -Runtime assembly tests using sim65 that should exit with an exit code of 0 when -the pass, or either -1 or a number indicating what part of the test failed on -error. +Runtime assembly tests using sim65 that should end with an exit code of 0 if +they pass. If they fail the exit code should be either -1, or a number +indicating what part of the test failed. From c8c6fc6a4064efb1a69a99fe75b37cdf5944f60f Mon Sep 17 00:00:00 2001 From: jede <jede@oric.org> Date: Fri, 17 Mar 2023 23:10:15 +0100 Subject: [PATCH 239/360] add xfseek --- asminc/telestrat.inc | 2 ++ libsrc/telestrat/lseek.s | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 libsrc/telestrat/lseek.s diff --git a/asminc/telestrat.inc b/asminc/telestrat.inc index 682696887..c57bd3de8 100644 --- a/asminc/telestrat.inc +++ b/asminc/telestrat.inc @@ -277,6 +277,8 @@ XRECLK = $3C ; Reset clock XCLCL = $3D ; Close clock XWRCLK = $3E ; Displays clock in the address in A & Y registers +XFSEEK = $3F ; Only in Orix + ; Sound primitives XSONPS = $40 ; Send data to PSG register (14 values) XOUPS = $42 ; Send Oups sound into PSG diff --git a/libsrc/telestrat/lseek.s b/libsrc/telestrat/lseek.s new file mode 100644 index 000000000..11d1fad33 --- /dev/null +++ b/libsrc/telestrat/lseek.s @@ -0,0 +1,39 @@ +; +; Jede (jede@oric.org), 2023-03-13 +; + +; off_t __fastcall__ lseek(int fd, off_t offset, int whence); + + .export _lseek + + .include "telestrat.inc" + .include "zeropage.inc" + + .import popax + +.proc _lseek + ; Save whence + sta tmp1 + ; Skip X + + ; Get offset and store + + jsr popax + sta tmp2 + stx tmp3 + + jsr popax + sta RESB + stx RESB+1 + + ; Get FD + jsr popax + ; Does not need X + sta RES ; Save FD + + lda tmp2 + ldy tmp3 + ldx tmp1 ; Get whence + BRK_TELEMON XFSEEK + rts +.endproc From fcbcbea4ad7653b279012b948b463bc6aa096080 Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Mon, 27 Mar 2023 09:23:40 -0400 Subject: [PATCH 240/360] Make some documentation fixes for KIM-1 platform. --- doc/kim1.sgml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/kim1.sgml b/doc/kim1.sgml index c3494b9b9..1387d3b19 100644 --- a/doc/kim1.sgml +++ b/doc/kim1.sgml @@ -45,8 +45,10 @@ system configuration before compiling and linking user programs. The ROMs and I/O areas are defined in the configuration files, as are most of the entry points for useful subroutines in the KIM-1 monitor ROM. cc65 generated programs compiled and linked using 4k config run in the memory range of $200 - $0FFF. The 60k config expands -this range to $DFFF. The starting memory location and entry point for running the program is -$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'. +this range to $DFFF. When using the 4k config the starting memory location and entry point +for running the program is $200, so when the program is transferred to the KIM-1, it is +executed by typing '200 G'. With the 60k config the default starting memory location and entry +point is $2000. Special locations: @@ -65,7 +67,7 @@ Special locations: <sect>Platform specific header files<p> -Programs containing KIM-1 code may use the <tt/kim.h/ header file. See the header file for more information. +Programs containing KIM-1 code may use the <tt/kim1.h/ header file. See the header file for more information. <sect>Loadable drivers<p> From 806ffe56757ee192d478565f9fb438f1e146ab08 Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Mon, 27 Mar 2023 17:56:25 -0400 Subject: [PATCH 241/360] Fixes and improvements to KIM-1 i/o routines. Tested on real KIM-1 hardware. read.s: - Remove commented out line. - Remove unused check for bell character. - Remove echo of newline (hardware always echoes entered characters). - This fixes gets() and fgets() so they return when CR is entered. write.s: - Fix check for adding return after linefeed (failed to work because OUTCHR changes A) - Remove unused check for bell character. kim1.inc: - Add symbol for monitor entry crt0.s: - Jump to KIM-1 monitor by address rather than using BRK (which relies on vector being set in RAM) --- asminc/kim1.inc | 2 +- libsrc/kim1/crt0.s | 6 ++---- libsrc/kim1/read.s | 7 +------ libsrc/kim1/write.s | 7 +++---- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/asminc/kim1.inc b/asminc/kim1.inc index 68f059490..2fb1117fa 100644 --- a/asminc/kim1.inc +++ b/asminc/kim1.inc @@ -15,7 +15,7 @@ OUTCHR := $1EA0 ; Output character INTCHR := $1E5A ; Input character without case conversion DUMPT := $1800 ; Dump memory to tape LOADT := $1873 ; Load memory from tape - +START := $1C4F ; Enter KIM-1 monitor ; --------------------------------------------------------------------------- ; System Memory diff --git a/libsrc/kim1/crt0.s b/libsrc/kim1/crt0.s index f1fee86c1..906b3b980 100644 --- a/libsrc/kim1/crt0.s +++ b/libsrc/kim1/crt0.s @@ -40,8 +40,6 @@ _init: cld ; Clear decimal mode jsr _main -; Back from main (this is also the _exit entry). There may be a more elegant way to -; return to the monitor on the KIM-1, but I don't know it! - -_exit: brk +; Back from main (this is also the _exit entry). Jumps to the KIM-1 monitor. +_exit: jmp START diff --git a/libsrc/kim1/read.s b/libsrc/kim1/read.s index 5566a9f27..dd178ee98 100644 --- a/libsrc/kim1/read.s +++ b/libsrc/kim1/read.s @@ -27,15 +27,10 @@ begin: dec ptr2 beq done ; If buffer full, return getch: jsr INTCHR ; Get character using Monitor ROM call - ;jsr OUTCHR ; Echo it and #$7F ; Clear top bit - cmp #$07 ; Check for '\a' - bne chkcr ; ...if BEL character - ;jsr BEEP ; Make beep sound TODO -chkcr: cmp #$0D ; Check for '\r' + cmp #$0D ; Check for '\r' bne putch ; ...if CR character lda #$0A ; Replace with '\n' - jsr OUTCHR ; and echo it putch: ldy #$00 ; Put char into return buffer sta (ptr1),y diff --git a/libsrc/kim1/write.s b/libsrc/kim1/write.s index 216f5031c..96bcc91d1 100644 --- a/libsrc/kim1/write.s +++ b/libsrc/kim1/write.s @@ -28,11 +28,10 @@ begin: dec ptr2 outch: ldy #0 lda (ptr1),y + pha ; Save A (changed by OUTCHR) jsr OUTCHR ; Send character using Monitor call - cmp #$07 ; Check for '\a' - bne chklf ; ...if BEL character -;jsr BEEP ; Make beep sound -chklf: cmp #$0A ; Check for 'n' + pla ; Restore A + cmp #$0A ; Check for '\n' bne next ; ...if LF character lda #$0D ; Add a carriage return jsr OUTCHR From 2dd558eae9cc31e794beeda3a3e31278ee971977 Mon Sep 17 00:00:00 2001 From: mooinglemur <mooinglemur@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:18:02 -0700 Subject: [PATCH 242/360] cx16: update RAM constants for ROM ver R42 --- asminc/cx16.inc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/asminc/cx16.inc b/asminc/cx16.inc index 1a916ecdb..be63780c8 100644 --- a/asminc/cx16.inc +++ b/asminc/cx16.inc @@ -239,12 +239,12 @@ BASIC_BUF := $0200 ; Location of command-line BASIC_BUF_LEN = 81 ; Maximum length of command-line SCREEN_PTR := $0262 ; Pointer to current row on text screen (16 bits) -STATUS := $0289 ; Status from previous I/O operation -IN_DEV := $028D ; Current input device number -OUT_DEV := $028E ; Current output device number -FNAM_LEN := $0291 ; Length of filename -SECADR := $0293 ; Secondary address -DEVNUM := $0294 ; Device number +STATUS := $0287 ; Status from previous I/O operation +IN_DEV := $028B ; Current input device number +OUT_DEV := $028C ; Current output device number +FNAM_LEN := $028F ; Length of filename +SECADR := $0291 ; Secondary address +DEVNUM := $0292 ; Device number CURS_COLOR := $0373 ; Color under the cursor CHARCOLOR := $0376 ; Cursor's color nybbles (high: background, low: foreground) RVS := $0377 ; Reverse flag @@ -258,8 +258,8 @@ LLEN := $0386 ; Line length NLINES := $0387 ; Number of screen lines ; BASIC -VARTAB := $03E2 ; Pointer to start of BASIC variables -MEMSIZE := $03EA ; Pointer to highest BASIC RAM location (+1) +VARTAB := $03E1 ; Pointer to start of BASIC variables +MEMSIZE := $03E9 ; Pointer to highest BASIC RAM location (+1) ; --------------------------------------------------------------------------- ; Vector and other locations From 3a5fbd34da2daf0004a51fd24f853ebfb90e7307 Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Wed, 29 Mar 2023 18:40:10 -0400 Subject: [PATCH 243/360] Add KIM-1 functions to write to the 7-segment LED display and get keypresses from the keypad. Includes sample program illustrating how to use them. Tested on real KIM-1 hardware. --- asminc/kim1.inc | 4 +++ include/kim1.h | 13 ++++++++++ libsrc/kim1/getkey.s | 18 ++++++++++++++ libsrc/kim1/scandisplay.s | 21 ++++++++++++++++ samples/kim1/kimKeyDisp.c | 52 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 libsrc/kim1/getkey.s create mode 100644 libsrc/kim1/scandisplay.s create mode 100644 samples/kim1/kimKeyDisp.c diff --git a/asminc/kim1.inc b/asminc/kim1.inc index 2fb1117fa..81e83b83c 100644 --- a/asminc/kim1.inc +++ b/asminc/kim1.inc @@ -16,6 +16,10 @@ INTCHR := $1E5A ; Input character without case conversion DUMPT := $1800 ; Dump memory to tape LOADT := $1873 ; Load memory from tape START := $1C4F ; Enter KIM-1 monitor +SCANDS := $1F1F ; Scan 7-segment display +KEYIN := $1F40 ; Open up keyboard channel +GETKEY := $1F6A ; Return key from keyboard + ; --------------------------------------------------------------------------- ; System Memory diff --git a/include/kim1.h b/include/kim1.h index dae246944..99843f8f8 100644 --- a/include/kim1.h +++ b/include/kim1.h @@ -56,5 +56,18 @@ int __fastcall__ loadt (unsigned char); /* Write to tape */ int __fastcall__ dumpt (unsigned char, const void*, const void*); + +/* Write to 7-segment LED display. Due to hardware limitations it only +** displays briefly, so must be called repeatedly to update the +** display. +**/ +void __fastcall__ scandisplay(unsigned char left, unsigned char middle, unsigned char right); + +/* +** Get a keypress from the keypad. Returns $00-$0F(0-F), $10(AD), $11(DA), $12(+), +** $13(GO), $14(PC) or $15 for no keypress. +**/ +int __fastcall__ getkey(); + /* End of sym1.h */ #endif diff --git a/libsrc/kim1/getkey.s b/libsrc/kim1/getkey.s new file mode 100644 index 000000000..b36cd4b4c --- /dev/null +++ b/libsrc/kim1/getkey.s @@ -0,0 +1,18 @@ +; +; int __fastcall__ getkey(); +; + +.include "kim1.inc" + +.import popa + +.export _getkey + +.proc _getkey + + jsr KEYIN ; Open up keyboard channel + jsr GETKEY ; Get key code + ldx #0 ; MSB of return value is zero + rts + +.endproc diff --git a/libsrc/kim1/scandisplay.s b/libsrc/kim1/scandisplay.s new file mode 100644 index 000000000..0f46a5de4 --- /dev/null +++ b/libsrc/kim1/scandisplay.s @@ -0,0 +1,21 @@ +; +; void __fastcall__ scandisplay(unsigned char left, unsigned char middle, unsigned char right); +; + +.include "kim1.inc" + +.import popa + +.export _scandisplay + +.proc _scandisplay + + sta $F9 ; Rightmost display data + jsr popa + sta $FA ; Middle display data + jsr popa + sta $FB ; Leftmost display data + jsr SCANDS + rts + +.endproc diff --git a/samples/kim1/kimKeyDisp.c b/samples/kim1/kimKeyDisp.c new file mode 100644 index 000000000..63839d19e --- /dev/null +++ b/samples/kim1/kimKeyDisp.c @@ -0,0 +1,52 @@ +/* Example illustrating scandisplay() and getkey() functions. */ + +#include <stdio.h> +#include <kim1.h> + +int main (void) +{ + int i, j, k, l; + int last = 15; + + printf("\nKIM-1 Demo\n"); + + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + for (k = 0; k < 16; k++) { + scandisplay(i, j, k); + + l = getkey(); + + if (l != last) { + switch (l) { + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x4: case 0x5: case 0x6: case 0x7: + case 0x8: case 0x9: case 0xa: case 0xb: + case 0xc: case 0xd: case 0xe: case 0xf: + printf("Key pressed: %X\n", l); + break; + case 0x10: + printf("Key pressed: AD\n"); + break; + case 0x11: + printf("Key pressed: DA\n"); + break; + case 0x12: + printf("Key pressed: +\n"); + break; + case 0x13: + printf("Key pressed: GO\n"); + break; + case 0x14: + printf("Key pressed: PC\n"); + break; + } + + last = l; + } + } + } + } + + return 0; +} From ed4edd908b8274a13ca1b8f988dfe5cdbb194d02 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Tue, 4 Apr 2023 00:40:33 +0200 Subject: [PATCH 244/360] fix copy'n'paste typo --- include/kim1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/kim1.h b/include/kim1.h index 99843f8f8..03c496223 100644 --- a/include/kim1.h +++ b/include/kim1.h @@ -69,5 +69,5 @@ void __fastcall__ scandisplay(unsigned char left, unsigned char middle, unsigned **/ int __fastcall__ getkey(); -/* End of sym1.h */ +/* End of kim1.h */ #endif From 19349acdcf731fe54d28f839385a4f431ee62d20 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Tue, 4 Apr 2023 00:57:52 +0200 Subject: [PATCH 245/360] fix typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 697132fde..e0e2c24e7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Core team members: * [Christian Groessler](https://github.com/groessler): Atari, Atari5200, and CreatiVision library Maintainer * [dqh](https://github.com/dqh-au): GHA help * [Greg King](https://github.com/greg-king5): all around hackery -* [groepaz](https://github.com/mrdudz): CBM libary, Project Maintainer +* [groepaz](https://github.com/mrdudz): CBM library, Project Maintainer * [Oliver Schmidt](https://github.com/oliverschmidt): Apple II library Maintainer External contributors: From 2a7533268cfcec42f217b7cf521a567da866e29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ola=20S=C3=B6der?= <rolfkopman@gmail.com> Date: Fri, 7 Apr 2023 23:44:30 +0200 Subject: [PATCH 246/360] Don't use hardcoded paths on Amiga Hardcoded paths don't make sense on AmigaOS, AROS and MorphOS. --- src/ca65/incpath.c | 2 +- src/cc65/incpath.c | 2 +- src/cl65/main.c | 2 +- src/ld65/filepath.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ca65/incpath.c b/src/ca65/incpath.c index 8ea67df6f..461f1ad79 100644 --- a/src/ca65/incpath.c +++ b/src/ca65/incpath.c @@ -75,7 +75,7 @@ void FinishIncludePaths (void) AddSubSearchPathFromEnv (IncSearchPath, "CC65_HOME", "asminc"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(CA65_INC) && !defined(_WIN32) +#if defined(CA65_INC) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (IncSearchPath, CA65_INC); #endif diff --git a/src/cc65/incpath.c b/src/cc65/incpath.c index 85f6e070b..3069079ac 100644 --- a/src/cc65/incpath.c +++ b/src/cc65/incpath.c @@ -76,7 +76,7 @@ void FinishIncludePaths (void) AddSubSearchPathFromEnv (SysIncSearchPath, "CC65_HOME", "include"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(CC65_INC) && !defined(_WIN32) +#if defined(CC65_INC) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (SysIncSearchPath, CC65_INC); #endif diff --git a/src/cl65/main.c b/src/cl65/main.c index 67e9444f4..553fb9ca6 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -1216,7 +1216,7 @@ static void OptPrintTargetPath (const char* Opt attribute ((unused)), SearchPaths* TargetPaths = NewSearchPath (); AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target"); -#if defined(CL65_TGT) && !defined(_WIN32) +#if defined(CL65_TGT) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (TargetPaths, CL65_TGT); #endif AddSubSearchPathFromBin (TargetPaths, "target"); diff --git a/src/ld65/filepath.c b/src/ld65/filepath.c index 1ceb2333e..c84fe6f46 100644 --- a/src/ld65/filepath.c +++ b/src/ld65/filepath.c @@ -88,13 +88,13 @@ void InitSearchPaths (void) AddSubSearchPathFromEnv (CfgDefaultPath, "CC65_HOME", "cfg"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(LD65_LIB) && !defined(_WIN32) +#if defined(LD65_LIB) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (LibDefaultPath, LD65_LIB); #endif -#if defined(LD65_OBJ) && !defined(_WIN32) +#if defined(LD65_OBJ) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (ObjDefaultPath, LD65_OBJ); #endif -#if defined(LD65_CFG) && !defined(_WIN32) +#if defined(LD65_CFG) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (CfgDefaultPath, LD65_CFG); #endif From 1f9594560ed0392bd0420dc79e1f586cc8c63218 Mon Sep 17 00:00:00 2001 From: Janne Johansson <icepic.dz@gmail.com> Date: Wed, 19 Apr 2023 09:15:03 +0200 Subject: [PATCH 247/360] Update lynxsprite.c Remove compiler warning about (signed) char wrapping around to -1 when set to 255. --- src/sp65/lynxsprite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sp65/lynxsprite.c b/src/sp65/lynxsprite.c index 566edacbe..6bd9b03de 100644 --- a/src/sp65/lynxsprite.c +++ b/src/sp65/lynxsprite.c @@ -312,7 +312,7 @@ static void AssembleByte(unsigned bits, char val) static unsigned char AnalyseNextChunks(signed *newlen, signed len, char data[32], char ColorBits) { char longest = 1; - char prev = 255; + unsigned char prev = 255; char count = 0; char index = 0; char lindex = 0; From 613ee94f445463c76135c5cb9ebffad6b9027cae Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Sun, 30 Apr 2023 18:40:09 -0400 Subject: [PATCH 248/360] Source listing in bootstrap.s is incorrect. The OSI C1P alternative boot file format works, but the code in the source listing does not match the ASCII-coded hex translation (which is actually used). This is confusing to anyone trying to maintain the code. Also, the source code does not assemble when ASM is defined. With these changes the source file should correctly match what is used at run time. --- libsrc/osic1p/bootstrap.s | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libsrc/osic1p/bootstrap.s b/libsrc/osic1p/bootstrap.s index e88e257fd..292f98914 100644 --- a/libsrc/osic1p/bootstrap.s +++ b/libsrc/osic1p/bootstrap.s @@ -34,7 +34,7 @@ ram_top := __MAIN_START__ + __MAIN_SIZE__ .ifdef ASM - .include "osic1p.inc" + .include "screen-c1p-24x24.s" .macpack generic load := $08 ; private variables @@ -45,20 +45,22 @@ GETCHAR := $FFBF ; gets one character from ACIA FIRSTVISC = $85 ; Offset of first visible character in video RAM LINEDIST = $20 ; Offset in video RAM between two lines - ldy #<$0000 + ldy #<$00 lda #<load_addr ldx #>load_addr sta load stx load+1 - ldx #(<load_size) + 1 - stx count - ldx #(>load_size) + 1 - stx count+1 ; save size with each byte incremented separately + lda #<load_size + eor #$FF + sta count + lda #>load_size + eor #$FF + sta count+1 -L1: dec count +L1: inc count bnz L2 - dec count+1 + inc count+1 bze L3 L2: jsr GETCHAR ; (doesn't change .Y) sta (load),y @@ -70,7 +72,7 @@ L2: jsr GETCHAR ; (doesn't change .Y) lsr a and #8 - 1 ora #$10 ; eight arrow characters - sta SCRNBASE + FIRSTVISC + 2 * LINEDIST + 11 + sta C1P_SCR_BASE + FIRSTVISC + 2 * LINEDIST + 11 iny bnz L1 From 4d97e30b557172d32435c83b1cb41f8eb5106042 Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Sun, 30 Apr 2023 18:40:09 -0400 Subject: [PATCH 249/360] Source listing in bootstrap.s is incorrect. The OSI C1P alternative boot file format works, but the code in the source listing does not match the ASCII-coded hex translation (which is actually used). This is confusing to anyone trying to maintain the code. Also, the source code did not assemble when ASM is defined. Also removed use of branch macros and an unnecessary "<" operator. With these changes the source file should correctly match what is used at run time. --- libsrc/osic1p/bootstrap.s | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/libsrc/osic1p/bootstrap.s b/libsrc/osic1p/bootstrap.s index e88e257fd..52ce31f84 100644 --- a/libsrc/osic1p/bootstrap.s +++ b/libsrc/osic1p/bootstrap.s @@ -34,7 +34,7 @@ ram_top := __MAIN_START__ + __MAIN_SIZE__ .ifdef ASM - .include "osic1p.inc" + .include "screen-c1p-24x24.s" .macpack generic load := $08 ; private variables @@ -45,21 +45,23 @@ GETCHAR := $FFBF ; gets one character from ACIA FIRSTVISC = $85 ; Offset of first visible character in video RAM LINEDIST = $20 ; Offset in video RAM between two lines - ldy #<$0000 + ldy #$00 lda #<load_addr ldx #>load_addr sta load stx load+1 - ldx #(<load_size) + 1 - stx count - ldx #(>load_size) + 1 - stx count+1 ; save size with each byte incremented separately + lda #<load_size + eor #$FF + sta count + lda #>load_size + eor #$FF + sta count+1 -L1: dec count - bnz L2 - dec count+1 - bze L3 +L1: inc count + bne L2 + inc count+1 + beq L3 L2: jsr GETCHAR ; (doesn't change .Y) sta (load),y @@ -70,12 +72,12 @@ L2: jsr GETCHAR ; (doesn't change .Y) lsr a and #8 - 1 ora #$10 ; eight arrow characters - sta SCRNBASE + FIRSTVISC + 2 * LINEDIST + 11 + sta C1P_SCR_BASE + FIRSTVISC + 2 * LINEDIST + 11 iny - bnz L1 + bne L1 inc load+1 - bnz L1 ; branch always + bne L1 ; branch always L3: jmp load_addr From 08223360d539aede5719696be9d287747950500b Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Tue, 2 May 2023 12:43:50 +0200 Subject: [PATCH 250/360] Update instr.c --- src/ca65/instr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 7cbefaecf..4f95ec75c 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -1617,7 +1617,7 @@ static void PutJMP (const InsDesc* Ins) if (EvalEA (Ins, &A)) { /* Check for indirect addressing */ - if (A.AddrModeBit & AM65_ABS_IND && CPU < CPU_65SC02) { + if ((A.AddrModeBit & AM65_ABS_IND) && (CPU < CPU_65SC02)) { /* Compare the low byte of the expression to 0xFF to check for ** a page cross. Be sure to use a copy of the expression otherwise From 1c26b1cf1b90172f16f7f7b0eed7ab36baa49165 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 14:42:00 -0400 Subject: [PATCH 251/360] RHS primary integer promotion must happen after loading the primary, not before. See: #2060 --- src/cc65/expr.c | 3 ++- test/val/bug2060.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/val/bug2060.c diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 691010b0a..9460569ed 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3090,9 +3090,10 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) Expr->Type = Expr2.Type; } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ - flags = typeadjust (Expr, &Expr2, 0); /* Load rhs into the primary */ LoadExpr (CF_NONE, &Expr2); + /* Adjust rhs primary if needed */ + flags = typeadjust (Expr, &Expr2, 0); } else { /* OOPS */ AddDone = -1; diff --git a/test/val/bug2060.c b/test/val/bug2060.c new file mode 100644 index 000000000..59b4774a4 --- /dev/null +++ b/test/val/bug2060.c @@ -0,0 +1,56 @@ +/* Test of bug: https://github.com/cc65/cc65/issues/2060 */ + +#include <stdio.h> + +#define W 320 + +unsigned long test1(unsigned char* p, unsigned long n) +{ + (void)p; + return n; +} + +unsigned long test0(unsigned char* p, int x, int y, unsigned char b) +{ + (void)b; + return test1(p, (long)y * W + x); +} + +#define TEST(ta,tb) \ + expect = (long)tb * W + ta; \ + result = test0(p,ta,tb,0x56); \ + printf("%4d * %3d + %4d = %08lx",tb,W,ta,result); \ + if (expect != result) { printf(" expected: %08lx\n",expect); ++fail; } \ + else printf("\n"); + +int main(void) +{ + unsigned char* p = (unsigned char*)0x1234; + unsigned long expect, result; + int fail = 0; + + TEST(1,3); + TEST(50,60); + TEST(99,88); + TEST(128,102); + TEST(129,102); + TEST(320,102); + /* Bug 2060 indicated failure when y > 102. + Because: (y * 320) > 32767 + The promotion of x from int to long had an incorrect high word, + because it was done before loading x into AX, rather than after. + */ + TEST(0,103); + TEST(150,170); + TEST(300,180); + /* x < 0 also fails because its high word sign extend is incorrect. */ + TEST(-100,50); + TEST(-49,99); + TEST(-300,-180); + /* This passed despite the bug, because y * 320 coincidentally had the + same high word. + */ + TEST(-1,-1); + + return fail; +} From 2c47ea45af0ad91a611c866b9f99a5c7eae4e5f1 Mon Sep 17 00:00:00 2001 From: Brad Smith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 18:18:10 -0400 Subject: [PATCH 252/360] bug895.c compliant token pasting syntax to remove warnings Gets rid of some unnecessary warning spam in the test log of lines like this: ``` bug895.c:95: Warning: Pasting formed "unsigned_long_14(", an invalid preprocessing token ``` --- test/val/bug895.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/val/bug895.c b/test/val/bug895.c index c4892d7b1..3c0331a6d 100644 --- a/test/val/bug895.c +++ b/test/val/bug895.c @@ -21,7 +21,7 @@ unsigned int uia, uib; unsigned long ula, ulb; #define OPTCMP8TEST_SINGLE(num,cmpop,asmprefix,vara,varb,b0,b1,a0,a1,typename,name) \ - typename name ## _ ## num ## (void) { \ + typename name ## _ ## num(void) { \ varb = b0; \ asm( asmprefix ); \ vara = a0; \ @@ -30,7 +30,7 @@ unsigned long ula, ulb; } #define OPTCMP8TEST_VERIFY(num,b,desc,printterm,name) \ - ASSERT_AreEqual(name ## _ ## num ##(),b,printterm,"Incorrect optimization of const comparison (" #name "_" #num ": " desc ")."); + ASSERT_AreEqual(name ## _ ## num(),b,printterm,"Incorrect optimization of const comparison (" #name "_" #num ": " desc ")."); /* Generates a set of comparison tests for one type and set of test values. ** name = a name for this test (no spaces) From e7046a02ff392d793647fccd76245ce1bc00c4cc Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 19:00:34 -0400 Subject: [PATCH 253/360] Disallow pass/return of 3-byte struct (#2022), document capability added in #1102. --- doc/cc65.sgml | 5 ++--- src/cc65/datatype.c | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 683249bda..2e99f3201 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -806,9 +806,8 @@ and the one defined by the ISO standard: <item> The datatypes "float" and "double" are not available. <p> -<item> C Functions may not return structs (or unions), and structs may not - be passed as parameters by value. However, struct assignment *is* - possible. +<item> C Functions may return structs (or unions) by value, but only of + 1, 2 or 4 byte sizes. <p> <item> Most of the C library is available with only the fastcall calling convention (<ref id="extension-fastcall" name="see below">). It means diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 6907ee099..caa41a7a4 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -803,7 +803,6 @@ const Type* GetStructReplacementType (const Type* SType) switch (SizeOf (SType)) { case 1: NewType = type_uchar; break; case 2: NewType = type_uint; break; - case 3: /* FALLTHROUGH */ case 4: NewType = type_ulong; break; default: NewType = SType; break; } From af11d4d947d090419827907604d8751a3eb01411 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 19:21:21 -0400 Subject: [PATCH 254/360] Document that struct-param is default off since: 3129266 --- doc/cc65.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 2e99f3201..023204f4d 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -741,7 +741,7 @@ Here is a description of all the command line options: <tag><tt/return-type/</tag> Warn about no return statement in function returning non-void. <tag><tt/struct-param/</tag> - Warn when passing structs by value. + Warn when passing structs by value. (Disabled by default.) <tag><tt/unknown-pragma/</tag> Warn about #pragmas that aren't recognized by cc65. <tag><tt/unreachable-code/</tag> From bf22f94a436345334e81fe70d196a8e805b7a778 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 20:02:58 -0400 Subject: [PATCH 255/360] struct pass and return by value test --- test/val/struct-by-value.c | 144 +++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 test/val/struct-by-value.c diff --git a/test/val/struct-by-value.c b/test/val/struct-by-value.c new file mode 100644 index 000000000..0e846c117 --- /dev/null +++ b/test/val/struct-by-value.c @@ -0,0 +1,144 @@ +/* Test of passing and returning structs by value. + Structs of 1, 2 and 4 bytes are supported. + Note that structs of 3 bytes are disabled, see: + https://github.com/cc65/cc65/issues/2022 +*/ + +int fail = 0; + +struct s1 { char a; }; +struct s2 { char a, b; }; +struct s3 { char a, b, c; }; +struct s4 { char a, b, c, d; }; + +const struct s1 c1 = { 1 }; +const struct s2 c2 = { 2, 3 }; +const struct s3 c3 = { 4, 5, 6 }; +const struct s4 c4 = { 7, 8, 9, 10 }; + +struct s1 return1() { return c1; } +struct s2 return2() { return c2; } +/*struct s3 return3() { return c3; }*/ +struct s4 return4() { return c4; } + +int compare1(struct s1 a, struct s1 b) +{ + if (a.a != b.a) return 1; + return 0; +} + +int compare2(struct s2 a, struct s2 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + return 0; +} + +/*int compare3(struct s3 a, struct s3 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + return 0; +}*/ + +int compare4(struct s4 a, struct s4 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + if (a.d != b.d) return 1; + return 0; +} + +int pass1(struct s1 p1) +{ + struct s1 a1; + a1 = p1; + if (a1.a != c1.a) return 1; + return 0; +} + +int pass2(struct s2 p2) +{ + struct s2 a2; + a2 = p2; + if (a2.a != c2.a) return 1; + if (a2.b != c2.b) return 1; + return 0; +} + +/*int pass3(struct s3 p3) +{ + struct s3 a3; + a3 = p3; + if (a3.a != c3.a) return 1; + if (a3.b != c3.b) return 1; + if (a3.c != c3.c) return 1; + return 0; +}*/ + +int pass4(struct s4 p4) +{ + struct s4 a4; + a4 = p4; + if (a4.a != c4.a) return 1; + if (a4.b != c4.b) return 1; + if (a4.c != c4.c) return 1; + if (a4.d != c4.d) return 1; + return 0; +} + +void reset(char* gg) +{ + char i; + for (i=0;i<5;++i) gg[i] = 128+i; +} + +int test(char* gg, char start) +{ + char i; + for (i=start;i<5;++i) + if (gg[i] != 128+i) return 1; + return 0; +} + +int main() +{ + /* Used to check #2022 bug condition of extra bytes being overwritten. */ + union + { + char gg[5]; + struct s1 g1; + struct s2 g2; + struct s3 g3; + struct s4 g4; + } guard; + + reset(guard.gg); + guard.g1 = return1(); + fail += compare1(guard.g1,c1); + fail += test(guard.gg,1); + + reset(guard.gg); + guard.g2 = return2(); + fail += compare2(guard.g2,c2); + fail += test(guard.gg,2); + + /*reset(guard.gg); + guard.g3 = return3(); + fail += compare3(guard.g3,c3); + fail += test(guard.gg,3);*/ + + reset(guard.gg); + guard.g4 = return4(); + fail += compare4(guard.g4,c4); + fail += test(guard.gg,4); + + fail += pass1(c1); + fail += pass2(c2); + /*fail += pass3(c3);*/ + fail += pass4(c4); + + return fail; +} From bf5b37a3b2b0a286e3cc14d1435f0ddbaa6cee4d Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 21:27:02 -0400 Subject: [PATCH 256/360] Error check for internal overflow of numerical constant See bug #2026 --- src/cc65/scanner.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 36fd1301b..055c02450 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -522,6 +522,7 @@ static void NumericConst (void) char C; unsigned DigitVal; unsigned long IVal; /* Value */ + int Overflow; /* Get the pp-number first, then parse on it */ CopyPPNumber (&Src); @@ -575,6 +576,7 @@ static void NumericConst (void) /* Since we now know the correct base, convert the input into a number */ SB_SetIndex (&Src, Index); IVal = 0; + Overflow = 0; while ((C = SB_Peek (&Src)) != '\0' && (Base <= 10 ? IsDigit (C) : IsXDigit (C))) { DigitVal = HexVal (C); if (DigitVal >= Base) { @@ -582,9 +584,17 @@ static void NumericConst (void) SB_Clear (&Src); break; } - IVal = (IVal * Base) + DigitVal; + if ((((unsigned long)(IVal * Base)) / Base) != IVal) + Overflow = 1; + IVal = IVal * Base; + if (((unsigned long)(IVal + DigitVal)) < IVal) + Overflow = 1; + IVal += DigitVal; SB_Skip (&Src); } + if (Overflow) + Error ("Numerical constant \"%s\" too large for internal 32-bit representation", + SB_GetConstBuf (&Src)); /* Distinguish between integer and floating point constants */ if (!IsFloat) { From 409235aee65ce5fd807a50b32a2a4ba664aaab70 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Tue, 2 May 2023 22:27:28 -0400 Subject: [PATCH 257/360] Optional warning for implicit constant conversion overflow --- doc/cc65.sgml | 2 ++ src/cc65/error.c | 2 ++ src/cc65/error.h | 1 + src/cc65/typeconv.c | 5 +++++ 4 files changed, 10 insertions(+) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 683249bda..5a094571a 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -754,6 +754,8 @@ Here is a description of all the command line options: Warn about unused function parameters. <tag><tt/unused-var/</tag> Warn about unused variables. + <tag><tt/const-overflow/</tag> + Warn if numerical constant conversion implies overflow. (Disabled by default.) </descrip> The full list of available warning names can be retrieved by using the diff --git a/src/cc65/error.c b/src/cc65/error.c index 3f36d9e97..6ac3e594b 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -79,6 +79,7 @@ IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */ IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */ IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */ IntStack WarnUnusedFunc = INTSTACK(1); /* - unused functions */ +IntStack WarnConstOverflow = INTSTACK(0); /* - overflow conversion of numerical constants */ /* Map the name of a warning to the intstack that holds its state */ typedef struct WarnMapEntry WarnMapEntry; @@ -102,6 +103,7 @@ static WarnMapEntry WarnMap[] = { { &WarnUnusedLabel, "unused-label" }, { &WarnUnusedParam, "unused-param" }, { &WarnUnusedVar, "unused-var" }, + { &WarnConstOverflow, "const-overflow" }, }; Collection DiagnosticStrBufs; diff --git a/src/cc65/error.h b/src/cc65/error.h index 7fcb03467..83be8c782 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -76,6 +76,7 @@ extern IntStack WarnUnusedLabel; /* - unused labels */ extern IntStack WarnUnusedParam; /* - unused parameters */ extern IntStack WarnUnusedVar; /* - unused variables */ extern IntStack WarnUnusedFunc; /* - unused functions */ +extern IntStack WarnConstOverflow; /* - overflow conversion of numerical constants */ /* Forward */ struct StrBuf; diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index f77ec3951..49dfcc597 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -128,6 +128,7 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) ** internally already represented by a long. */ if (NewBits <= OldBits) { + unsigned long OldVal = Expr->IVal; /* Cut the value to the new size */ Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits)); @@ -139,6 +140,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) Expr->IVal |= shl_l (~0UL, NewBits); } } + + if ((OldVal != Expr->IVal) && IS_Get (&WarnConstOverflow)) { + Warning ("Implicit conversion of constant overflows %d-bit destination", NewBits); + } } /* Do the integer constant <-> absolute address conversion if necessary */ From 65f773f5ee96d3d872fe6fd06fba079fa6b64c6a Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 01:01:21 -0400 Subject: [PATCH 258/360] Explicit z: should suppress "Suspicious address expression" warning #194 --- src/ca65/ea.h | 5 +++++ src/ca65/ea65.c | 2 ++ src/ca65/instr.c | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ca65/ea.h b/src/ca65/ea.h index d861e9a6c..487027c02 100644 --- a/src/ca65/ea.h +++ b/src/ca65/ea.h @@ -43,6 +43,10 @@ /*****************************************************************************/ +/* EffAddr Flags */ +#define EFFADDR_OVERRIDE_ZP 0x00000001UL + + /* GetEA result struct */ typedef struct EffAddr EffAddr; @@ -51,6 +55,7 @@ struct EffAddr { unsigned long AddrModeSet; /* Possible addressing modes */ struct ExprNode* Expr; /* Expression if any (NULL otherwise) */ unsigned Reg; /* Register number in sweet16 mode */ + unsigned long Flags; /* Other properties */ /* The following fields are used inside instr.c */ unsigned AddrMode; /* Actual addressing mode used */ diff --git a/src/ca65/ea65.c b/src/ca65/ea65.c index 275d90b56..5bd2ba82b 100644 --- a/src/ca65/ea65.c +++ b/src/ca65/ea65.c @@ -72,11 +72,13 @@ void GetEA (EffAddr* A) /* Clear the output struct */ A->AddrModeSet = 0; A->Expr = 0; + A->Flags = 0; /* Handle an addressing size override */ switch (CurTok.Tok) { case TOK_OVERRIDE_ZP: Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y; + A->Flags |= EFFADDR_OVERRIDE_ZP; NextTok (); break; diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 4f95ec75c..89162c3c6 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -1269,7 +1269,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) ExprNode* Left = A->Expr->Left; if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) && Left->Op == EXPR_SYMBOL && - GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) { + GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP && + !(A->Flags & EFFADDR_OVERRIDE_ZP)) { /* Output a warning */ Warning (1, "Suspicious address expression"); From 56c715af40ed1cad1a3b2a29de50e7ceaa9911e4 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 01:14:27 -0400 Subject: [PATCH 259/360] Error for struct/union with a duplicate member #2015 --- src/cc65/symtab.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 72a2ac007..d9270f604 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -793,6 +793,8 @@ static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags) */ Error ("Redeclaration of enumerator constant '%s'", Sym->Name); Sym = 0; + } else if (Flags & SC_STRUCTFIELD) { + Error ("Duplicate member '%s'", Sym->Name); } } } From 4d698bf18c89e8426e4ba8a37e4b72d1d51ee7ba Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 03:05:14 -0400 Subject: [PATCH 260/360] Don't use a,x,y in macro parameter example, document why not. #392 --- doc/ca65.sgml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 360b0bab2..2f95a032e 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -4262,8 +4262,13 @@ macro actually takes in the definition. You may also leave intermediate parameters empty. Empty parameters are replaced by empty space (that is, they are removed when the macro is expanded). If you have a look at our macro definition above, you will see, that replacing the "addr" parameter -by nothing will lead to wrong code in most lines. To help you, writing -macros with a variable parameter list, there are some control commands: +by nothing will lead to wrong code in most lines. + +The names "a", "x" and "y" should be avoided for macro parameters, as these +will usually conflict with the 6502 registers. + +For writing macros with a variable parameter list, control commands are +available: <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> tests the rest of the line and returns true, if there are any tokens on the remainder of the line. Since @@ -4274,15 +4279,15 @@ opposite. Look at this example: <tscreen><verb> -.macro ldaxy a, x, y -.ifnblank a - lda #a +.macro ldaxy i, j, k +.ifnblank i + lda #i .endif -.ifnblank x - ldx #x +.ifnblank j + ldx #j .endif -.ifnblank y - ldy #y +.ifnblank k + ldy #k .endif .endmacro </verb></tscreen> From 2b60adfa11ad6b348b70cc224337f1cac6b4c125 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 03:26:10 -0400 Subject: [PATCH 261/360] Document directives that use SetBoolOption "can" use +/- rather than "must" #1772 --- doc/ca65.sgml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 360b0bab2..72a133299 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2283,7 +2283,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH Switch on or off case sensitivity on identifiers. The default is off (that is, identifiers are case sensitive), but may be changed by the -i switch on the command line. - The command must be followed by a '+' or '-' character to switch the + The command can be followed by a '+' or '-' character to switch the option on or off respectively. Example: @@ -2432,7 +2432,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH Switch on or off debug info generation. The default is off (that is, the object file will not contain debug infos), but may be changed by the -g switch on the command line. - The command must be followed by a '+' or '-' character to switch the + The command can be followed by a '+' or '-' character to switch the option on or off respectively. Example: @@ -3380,7 +3380,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH Note: Line continuations do not work in a comment. A backslash at the end of a comment is treated as part of the comment and does not trigger line continuation. - The command must be followed by a '+' or '-' character to switch the + The command can be followed by a '+' or '-' character to switch the option on or off respectively. Example: @@ -3395,7 +3395,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH <sect1><tt>.LIST</tt><label id=".LIST"><p> - Enable output to the listing. The command must be followed by a boolean + Enable output to the listing. The command can be followed by a boolean switch ("on", "off", "+" or "-") and will enable or disable listing output. The option has no effect if the listing is not enabled by the command line @@ -4040,7 +4040,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE" <sect1><tt>.SMART</tt><label id=".SMART"><p> - Switch on or off smart mode. The command must be followed by a '+' or '-' + Switch on or off smart mode. The command can be followed by a '+' or '-' character to switch the option on or off respectively. The default is off (that is, the assembler doesn't try to be smart), but this default may be changed by the -s switch on the command line. From 86e3a640d5f785311dea52a266ef16bf290d9e0c Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 05:03:11 -0400 Subject: [PATCH 262/360] Support for three line ending types: \r, \r\n, \n. #1894 --- src/ca65/scanner.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index bf0a85183..d32939646 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -112,6 +112,7 @@ struct CharSource { CharSource* Next; /* Linked list of char sources */ token_t Tok; /* Last token */ int C; /* Last character */ + int SkipN; /* For '\r\n' line endings, skip '\n\ if next */ const CharSourceFunctions* Func; /* Pointer to function table */ union { InputFile File; /* File data */ @@ -325,6 +326,7 @@ static void UseCharSource (CharSource* S) Source = S; /* Read the first character from the new file */ + S->SkipN = 0; S->Func->NextChar (S); /* Setup the next token so it will be skipped on the next call to @@ -386,6 +388,10 @@ static void IFNextChar (CharSource* S) while (1) { int N = fgetc (S->V.File.F); + if (N == '\n' && S->SkipN) + N = fgetc (S->V.File.F); + S->SkipN = 0; + if (N == EOF) { /* End of file. Accept files without a newline at the end */ if (SB_NotEmpty (&S->V.File.Line)) { @@ -401,9 +407,12 @@ static void IFNextChar (CharSource* S) /* Check for end of line */ } else if (N == '\n') { - /* End of line */ break; + } else if (N == '\r') { + /* End of line, skip '\n' if it's the next character */ + S->SkipN = 1; + break; /* Collect other stuff */ } else { From 456fa9f963dcba838a135416a5d52957b54c3ffb Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 05:36:37 -0400 Subject: [PATCH 263/360] cc65 document: both pass and return of structs are allowed --- doc/cc65.sgml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 023204f4d..1476b40a3 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -806,8 +806,8 @@ and the one defined by the ISO standard: <item> The datatypes "float" and "double" are not available. <p> -<item> C Functions may return structs (or unions) by value, but only of - 1, 2 or 4 byte sizes. +<item> C Functions may pass and return structs (or unions) by value, but only + of 1, 2 or 4 byte sizes. <p> <item> Most of the C library is available with only the fastcall calling convention (<ref id="extension-fastcall" name="see below">). It means From 6ffc4004d7d7bbae4ba48aba53263545d651d750 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Wed, 3 May 2023 14:24:13 +0200 Subject: [PATCH 264/360] Revert "Forbid 3-byte struct pass/return by value, document struct value pass/return" --- doc/cc65.sgml | 7 +- src/cc65/datatype.c | 1 + test/val/struct-by-value.c | 144 ------------------------------------- 3 files changed, 5 insertions(+), 147 deletions(-) delete mode 100644 test/val/struct-by-value.c diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 1476b40a3..683249bda 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -741,7 +741,7 @@ Here is a description of all the command line options: <tag><tt/return-type/</tag> Warn about no return statement in function returning non-void. <tag><tt/struct-param/</tag> - Warn when passing structs by value. (Disabled by default.) + Warn when passing structs by value. <tag><tt/unknown-pragma/</tag> Warn about #pragmas that aren't recognized by cc65. <tag><tt/unreachable-code/</tag> @@ -806,8 +806,9 @@ and the one defined by the ISO standard: <item> The datatypes "float" and "double" are not available. <p> -<item> C Functions may pass and return structs (or unions) by value, but only - of 1, 2 or 4 byte sizes. +<item> C Functions may not return structs (or unions), and structs may not + be passed as parameters by value. However, struct assignment *is* + possible. <p> <item> Most of the C library is available with only the fastcall calling convention (<ref id="extension-fastcall" name="see below">). It means diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index caa41a7a4..6907ee099 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -803,6 +803,7 @@ const Type* GetStructReplacementType (const Type* SType) switch (SizeOf (SType)) { case 1: NewType = type_uchar; break; case 2: NewType = type_uint; break; + case 3: /* FALLTHROUGH */ case 4: NewType = type_ulong; break; default: NewType = SType; break; } diff --git a/test/val/struct-by-value.c b/test/val/struct-by-value.c deleted file mode 100644 index 0e846c117..000000000 --- a/test/val/struct-by-value.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Test of passing and returning structs by value. - Structs of 1, 2 and 4 bytes are supported. - Note that structs of 3 bytes are disabled, see: - https://github.com/cc65/cc65/issues/2022 -*/ - -int fail = 0; - -struct s1 { char a; }; -struct s2 { char a, b; }; -struct s3 { char a, b, c; }; -struct s4 { char a, b, c, d; }; - -const struct s1 c1 = { 1 }; -const struct s2 c2 = { 2, 3 }; -const struct s3 c3 = { 4, 5, 6 }; -const struct s4 c4 = { 7, 8, 9, 10 }; - -struct s1 return1() { return c1; } -struct s2 return2() { return c2; } -/*struct s3 return3() { return c3; }*/ -struct s4 return4() { return c4; } - -int compare1(struct s1 a, struct s1 b) -{ - if (a.a != b.a) return 1; - return 0; -} - -int compare2(struct s2 a, struct s2 b) -{ - if (a.a != b.a) return 1; - if (a.b != b.b) return 1; - return 0; -} - -/*int compare3(struct s3 a, struct s3 b) -{ - if (a.a != b.a) return 1; - if (a.b != b.b) return 1; - if (a.c != b.c) return 1; - return 0; -}*/ - -int compare4(struct s4 a, struct s4 b) -{ - if (a.a != b.a) return 1; - if (a.b != b.b) return 1; - if (a.c != b.c) return 1; - if (a.d != b.d) return 1; - return 0; -} - -int pass1(struct s1 p1) -{ - struct s1 a1; - a1 = p1; - if (a1.a != c1.a) return 1; - return 0; -} - -int pass2(struct s2 p2) -{ - struct s2 a2; - a2 = p2; - if (a2.a != c2.a) return 1; - if (a2.b != c2.b) return 1; - return 0; -} - -/*int pass3(struct s3 p3) -{ - struct s3 a3; - a3 = p3; - if (a3.a != c3.a) return 1; - if (a3.b != c3.b) return 1; - if (a3.c != c3.c) return 1; - return 0; -}*/ - -int pass4(struct s4 p4) -{ - struct s4 a4; - a4 = p4; - if (a4.a != c4.a) return 1; - if (a4.b != c4.b) return 1; - if (a4.c != c4.c) return 1; - if (a4.d != c4.d) return 1; - return 0; -} - -void reset(char* gg) -{ - char i; - for (i=0;i<5;++i) gg[i] = 128+i; -} - -int test(char* gg, char start) -{ - char i; - for (i=start;i<5;++i) - if (gg[i] != 128+i) return 1; - return 0; -} - -int main() -{ - /* Used to check #2022 bug condition of extra bytes being overwritten. */ - union - { - char gg[5]; - struct s1 g1; - struct s2 g2; - struct s3 g3; - struct s4 g4; - } guard; - - reset(guard.gg); - guard.g1 = return1(); - fail += compare1(guard.g1,c1); - fail += test(guard.gg,1); - - reset(guard.gg); - guard.g2 = return2(); - fail += compare2(guard.g2,c2); - fail += test(guard.gg,2); - - /*reset(guard.gg); - guard.g3 = return3(); - fail += compare3(guard.g3,c3); - fail += test(guard.gg,3);*/ - - reset(guard.gg); - guard.g4 = return4(); - fail += compare4(guard.g4,c4); - fail += test(guard.gg,4); - - fail += pass1(c1); - fail += pass2(c2); - /*fail += pass3(c3);*/ - fail += pass4(c4); - - return fail; -} From 387d455cb45d7fc7249ffe1e1d927fb0300e897d Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Wed, 3 May 2023 11:16:22 -0400 Subject: [PATCH 265/360] Revised patch. Uses code in source listing. Tested on a real OSI C1P machine. --- libsrc/osic1p/bootstrap.s | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/libsrc/osic1p/bootstrap.s b/libsrc/osic1p/bootstrap.s index 52ce31f84..0d8a74eb7 100644 --- a/libsrc/osic1p/bootstrap.s +++ b/libsrc/osic1p/bootstrap.s @@ -35,7 +35,6 @@ ram_top := __MAIN_START__ + __MAIN_SIZE__ .ifdef ASM .include "screen-c1p-24x24.s" - .macpack generic load := $08 ; private variables count := $0A @@ -51,16 +50,14 @@ LINEDIST = $20 ; Offset in video RAM between two lines sta load stx load+1 - lda #<load_size - eor #$FF - sta count - lda #>load_size - eor #$FF - sta count+1 + ldx #(<load_size) + 1 + stx count + ldx #(>load_size) + 1 + stx count+1 ; save size with each byte incremented separately -L1: inc count +L1: dec count bne L2 - inc count+1 + dec count+1 beq L3 L2: jsr GETCHAR ; (doesn't change .Y) sta (load),y @@ -114,18 +111,15 @@ CR = $0D hex2 >load_addr .byte CR, "85", CR, "08", CR .byte "86", CR, "09", CR - .byte "A9", CR - hex2 <load_size - .byte CR, "49", CR, "FF", CR - .byte "85", CR, "0A", CR - .byte "A9", CR - hex2 >load_size - .byte CR, "49", CR, "FF", CR - .byte "85", CR, "0B", CR - - .byte "E6", CR, "0A", CR + .byte "A2", CR + hex2 (<load_size) + 1 + .byte CR, "86", CR, "0A", CR + .byte "A2", CR + hex2 (>load_size) + 1 + .byte CR, "86", CR, "0B", CR + .byte "C6", CR, "0A", CR .byte "D0", CR, "04", CR - .byte "E6", CR, "0B", CR + .byte "C6", CR, "0B", CR .byte "F0", CR, "16", CR .byte "20", CR, "BF", CR, "FF", CR .byte "91", CR, "08", CR From 016008b6df5a1a0283a29ba1e18255e39a229dd5 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 11:57:50 -0400 Subject: [PATCH 266/360] ca65: Suppress '.size' error for multiply-defined symbols --- src/ca65/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ca65/main.c b/src/ca65/main.c index 7183ff046..d45201cad 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -858,7 +858,11 @@ static void OneLine (void) /* The line has switched the segment */ Size = 0; } - DefSizeOfSymbol (Sym, Size); + /* Suppress .size Symbol if this Symbol already has a multiply-defined error, + ** as it will only create its own additional unnecessary error. + */ + if ((Sym->Flags & SF_MULTDEF) == 0) + DefSizeOfSymbol (Sym, Size); } /* Line separator must come here */ From 4e6b94de5cf3e073897c610e09c372d9ac36e57c Mon Sep 17 00:00:00 2001 From: Brad Smith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 12:19:05 -0400 Subject: [PATCH 267/360] braces --- src/ca65/scanner.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index d32939646..add365e84 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -388,8 +388,9 @@ static void IFNextChar (CharSource* S) while (1) { int N = fgetc (S->V.File.F); - if (N == '\n' && S->SkipN) + if (N == '\n' && S->SkipN) { N = fgetc (S->V.File.F); + } S->SkipN = 0; if (N == EOF) { From 1f18ab218ed96d9d7eaf3aecb97d1a7764bb15fd Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 13:35:51 -0400 Subject: [PATCH 268/360] Improve struct size error message to include the detected size --- src/cc65/function.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/function.c b/src/cc65/function.c index 39f04843f..38a8f45aa 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -601,7 +601,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D) ** We don't currently support this case. */ if (RType == Param->Type) { - Error ("Passing '%s' of this size by value is not supported", GetFullTypeName (Param->Type)); + Error ("Passing '%s' of this size (%d) by value is not supported", GetFullTypeName (Param->Type), SizeOf (RType)); } } From ae7a1416fe53de39b991c26a8dc2050a6e98fbe4 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Wed, 3 May 2023 20:02:12 +0200 Subject: [PATCH 269/360] Revert "Revert "Forbid 3-byte struct pass/return by value, document struct value pass/return"" --- doc/cc65.sgml | 7 +- src/cc65/datatype.c | 1 - test/val/struct-by-value.c | 144 +++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 test/val/struct-by-value.c diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 683249bda..1476b40a3 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -741,7 +741,7 @@ Here is a description of all the command line options: <tag><tt/return-type/</tag> Warn about no return statement in function returning non-void. <tag><tt/struct-param/</tag> - Warn when passing structs by value. + Warn when passing structs by value. (Disabled by default.) <tag><tt/unknown-pragma/</tag> Warn about #pragmas that aren't recognized by cc65. <tag><tt/unreachable-code/</tag> @@ -806,9 +806,8 @@ and the one defined by the ISO standard: <item> The datatypes "float" and "double" are not available. <p> -<item> C Functions may not return structs (or unions), and structs may not - be passed as parameters by value. However, struct assignment *is* - possible. +<item> C Functions may pass and return structs (or unions) by value, but only + of 1, 2 or 4 byte sizes. <p> <item> Most of the C library is available with only the fastcall calling convention (<ref id="extension-fastcall" name="see below">). It means diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 6907ee099..caa41a7a4 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -803,7 +803,6 @@ const Type* GetStructReplacementType (const Type* SType) switch (SizeOf (SType)) { case 1: NewType = type_uchar; break; case 2: NewType = type_uint; break; - case 3: /* FALLTHROUGH */ case 4: NewType = type_ulong; break; default: NewType = SType; break; } diff --git a/test/val/struct-by-value.c b/test/val/struct-by-value.c new file mode 100644 index 000000000..0e846c117 --- /dev/null +++ b/test/val/struct-by-value.c @@ -0,0 +1,144 @@ +/* Test of passing and returning structs by value. + Structs of 1, 2 and 4 bytes are supported. + Note that structs of 3 bytes are disabled, see: + https://github.com/cc65/cc65/issues/2022 +*/ + +int fail = 0; + +struct s1 { char a; }; +struct s2 { char a, b; }; +struct s3 { char a, b, c; }; +struct s4 { char a, b, c, d; }; + +const struct s1 c1 = { 1 }; +const struct s2 c2 = { 2, 3 }; +const struct s3 c3 = { 4, 5, 6 }; +const struct s4 c4 = { 7, 8, 9, 10 }; + +struct s1 return1() { return c1; } +struct s2 return2() { return c2; } +/*struct s3 return3() { return c3; }*/ +struct s4 return4() { return c4; } + +int compare1(struct s1 a, struct s1 b) +{ + if (a.a != b.a) return 1; + return 0; +} + +int compare2(struct s2 a, struct s2 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + return 0; +} + +/*int compare3(struct s3 a, struct s3 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + return 0; +}*/ + +int compare4(struct s4 a, struct s4 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + if (a.d != b.d) return 1; + return 0; +} + +int pass1(struct s1 p1) +{ + struct s1 a1; + a1 = p1; + if (a1.a != c1.a) return 1; + return 0; +} + +int pass2(struct s2 p2) +{ + struct s2 a2; + a2 = p2; + if (a2.a != c2.a) return 1; + if (a2.b != c2.b) return 1; + return 0; +} + +/*int pass3(struct s3 p3) +{ + struct s3 a3; + a3 = p3; + if (a3.a != c3.a) return 1; + if (a3.b != c3.b) return 1; + if (a3.c != c3.c) return 1; + return 0; +}*/ + +int pass4(struct s4 p4) +{ + struct s4 a4; + a4 = p4; + if (a4.a != c4.a) return 1; + if (a4.b != c4.b) return 1; + if (a4.c != c4.c) return 1; + if (a4.d != c4.d) return 1; + return 0; +} + +void reset(char* gg) +{ + char i; + for (i=0;i<5;++i) gg[i] = 128+i; +} + +int test(char* gg, char start) +{ + char i; + for (i=start;i<5;++i) + if (gg[i] != 128+i) return 1; + return 0; +} + +int main() +{ + /* Used to check #2022 bug condition of extra bytes being overwritten. */ + union + { + char gg[5]; + struct s1 g1; + struct s2 g2; + struct s3 g3; + struct s4 g4; + } guard; + + reset(guard.gg); + guard.g1 = return1(); + fail += compare1(guard.g1,c1); + fail += test(guard.gg,1); + + reset(guard.gg); + guard.g2 = return2(); + fail += compare2(guard.g2,c2); + fail += test(guard.gg,2); + + /*reset(guard.gg); + guard.g3 = return3(); + fail += compare3(guard.g3,c3); + fail += test(guard.gg,3);*/ + + reset(guard.gg); + guard.g4 = return4(); + fail += compare4(guard.g4,c4); + fail += test(guard.gg,4); + + fail += pass1(c1); + fail += pass2(c2); + /*fail += pass3(c3);*/ + fail += pass4(c4); + + return fail; +} From 440c91fad96e6b94cdec1e4cf249dc0ca0d28fe6 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 14:11:30 -0400 Subject: [PATCH 270/360] braces for 1-line if --- src/ca65/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ca65/main.c b/src/ca65/main.c index d45201cad..fedbb0d4b 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -861,8 +861,9 @@ static void OneLine (void) /* Suppress .size Symbol if this Symbol already has a multiply-defined error, ** as it will only create its own additional unnecessary error. */ - if ((Sym->Flags & SF_MULTDEF) == 0) + if ((Sym->Flags & SF_MULTDEF) == 0) { DefSizeOfSymbol (Sym, Size); + } } /* Line separator must come here */ From 9a502c69dc9d3c4c29791b75d9f03796487e3cc7 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 16:46:59 -0400 Subject: [PATCH 271/360] fix tab, braces for 1-line if, Expr->Ival is signed --- src/cc65/error.c | 2 +- src/cc65/scanner.c | 9 ++++++--- src/cc65/typeconv.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cc65/error.c b/src/cc65/error.c index 6ac3e594b..39b067825 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -103,7 +103,7 @@ static WarnMapEntry WarnMap[] = { { &WarnUnusedLabel, "unused-label" }, { &WarnUnusedParam, "unused-param" }, { &WarnUnusedVar, "unused-var" }, - { &WarnConstOverflow, "const-overflow" }, + { &WarnConstOverflow, "const-overflow" }, }; Collection DiagnosticStrBufs; diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 055c02450..ec49d0e3c 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -584,17 +584,20 @@ static void NumericConst (void) SB_Clear (&Src); break; } - if ((((unsigned long)(IVal * Base)) / Base) != IVal) + if ((((unsigned long)(IVal * Base)) / Base) != IVal) { Overflow = 1; + } IVal = IVal * Base; - if (((unsigned long)(IVal + DigitVal)) < IVal) + if (((unsigned long)(IVal + DigitVal)) < IVal) { Overflow = 1; + } IVal += DigitVal; SB_Skip (&Src); } - if (Overflow) + if (Overflow) { Error ("Numerical constant \"%s\" too large for internal 32-bit representation", SB_GetConstBuf (&Src)); + } /* Distinguish between integer and floating point constants */ if (!IsFloat) { diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 49dfcc597..e1d95ff63 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -128,7 +128,7 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) ** internally already represented by a long. */ if (NewBits <= OldBits) { - unsigned long OldVal = Expr->IVal; + long OldVal = Expr->IVal; /* Cut the value to the new size */ Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits)); From 49bd5681136fc4afff5f46f796eeb777c0e691d1 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 17:55:02 -0400 Subject: [PATCH 272/360] error test for integer constant too large for internal representation --- test/err/huge-integer-constant.c | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 test/err/huge-integer-constant.c diff --git a/test/err/huge-integer-constant.c b/test/err/huge-integer-constant.c new file mode 100644 index 000000000..1f423347c --- /dev/null +++ b/test/err/huge-integer-constant.c @@ -0,0 +1,7 @@ +/* too big for internal integer representation */ +unsigned long huge = 4294967296; + +int main(void) +{ + return 0; +} From e3cb8dfb9be6e4f9244fdecba6610f6a72116763 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 19:27:37 -0400 Subject: [PATCH 273/360] Numerical constant scanner requires explicitly 32-bit sized type for cross-platform consistency --- src/cc65/scanner.c | 16 +++++++++++----- test/val/common.h | 1 + test/val/cq241.c | 19 +++++++++++++++++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index ec49d0e3c..f747fb458 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -39,6 +39,7 @@ #include <errno.h> #include <ctype.h> #include <math.h> +#include <inttypes.h> /* common */ #include "chartype.h" @@ -151,6 +152,11 @@ static const struct Keyword { #define IT_ULONG 0x08 +/* Internal type for numeric constant scanning. +** Size must be explicit for cross-platform uniformity. +*/ +typedef uint32_t scan_t; + /*****************************************************************************/ /* code */ @@ -521,7 +527,7 @@ static void NumericConst (void) int IsFloat; char C; unsigned DigitVal; - unsigned long IVal; /* Value */ + scan_t IVal; /* Scanned value. */ int Overflow; /* Get the pp-number first, then parse on it */ @@ -584,19 +590,19 @@ static void NumericConst (void) SB_Clear (&Src); break; } - if ((((unsigned long)(IVal * Base)) / Base) != IVal) { + if (((scan_t)(IVal * Base) / Base) != IVal) { Overflow = 1; } IVal = IVal * Base; - if (((unsigned long)(IVal + DigitVal)) < IVal) { + if (((scan_t)(IVal + DigitVal)) < IVal) { Overflow = 1; } IVal += DigitVal; SB_Skip (&Src); } if (Overflow) { - Error ("Numerical constant \"%s\" too large for internal 32-bit representation", - SB_GetConstBuf (&Src)); + Error ("Numerical constant \"%s\" too large for internal %d-bit representation", + SB_GetConstBuf (&Src), (int)(sizeof(IVal)*8)); } /* Distinguish between integer and floating point constants */ diff --git a/test/val/common.h b/test/val/common.h index dada61a14..61da6c325 100644 --- a/test/val/common.h +++ b/test/val/common.h @@ -20,3 +20,4 @@ #define SIZEOF_LONG_32BIT #define UNSIGNED_CHARS #define UNSIGNED_BITFIELDS +#define INTEGER_CONSTANT_MAX_32BIT diff --git a/test/val/cq241.c b/test/val/cq241.c index 611b5a376..a6d6c5324 100644 --- a/test/val/cq241.c +++ b/test/val/cq241.c @@ -4,6 +4,14 @@ !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ +/* INTEGER_CONSTANT_MAX_32BIT +** This suppresses constants longer than 32-bit, which are now an error: +** https://github.com/cc65/cc65/pull/2084 +** Because cc65's internal representation is implicitly/explicitly +** 32-bit in many places, values larger than this aren't representable, +** but also can't be checked for overflow once accepted. +*/ + #include "common.h" struct defs { @@ -62,7 +70,12 @@ long pow2(long n) { return s; } - long d[39], o[39], x[39]; +#ifndef INTEGER_CONSTANT_MAX_32BIT +#define CTCOUNT 39 +#else +#define CTCOUNT 36 +#endif + long d[CTCOUNT], o[CTCOUNT], x[CTCOUNT]; #ifndef NO_OLD_FUNC_DECL s241(pd0) @@ -212,13 +225,15 @@ int s241(struct defs *pd0) { d[33] = 1073741823; o[33] = 07777777777; x[33] = 0x3fffffff; d[34] = 1073741824; o[34] = 010000000000; x[34] = 0x40000000; d[35] = 4294967295; o[35] = 037777777777; x[35] = 0xffffffff; +#if CTCOUNT > 36 d[36] = 4294967296; o[36] = 040000000000; x[36] = 0x100000000; d[37] = 68719476735; o[37] = 0777777777777; x[37] = 0xfffffffff; d[38] = 68719476736; o[38] = 01000000000000; x[38] = 0x1000000000; +#endif /* WHEW! */ - for (j=0; j<39; j++){ + for (j=0; j<CTCOUNT; j++){ if ( g[j] != d[j] || d[j] != o[j] || o[j] != x[j]) { From 8e75e5b51a03d1df40e0f052d838dade6a0a6200 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 19:42:05 -0400 Subject: [PATCH 274/360] Suppress overflow warning when conversion is an explicit cast --- src/cc65/typeconv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index e1d95ff63..6bdb45b5f 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -55,7 +55,7 @@ -static void DoConversion (ExprDesc* Expr, const Type* NewType) +static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit) /* Emit code to convert the given expression to a new type. */ { const Type* OldType; @@ -141,7 +141,7 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) } } - if ((OldVal != Expr->IVal) && IS_Get (&WarnConstOverflow)) { + if ((OldVal != Expr->IVal) && IS_Get (&WarnConstOverflow) && !Explicit) { Warning ("Implicit conversion of constant overflows %d-bit destination", NewBits); } } @@ -288,7 +288,7 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType) /* Both types must be complete */ if (!IsIncompleteESUType (NewType) && !IsIncompleteESUType (Expr->Type)) { /* Do the actual conversion */ - DoConversion (Expr, NewType); + DoConversion (Expr, NewType, 0); } else { /* We should have already generated error elsewhere so that we ** could just silently fail here to avoid excess errors, but to @@ -335,7 +335,7 @@ void TypeCast (ExprDesc* Expr) ReplaceType (Expr, NewType); } else if (IsCastType (Expr->Type)) { /* Convert the value. The result has always the new type */ - DoConversion (Expr, NewType); + DoConversion (Expr, NewType, 1); } else { TypeCompatibilityDiagnostic (NewType, Expr->Type, 1, "Cast to incompatible type '%s' from '%s'"); From b5f255f9123dc898e494321406edd434b89a6d49 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 19:54:40 -0400 Subject: [PATCH 275/360] Test case for const-overflow warnings --- test/err/integer-const-overflow.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/err/integer-const-overflow.c diff --git a/test/err/integer-const-overflow.c b/test/err/integer-const-overflow.c new file mode 100644 index 000000000..37cc0f01e --- /dev/null +++ b/test/err/integer-const-overflow.c @@ -0,0 +1,20 @@ +/* Integer constant overflow warnings. */ + +/* Warnings as errors. */ +#pragma warn(error,on) + +/* Warn on const overflow */ +#pragma warn(const-overflow,on) + +unsigned char a = 256; +signed char b = 128; +unsigned char c = -129; +unsigned short int d = 0x00010000; +unsigned short int e = 0x80000000; +signed short int f = 32768L; +signed short int g = -32769L; + +int main(void) +{ + return 0; +} From 84eafb7f9c255d6a82a8062a6d8a8f3c0eb60a72 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Wed, 3 May 2023 21:09:03 -0400 Subject: [PATCH 276/360] err test for struct with duplicate member --- test/err/struct-duplicate-member.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/err/struct-duplicate-member.c diff --git a/test/err/struct-duplicate-member.c b/test/err/struct-duplicate-member.c new file mode 100644 index 000000000..30cd06207 --- /dev/null +++ b/test/err/struct-duplicate-member.c @@ -0,0 +1,17 @@ +/* Ensure that a duplicate member in a struct produces an error. +** https://github.com/cc65/cc65/issues/2015 +*/ + +struct bads { + int a; + int a; /* this is an error */ +}; + +union badu { + int a, a; /* also an error */ +}; + +int main(void) +{ + return 0; +} From 13f317e660b543ec6037e69c17f3226dbee3d171 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 09:18:33 +0200 Subject: [PATCH 277/360] Update Contributing.md --- Contributing.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Contributing.md b/Contributing.md index eb26e920b..3b355373c 100644 --- a/Contributing.md +++ b/Contributing.md @@ -74,10 +74,12 @@ color := $0787 The following is still very incomplete - if in doubt please look at existing sourcefiles and adapt to the existing style -* Your files should obey the C89 standard. +* Your files should generally obey the C89 standard, with a few C99 things (this is a bit similar to what cc65 itself supports). The exceptions are: + * use stdint.h for variables that require a certain bit size + * In printf-style functions use the PRIX64 (and similar) macros to deal with 64bit values (from inttypes.h) +This list is not necessarily complete - if in doubt, please ask. * We generally have a "no warnings" policy -* Warnings must not be hidden by using typecasts - fix the code instead - * In printf-style functions use the PRIX64 (and similar) macros to deal with 64bit values + * Warnings must not be hidden by using typecasts - fix the code instead * The normal indentation width should be four spaces. * You must use ANSI C comments (```/* */```); you must not use C++ comments (```//```). * When you add functions to an existing file, you should separate them by the same number of blank lines that separate the functions that already are in that file. From ca8201a314bc0b6539a49518c334cc297e651764 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Thu, 4 May 2023 05:44:20 -0400 Subject: [PATCH 278/360] Overflow test optimization suggested by kugelfuhr User CHAR_BIT instead of 8 --- src/cc65/scanner.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index f747fb458..54ce02158 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -590,19 +590,15 @@ static void NumericConst (void) SB_Clear (&Src); break; } - if (((scan_t)(IVal * Base) / Base) != IVal) { + if (((scan_t)(IVal * Base + DigitVal) / Base) != IVal) { Overflow = 1; } - IVal = IVal * Base; - if (((scan_t)(IVal + DigitVal)) < IVal) { - Overflow = 1; - } - IVal += DigitVal; + IVal = IVal * Base + DigitVal; SB_Skip (&Src); } if (Overflow) { Error ("Numerical constant \"%s\" too large for internal %d-bit representation", - SB_GetConstBuf (&Src), (int)(sizeof(IVal)*8)); + SB_GetConstBuf (&Src), (int)(sizeof(IVal)*CHAR_BIT)); } /* Distinguish between integer and floating point constants */ From 69f4cd184779925ca399823acc56e50dcff1dc29 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Thu, 4 May 2023 05:48:48 -0400 Subject: [PATCH 279/360] limits.h was apparently already included somewhere on windows but not linux --- src/cc65/scanner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 54ce02158..ede77cb2c 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -40,6 +40,7 @@ #include <ctype.h> #include <math.h> #include <inttypes.h> +#include <limits.h> /* common */ #include "chartype.h" @@ -590,6 +591,7 @@ static void NumericConst (void) SB_Clear (&Src); break; } + /* Test result of adding digit for overflow. */ if (((scan_t)(IVal * Base + DigitVal) / Base) != IVal) { Overflow = 1; } From 0957c36115126f067d42ed5a74210993a6e1e710 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 14:19:27 +0200 Subject: [PATCH 280/360] try verbose dry run to see what it does :) --- .github/workflows/snapshot-on-push-master.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index e8be4400e..38158b384 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -111,7 +111,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - #git push -v + git push -n -v # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 45258d060dc614a2ed07a08711bb4341d19cdb19 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 14:47:02 +0200 Subject: [PATCH 281/360] lets see if this works --- .github/workflows/snapshot-on-push-master.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 38158b384..dc7e6007e 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -7,6 +7,10 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +# suggested at https://jonathansoma.com/everything/git/github-actions-403-error/ +permissions: + contents: write + jobs: build_windows: name: Build (Windows) From 7c5595efbc008aa32645cdb12ad52b186e6e0c67 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 15:02:32 +0200 Subject: [PATCH 282/360] another try --- .github/workflows/snapshot-on-push-master.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index dc7e6007e..759446dc2 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -39,6 +39,8 @@ jobs: runs-on: ubuntu-latest steps: +# inspired by https://github.com/JuliaRegistries/TagBot/blob/master/example.yml + token: ${{ secrets.GITHUB_TOKEN }} - name: Install Dependencies shell: bash run: | From c0dd3b9d9ac9f5e19c6341ae23e75278b0cecf82 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 15:10:10 +0200 Subject: [PATCH 283/360] like this? awesome how everyone does something different :) --- .github/workflows/snapshot-on-push-master.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 759446dc2..933bc05ba 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -39,8 +39,6 @@ jobs: runs-on: ubuntu-latest steps: -# inspired by https://github.com/JuliaRegistries/TagBot/blob/master/example.yml - token: ${{ secrets.GITHUB_TOKEN }} - name: Install Dependencies shell: bash run: | @@ -108,6 +106,8 @@ jobs: repository: cc65/doc path: doc.git - name: Update the online documents. + with: + github_token: ${{ secrets.GITHUB_TOKEN }} run: | cd doc.git rm *.* From 681c51b37e3fa3be8d6518c40506fd62ef4dff6d Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 15:12:46 +0200 Subject: [PATCH 284/360] yawn --- .github/workflows/snapshot-on-push-master.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 933bc05ba..7baa69ba7 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -8,8 +8,13 @@ concurrency: cancel-in-progress: true # suggested at https://jonathansoma.com/everything/git/github-actions-403-error/ +# https://github.com/orgs/community/discussions/26694 permissions: + deployments: write contents: write + statuses: write + actions: write + checks: read jobs: build_windows: @@ -106,8 +111,6 @@ jobs: repository: cc65/doc path: doc.git - name: Update the online documents. - with: - github_token: ${{ secrets.GITHUB_TOKEN }} run: | cd doc.git rm *.* From 20f0427fa42278bac6790f3a1bc0d2d2c8b634e1 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 15:20:33 +0200 Subject: [PATCH 285/360] comment out the push again. who knows whats wrong. sigh --- .github/workflows/snapshot-on-push-master.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 7baa69ba7..75e93b0f8 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -120,7 +120,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - git push -n -v + #git push -n -v # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 99a0d64b935ad2c0aaa85d35d4c7cbb68d8d3b18 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 20:03:27 +0200 Subject: [PATCH 286/360] lets see if that token stuff works --- .github/workflows/snapshot-on-push-master.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 75e93b0f8..3a69ab44b 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -109,6 +109,8 @@ jobs: uses: actions/checkout@v3 with: repository: cc65/doc + # this token will expire, if it does, generate a new one as decribed in https://github.com/cc65/cc65/issues/2065 + token: ${{ secrets.DOC_PAT }} # use secret token instead of default path: doc.git - name: Update the online documents. run: | @@ -120,7 +122,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - #git push -n -v + git push -n -v # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 3536761110067f79231775d304f73dcccf42e355 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 20:30:28 +0200 Subject: [PATCH 287/360] another try --- .github/workflows/snapshot-on-push-master.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 3a69ab44b..c562ad0dd 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -9,12 +9,12 @@ concurrency: # suggested at https://jonathansoma.com/everything/git/github-actions-403-error/ # https://github.com/orgs/community/discussions/26694 -permissions: - deployments: write - contents: write - statuses: write - actions: write - checks: read +#permissions: +# deployments: write +# contents: write +# statuses: write +# actions: write +# checks: read jobs: build_windows: From 0369838f24aece6035321de618f8992c46e9ee91 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 20:45:35 +0200 Subject: [PATCH 288/360] bleh --- .github/workflows/snapshot-on-push-master.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index c562ad0dd..f5f690083 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -122,7 +122,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - git push -n -v + -git push -v # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 926d09a14d812509102f722232d6ffd88d18af1f Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 20:48:52 +0200 Subject: [PATCH 289/360] i'm not patient enough --- .github/workflows/snapshot-on-push-master.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index f5f690083..2b346f1d3 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -66,15 +66,15 @@ jobs: - name: Build the platform libraries. shell: bash run: make -j2 lib QUIET=1 - - name: Run the regression tests. - shell: bash - run: make test QUIET=1 - - name: Test that the samples can be built. - shell: bash - run: make -j2 samples - - name: Remove the output from the samples tests. - shell: bash - run: make -C samples clean +# - name: Run the regression tests. +# shell: bash +# run: make test QUIET=1 +# - name: Test that the samples can be built. +# shell: bash +# run: make -j2 samples +# - name: Remove the output from the samples tests. +# shell: bash +# run: make -C samples clean - name: Remove programs in util directory shell: bash run: make -C util clean From 17f58d934fd2a5bc7b709de36a718e0938cd48d5 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 20:52:50 +0200 Subject: [PATCH 290/360] AGAIN --- .github/workflows/snapshot-on-push-master.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 2b346f1d3..f5340495e 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -122,7 +122,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - -git push -v + git push -v # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From ea90c934d7fd1fccfce4302c2ed0426297ccbc1e Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 20:59:18 +0200 Subject: [PATCH 291/360] try gain with classic token --- .github/workflows/snapshot-on-push-master.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index f5340495e..d859054ec 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -122,7 +122,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - git push -v + git push -n -v # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 610dfbb41ca54b6d0fc8a4661b2f88d79b101ca5 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 21:07:23 +0200 Subject: [PATCH 292/360] try normal push, also try actions/upload-artifact@v3 --- .github/workflows/snapshot-on-push-master.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index d859054ec..20b1ea8f7 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -95,12 +95,12 @@ jobs: mv cc65.zip cc65-snapshot-win32.zip - name: Upload a 32-bit Snapshot Zip - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: cc65-snapshot-win32.zip path: cc65-snapshot-win32.zip - name: Upload a 64-bit Snapshot Zip - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: cc65-snapshot-win64.zip path: cc65-snapshot-win64.zip @@ -122,7 +122,7 @@ jobs: git config push.default simple git add -A git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - git push -n -v + git push # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 7053dac3a99625d169b25a1b7a479d1a17a87091 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 21:13:37 +0200 Subject: [PATCH 293/360] remove token from cc65/doc, reenable the tests again --- .github/workflows/snapshot-on-push-master.yml | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 20b1ea8f7..62d6c6adb 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -7,15 +7,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -# suggested at https://jonathansoma.com/everything/git/github-actions-403-error/ -# https://github.com/orgs/community/discussions/26694 -#permissions: -# deployments: write -# contents: write -# statuses: write -# actions: write -# checks: read - jobs: build_windows: name: Build (Windows) @@ -66,15 +57,15 @@ jobs: - name: Build the platform libraries. shell: bash run: make -j2 lib QUIET=1 -# - name: Run the regression tests. -# shell: bash -# run: make test QUIET=1 -# - name: Test that the samples can be built. -# shell: bash -# run: make -j2 samples -# - name: Remove the output from the samples tests. -# shell: bash -# run: make -C samples clean + - name: Run the regression tests. + shell: bash + run: make test QUIET=1 + - name: Test that the samples can be built. + shell: bash + run: make -j2 samples + - name: Remove the output from the samples tests. + shell: bash + run: make -C samples clean - name: Remove programs in util directory shell: bash run: make -C util clean @@ -110,6 +101,8 @@ jobs: with: repository: cc65/doc # this token will expire, if it does, generate a new one as decribed in https://github.com/cc65/cc65/issues/2065 + # - apparently only a "classic" token works here + # - the token must exist in the cc65/cc65 repo token: ${{ secrets.DOC_PAT }} # use secret token instead of default path: doc.git - name: Update the online documents. From 769b31637689c0ead7983cddf85b5ca019804f3b Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 21:27:48 +0200 Subject: [PATCH 294/360] lets see if this will not fail when there are no changes in the docs --- .github/workflows/snapshot-on-push-master.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 62d6c6adb..9883003fb 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -114,8 +114,8 @@ jobs: git config user.email "cc65.nomail@github.com" git config push.default simple git add -A - git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - git push + git diff-index --quiet HEAD || git commit -m "Updated from cc65 commit ${GITHUB_SHA}." + git diff-index --quiet HEAD || git push # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 4ef849cb81c2a00e8716d8827eb45e27e8575269 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 21:44:57 +0200 Subject: [PATCH 295/360] Force background image to snap left, adapted from https://github.com/cc65/doc/pull/1 --- doc/doc.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/doc.css b/doc/doc.css index e4c316e16..6bd538681 100644 --- a/doc/doc.css +++ b/doc/doc.css @@ -2,12 +2,14 @@ body { font-family: arial, helvetica, sans-serif; font-size: 100%; text-align: justify; - margin-left: 110px; - margin-top: 10px; - margin-right: 30px; - margin-bottom: 10px; + margin: 0px; + padding-left: 110px; + padding-top: 10px; + padding-right: 30px; + padding-bottom: 10px; background-image: url(doc.png); background-repeat: repeat-y; + background-position:left top; } h1, h2, h2 a:link, h2 a:active, h2 a:visited { From e228e4d65c3edd22488a90a8878fb6aa71f42a9f Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 21:58:37 +0200 Subject: [PATCH 296/360] try something else, again --- .github/workflows/snapshot-on-push-master.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 9883003fb..fb42bfcb3 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -114,8 +114,9 @@ jobs: git config user.email "cc65.nomail@github.com" git config push.default simple git add -A - git diff-index --quiet HEAD || git commit -m "Updated from cc65 commit ${GITHUB_SHA}." - git diff-index --quiet HEAD || git push + if git commit -m "Updated from cc65 commit ${GITHUB_SHA}." ; then + git push + fi # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 71bb11bee120872d911b98e58ce869df60b3610f Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 22:09:22 +0200 Subject: [PATCH 297/360] make the commit message a url, also check if it really doesnt fail when there is nothing to commit --- .github/workflows/snapshot-on-push-master.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index fb42bfcb3..50f5cd296 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -114,7 +114,8 @@ jobs: git config user.email "cc65.nomail@github.com" git config push.default simple git add -A - if git commit -m "Updated from cc65 commit ${GITHUB_SHA}." ; then + # prevent failure when there is nothing to commit + if git commit -m "Updated from https://github.com/cc65/cc65/commit/${GITHUB_SHA}" ; then git push fi From 69fd3d79985f09b41edb59c83fdc7c9b0bdfe9dc Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 4 May 2023 22:21:36 +0200 Subject: [PATCH 298/360] tweak --- doc/doc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doc.css b/doc/doc.css index 6bd538681..0f6e90d67 100644 --- a/doc/doc.css +++ b/doc/doc.css @@ -27,7 +27,7 @@ h1 { } h2 { - font-size: 160%; + font-size: 150%; text-shadow: 1px 1px 3px #303030; letter-spacing: 1px; margin-top: 2em; From cfc8a41a031c244ebf5162b08ac88817e7dd175e Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Thu, 4 May 2023 17:07:34 -0400 Subject: [PATCH 299/360] guard test to ensure 3-byte struct isn't re-enabled without evaluation by accident --- test/misc/Makefile | 5 ++ test/misc/struct-by-value.c | 156 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 test/misc/struct-by-value.c diff --git a/test/misc/Makefile b/test/misc/Makefile index d0b8979b0..c708b160b 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -163,6 +163,11 @@ $(WORKDIR)/goto.$1.$2.prg: goto.c $(ISEQUAL) | $(WORKDIR) $(CC65) -t sim$2 -$1 -o $$@ $$< 2>$(WORKDIR)/goto.$1.$2.out $(ISEQUAL) $(WORKDIR)/goto.$1.$2.out goto.ref +# should not compile until 3-byte struct by value tests are re-enabled +$(WORKDIR)/struct-by-value.$1.$2.prg: struct-by-value.c | $(WORKDIR) + $(if $(QUIET),echo misc/struct-by-value.$1.$2.prg) + $(NOT) $(CC65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) + # the rest are tests that fail currently for one reason or another $(WORKDIR)/sitest.$1.$2.prg: sitest.c | $(WORKDIR) @echo "FIXME: " $$@ "currently does not compile." diff --git a/test/misc/struct-by-value.c b/test/misc/struct-by-value.c new file mode 100644 index 000000000..fc44f8729 --- /dev/null +++ b/test/misc/struct-by-value.c @@ -0,0 +1,156 @@ +/* This test ensures that compilation fails if a 3-byte struct by value +** is attempted, to avoid re-introducting a bug by accident: +** https://github.com/cc65/cc65/issues/2022 +** When 3-byte structs are re-enabled, this test will compile, +** which should trigger a "misc" test failure. +** When this happens: +** Delete this comment from the top. +** Replace test/val/struct-by-value.c with this one. +** See: +** https://github.com/cc65/cc65/issues/2086 +*/ + +/* Test of passing and returning structs by value. + Structs of 1, 2, 3, 4 bytes are supported. + Note that structs of 3 bytes had a past issue: + https://github.com/cc65/cc65/issues/2022 +*/ + +int fail = 0; + +struct s1 { char a; }; +struct s2 { char a, b; }; +struct s3 { char a, b, c; }; +struct s4 { char a, b, c, d; }; + +const struct s1 c1 = { 1 }; +const struct s2 c2 = { 2, 3 }; +const struct s3 c3 = { 4, 5, 6 }; +const struct s4 c4 = { 7, 8, 9, 10 }; + +struct s1 return1() { return c1; } +struct s2 return2() { return c2; } +struct s3 return3() { return c3; } +struct s4 return4() { return c4; } + +int compare1(struct s1 a, struct s1 b) +{ + if (a.a != b.a) return 1; + return 0; +} + +int compare2(struct s2 a, struct s2 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + return 0; +} + +int compare3(struct s3 a, struct s3 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + return 0; +} + +int compare4(struct s4 a, struct s4 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + if (a.d != b.d) return 1; + return 0; +} + +int pass1(struct s1 p1) +{ + struct s1 a1; + a1 = p1; + if (a1.a != c1.a) return 1; + return 0; +} + +int pass2(struct s2 p2) +{ + struct s2 a2; + a2 = p2; + if (a2.a != c2.a) return 1; + if (a2.b != c2.b) return 1; + return 0; +} + +int pass3(struct s3 p3) +{ + struct s3 a3; + a3 = p3; + if (a3.a != c3.a) return 1; + if (a3.b != c3.b) return 1; + if (a3.c != c3.c) return 1; + return 0; +} + +int pass4(struct s4 p4) +{ + struct s4 a4; + a4 = p4; + if (a4.a != c4.a) return 1; + if (a4.b != c4.b) return 1; + if (a4.c != c4.c) return 1; + if (a4.d != c4.d) return 1; + return 0; +} + +void reset(char* gg) +{ + char i; + for (i=0;i<5;++i) gg[i] = 128+i; +} + +int test(char* gg, char start) +{ + char i; + for (i=start;i<5;++i) + if (gg[i] != 128+i) return 1; + return 0; +} + +int main() +{ + /* Used to check #2022 bug condition of extra bytes being overwritten. */ + union + { + char gg[5]; + struct s1 g1; + struct s2 g2; + struct s3 g3; + struct s4 g4; + } guard; + + reset(guard.gg); + guard.g1 = return1(); + fail += compare1(guard.g1,c1); + fail += test(guard.gg,1); + + reset(guard.gg); + guard.g2 = return2(); + fail += compare2(guard.g2,c2); + fail += test(guard.gg,2); + + reset(guard.gg); + guard.g3 = return3(); + fail += compare3(guard.g3,c3); + fail += test(guard.gg,3); + + reset(guard.gg); + guard.g4 = return4(); + fail += compare4(guard.g4,c4); + fail += test(guard.gg,4); + + fail += pass1(c1); + fail += pass2(c2); + fail += pass3(c3); + fail += pass4(c4); + + return fail; +} From e57c991de791a0677177cd2e68ab02a05414aa9f Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 10:56:43 -0400 Subject: [PATCH 300/360] master push workflow can include a docs snapshot --- .github/workflows/snapshot-on-push-master.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 50f5cd296..5b37e3645 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -118,9 +118,16 @@ jobs: if git commit -m "Updated from https://github.com/cc65/cc65/commit/${GITHUB_SHA}" ; then git push fi + - name: Package offline documents. + run: 7z a cc65-snapshot-docs.zip ./html/*.* + - name: Upload a Documents Snapshot Zip + uses: actions/upload-artifact@v3 + with: + name: cc65-snapshot-docs.zip + path: cc65-snapshot-docs.zip # enter secrets under "repository secrets" - - name: Upload snapshot to sourceforge + - name: Upload 32-bit Windows snapshot to sourceforge uses: nogsantos/scp-deploy@master with: src: cc65-snapshot-win32.zip @@ -129,5 +136,14 @@ jobs: port: ${{ secrets.SSH_PORT }} user: ${{ secrets.SSH_USER }} key: ${{ secrets.SSH_KEY }} + - name: Upload documents snapshot to sourceforge + uses: nogsantos/scp-deploy@master + with: + src: cc65-snapshot-docs.zip + host: ${{ secrets.SSH_HOST }} + remote: ${{ secrets.SSH_DIR }} + port: ${{ secrets.SSH_PORT }} + user: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_KEY }} # TODO: Publish snapshot zip at https://github.com/cc65/cc65.github.io From 0cad5bef8169b634f288874e324f838a5da89884 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 10:58:18 -0400 Subject: [PATCH 301/360] include docs snapshot with pull request build so that PRs can preview it easily --- .github/workflows/build-on-pull-request.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 05d6a4a39..55be5db1e 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -43,6 +43,11 @@ jobs: - name: Build the document files. shell: bash run: make -j2 doc + - name: Upload a documents snapshot. + uses: actions/upload-artifact@v3 + with: + name: docs + path: ./html - name: Build 64-bit Windows versions of the tools. run: | make -C src clean From 8f356f5093e7c9bbae33fe5103e3812f73eb8c30 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 11:00:06 -0400 Subject: [PATCH 302/360] artifact upload should not end with .zip as it is appended automatically fixes ".zip.zip" artifact filenames --- .github/workflows/snapshot-on-push-master.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 5b37e3645..408bdbb63 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -88,12 +88,12 @@ jobs: - name: Upload a 32-bit Snapshot Zip uses: actions/upload-artifact@v3 with: - name: cc65-snapshot-win32.zip + name: cc65-snapshot-win32 path: cc65-snapshot-win32.zip - name: Upload a 64-bit Snapshot Zip uses: actions/upload-artifact@v3 with: - name: cc65-snapshot-win64.zip + name: cc65-snapshot-win64 path: cc65-snapshot-win64.zip - name: Get the online documents repo. @@ -123,7 +123,7 @@ jobs: - name: Upload a Documents Snapshot Zip uses: actions/upload-artifact@v3 with: - name: cc65-snapshot-docs.zip + name: cc65-snapshot-docs path: cc65-snapshot-docs.zip # enter secrets under "repository secrets" From 9f3e47e9c93d1aa5b439a5ecf2f38ec0a5a41b4c Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 11:04:31 -0400 Subject: [PATCH 303/360] test/standard was never added to test makefile --- test/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Makefile b/test/Makefile index abc70d58f..22e425c9c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,6 +22,7 @@ continue: @$(MAKE) -C val all @$(MAKE) -C ref all @$(MAKE) -C err all + @$(MAKE) -C standard all @$(MAKE) -C misc all @$(MAKE) -C todo all @@ -31,6 +32,7 @@ mostlyclean: @$(MAKE) -C val clean @$(MAKE) -C ref clean @$(MAKE) -C err clean + @$(MAKE) -C standard clean @$(MAKE) -C misc clean @$(MAKE) -C todo clean From 5c20fb28123bd938c18618d321766d85b9ecb4fc Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 11:28:42 -0400 Subject: [PATCH 304/360] test/todo makefile uses testwrk/val by mistake --- test/todo/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/todo/Makefile b/test/todo/Makefile index 17561f8f4..062b899ce 100644 --- a/test/todo/Makefile +++ b/test/todo/Makefile @@ -31,7 +31,7 @@ CA65 := $(if $(wildcard ../../bin/ca65*),..$S..$Sbin$Sca65,ca65) LD65 := $(if $(wildcard ../../bin/ld65*),..$S..$Sbin$Sld65,ld65) SIM65 := $(if $(wildcard ../../bin/sim65*),..$S..$Sbin$Ssim65,sim65) -WORKDIR = ../../testwrk/val +WORKDIR = ../../testwrk/todo OPTIONS = g O Os Osi Osir Osr Oi Oir Or @@ -49,7 +49,7 @@ $(WORKDIR): define PRG_template $(WORKDIR)/%.$1.$2.prg: %.c | $(WORKDIR) - $(if $(QUIET),echo val/$$*.$1.$2.prg) + $(if $(QUIET),echo todo/$$*.$1.$2.prg) $(CC65) -t sim$2 $$(CC65FLAGS) -$1 -o $$(@:.prg=.s) $$< $(NULLERR) $(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR) $(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR) From c662c7a36f6c31c15858e7656c652f864c9d5aaf Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 12:02:50 -0400 Subject: [PATCH 305/360] use diff-index to prevent commit instead of bash if preferred because the if suppresses all git commit errors, instead of the one error we need to suppress (commit with no changes) --- .github/workflows/snapshot-on-push-master.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 50f5cd296..cba5b89dd 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -115,9 +115,8 @@ jobs: git config push.default simple git add -A # prevent failure when there is nothing to commit - if git commit -m "Updated from https://github.com/cc65/cc65/commit/${GITHUB_SHA}" ; then - git push - fi + git diff-index --quiet HEAD || git commit -m "Updated from https://github.com/cc65/cc65/commit/${GITHUB_SHA}" + git push # enter secrets under "repository secrets" - name: Upload snapshot to sourceforge From 1c58b302d8857928832931dfb2fd23a7c448919a Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Fri, 5 May 2023 12:31:19 -0400 Subject: [PATCH 306/360] Bugfix for the .ISMNEMONIC, .ISMNEM builtin function --- src/ca65/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 812b6e90c..5dcf5ca71 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -496,7 +496,7 @@ static ExprNode* FuncIsMnemonic (void) /* Skip the name */ NextTok (); - return GenLiteralExpr (Instr > 0); + return GenLiteralExpr (Instr >= 0); } From 17706208e80de82dff33a6e5feef53d330de4d9d Mon Sep 17 00:00:00 2001 From: Jeff Tranter <tranter@pobox.com> Date: Fri, 5 May 2023 18:02:42 -0400 Subject: [PATCH 307/360] Add support for 48x12 video mode on Challenger 1P. Tested on real C1P hardware. --- doc/osi.sgml | 13 +++++++++++++ libsrc/osic1p/extra/screen-c1p-48x12.s | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 libsrc/osic1p/extra/screen-c1p-48x12.s diff --git a/doc/osi.sgml b/doc/osi.sgml index eeaee4a97..62d466406 100644 --- a/doc/osi.sgml +++ b/doc/osi.sgml @@ -187,8 +187,21 @@ Currently the following extra screen configuration modules are implemented: <itemize> <item><tt>osic1p-screen-s3-32x28.o</tt>: 32 columns by 28 lines mode for Briel Superboard ///</item> +<item><tt>osic1p-screen-c1p-48x12.s</tt>: 48 columns by 12 lines mode +for Challenger 1P</item> </itemize> +On the Briel Superboard /// you enter 32 column mode by holding down +the BREAK key on powerup. + +On the Challenger 1P you can enable 48 column mode by writing a 1 to +bit 0 of address $D800, and writing a 0 to go back to 24 column mode. +You can use code like the following to do this: + +<tscreen><verb> +*(char*)0xd800 = 1; /* Switch to 48 column mode */ +</verb></tscreen> + <sect>Limitations<p> <sect1>stdio implementation<p> diff --git a/libsrc/osic1p/extra/screen-c1p-48x12.s b/libsrc/osic1p/extra/screen-c1p-48x12.s new file mode 100644 index 000000000..91a61338b --- /dev/null +++ b/libsrc/osic1p/extra/screen-c1p-48x12.s @@ -0,0 +1,16 @@ +; +; Implementation of screen-layout related functions for Challenger 1P in 48x12 mode. +; + + .include "../osiscreen.inc" + +C1P_SCR_BASE := $D000 ; Base of C1P video RAM +C1P_VRAM_SIZE = $0400 ; Size of C1P video RAM (1 kB) +C1P_SCR_WIDTH = $30 ; Screen width +C1P_SCR_HEIGHT = $0C ; Screen height +C1P_SCR_FIRSTCHAR = $8B ; Offset of cursor position (0, 0) from base + ; of video RAM +C1P_SCROLL_DIST = $40 ; Memory distance for scrolling by one line + +osi_screen_funcs C1P_SCR_BASE, C1P_VRAM_SIZE, C1P_SCR_FIRSTCHAR, \ + C1P_SCR_WIDTH, C1P_SCR_HEIGHT, C1P_SCROLL_DIST From 18570d18b811ed325972db70b8a21d3668e1e80a Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Fri, 5 May 2023 18:43:10 -0400 Subject: [PATCH 308/360] add test --- test/asm/err/ismnemonic.s | 808 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 808 insertions(+) create mode 100644 test/asm/err/ismnemonic.s diff --git a/test/asm/err/ismnemonic.s b/test/asm/err/ismnemonic.s new file mode 100644 index 000000000..438afed70 --- /dev/null +++ b/test/asm/err/ismnemonic.s @@ -0,0 +1,808 @@ +; Tests to ensure .ismnemonic is working correctly +; The .ismnemonic function calls FindInstruction internally, +; which is how the assembler detects all instructions +; +; Currently supported CPUs: +; "6502" +; "6502X" +; "6502DTV" +; "65SC02" +; "65C02" +; "4510" +; "huc6280" +; "65816" +; "sweet16" + +.macro test_Ismnemonic instr + .if .ismnemonic(instr) + ; do nothing + .else + .error .sprintf(".ISMNEMONIC failed for instruction: %s", .string(instr)) + .endif +.endmacro + +; there is no instruction table for "none", make sure 'adc' (common to all CPUs) and 'add' (sweet16) doesn't match +.setcpu "none" +.if .ismnemonic(adc) || .ismnemonic(add) + .error ".ISMNEMONIC with CPU set to 'none' should not match any instructions." +.endif + +.setcpu "6502" +test_Ismnemonic adc +test_Ismnemonic and +test_Ismnemonic asl +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic brk +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic php +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rti +test_Ismnemonic rts +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic sta +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya + +.setcpu "6502X" +test_Ismnemonic adc +test_Ismnemonic alr +test_Ismnemonic anc +test_Ismnemonic and +test_Ismnemonic ane +test_Ismnemonic arr +test_Ismnemonic asl +test_Ismnemonic axs +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic brk +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic dcp +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic isc +test_Ismnemonic jam +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic las +test_Ismnemonic lax +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic php +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic rla +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rra +test_Ismnemonic rti +test_Ismnemonic rts +test_Ismnemonic sax +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic sha +test_Ismnemonic shx +test_Ismnemonic shy +test_Ismnemonic slo +test_Ismnemonic sre +test_Ismnemonic sta +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic tas +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya + +.setcpu "6502DTV" +test_Ismnemonic adc +test_Ismnemonic alr +test_Ismnemonic anc +test_Ismnemonic and +test_Ismnemonic ane +test_Ismnemonic arr +test_Ismnemonic asl +test_Ismnemonic axs +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic bra +test_Ismnemonic brk +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic las +test_Ismnemonic lax +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic php +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic rla +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rra +test_Ismnemonic rti +test_Ismnemonic rts +test_Ismnemonic sac +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic sha +test_Ismnemonic shx +test_Ismnemonic shy +test_Ismnemonic sir +test_Ismnemonic sta +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya + +.setcpu "65SC02" +test_Ismnemonic adc +test_Ismnemonic and +test_Ismnemonic asl +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic bra +test_Ismnemonic brk +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic dea +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic ina +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic php +test_Ismnemonic phx +test_Ismnemonic phy +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic plx +test_Ismnemonic ply +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rti +test_Ismnemonic rts +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic sta +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic stz +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic trb +test_Ismnemonic tsb +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya + +.setcpu "65C02" +test_Ismnemonic adc +test_Ismnemonic and +test_Ismnemonic asl +test_Ismnemonic bbr0 +test_Ismnemonic bbr1 +test_Ismnemonic bbr2 +test_Ismnemonic bbr3 +test_Ismnemonic bbr4 +test_Ismnemonic bbr5 +test_Ismnemonic bbr6 +test_Ismnemonic bbr7 +test_Ismnemonic bbs0 +test_Ismnemonic bbs1 +test_Ismnemonic bbs2 +test_Ismnemonic bbs3 +test_Ismnemonic bbs4 +test_Ismnemonic bbs5 +test_Ismnemonic bbs6 +test_Ismnemonic bbs7 +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic bra +test_Ismnemonic brk +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic dea +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic ina +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic php +test_Ismnemonic phx +test_Ismnemonic phy +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic plx +test_Ismnemonic ply +test_Ismnemonic rmb0 +test_Ismnemonic rmb1 +test_Ismnemonic rmb2 +test_Ismnemonic rmb3 +test_Ismnemonic rmb4 +test_Ismnemonic rmb5 +test_Ismnemonic rmb6 +test_Ismnemonic rmb7 +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rti +test_Ismnemonic rts +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic smb0 +test_Ismnemonic smb1 +test_Ismnemonic smb2 +test_Ismnemonic smb3 +test_Ismnemonic smb4 +test_Ismnemonic smb5 +test_Ismnemonic smb6 +test_Ismnemonic smb7 +test_Ismnemonic sta +test_Ismnemonic stp +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic stz +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic trb +test_Ismnemonic tsb +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya +test_Ismnemonic wai + +.setcpu "4510" +test_Ismnemonic adc +test_Ismnemonic and +test_Ismnemonic asl +test_Ismnemonic asr +test_Ismnemonic asw +test_Ismnemonic bbr0 +test_Ismnemonic bbr1 +test_Ismnemonic bbr2 +test_Ismnemonic bbr3 +test_Ismnemonic bbr4 +test_Ismnemonic bbr5 +test_Ismnemonic bbr6 +test_Ismnemonic bbr7 +test_Ismnemonic bbs0 +test_Ismnemonic bbs1 +test_Ismnemonic bbs2 +test_Ismnemonic bbs3 +test_Ismnemonic bbs4 +test_Ismnemonic bbs5 +test_Ismnemonic bbs6 +test_Ismnemonic bbs7 +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic bra +test_Ismnemonic brk +test_Ismnemonic bsr +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cle +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic cpz +test_Ismnemonic dea +test_Ismnemonic dec +test_Ismnemonic dew +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic dez +test_Ismnemonic eom +test_Ismnemonic eor +test_Ismnemonic ina +test_Ismnemonic inc +test_Ismnemonic inw +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic inz +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic lbcc +test_Ismnemonic lbcs +test_Ismnemonic lbeq +test_Ismnemonic lbmi +test_Ismnemonic lbne +test_Ismnemonic lbpl +test_Ismnemonic lbra +test_Ismnemonic lbvc +test_Ismnemonic lbvs +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic ldz +test_Ismnemonic lsr +test_Ismnemonic map +test_Ismnemonic neg +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic phd +test_Ismnemonic php +test_Ismnemonic phw +test_Ismnemonic phx +test_Ismnemonic phy +test_Ismnemonic phz +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic plx +test_Ismnemonic ply +test_Ismnemonic plz +test_Ismnemonic rmb0 +test_Ismnemonic rmb1 +test_Ismnemonic rmb2 +test_Ismnemonic rmb3 +test_Ismnemonic rmb4 +test_Ismnemonic rmb5 +test_Ismnemonic rmb6 +test_Ismnemonic rmb7 +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic row +test_Ismnemonic rti +test_Ismnemonic rtn +test_Ismnemonic rts +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic see +test_Ismnemonic sei +test_Ismnemonic smb0 +test_Ismnemonic smb1 +test_Ismnemonic smb2 +test_Ismnemonic smb3 +test_Ismnemonic smb4 +test_Ismnemonic smb5 +test_Ismnemonic smb6 +test_Ismnemonic smb7 +test_Ismnemonic sta +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic stz +test_Ismnemonic tab +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic taz +test_Ismnemonic tba +test_Ismnemonic trb +test_Ismnemonic tsb +test_Ismnemonic tsx +test_Ismnemonic tsy +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya +test_Ismnemonic tys +test_Ismnemonic tza + +.setcpu "HuC6280" +test_Ismnemonic adc +test_Ismnemonic and +test_Ismnemonic asl +test_Ismnemonic bbr0 +test_Ismnemonic bbr1 +test_Ismnemonic bbr2 +test_Ismnemonic bbr3 +test_Ismnemonic bbr4 +test_Ismnemonic bbr5 +test_Ismnemonic bbr6 +test_Ismnemonic bbr7 +test_Ismnemonic bbs0 +test_Ismnemonic bbs1 +test_Ismnemonic bbs2 +test_Ismnemonic bbs3 +test_Ismnemonic bbs4 +test_Ismnemonic bbs5 +test_Ismnemonic bbs6 +test_Ismnemonic bbs7 +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic bra +test_Ismnemonic brk +test_Ismnemonic bsr +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic cla +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic clx +test_Ismnemonic cly +test_Ismnemonic cmp +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic csh +test_Ismnemonic csl +test_Ismnemonic dea +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic ina +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic jmp +test_Ismnemonic jsr +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pha +test_Ismnemonic php +test_Ismnemonic phx +test_Ismnemonic phy +test_Ismnemonic pla +test_Ismnemonic plp +test_Ismnemonic plx +test_Ismnemonic ply +test_Ismnemonic rmb0 +test_Ismnemonic rmb1 +test_Ismnemonic rmb2 +test_Ismnemonic rmb3 +test_Ismnemonic rmb4 +test_Ismnemonic rmb5 +test_Ismnemonic rmb6 +test_Ismnemonic rmb7 +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rti +test_Ismnemonic rts +test_Ismnemonic sax +test_Ismnemonic say +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic set +test_Ismnemonic smb0 +test_Ismnemonic smb1 +test_Ismnemonic smb2 +test_Ismnemonic smb3 +test_Ismnemonic smb4 +test_Ismnemonic smb5 +test_Ismnemonic smb6 +test_Ismnemonic smb7 +test_Ismnemonic st0 +test_Ismnemonic st1 +test_Ismnemonic st2 +test_Ismnemonic sta +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic stz +test_Ismnemonic sxy +test_Ismnemonic tai +test_Ismnemonic tam +test_Ismnemonic tam0 +test_Ismnemonic tam1 +test_Ismnemonic tam2 +test_Ismnemonic tam3 +test_Ismnemonic tam4 +test_Ismnemonic tam5 +test_Ismnemonic tam6 +test_Ismnemonic tam7 +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic tdd +test_Ismnemonic tia +test_Ismnemonic tii +test_Ismnemonic tin +test_Ismnemonic tma +test_Ismnemonic tma0 +test_Ismnemonic tma1 +test_Ismnemonic tma2 +test_Ismnemonic tma3 +test_Ismnemonic tma4 +test_Ismnemonic tma5 +test_Ismnemonic tma6 +test_Ismnemonic tma7 +test_Ismnemonic trb +test_Ismnemonic tsb +test_Ismnemonic tst +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic tya + +.setcpu "65816" +test_Ismnemonic adc +test_Ismnemonic and +test_Ismnemonic asl +test_Ismnemonic bcc +test_Ismnemonic bcs +test_Ismnemonic beq +test_Ismnemonic bit +test_Ismnemonic bmi +test_Ismnemonic bne +test_Ismnemonic bpl +test_Ismnemonic bra +test_Ismnemonic brk +test_Ismnemonic brl +test_Ismnemonic bvc +test_Ismnemonic bvs +test_Ismnemonic clc +test_Ismnemonic cld +test_Ismnemonic cli +test_Ismnemonic clv +test_Ismnemonic cmp +test_Ismnemonic cop +test_Ismnemonic cpa +test_Ismnemonic cpx +test_Ismnemonic cpy +test_Ismnemonic dea +test_Ismnemonic dec +test_Ismnemonic dex +test_Ismnemonic dey +test_Ismnemonic eor +test_Ismnemonic ina +test_Ismnemonic inc +test_Ismnemonic inx +test_Ismnemonic iny +test_Ismnemonic jml +test_Ismnemonic jmp +test_Ismnemonic jsl +test_Ismnemonic jsr +test_Ismnemonic lda +test_Ismnemonic ldx +test_Ismnemonic ldy +test_Ismnemonic lsr +test_Ismnemonic mvn +test_Ismnemonic mvp +test_Ismnemonic nop +test_Ismnemonic ora +test_Ismnemonic pea +test_Ismnemonic pei +test_Ismnemonic per +test_Ismnemonic pha +test_Ismnemonic phb +test_Ismnemonic phd +test_Ismnemonic phk +test_Ismnemonic php +test_Ismnemonic phx +test_Ismnemonic phy +test_Ismnemonic pla +test_Ismnemonic plb +test_Ismnemonic pld +test_Ismnemonic plp +test_Ismnemonic plx +test_Ismnemonic ply +test_Ismnemonic rep +test_Ismnemonic rol +test_Ismnemonic ror +test_Ismnemonic rti +test_Ismnemonic rtl +test_Ismnemonic rts +test_Ismnemonic sbc +test_Ismnemonic sec +test_Ismnemonic sed +test_Ismnemonic sei +test_Ismnemonic sep +test_Ismnemonic sta +test_Ismnemonic stp +test_Ismnemonic stx +test_Ismnemonic sty +test_Ismnemonic stz +test_Ismnemonic swa +test_Ismnemonic tad +test_Ismnemonic tas +test_Ismnemonic tax +test_Ismnemonic tay +test_Ismnemonic tcd +test_Ismnemonic tcs +test_Ismnemonic tda +test_Ismnemonic tdc +test_Ismnemonic trb +test_Ismnemonic tsa +test_Ismnemonic tsb +test_Ismnemonic tsc +test_Ismnemonic tsx +test_Ismnemonic txa +test_Ismnemonic txs +test_Ismnemonic txy +test_Ismnemonic tya +test_Ismnemonic tyx +test_Ismnemonic wai +test_Ismnemonic wdm +test_Ismnemonic xba +test_Ismnemonic xce + +.setcpu "sweet16" +test_Ismnemonic add +test_Ismnemonic bc +test_Ismnemonic bk +test_Ismnemonic bm +test_Ismnemonic bm1 +test_Ismnemonic bnc +test_Ismnemonic bnm1 +test_Ismnemonic bnz +test_Ismnemonic bp +test_Ismnemonic br +test_Ismnemonic bs +test_Ismnemonic bz +test_Ismnemonic cpr +test_Ismnemonic dcr +test_Ismnemonic inr +test_Ismnemonic ld +test_Ismnemonic ldd +test_Ismnemonic pop +test_Ismnemonic popd +test_Ismnemonic rs +test_Ismnemonic rtn +test_Ismnemonic set +test_Ismnemonic st +test_Ismnemonic std +test_Ismnemonic stp +test_Ismnemonic sub From c5cf32ac47836b770e73323c10a5aa6b5e8d1195 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Fri, 5 May 2023 18:50:44 -0400 Subject: [PATCH 309/360] add test - fix --- test/asm/{err => val}/ismnemonic.s | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/asm/{err => val}/ismnemonic.s (100%) diff --git a/test/asm/err/ismnemonic.s b/test/asm/val/ismnemonic.s similarity index 100% rename from test/asm/err/ismnemonic.s rename to test/asm/val/ismnemonic.s From 7994889213352a82c904efd06f5b82bbfdf193e7 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Fri, 5 May 2023 19:07:14 -0400 Subject: [PATCH 310/360] add test - fix again --- test/asm/val/ismnemonic.s | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/asm/val/ismnemonic.s b/test/asm/val/ismnemonic.s index 438afed70..4ba74c97f 100644 --- a/test/asm/val/ismnemonic.s +++ b/test/asm/val/ismnemonic.s @@ -13,18 +13,22 @@ ; "65816" ; "sweet16" +; count any errors: +ismnemonic_error .set 0 + +; macro to test an instruction .macro test_Ismnemonic instr .if .ismnemonic(instr) ; do nothing .else - .error .sprintf(".ISMNEMONIC failed for instruction: %s", .string(instr)) + ismnemonic_error .set ismnemonic_error + 1 .endif .endmacro ; there is no instruction table for "none", make sure 'adc' (common to all CPUs) and 'add' (sweet16) doesn't match .setcpu "none" .if .ismnemonic(adc) || .ismnemonic(add) - .error ".ISMNEMONIC with CPU set to 'none' should not match any instructions." + ismnemonic_error .set ismnemonic_error + 1 .endif .setcpu "6502" @@ -806,3 +810,17 @@ test_Ismnemonic st test_Ismnemonic std test_Ismnemonic stp test_Ismnemonic sub + + .setcpu "6502" + + .import _exit + .export _main + +_main: + .if ismnemonic_error + ldx #$01 + .else + ldx #$00 + .endif + txa + jmp _exit From dd0a2bf1bc78188b75a22003590f20a4fedac941 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Fri, 5 May 2023 19:10:16 -0400 Subject: [PATCH 311/360] add test - fix stlye --- test/asm/val/ismnemonic.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/asm/val/ismnemonic.s b/test/asm/val/ismnemonic.s index 4ba74c97f..a4534a9c4 100644 --- a/test/asm/val/ismnemonic.s +++ b/test/asm/val/ismnemonic.s @@ -815,7 +815,7 @@ test_Ismnemonic sub .import _exit .export _main - + _main: .if ismnemonic_error ldx #$01 From 8d048699ee6b33c68f06bc6d0a16e521a733a386 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 21:32:34 -0400 Subject: [PATCH 312/360] grc65 fix flawed text parsing Was using fseek(F,-1,SEEK_CUR) which is invalid for text files, behaviour unreliable across platforms. Added check for internal buffer overflow. --- src/grc65/main.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/grc65/main.c b/src/grc65/main.c index 349b5c110..ac654300d 100644 --- a/src/grc65/main.c +++ b/src/grc65/main.c @@ -850,8 +850,12 @@ static char *filterInput (FILE *F, char *tbl) /* loads file into buffer filtering it out */ int a, prevchar = -1, i = 0, bracket = 0, quote = 1; - for (;;) { - a = getc(F); + a = getc(F); + while (1) + { + if (i >= BLOODY_BIG_BUFFER) { + AbEnd ("File too large for internal parsing buffer (%d bytes).",BLOODY_BIG_BUFFER); + } if ((a == '\n') || (a == '\015')) a = ' '; if (a == ',' && quote) a = ' '; if (a == '\042') quote =! quote; @@ -873,13 +877,18 @@ static char *filterInput (FILE *F, char *tbl) if (a == ';' && quote) { do { a = getc (F); - } while (a != '\n'); - fseek (F, -1, SEEK_CUR); + } while (a != '\n' && a != EOF); + /* Don't discard this newline/EOF, continue to next loop. + ** A previous implementation used fseek(F,-1,SEEK_CUR), + ** which is invalid for text mode files, and was unreliable across platforms. + */ + continue; } else { tbl[i++] = a; prevchar = a; } } + a = getc(F); } if (bracket != 0) AbEnd ("There are unclosed brackets!"); From f2e7609046b4febb23a5726f2f4dbd1489aac929 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 21:45:57 -0400 Subject: [PATCH 313/360] sim65 cycles 32-bit range fix long is 64-bit on some platforms, making this inconsistent, added range check to catch overflow. reduced tests requesting 5 billion cycles to 2^32-1 so they can fun on 32-bit long sim65. --- src/sim65/main.c | 5 +++++ test/asm/val/Makefile | 3 ++- test/standard/Makefile | 3 ++- test/val/Makefile | 3 ++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/sim65/main.c b/src/sim65/main.c index f2daf9295..9e371fd5d 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -36,6 +36,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <limits.h> /* common */ #include "abend.h" @@ -140,6 +141,10 @@ static void OptQuitXIns (const char* Opt attribute ((unused)), /* quit after MaxCycles cycles */ { MaxCycles = strtoul(Arg, NULL, 0); + /* Guard against overflow. */ + if (MaxCycles == ULONG_MAX && errno == ERANGE) { + Error("'-x parameter out of range. Max: %lu",ULONG_MAX); + } } static unsigned char ReadProgramFile (void) diff --git a/test/asm/val/Makefile b/test/asm/val/Makefile index 91dae9afd..49b6d5290 100644 --- a/test/asm/val/Makefile +++ b/test/asm/val/Makefile @@ -22,7 +22,8 @@ ifdef QUIET NULLERR = 2>$(NULLDEV) endif -SIM65FLAGS = -x 5000000000 +# sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. +SIM65FLAGS = -x 4294967295 CA65 := $(if $(wildcard ../../../bin/ca65*),..$S..$S..$Sbin$Sca65,ca65) LD65 := $(if $(wildcard ../../../bin/ld65*),..$S..$S..$Sbin$Sld65,ld65) diff --git a/test/standard/Makefile b/test/standard/Makefile index 054623b79..9993ba699 100644 --- a/test/standard/Makefile +++ b/test/standard/Makefile @@ -22,7 +22,8 @@ ifdef QUIET NULLERR = 2>$(NULLDEV) endif -SIM65FLAGS = -x 5000000000 -c +# sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. +SIM65FLAGS = -x 4294967295 -c CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) CA65 := $(if $(wildcard ../../bin/ca65*),..$S..$Sbin$Sca65,ca65) diff --git a/test/val/Makefile b/test/val/Makefile index a3722f7bf..8820e535a 100644 --- a/test/val/Makefile +++ b/test/val/Makefile @@ -24,7 +24,8 @@ ifdef QUIET NULLERR = 2>$(NULLDEV) endif -SIM65FLAGS = -x 5000000000 -c +# sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. +SIM65FLAGS = -x 4294967295 -c CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) CA65 := $(if $(wildcard ../../bin/ca65*),..$S..$Sbin$Sca65,ca65) From 773716c32ae0f19a78264c511d89758600288dce Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 21:46:11 -0400 Subject: [PATCH 314/360] sim65 close(-1) crash fix test/val/constexpr.c relies on close(-1) to return -1 for some reason (comment says "abuse"), but on MSVC close(-1) is treated as a security issue and terminates the program instead of returning -1 simulating this desire for sim65, though constexpr.c may also warrant a review --- src/sim65/paravirt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index 9e5c28432..0b16f89e9 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -242,7 +242,15 @@ static void PVClose (CPURegs* Regs) Print (stderr, 2, "PVClose ($%04X)\n", FD); - RetVal = close (FD); + if (FD != 0xFFFF) { + RetVal = close (FD); + } else { + /* test/val/constexpr.c "abuses" close, expecting close(-1) to return -1. + ** This behaviour is not the same on all target platforms. + ** MSVC's close treats it as a fatal error instead and terminates. + */ + RetVal = 0xFFFF; + } SetAX (Regs, RetVal); } From c03d00bc805ffdda6afe1866d6263e7eef098a39 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 21:46:42 -0400 Subject: [PATCH 315/360] sim65 suppress uninitialized variable warning the EOF check was protecting uninitialized Val2 but the compiler can't figure that out --- src/sim65/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sim65/main.c b/src/sim65/main.c index 9e371fd5d..27299168e 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -189,6 +189,7 @@ static unsigned char ReadProgramFile (void) } /* Get load address */ + Val2 = 0; /* suppress uninitialized variable warning */ if (((Val = fgetc(F)) == EOF) || ((Val2 = fgetc(F)) == EOF)) { Error ("'%s': Header missing load address", ProgramFile); From df749abbfba01458907fd954beb47e96756d4fe7 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 21:56:52 -0400 Subject: [PATCH 316/360] libtest target alternative to libs saves me about 20 minutes if I only want to run tests --- Makefile | 4 ++-- libsrc/Makefile | 8 +++++++- test/readme.txt | 6 +++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 909de81ec..29fcbbf96 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ mostlyclean clean: avail unavail bin: @$(MAKE) -C src --no-print-directory $@ -lib: +lib libtest: @$(MAKE) -C libsrc --no-print-directory $@ doc html info: @@ -43,7 +43,7 @@ util: checkstyle: @$(MAKE) -C .github/checks --no-print-directory $@ -# simple "test" target, only run regression tests for c64 target +# runs regression tests, requires libtest target libraries test: @$(MAKE) -C test --no-print-directory $@ diff --git a/libsrc/Makefile b/libsrc/Makefile index 627897d9b..732fa1d0e 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -39,6 +39,10 @@ TARGETS = apple2 \ sym1 \ telestrat +TARGETTEST = none \ + sim6502 \ + sim65c02 + DRVTYPES = emd \ joy \ mou \ @@ -53,7 +57,7 @@ OUTPUTDIRS := lib $(subst ../,,$(wildcard ../target/*/drv/*)) \ $(subst ../,,$(wildcard ../target/*/util)) -.PHONY: all mostlyclean clean install zip lib $(TARGETS) +.PHONY: all mostlyclean clean install zip lib libtest $(TARGETS) .SUFFIXES: @@ -81,6 +85,8 @@ datadir = $(PREFIX)/share/cc65 all lib: $(TARGETS) +libtest: $(TARGETTEST) + mostlyclean: $(call RMDIR,../libwrk) diff --git a/test/readme.txt b/test/readme.txt index 41d19aee3..d3f17148e 100644 --- a/test/readme.txt +++ b/test/readme.txt @@ -68,7 +68,11 @@ compiler is working as expected (when the tests behave as described): which will require additional changes to the makefile(s). -To run the tests use "make" in this (top) directory, the makefile should exit +These tests only require a subset of the platform libraries. In the (top) +directory above this one, "make libtest" can be used to build only those +libraries needed for testing, instead of "make lib". + +To run the tests use "make" in this (test) directory, the makefile should exit with no error. When a test failed you can use "make continue" to run further tests. From a022f7203dca1b7b4a00a2fdfff577b9f08ec90d Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Fri, 5 May 2023 22:05:10 -0400 Subject: [PATCH 317/360] workflow for manually dispatched Windows build and test --- .github/workflows/build-on-pull-request.yml | 4 ++ .github/workflows/snapshot-on-push-master.yml | 4 ++ .github/workflows/windows-test-manual.yml | 43 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 .github/workflows/windows-test-manual.yml diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 05d6a4a39..57f00751d 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -67,3 +67,7 @@ jobs: - name: Build app (release) run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release + + # The regression tests are currently too slow to run for this Windows build, + # but the "Windows Test Manual" workflow (windows-test-manual.yml) can by + # manually dispatched from the Actions menu to test as needed. diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 50f5cd296..43fcce0a8 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -29,6 +29,10 @@ jobs: - name: Build app (release) run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release + # The regression tests are currently too slow to run for this Windows build, + # but the "Windows Test Manual" workflow (windows-test-manual.yml) can by + # manually dispatched from the Actions menu to test as needed. + build_linux: name: Build, Test, and Snapshot (Linux) if: github.repository == 'cc65/cc65' diff --git a/.github/workflows/windows-test-manual.yml b/.github/workflows/windows-test-manual.yml new file mode 100644 index 000000000..854327726 --- /dev/null +++ b/.github/workflows/windows-test-manual.yml @@ -0,0 +1,43 @@ +name: Windows Test Manual +# Manually dispatched because it's much slower than the Linux test. + +on: + workflow_dispatch: + +jobs: + build_windows: + name: Build, Test (Windows MSVC) + runs-on: windows-latest + + steps: + - name: Git Setup + shell: bash + run: git config --global core.autocrlf input + + - name: Checkout source + uses: actions/checkout@v3 + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: Build app (MSVC debug) + run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug + + - name: Build app (MSVC release) + run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release + + - name: Build utils (MinGW) + shell: cmd + run: make -j2 util + + - name: Build the platform libraries (make lib) + shell: cmd + run: make -j2 lib QUIET=1 + + - name: Run the regression tests (make test) + shell: cmd + run: make test QUIET=1 + + - name: Test that the samples can be built (make samples) + shell: cmd + run: make -j2 samples From 1df7ab0352a43546c6ece76830594a687681c938 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sat, 6 May 2023 11:55:21 -0400 Subject: [PATCH 318/360] opening brace on same line as while other AbEnd messages don't end in . --- src/grc65/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/grc65/main.c b/src/grc65/main.c index ac654300d..adce3dc47 100644 --- a/src/grc65/main.c +++ b/src/grc65/main.c @@ -851,10 +851,9 @@ static char *filterInput (FILE *F, char *tbl) int a, prevchar = -1, i = 0, bracket = 0, quote = 1; a = getc(F); - while (1) - { + while (1) { if (i >= BLOODY_BIG_BUFFER) { - AbEnd ("File too large for internal parsing buffer (%d bytes).",BLOODY_BIG_BUFFER); + AbEnd ("File too large for internal parsing buffer (%d bytes)",BLOODY_BIG_BUFFER); } if ((a == '\n') || (a == '\015')) a = ' '; if (a == ',' && quote) a = ' '; From 532681c9613af15b1993e08db12761855c9707c6 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sat, 6 May 2023 12:06:06 -0400 Subject: [PATCH 319/360] braces were requested combining the two a = ' ' cases was requested --- src/grc65/main.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/grc65/main.c b/src/grc65/main.c index adce3dc47..7d31bfc52 100644 --- a/src/grc65/main.c +++ b/src/grc65/main.c @@ -855,12 +855,20 @@ static char *filterInput (FILE *F, char *tbl) if (i >= BLOODY_BIG_BUFFER) { AbEnd ("File too large for internal parsing buffer (%d bytes)",BLOODY_BIG_BUFFER); } - if ((a == '\n') || (a == '\015')) a = ' '; - if (a == ',' && quote) a = ' '; - if (a == '\042') quote =! quote; + if (((a == '\n') || (a == '\015')) || + (a == ',' && quote)) { + a = ' '; + } + if (a == '\042') { + quote =! quote; + } if (quote) { - if ((a == '{') || (a == '(')) bracket++; - if ((a == '}') || (a == ')')) bracket--; + if ((a == '{') || (a == '(')) { + bracket++; + } + if ((a == '}') || (a == ')')) { + bracket--; + } } if (a == EOF) { tbl[i] = '\0'; From fe35386b794b5359c726a5867b26f8dc58c26615 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 6 May 2023 12:56:34 -0400 Subject: [PATCH 320/360] add test - add overloading instruction test --- test/asm/val/ismnemonic.s | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/asm/val/ismnemonic.s b/test/asm/val/ismnemonic.s index a4534a9c4..2d131e7a9 100644 --- a/test/asm/val/ismnemonic.s +++ b/test/asm/val/ismnemonic.s @@ -21,14 +21,34 @@ ismnemonic_error .set 0 .if .ismnemonic(instr) ; do nothing .else - ismnemonic_error .set ismnemonic_error + 1 + ismnemonic_error .set 1 .endif .endmacro +; test .feature ubiquitous_idents + + ; allow overloading mnemonics +.feature ubiquitous_idents + +.setcpu "6502" + +; make an adc macro +.macro adc +.endmacro + +; should not match +.if .ismnemonic(adc) + ismnemonic_error .set 1 +.endif + +.delmac adc + +; test all instructions: + ; there is no instruction table for "none", make sure 'adc' (common to all CPUs) and 'add' (sweet16) doesn't match .setcpu "none" .if .ismnemonic(adc) || .ismnemonic(add) - ismnemonic_error .set ismnemonic_error + 1 + ismnemonic_error .set 1 .endif .setcpu "6502" From 84f0ab322d4b056191fd09d8fbc792ba1e045453 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sat, 6 May 2023 13:54:28 -0400 Subject: [PATCH 321/360] sim65: cycles does not increment 1 at a time, so some small overhead is needed in range check --- src/sim65/main.c | 11 ++++++++--- test/asm/val/Makefile | 2 +- test/standard/Makefile | 2 +- test/val/Makefile | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/sim65/main.c b/src/sim65/main.c index 27299168e..d92d52ef6 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -64,6 +64,12 @@ const char* ProgramFile; /* exit simulator after MaxCycles Cycles */ unsigned long MaxCycles; +/* maximum number of cycles that can be tested, +** requires overhead for longest possible instruction, +** which should be 7, using 16 for safety. +*/ +#define MAXCYCLES_LIMIT (ULONG_MAX-16) + /* Header signature 'sim65' */ static const unsigned char HeaderSignature[] = { 0x73, 0x69, 0x6D, 0x36, 0x35 @@ -73,7 +79,6 @@ static const unsigned char HeaderSignature[] = { static const unsigned char HeaderVersion = 2; - /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -142,8 +147,8 @@ static void OptQuitXIns (const char* Opt attribute ((unused)), { MaxCycles = strtoul(Arg, NULL, 0); /* Guard against overflow. */ - if (MaxCycles == ULONG_MAX && errno == ERANGE) { - Error("'-x parameter out of range. Max: %lu",ULONG_MAX); + if (MaxCycles >= MAXCYCLES_LIMIT) { + Error("'-x parameter out of range. Max: %lu",MAXCYCLES_LIMIT); } } diff --git a/test/asm/val/Makefile b/test/asm/val/Makefile index 49b6d5290..09a6b91bc 100644 --- a/test/asm/val/Makefile +++ b/test/asm/val/Makefile @@ -23,7 +23,7 @@ ifdef QUIET endif # sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. -SIM65FLAGS = -x 4294967295 +SIM65FLAGS = -x 4000000000 CA65 := $(if $(wildcard ../../../bin/ca65*),..$S..$S..$Sbin$Sca65,ca65) LD65 := $(if $(wildcard ../../../bin/ld65*),..$S..$S..$Sbin$Sld65,ld65) diff --git a/test/standard/Makefile b/test/standard/Makefile index 9993ba699..40299c1bf 100644 --- a/test/standard/Makefile +++ b/test/standard/Makefile @@ -23,7 +23,7 @@ ifdef QUIET endif # sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. -SIM65FLAGS = -x 4294967295 -c +SIM65FLAGS = -x 4000000000 -c CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) CA65 := $(if $(wildcard ../../bin/ca65*),..$S..$Sbin$Sca65,ca65) diff --git a/test/val/Makefile b/test/val/Makefile index 8820e535a..158967f9e 100644 --- a/test/val/Makefile +++ b/test/val/Makefile @@ -25,7 +25,7 @@ ifdef QUIET endif # sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. -SIM65FLAGS = -x 4294967295 -c +SIM65FLAGS = -x 4000000000 -c CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) CA65 := $(if $(wildcard ../../bin/ca65*),..$S..$Sbin$Sca65,ca65) From 11cc5b6f06ca9bf1341eb6cc6e5055e5d01c2bc8 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 6 May 2023 14:24:53 -0400 Subject: [PATCH 322/360] remove .feature requirment for addrsize function, silently ignore '.feature addrsize' --- doc/ca65.sgml | 10 ---------- src/ca65/feature.c | 3 ++- src/ca65/global.c | 1 - src/ca65/global.h | 1 - src/ca65/scanner.c | 17 ----------------- 5 files changed, 2 insertions(+), 30 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 258808998..b4ef3e188 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -1409,10 +1409,6 @@ either a string or an expression value. .endmacro </verb></tscreen> - This command is new and must be enabled with the <tt/.FEATURE addrsize/ command. - - See: <tt><ref id=".FEATURE" name=".FEATURE"></tt> - <sect1><tt>.BANK</tt><label id=".BANK"><p> @@ -2795,12 +2791,6 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH <descrip> - <tag><tt>addrsize</tt><label id="addrsize"></tag> - - Enables the .ADDRSIZE pseudo function. This function is experimental and not enabled by default. - - See also: <tt><ref id=".ADDRSIZE" name=".ADDRSIZE"></tt> - <tag><tt>at_in_identifiers</tt><label id="at_in_identifiers"></tag> Accept the at character ('@') as a valid character in identifiers. The diff --git a/src/ca65/feature.c b/src/ca65/feature.c index 41177d66b..8b915cfda 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -118,10 +118,11 @@ void SetFeature (feature_t Feature, unsigned char On) case FEAT_C_COMMENTS: CComments = On; break; case FEAT_FORCE_RANGE: ForceRange = On; break; case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= On; break; - case FEAT_ADDRSIZE: AddrSize = On; break; case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = On; break; case FEAT_STRING_ESCAPES: StringEscapes = On; break; case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = On; break; + /* Accept, but ignore addrsize */ + case FEAT_ADDRSIZE: break; default: break; } } diff --git a/src/ca65/global.c b/src/ca65/global.c index 337677e31..050d19e09 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -85,5 +85,4 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */ unsigned char CComments = 0; /* Allow C like comments */ unsigned char ForceRange = 0; /* Force values into expected range */ unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */ -unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */ unsigned char BracketAsIndirect = 0; /* Use '[]' not '()' for indirection */ diff --git a/src/ca65/global.h b/src/ca65/global.h index 46fb6c763..b3de99df5 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -87,7 +87,6 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */ extern unsigned char CComments; /* Allow C like comments */ extern unsigned char ForceRange; /* Force values into expected range */ extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */ -extern unsigned char AddrSize; /* Allow .ADDRSIZE function */ extern unsigned char BracketAsIndirect; /* Use '[]' not '()' for indirection */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index add365e84..185100025 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -748,24 +748,7 @@ static token_t FindDotKeyword (void) R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]), sizeof (DotKeywords [0]), CmpDotKeyword); if (R != 0) { - - /* By default, disable any somewhat experiemental DotKeyword. */ - - switch (R->Tok) { - - case TOK_ADDRSIZE: - /* Disallow .ADDRSIZE function by default */ - if (AddrSize == 0) { - return TOK_NONE; - } - break; - - default: - break; - } - return R->Tok; - } else { return TOK_NONE; } From 560085cb1763c331ab5e0e47272b66026e59a36b Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 6 May 2023 16:22:04 -0400 Subject: [PATCH 323/360] modify and add tests --- test/asm/val/addrsize.s | 32 ++++++++++++++++++++++++++++++++ test/asm/val/feature.s | 13 ------------- 2 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 test/asm/val/addrsize.s diff --git a/test/asm/val/addrsize.s b/test/asm/val/addrsize.s new file mode 100644 index 000000000..932090df0 --- /dev/null +++ b/test/asm/val/addrsize.s @@ -0,0 +1,32 @@ +; test .addrsize and ensure .feature addrsize is allowed, but inactive + +.export _main + +.segment "ZEROPAGE" +zplabel: + +.segment "CODE" +abslabel: + +; exit with 0 + +_main: + lda #0 + tax + rts + + +.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" +.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" + +.feature addrsize +.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" +.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" + +.feature addrsize + +.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" +.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" + +.feature addrsize - +.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" +.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" diff --git a/test/asm/val/feature.s b/test/asm/val/feature.s index 4428cf4c2..39e3a7862 100644 --- a/test/asm/val/feature.s +++ b/test/asm/val/feature.s @@ -2,12 +2,6 @@ .export _main -.segment "ZEROPAGE" -zplabel: - -.segment "CODE" -abslabel: - ; exit with 0 _main: @@ -17,13 +11,6 @@ _main: tax rts - -.feature addrsize + -.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" -.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" -.feature addrsize - - - .feature at_in_identifiers on ident@with@at: rts From bee29dedd17841d77c861fb737874e8905ebe7d3 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sat, 6 May 2023 17:11:57 -0400 Subject: [PATCH 324/360] fix feature.s test --- test/asm/val/feature.s | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/asm/val/feature.s b/test/asm/val/feature.s index 39e3a7862..0def9d92c 100644 --- a/test/asm/val/feature.s +++ b/test/asm/val/feature.s @@ -2,6 +2,11 @@ .export _main +.segment "ZEROPAGE" +zplabel: + +.segment "CODE" + ; exit with 0 _main: From 56df849101318a9a2aa61b407d5c0f9fb7fd2eb6 Mon Sep 17 00:00:00 2001 From: mvax <big.jt@protonmail.com> Date: Sun, 7 May 2023 14:53:44 -0400 Subject: [PATCH 325/360] add warning for .feature addrsize, clean up switch in SetFeature --- src/ca65/feature.c | 2 -- src/ca65/pseudo.c | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ca65/feature.c b/src/ca65/feature.c index 8b915cfda..9f5ca5876 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -121,8 +121,6 @@ void SetFeature (feature_t Feature, unsigned char On) case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = On; break; case FEAT_STRING_ESCAPES: StringEscapes = On; break; case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = On; break; - /* Accept, but ignore addrsize */ - case FEAT_ADDRSIZE: break; default: break; } } diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 1877512d5..cf4d1f64b 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1043,6 +1043,12 @@ static void DoFeature (void) ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal); return; } + + if (Feature == FEAT_ADDRSIZE) { + /* Warn for depreciated .feature addrsize */ + Warning (1, "Depreciated feature: '.feature addrsize'. Pseudo function .addrsize is always available."); + } + NextTok (); /* Optional +/- or ON/OFF */ From 0081fe548ce3908dee2624a322d89af8d06ed4bb Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 7 May 2023 16:26:42 -0400 Subject: [PATCH 326/360] sim64 universal 64-bit cycle count support: MaxCycleCount is accounted by countdown, eliminating the 1-instruction-overhead issue, and removing the need to compare against a growing TotalCycles. Makes main.c responsible for counting total cycles, instead of 6502.c, so the size of MaxCycleCount etc. is fully determined in one location. Makes error.c responsible for PrintCycles instead of paravirt.c, so that it can be treated globally instead of Return value of main() should be SIM65_ERROR because it is unreachable by design. --- src/sim65/6502.c | 18 ------------------ src/sim65/6502.h | 6 ------ src/sim65/error.c | 25 +++++++++++++++++++++++++ src/sim65/error.h | 6 ++++++ src/sim65/main.c | 40 +++++++++++++++++++++------------------- src/sim65/paravirt.c | 6 +----- 6 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/sim65/6502.c b/src/sim65/6502.c index 6c23b0dfc..9d2c93da8 100644 --- a/src/sim65/6502.c +++ b/src/sim65/6502.c @@ -64,18 +64,12 @@ static CPURegs Regs; /* Cycles for the current insn */ static unsigned Cycles; -/* Total number of CPU cycles exec'd */ -static unsigned long TotalCycles; - /* NMI request active */ static unsigned HaveNMIRequest; /* IRQ request active */ static unsigned HaveIRQRequest; -/* flag to print cycles at program termination */ -int PrintCycles; - /*****************************************************************************/ /* Helper functions and macros */ @@ -3277,18 +3271,6 @@ unsigned ExecuteInsn (void) Handlers[CPU][OPC] (); } - /* Count cycles */ - TotalCycles += Cycles; - /* Return the number of clock cycles needed by this insn */ return Cycles; } - - - -unsigned long GetCycles (void) -/* Return the total number of cycles executed */ -{ - /* Return the total number of cycles */ - return TotalCycles; -} diff --git a/src/sim65/6502.h b/src/sim65/6502.h index f8e894567..39b995793 100644 --- a/src/sim65/6502.h +++ b/src/sim65/6502.h @@ -96,12 +96,6 @@ unsigned ExecuteInsn (void); ** executed instruction. */ -unsigned long GetCycles (void); -/* Return the total number of clock cycles executed */ - -extern int PrintCycles; -/* flag to print cycles at program termination */ - /* End of 6502.h */ diff --git a/src/sim65/error.c b/src/sim65/error.c index 441b07d2a..fc24ca006 100644 --- a/src/sim65/error.c +++ b/src/sim65/error.c @@ -41,6 +41,20 @@ +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* flag to print cycles at program termination */ +int PrintCycles = 0; + +/* cycles are counted by main.c */ +extern unsigned long long TotalCycles; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -99,3 +113,14 @@ void Internal (const char* Format, ...) va_end (ap); exit (SIM65_ERROR); } + + + +void SimExit (int Code) +/* Exit the simulation with an exit code */ +{ + if (PrintCycles) { + fprintf (stdout, "%llu cycles\n", TotalCycles); + } + exit (Code); +} diff --git a/src/sim65/error.h b/src/sim65/error.h index ea54fa048..a016881c6 100644 --- a/src/sim65/error.h +++ b/src/sim65/error.h @@ -55,6 +55,9 @@ #define SIM65_ERROR_TIMEOUT 0x7E /* An error result for max CPU instructions exceeded. */ +extern int PrintCycles; +/* flag to print cycles at program termination */ + /*****************************************************************************/ @@ -75,6 +78,9 @@ void ErrorCode (int Code, const char* Format, ...) attribute((noreturn, format(p void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ +void SimExit (int Code); +/* Exit the simulation with an exit code */ + /* End of error.h */ diff --git a/src/sim65/main.c b/src/sim65/main.c index d92d52ef6..f5ace1909 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -36,7 +36,6 @@ #include <string.h> #include <stdlib.h> #include <errno.h> -#include <limits.h> /* common */ #include "abend.h" @@ -61,14 +60,14 @@ /* Name of program file */ const char* ProgramFile; -/* exit simulator after MaxCycles Cycles */ -unsigned long MaxCycles; +/* count of total cycles executed */ +unsigned long long TotalCycles = 0; -/* maximum number of cycles that can be tested, -** requires overhead for longest possible instruction, -** which should be 7, using 16 for safety. -*/ -#define MAXCYCLES_LIMIT (ULONG_MAX-16) +/* exit simulator after MaxCycles Cccles */ +unsigned long long MaxCycles = 0; + +/* countdown from MaxCycles */ +unsigned long long RemainCycles; /* Header signature 'sim65' */ static const unsigned char HeaderSignature[] = { @@ -145,11 +144,7 @@ static void OptQuitXIns (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* quit after MaxCycles cycles */ { - MaxCycles = strtoul(Arg, NULL, 0); - /* Guard against overflow. */ - if (MaxCycles >= MAXCYCLES_LIMIT) { - Error("'-x parameter out of range. Max: %lu",MAXCYCLES_LIMIT); - } + MaxCycles = strtoull(Arg, NULL, 0); } static unsigned char ReadProgramFile (void) @@ -247,6 +242,7 @@ int main (int argc, char* argv[]) unsigned I; unsigned char SPAddr; + unsigned int Cycles; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "sim65"); @@ -309,18 +305,24 @@ int main (int argc, char* argv[]) MemInit (); SPAddr = ReadProgramFile (); - ParaVirtInit (I, SPAddr); Reset (); + RemainCycles = MaxCycles; while (1) { - ExecuteInsn (); - if (MaxCycles && (GetCycles () >= MaxCycles)) { - ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles reached."); + Cycles = ExecuteInsn (); + TotalCycles += Cycles; + if (MaxCycles) { + if (Cycles > RemainCycles) { + ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles (%llu) reached.", MaxCycles); + } + RemainCycles -= Cycles; } } - /* Return an apropriate exit code */ - return EXIT_SUCCESS; + /* Unreachable. sim65 program must exit through paravirtual PVExit + ** or timeout from MaxCycles producing an error. + */ + return SIM65_ERROR; } diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index 0b16f89e9..af162acfa 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -124,11 +124,7 @@ static unsigned PopParam (unsigned char Incr) static void PVExit (CPURegs* Regs) { Print (stderr, 1, "PVExit ($%02X)\n", Regs->AC); - if (PrintCycles) { - Print (stdout, 0, "%lu cycles\n", GetCycles ()); - } - - exit (Regs->AC); + SimExit (Regs->AC); } From aad64063c97d2b379955f90d006c244c744c559e Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 7 May 2023 16:33:07 -0400 Subject: [PATCH 327/360] makefiles no longer need comment about sim65 64-bit support --- test/asm/val/Makefile | 1 - test/standard/Makefile | 1 - test/val/Makefile | 1 - 3 files changed, 3 deletions(-) diff --git a/test/asm/val/Makefile b/test/asm/val/Makefile index 09a6b91bc..54b1100ec 100644 --- a/test/asm/val/Makefile +++ b/test/asm/val/Makefile @@ -22,7 +22,6 @@ ifdef QUIET NULLERR = 2>$(NULLDEV) endif -# sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. SIM65FLAGS = -x 4000000000 CA65 := $(if $(wildcard ../../../bin/ca65*),..$S..$S..$Sbin$Sca65,ca65) diff --git a/test/standard/Makefile b/test/standard/Makefile index 40299c1bf..bf513c84e 100644 --- a/test/standard/Makefile +++ b/test/standard/Makefile @@ -22,7 +22,6 @@ ifdef QUIET NULLERR = 2>$(NULLDEV) endif -# sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. SIM65FLAGS = -x 4000000000 -c CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) diff --git a/test/val/Makefile b/test/val/Makefile index 158967f9e..56d8e5ff9 100644 --- a/test/val/Makefile +++ b/test/val/Makefile @@ -24,7 +24,6 @@ ifdef QUIET NULLERR = 2>$(NULLDEV) endif -# sim65 can support 64-bit cycle counts on some platforms, but not all. This must fit in 32-bit. SIM65FLAGS = -x 4000000000 -c CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) From 3419cbd3484427ad732289c5ff7cab41639cf1ca Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 7 May 2023 16:33:47 -0400 Subject: [PATCH 328/360] sim65 64-bit cycle count tests These take ~10 seconds to run locally --- test/asm/Makefile | 2 +- test/asm/misc/Makefile | 70 +++++++++++++++++++++++++++++++ test/asm/misc/sim65-time-wait.inc | 55 ++++++++++++++++++++++++ test/asm/misc/sim65-timein.s | 17 ++++++++ test/asm/misc/sim65-timeout.s | 17 ++++++++ test/asm/readme.txt | 6 +++ 6 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 test/asm/misc/Makefile create mode 100644 test/asm/misc/sim65-time-wait.inc create mode 100644 test/asm/misc/sim65-timein.s create mode 100644 test/asm/misc/sim65-timeout.s diff --git a/test/asm/Makefile b/test/asm/Makefile index 3481dae78..dea53f6b2 100644 --- a/test/asm/Makefile +++ b/test/asm/Makefile @@ -12,7 +12,7 @@ endif WORKDIR = ../testwrk/asm -SUBDIRS = cpudetect opcodes listing val err +SUBDIRS = cpudetect opcodes listing val err misc .PHONY: all continue mostlyclean clean diff --git a/test/asm/misc/Makefile b/test/asm/misc/Makefile new file mode 100644 index 000000000..5a9d4f3ef --- /dev/null +++ b/test/asm/misc/Makefile @@ -0,0 +1,70 @@ +# Makefile for the remaining asm tests that need special care in one way or another + +ifneq ($(shell echo),) + CMD_EXE = 1 +endif + +ifdef CMD_EXE + S = $(subst /,\,/) + NOT = - # Hack + EXE = .exe + NULLDEV = nul: + MKDIR = mkdir $(subst /,\,$1) + RMDIR = -rmdir /s /q $(subst /,\,$1) +else + S = / + NOT = ! + EXE = + NULLDEV = /dev/null + MKDIR = mkdir -p $1 + RMDIR = $(RM) -r $1 +endif + +ifdef QUIET + .SILENT: + NULLOUT = >$(NULLDEV) + NULLERR = 2>$(NULLDEV) +endif + +SIM65FLAGS = -x 200000000 + +CA65 := $(if $(wildcard ../../../bin/ca65*),..$S..$S..$Sbin$Sca65,ca65) +LD65 := $(if $(wildcard ../../../bin/ld65*),..$S..$S..$Sbin$Sld65,ld65) +SIM65 := $(if $(wildcard ../../../bin/sim65*),..$S..$S..$Sbin$Ssim65,sim65) + +WORKDIR = ..$S..$S..$Stestwrk$Sasm$Smisc + +.PHONY: all clean + +SOURCES := $(wildcard *.s) +TESTS = $(SOURCES:%.s=$(WORKDIR)/%.6502.prg) +TESTS += $(SOURCES:%.s=$(WORKDIR)/%.65c02.prg) + +all: $(TESTS) + +$(WORKDIR): + $(call MKDIR,$(WORKDIR)) + +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) + $(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) + $(NOT) $(SIM65) -x 4400000000 -c $$@ $(NULLOUT) $(NULLERR) + +endef # PRG_template + +$(eval $(call PRG_template,6502)) +$(eval $(call PRG_template,65c02)) + +clean: + @$(call RMDIR,$(WORKDIR)) diff --git a/test/asm/misc/sim65-time-wait.inc b/test/asm/misc/sim65-time-wait.inc new file mode 100644 index 000000000..bc761ac16 --- /dev/null +++ b/test/asm/misc/sim65-time-wait.inc @@ -0,0 +1,55 @@ +; Shared timer for: +; sim65-timein.s +; sim65-timeout.s + +; wait A * 100,000,000 cycles, plus small amount of overhead +wait100m: + tay + bne :+ + rts ; return quickly if A=0 +: + jsr wait50331648 ; 50331648 + jsr wait25165824 ; 75497472 + jsr wait12582912 ; 88080384 + jsr wait6291456 ; 94371840 + jsr wait3145728 ; 97517568 + jsr wait1572864 ; 99090432 + jsr wait786432 ; 99876864 + jsr wait98304 ; 99975168 + jsr wait24576 ; 99999744 + jsr wait192 ; 99999936 + jsr wait48 ; 99999984 + nop ; 99999986 + nop ; 99999988 + php ; 99999991 + plp ; 99999995 + dey ; 99999997 + bne :- ; 100000000 + rts +; Note that this branch could cross a page if poorly aligned, +; adding an additional 1 cycle per loop. +; This precision is not important for the tests used. + +wait50331648: jsr wait25165824 +wait25165824: jsr wait12582912 +wait12582912: jsr wait6291456 +wait6291456: jsr wait3145728 +wait3145728: jsr wait1572864 +wait1572864: jsr wait786432 +wait786432: jsr wait393216 +wait393216: jsr wait196608 +wait196608: jsr wait98304 +wait98304: jsr wait49152 +wait49152: jsr wait24576 +wait24576: jsr wait12288 +wait12288: jsr wait6144 +wait6144: jsr wait3072 +wait3072: jsr wait1536 +wait1536: jsr wait768 +wait768: jsr wait384 +wait384: jsr wait192 +wait192: jsr wait96 +wait96: jsr wait48 +wait48: jsr wait24 +wait24: jsr wait12 +wait12: rts diff --git a/test/asm/misc/sim65-timein.s b/test/asm/misc/sim65-timein.s new file mode 100644 index 000000000..13365f0a8 --- /dev/null +++ b/test/asm/misc/sim65-timein.s @@ -0,0 +1,17 @@ +; Verifies that sim65 can handle 64-bit timeout counter. +; sim65 sim65-timein.prg -x 4400000000 + +.export _main +.import exit + +_main: + ; wait ~4,300,000,000 cycles + lda #43 + jsr wait100m + ; This is a positive test. + ; If the timeout did not occur, returning 0 reports success. + lda #0 + rts + +; wait100m +.include "sim65-time-wait.inc" diff --git a/test/asm/misc/sim65-timeout.s b/test/asm/misc/sim65-timeout.s new file mode 100644 index 000000000..6f1778dcd --- /dev/null +++ b/test/asm/misc/sim65-timeout.s @@ -0,0 +1,17 @@ +; Verifies that sim65 can handle 64-bit timeout counter. +; sim65 sim65-timeout.prg -x 4400000000 + +.export _main +.import exit + +_main: + ; wait ~4,500,000,000 cycles + lda #45 + jsr wait100m + ; This is a negative test. + ; If the timeout did not occur, returning 0 reports failure. + lda #0 + rts + +; wait100m +.include "sim65-time-wait.inc" diff --git a/test/asm/readme.txt b/test/asm/readme.txt index 49b530d1c..9b716e60c 100644 --- a/test/asm/readme.txt +++ b/test/asm/readme.txt @@ -36,3 +36,9 @@ val: Runtime assembly tests using sim65 that should end with an exit code of 0 if they pass. If they fail the exit code should be either -1, or a number indicating what part of the test failed. + + +misc: +----- + +This is for tests that require special make steps or conditions. From 7f0baff792bd4f5b4937dc1d19811f310ba7b29f Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 7 May 2023 16:35:05 -0400 Subject: [PATCH 329/360] document how to return from assembly sim65 test --- doc/sim65.sgml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/sim65.sgml b/doc/sim65.sgml index 310de4667..c838cd3b0 100644 --- a/doc/sim65.sgml +++ b/doc/sim65.sgml @@ -126,9 +126,17 @@ a set of built-in paravirtualization functions (<ref id="paravirt-internal" name <sect>Creating a Test in Assembly<p> Assembly tests may similarly be assembled and linked with -<tt/--target sim6502/ or <tt/--target sim65c02/, -and the sim65 library provides an <tt/exit/ symbol that the program may <tt/JMP/ -to terminate with the current A register value as an exit code. +<tt/--target sim6502/ or <tt/--target sim65c02/. +Define and export <tt/_main/ as an entry point, +and the sim65 library provides two ways to return an 8-bit exit code: + +<itemize> + +<item>Return from <tt/_main/ with the exit code in <tt/A/. + +<item><tt/jmp exit/ with the code in <tt/A/. + +</itemize> The binary file has a 12 byte header: From 2cb457b85f8019e6437907ddd19e3d2c5f2546c6 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 7 May 2023 16:51:12 -0400 Subject: [PATCH 330/360] sim65 use error codes outside the simulated program's range for non-sim errors --- doc/sim65.sgml | 7 +++++++ src/sim65/error.h | 8 +++++--- src/sim65/paravirt.c | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/doc/sim65.sgml b/doc/sim65.sgml index c838cd3b0..b1e5afbdc 100644 --- a/doc/sim65.sgml +++ b/doc/sim65.sgml @@ -44,6 +44,13 @@ The simulator is called as follows: --version Print the simulator version number </verb></tscreen> +sim65 will exit with the error code of the simulated program, +which is limited to an 8-bit result 0-255. + +An error in sim65, like bad arguments or an internal problem will exit with <tt/1/. + +A timeout from <tt/-x/ will exist with <tt/2/. + <sect1>Command line options in detail<p> diff --git a/src/sim65/error.h b/src/sim65/error.h index a016881c6..6dbee974c 100644 --- a/src/sim65/error.h +++ b/src/sim65/error.h @@ -49,10 +49,12 @@ -#define SIM65_ERROR 0x7F -/* Does not use EXIT_FAILURE because it may overlap with test results. */ +#define SIM65_ERROR -1 +/* An error result for errors that are not part of the simulated test. +** Note that set simulated test can only return 8-bit errors 0-255. +*/ -#define SIM65_ERROR_TIMEOUT 0x7E +#define SIM65_ERROR_TIMEOUT -2 /* An error result for max CPU instructions exceeded. */ extern int PrintCycles; diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index af162acfa..2e52d6e7e 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -124,7 +124,7 @@ static unsigned PopParam (unsigned char Incr) static void PVExit (CPURegs* Regs) { Print (stderr, 1, "PVExit ($%02X)\n", Regs->AC); - SimExit (Regs->AC); + SimExit (Regs->AC); /* Error code in range 0-255. */ } From f15e9c41593cec0aed3eb17b01a91985e778f1e7 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Sun, 7 May 2023 17:41:54 -0400 Subject: [PATCH 331/360] Linux build rejects %llu in ErrorCode --- src/sim65/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sim65/main.c b/src/sim65/main.c index f5ace1909..3c7cdc157 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -315,7 +315,7 @@ int main (int argc, char* argv[]) TotalCycles += Cycles; if (MaxCycles) { if (Cycles > RemainCycles) { - ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles (%llu) reached.", MaxCycles); + ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles reached."); } RemainCycles -= Cycles; } From 02d38ae17eb9705f9afeb8a50661b3ab8860971b Mon Sep 17 00:00:00 2001 From: Irgendwer <C.Krueger.B@web.de> Date: Mon, 8 May 2023 15:28:22 +0200 Subject: [PATCH 332/360] Fixed comments for Atari OS memory location --- include/_atarios.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/_atarios.h b/include/_atarios.h index ec33b98c9..cbf33bda6 100644 --- a/include/_atarios.h +++ b/include/_atarios.h @@ -334,17 +334,17 @@ struct __os { void (*vserin)(void); // = $020A/$020B POKEY SERIAL INPUT READY IRQ void (*vseror)(void); // = $020C/$020D POKEY SERIAL OUTPUT READY IRQ void (*vseroc)(void); // = $020E/$020F POKEY SERIAL OUTPUT COMPLETE IRQ - void (*vtimr1)(void); // = $0210/$0201 POKEY TIMER 1 IRQ - void (*vtimr2)(void); // = $0212/$0203 POKEY TIMER 2 IRQ - void (*vtimr4)(void); // = $0214/$0205 POKEY TIMER 4 IRQ - void (*vimirq)(void); // = $0216/$0207 IMMEDIATE IRQ VECTOR - unsigned int cdtmv1; // = $0218/$0210 COUNT DOWN TIMER 1 + void (*vtimr1)(void); // = $0210/$0211 POKEY TIMER 1 IRQ + void (*vtimr2)(void); // = $0212/$0213 POKEY TIMER 2 IRQ + void (*vtimr4)(void); // = $0214/$0215 POKEY TIMER 4 IRQ + void (*vimirq)(void); // = $0216/$0217 IMMEDIATE IRQ VECTOR + unsigned int cdtmv1; // = $0218/$0219 COUNT DOWN TIMER 1 unsigned int cdtmv2; // = $021A/$021B COUNT DOWN TIMER 2 unsigned int cdtmv3; // = $021C/$021D COUNT DOWN TIMER 3 unsigned int cdtmv4; // = $021E/$021F COUNT DOWN TIMER 4 unsigned int cdtmv5; // = $0220/$0221 COUNT DOWN TIMER 5 void (*vvblki)(void); // = $0222/$0223 IMMEDIATE VERTICAL BLANK NMI VECTOR - void (*vvblkd)(void); // = $0224/$0224 DEFERRED VERTICAL BLANK NMI VECTOR + void (*vvblkd)(void); // = $0224/$0225 DEFERRED VERTICAL BLANK NMI VECTOR void (*cdtma1)(void); // = $0226/$0227 COUNT DOWN TIMER 1 JSR ADDRESS void (*cdtma2)(void); // = $0228/$0229 COUNT DOWN TIMER 2 JSR ADDRESS unsigned char cdtmf3; // = $022A COUNT DOWN TIMER 3 FLAG From a058d4a2f3bd0361a0b03ffecb39b22d8cc0eb93 Mon Sep 17 00:00:00 2001 From: Movax12 <jeremiah.turner@gmail.com> Date: Mon, 8 May 2023 16:55:54 -0400 Subject: [PATCH 333/360] Fix warning message, remove comment --- src/ca65/pseudo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index cf4d1f64b..2ce1ae087 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1045,8 +1045,7 @@ static void DoFeature (void) } if (Feature == FEAT_ADDRSIZE) { - /* Warn for depreciated .feature addrsize */ - Warning (1, "Depreciated feature: '.feature addrsize'. Pseudo function .addrsize is always available."); + Warning (1, "Deprecated feature: '.feature addrsize'. Pseudo function .addrsize is always available."); } NextTok (); From ce6097ea7ebf4d37abc6865c1afc806876e5e2f5 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 8 May 2023 18:12:57 -0400 Subject: [PATCH 334/360] rename windows-test-manual to windows-test-scheduled --- .../{windows-test-manual.yml => windows-test-scheduled.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{windows-test-manual.yml => windows-test-scheduled.yml} (100%) diff --git a/.github/workflows/windows-test-manual.yml b/.github/workflows/windows-test-scheduled.yml similarity index 100% rename from .github/workflows/windows-test-manual.yml rename to .github/workflows/windows-test-scheduled.yml From 07963abd52ff5ccf3c5ef7790451454e1c0f3d0b Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 8 May 2023 18:21:21 -0400 Subject: [PATCH 335/360] replace manual-only tests with scheduled test and manual dispatch cache is used to prevent unnecessary rebuild if the previous build was successful make steps now use SHELL=cmd to provide cmd.exe subshell --- .github/workflows/windows-test-scheduled.yml | 48 +++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows-test-scheduled.yml b/.github/workflows/windows-test-scheduled.yml index 854327726..c3516772b 100644 --- a/.github/workflows/windows-test-scheduled.yml +++ b/.github/workflows/windows-test-scheduled.yml @@ -1,8 +1,16 @@ -name: Windows Test Manual -# Manually dispatched because it's much slower than the Linux test. +name: Windows Test Scheduled +# Scheduled or manually dispatched because it's slower than the Linux test. on: + schedule: + - cron: '0 0 */1 * *' + # every 1 days workflow_dispatch: + # allow manual dispatch +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + # don't run more than once at a time jobs: build_windows: @@ -10,34 +18,62 @@ jobs: runs-on: windows-latest steps: + + # This cache is used to remember the last build. + # If there are no changes and the last build was successful, + # the build and test steps will be omitted. + # If the last build failed, the full attempt will be repeated. + # Github Actions will retain the last build cache for up to 7 days. + + - name: Create Cache + shell: bash + run: mkdir ~/.cache-sha + + - name: Cache SHA + uses: actions/cache@v3 + id: check-sha + with: + path: ~/.cache-sha + key: cache-sha-wintest-${{ github.sha }} + - name: Git Setup + if: steps.check-sha.outputs.cache-hit != 'true' shell: bash run: git config --global core.autocrlf input - name: Checkout source + if: steps.check-sha.outputs.cache-hit != 'true' uses: actions/checkout@v3 - name: Add msbuild to PATH + if: steps.check-sha.outputs.cache-hit != 'true' uses: microsoft/setup-msbuild@v1.1 - name: Build app (MSVC debug) + if: steps.check-sha.outputs.cache-hit != 'true' run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug - name: Build app (MSVC release) + if: steps.check-sha.outputs.cache-hit != 'true' run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release - name: Build utils (MinGW) + if: steps.check-sha.outputs.cache-hit != 'true' shell: cmd - run: make -j2 util + run: make -j2 util SHELL=cmd - name: Build the platform libraries (make lib) + if: steps.check-sha.outputs.cache-hit != 'true' shell: cmd - run: make -j2 lib QUIET=1 + run: make lib QUIET=1 SHELL=cmd + # make -j2 lib fails with SHELL=cmd (not sure why) - name: Run the regression tests (make test) + if: steps.check-sha.outputs.cache-hit != 'true' shell: cmd - run: make test QUIET=1 + run: make test QUIET=1 SHELL=cmd - name: Test that the samples can be built (make samples) + if: steps.check-sha.outputs.cache-hit != 'true' shell: cmd - run: make -j2 samples + run: make -j2 samples SHELL=cmd From 76328da6824493b75a0d9863c1730e0dcf418ad5 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 8 May 2023 20:57:50 -0400 Subject: [PATCH 336/360] librsc/Makefile: ../lib directory must be created globally before make lib targets in parallel prevents conflict of individual targets each trying to create ../lib enable -j2 in make lib windows action --- .github/workflows/windows-test-scheduled.yml | 3 +-- libsrc/Makefile | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows-test-scheduled.yml b/.github/workflows/windows-test-scheduled.yml index c3516772b..451b37f79 100644 --- a/.github/workflows/windows-test-scheduled.yml +++ b/.github/workflows/windows-test-scheduled.yml @@ -65,8 +65,7 @@ jobs: - name: Build the platform libraries (make lib) if: steps.check-sha.outputs.cache-hit != 'true' shell: cmd - run: make lib QUIET=1 SHELL=cmd - # make -j2 lib fails with SHELL=cmd (not sure why) + run: make -j2 lib QUIET=1 SHELL=cmd - name: Run the regression tests (make test) if: steps.check-sha.outputs.cache-hit != 'true' diff --git a/libsrc/Makefile b/libsrc/Makefile index 732fa1d0e..0873d019f 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -122,9 +122,13 @@ endef # ZIP_recipe zip: $(foreach dir,$(OUTPUTDIRS),$(ZIP_recipe)) -$(TARGETS): +$(TARGETS): | ../lib @$(MAKE) --no-print-directory $@ +# ../lib must be created globally before doing lib targets in parallel +../lib: + @$(call MKDIR,$@) + else # TARGET CA65FLAGS = @@ -293,10 +297,12 @@ $(EXTRA_OBJPAT): $(EXTRA_SRCPAT) | ../libwrk/$(TARGET) ../lib @echo $(TARGET) - $(<F) @$(CA65) -t $(TARGET) $(CA65FLAGS) --create-dep $(@:../lib/%.o=../libwrk/$(TARGET)/%.d) -o $@ $< +$(EXTRA_OBJS): | ../lib + ../lib/$(TARGET).lib: $(OBJS) | ../lib $(AR65) a $@ $? -../libwrk/$(TARGET) ../lib ../target/$(TARGET)/util: +../libwrk/$(TARGET) ../target/$(TARGET)/util: @$(call MKDIR,$@) $(TARGET): $(EXTRA_OBJS) ../lib/$(TARGET).lib From eb2b013d6246ea6e112b769ea0e281ea9d926ff1 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Mon, 8 May 2023 21:22:18 -0400 Subject: [PATCH 337/360] remove workflow comments this obsoletes --- .github/workflows/build-on-pull-request.yml | 4 ---- .github/workflows/snapshot-on-push-master.yml | 4 ---- 2 files changed, 8 deletions(-) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 1ad810382..55be5db1e 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -72,7 +72,3 @@ jobs: - name: Build app (release) run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release - - # The regression tests are currently too slow to run for this Windows build, - # but the "Windows Test Manual" workflow (windows-test-manual.yml) can by - # manually dispatched from the Actions menu to test as needed. diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 6ba6b63ed..2aedb0e25 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -29,10 +29,6 @@ jobs: - name: Build app (release) run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release - # The regression tests are currently too slow to run for this Windows build, - # but the "Windows Test Manual" workflow (windows-test-manual.yml) can by - # manually dispatched from the Actions menu to test as needed. - build_linux: name: Build, Test, and Snapshot (Linux) if: github.repository == 'cc65/cc65' From 3b7be09a7f7a70bff6ee463b24d5514ec52ca1d4 Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Thu, 11 May 2023 19:50:58 -0400 Subject: [PATCH 338/360] extern redeclared as static = error (C spec: undefined) static redeclared as extern = warning (C spec: ignore extern) See: #2111 --- src/cc65/symtab.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index d9270f604..a2bbf13dd 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -1340,15 +1340,14 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) Name); Entry = 0; } else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) { - /* If a static declaration follows a non-static declaration, then - ** diagnose the conflict. It will warn and compile an extern - ** declaration if both declarations are global, otherwise give an - ** error. + /* If a static declaration follows a non-static declaration, then the result is undefined. + ** Most compilers choose to either give an error at compile time, + ** or remove the extern property for a link time error if used. */ if (SymTab == SymTab0 && (Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) { - Warning ("Static declaration of '%s' follows non-static declaration", Name); + Error ("Static declaration of '%s' follows non-static declaration", Name); } else if ((Flags & SC_EXTERN) != 0 && (Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) && (Entry->Flags & SC_EXTERN) == 0) { @@ -1360,8 +1359,12 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) */ if (Entry->Owner == SymTab0) { if ((Flags & SC_STORAGE) == 0) { - /* Linkage must be unchanged */ + /* Linkage must be unchanged. + ** The C standard specifies that a later extern declaration will be ignored, + ** and will use the previous linkage instead. Giving a warning for this case. + */ Flags &= ~SC_EXTERN; + Warning ("Extern declaration of '%s' follows static declaration, extern ignored", Name); } else { Error ("Non-static declaration of '%s' follows static declaration", Name); } From 5a30d746b404d00463efe909a9d69b3d23f3a30b Mon Sep 17 00:00:00 2001 From: bbbradsmith <bbbradsmith@users.noreply.github.com> Date: Thu, 11 May 2023 20:15:27 -0400 Subject: [PATCH 339/360] extern/static conflict test: remove warning as errors to match the new expected cases --- test/val/decl-static-extern.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/val/decl-static-extern.c b/test/val/decl-static-extern.c index 6918e0033..2be4d336f 100644 --- a/test/val/decl-static-extern.c +++ b/test/val/decl-static-extern.c @@ -7,13 +7,12 @@ /* see: https://github.com/cc65/cc65/issues/191 + https://github.com/cc65/cc65/issues/2111 */ -#pragma warn(error, on) - static int n = 0; -extern int n; /* should not give an error */ -static int n; /* should not give an error */ +extern int n; /* extern is ignored, gives a warning but keeps previous static definiton */ +static int n; /* no error or warning, the previous static is still in effect */ int main(void) { From 5d9306fed35babfe0061ae31e7f90d5228367203 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Fri, 12 May 2023 02:32:14 +0200 Subject: [PATCH 340/360] Fixed header #2110 --- include/stdlib.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index 4e7ffbd6a..05148d7da 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -44,6 +44,12 @@ typedef unsigned size_t; #define _HAVE_size_t #endif +/* NULL pointer */ +#ifndef _HAVE_NULL +#define NULL ((void *) 0) +#define _HAVE_NULL +#endif + /* Standard exit codes */ #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 @@ -167,6 +173,3 @@ int __fastcall__ putenv (char* s); /* End of stdlib.h */ #endif - - - From 6579df4e91981e0516da5216e7cb9a8b82a288b9 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 14 May 2023 02:43:35 +0200 Subject: [PATCH 341/360] Update stdlib.h --- include/stdlib.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index 05148d7da..e789f732b 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -45,9 +45,8 @@ typedef unsigned size_t; #endif /* NULL pointer */ -#ifndef _HAVE_NULL -#define NULL ((void *) 0) -#define _HAVE_NULL +#ifndef NULL +#define NULL ((void *) 0) #endif /* Standard exit codes */ From 680ddaf37d034deededf7a9c814d7a9a6d3ee7c5 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 14 May 2023 17:27:04 +0200 Subject: [PATCH 342/360] Update locale.h --- include/locale.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/locale.h b/include/locale.h index 3f23e01d2..f408e1ef3 100644 --- a/include/locale.h +++ b/include/locale.h @@ -39,9 +39,8 @@ /* NULL pointer */ -#ifndef _HAVE_NULL -#define NULL 0 -#define _HAVE_NULL +#ifndef NULL +#define NULL ((void *) 0) #endif /* Locale information constants */ @@ -82,6 +81,3 @@ char* __fastcall__ setlocale (int category, const char* locale); /* End of locale.h */ #endif - - - From fd74e6b005bb2d5482310cb5286081065e750310 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 14 May 2023 17:28:09 +0200 Subject: [PATCH 343/360] Update stdio.h --- include/stdio.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/stdio.h b/include/stdio.h index 858dd5059..012b8e2ba 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -38,9 +38,8 @@ /* NULL pointer */ -#ifndef _HAVE_NULL -#define NULL 0 -#define _HAVE_NULL +#ifndef NULL +#define NULL ((void *) 0) #endif /* size_t is needed */ From c55459b287ec0c5fddbb6c695ea14e7222db1052 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 14 May 2023 17:28:48 +0200 Subject: [PATCH 344/360] Update string.h --- include/string.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/string.h b/include/string.h index 854359dad..abaf80e7d 100644 --- a/include/string.h +++ b/include/string.h @@ -37,9 +37,8 @@ #define _STRING_H /* NULL pointer */ -#ifndef _HAVE_NULL -#define NULL 0 -#define _HAVE_NULL +#ifndef NULL +#define NULL ((void *) 0) #endif /* size_t is needed */ From ba6747f5da0dd0c3c0cfab96098ad8cc4bfec11a Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 14 May 2023 17:29:42 +0200 Subject: [PATCH 345/360] Update time.h --- include/time.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/time.h b/include/time.h index 642d68c4e..bfc2ac435 100644 --- a/include/time.h +++ b/include/time.h @@ -39,9 +39,8 @@ /* NULL pointer */ -#ifndef _HAVE_NULL -#define NULL 0 -#define _HAVE_NULL +#ifndef NULL +#define NULL ((void *) 0) #endif /* size_t is needed */ From dd58c7ff5002ad1da1522c2764d60acac27a5546 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Sun, 14 May 2023 17:32:30 +0200 Subject: [PATCH 346/360] Update stddef.h --- include/stddef.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/stddef.h b/include/stddef.h index ca93edf62..d2bfd6138 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -53,9 +53,8 @@ typedef unsigned size_t; #endif /* NULL pointer */ -#ifndef _HAVE_NULL -#define NULL ((void *) 0) -#define _HAVE_NULL +#ifndef NULL +#define NULL ((void *) 0) #endif /* offsetof macro */ @@ -65,6 +64,3 @@ typedef unsigned size_t; /* End of stddef.h */ #endif - - - From 19436f515938e4b16afc214073ff40f5e1e9a45e Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Wed, 17 May 2023 20:24:36 +0200 Subject: [PATCH 347/360] Update gconst.h --- include/geos/gconst.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/geos/gconst.h b/include/geos/gconst.h index e70eb9304..55a99a21f 100644 --- a/include/geos/gconst.h +++ b/include/geos/gconst.h @@ -4,14 +4,14 @@ reassembled by Maciej 'YTM/Elysium' Witkowiak */ -/* Here are constants which didn't fit into any other cathegory... */ +/* Here are constants which didn't fit into any other category... */ #ifndef _GCONST_H #define _GCONST_H -#define NULL 0 -#define FALSE NULL +#define NULL ((void *) 0) #define TRUE 0xff +#define FALSE ~TRUE #define MOUSE_SPRNUM 0 #define DISK_DRV_LGH 0x0d80 From 767875b5a73f5630e75fe60a70473a17dda6a10f Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Thu, 18 May 2023 00:08:26 +0200 Subject: [PATCH 348/360] Added guard --- include/geos/gconst.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/geos/gconst.h b/include/geos/gconst.h index 55a99a21f..a1b6a1d86 100644 --- a/include/geos/gconst.h +++ b/include/geos/gconst.h @@ -9,7 +9,9 @@ #ifndef _GCONST_H #define _GCONST_H +#ifndef NULL #define NULL ((void *) 0) +#endif #define TRUE 0xff #define FALSE ~TRUE #define MOUSE_SPRNUM 0 From 8ff008722b97790fa65aa464b01107b8ba58967d Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Fri, 19 May 2023 02:49:49 +0200 Subject: [PATCH 349/360] Fixed test Don't define NULL yourself. QED --- test/val/add4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/test/val/add4.c b/test/val/add4.c index f02a7fb9c..2371aea69 100644 --- a/test/val/add4.c +++ b/test/val/add4.c @@ -22,7 +22,6 @@ long long0 = 0; long long1 = 0; unsigned long ulong0 = 0; unsigned long ulong1 = 0; -#define NULL 0 char *cP0=NULL; char *cP1=NULL; int *iP0=NULL; From accd57460b5b7961b579368a49969f0888ccbbc1 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Fri, 19 May 2023 15:48:31 +0200 Subject: [PATCH 350/360] Reverted gconst.h --- include/geos/gconst.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/geos/gconst.h b/include/geos/gconst.h index a1b6a1d86..3e42feed7 100644 --- a/include/geos/gconst.h +++ b/include/geos/gconst.h @@ -12,8 +12,8 @@ #ifndef NULL #define NULL ((void *) 0) #endif +#define FALSE 0 #define TRUE 0xff -#define FALSE ~TRUE #define MOUSE_SPRNUM 0 #define DISK_DRV_LGH 0x0d80 From 40ff9281c6ea020726cd8deb1ffb7b0a2b8bf6e9 Mon Sep 17 00:00:00 2001 From: polluks2 <74630735+polluks2@users.noreply.github.com> Date: Fri, 19 May 2023 16:36:19 +0200 Subject: [PATCH 351/360] Fixed typo --- doc/funcref.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/funcref.sgml b/doc/funcref.sgml index 6418723b5..2a6d77adc 100644 --- a/doc/funcref.sgml +++ b/doc/funcref.sgml @@ -976,7 +976,7 @@ previously been allocated by <tt/<ref id="malloc" name="malloc">/, <tt/<ref id="calloc" name="calloc">/ or <tt/<ref id="realloc" name="realloc">/. <tag/Notes/<itemize> <item>Passing a pointer to a block that was is not the result of one of the -allocation functions, or that has been free'd will give unpredicable results. +allocation functions, or that has been free'd will give unpredictable results. <item>The function is available only as a fastcall function; so, it may be used only in the presence of a prototype. </itemize> From 1377ba0d360aaa0cb505c7bd78129c2c7d4c4cb4 Mon Sep 17 00:00:00 2001 From: jede <jede@oric.org> Date: Tue, 23 May 2023 23:08:56 +0200 Subject: [PATCH 352/360] fix compute length for read and write for telestrat target --- libsrc/telestrat/read.s | 15 ++++++++------- libsrc/telestrat/write.s | 16 ++++++++-------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index f31909f45..b89f246cc 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -30,13 +30,14 @@ ldy ptr1+1 BRK_TELEMON XFREAD ; compute nb of bytes read - lda PTR_READ_DEST+1 sec - sbc ptr2+1 - tax - lda PTR_READ_DEST - sec - sbc ptr2 - ; here A and X contains number of bytes read + lda PTR_READ_DEST + sbc ptr2 + sta tmp1 + lda PTR_READ_DEST+1 + sbc ptr2+1 + tax + lda tmp1 + rts .endproc diff --git a/libsrc/telestrat/write.s b/libsrc/telestrat/write.s index 2ce2657ac..06524f749 100644 --- a/libsrc/telestrat/write.s +++ b/libsrc/telestrat/write.s @@ -42,16 +42,16 @@ next: ldy ptr3+1 ldx tmp1 ; send fd in X BRK_TELEMON XFWRITE + ; compute nb of bytes written - - - lda PTR_READ_DEST+1 sec - sbc ptr1+1 - tax - lda PTR_READ_DEST - sec - sbc ptr1 + lda PTR_READ_DEST + sbc ptr1 + sta tmp1 + lda PTR_READ_DEST+1 + sbc ptr1+1 + tax + lda tmp1 rts From 1ca9d7e9e707658e2777784fb607d3cabb48b25c Mon Sep 17 00:00:00 2001 From: jede <jede@oric.org> Date: Tue, 23 May 2023 23:15:23 +0200 Subject: [PATCH 353/360] fix tab --- libsrc/telestrat/read.s | 12 ++++++------ libsrc/telestrat/write.s | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index b89f246cc..1d2315dce 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -31,12 +31,12 @@ BRK_TELEMON XFREAD ; compute nb of bytes read sec - lda PTR_READ_DEST - sbc ptr2 - sta tmp1 - lda PTR_READ_DEST+1 - sbc ptr2+1 - tax + lda PTR_READ_DEST + sbc ptr2 + sta tmp1 + lda PTR_READ_DEST+1 + sbc ptr2+1 + tax lda tmp1 rts diff --git a/libsrc/telestrat/write.s b/libsrc/telestrat/write.s index 06524f749..16bc64d69 100644 --- a/libsrc/telestrat/write.s +++ b/libsrc/telestrat/write.s @@ -45,12 +45,12 @@ next: ; compute nb of bytes written sec - lda PTR_READ_DEST - sbc ptr1 - sta tmp1 - lda PTR_READ_DEST+1 - sbc ptr1+1 - tax + lda PTR_READ_DEST + sbc ptr1 + sta tmp1 + lda PTR_READ_DEST+1 + sbc ptr1+1 + tax lda tmp1 rts From 480600093cef2d67d5e39253364c258d6266300e Mon Sep 17 00:00:00 2001 From: jede <jede@oric.org> Date: Thu, 25 May 2023 18:09:03 +0200 Subject: [PATCH 354/360] fix pla/pha instead of tmp1 --- libsrc/telestrat/read.s | 4 ++-- libsrc/telestrat/write.s | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/telestrat/read.s b/libsrc/telestrat/read.s index 1d2315dce..736546363 100644 --- a/libsrc/telestrat/read.s +++ b/libsrc/telestrat/read.s @@ -33,11 +33,11 @@ sec lda PTR_READ_DEST sbc ptr2 - sta tmp1 + pha lda PTR_READ_DEST+1 sbc ptr2+1 tax - lda tmp1 + pla rts .endproc diff --git a/libsrc/telestrat/write.s b/libsrc/telestrat/write.s index 16bc64d69..37a896696 100644 --- a/libsrc/telestrat/write.s +++ b/libsrc/telestrat/write.s @@ -47,11 +47,11 @@ next: sec lda PTR_READ_DEST sbc ptr1 - sta tmp1 + pha lda PTR_READ_DEST+1 sbc ptr1+1 tax - lda tmp1 + pla rts From c8aa9cc70372accedf5c506ab48090d0890caf4f Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 29 May 2023 17:20:09 +0200 Subject: [PATCH 355/360] add struct assign check related to #2079 --- test/val/bug2079-struct-assign.c | 66 ++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 test/val/bug2079-struct-assign.c diff --git a/test/val/bug2079-struct-assign.c b/test/val/bug2079-struct-assign.c new file mode 100644 index 000000000..b8a41fe8b --- /dev/null +++ b/test/val/bug2079-struct-assign.c @@ -0,0 +1,66 @@ + +/* test struct assignment, of structs with a length of 3, which happen to be + a special case eg when passing/returning structs + related to bugs #2022, #2079 */ + +#include <stdio.h> +#include <stdlib.h> + +int failures = 0; + +struct foo { char a; char b; char c; }; +struct foo foo, bar; +void f3(void) +{ + foo.a = 6; + foo.b = 6; + foo.c = 6; + bar.a = 1; + bar.b = 2; + bar.c = 3; + foo = bar; + printf("%d %d %d, %d %d %d (1,2,3 1,2,3)\n", + foo.a, foo.b, foo.c, + bar.a, bar.b, bar.c); + if ((foo.a != 1) || (foo.b != 2) || (foo.c != 3) || + (bar.a != 1) || (bar.b != 2) || (bar.c != 3)) { + failures++; + } + foo.a = 3; + foo.b = 2; + foo.c = 1; + printf("%d %d %d, %d %d %d (3,2,1 1,2,3)\n", + foo.a, foo.b, foo.c, + bar.a, bar.b, bar.c); + if ((foo.a != 3) || (foo.b != 2) || (foo.c != 1) || + (bar.a != 1) || (bar.b != 2) || (bar.c != 3)) { + failures++; + } + bar.a = 5; + bar.b = 6; + bar.c = 7; + printf("%d %d %d, %d %d %d (3,2,1 5,6,7)\n", + foo.a, foo.b, foo.c, + bar.a, bar.b, bar.c); + if ((foo.a != 3) || (foo.b != 2) || (foo.c != 1) || + (bar.a != 5) || (bar.b != 6) || (bar.c != 7)) { + failures++; + } + bar = foo; + foo.a = 6; + foo.b = 6; + foo.c = 6; + printf("%d %d %d, %d %d %d (6,6,6 3,2,1)\n", + foo.a, foo.b, foo.c, + bar.a, bar.b, bar.c); + if ((foo.a != 6) || (foo.b != 6) || (foo.c != 6) || + (bar.a != 3) || (bar.b != 2) || (bar.c != 1)) { + failures++; + } +} + +int main(void) +{ + f3(); + return failures; +} From 59941d94642a6fc25c6392486fca2b7e4aae46bf Mon Sep 17 00:00:00 2001 From: MooingLemur <mooinglemur@users.noreply.github.com> Date: Thu, 15 Jun 2023 21:30:26 -0400 Subject: [PATCH 356/360] cx16: use KERNAL memsiz for MEMSIZE in asminc/cx16.inc --- asminc/cx16.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asminc/cx16.inc b/asminc/cx16.inc index be63780c8..d264add38 100644 --- a/asminc/cx16.inc +++ b/asminc/cx16.inc @@ -259,7 +259,7 @@ NLINES := $0387 ; Number of screen lines ; BASIC VARTAB := $03E1 ; Pointer to start of BASIC variables -MEMSIZE := $03E9 ; Pointer to highest BASIC RAM location (+1) +MEMSIZE := $0259 ; Pointer to highest BASIC RAM location (+1) ; --------------------------------------------------------------------------- ; Vector and other locations From 3e166c760dcd7dd071aa86f464ce480bf07504e9 Mon Sep 17 00:00:00 2001 From: baktragh <zylon@post.cz> Date: Mon, 26 Jun 2023 16:38:41 +0200 Subject: [PATCH 357/360] Update _atari5200os.h with POT shadows Update the OS struct with POT shadow registers, according to the https://web.archive.org/web/20120830055323/http://www.atarimuseum.com/videogames/consoles/5200/conv_to_5200.html document --- include/_atari5200os.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/_atari5200os.h b/include/_atari5200os.h index 5bba43016..88636dc7f 100644 --- a/include/_atari5200os.h +++ b/include/_atari5200os.h @@ -54,7 +54,15 @@ struct __os { unsigned char color2; // = $0E PF color 2 unsigned char color3; // = $0F PF color 3 unsigned char color4; // = $10 PF color 4 - unsigned char _free_1[0xEF]; // = $11-$FF User space + unsigned char pot0; // = $11 POT0 shadow + unsigned char pot1; // = $12 POT1 shadow + unsigned char pot2; // = $13 POT2 shadow + unsigned char pot3; // = $14 POT3 shadow + unsigned char pot4; // = $15 POT4 shadow + unsigned char pot5; // = $16 POT5 shadow + unsigned char pot6; // = $17 POT6 shadow + unsigned char pot7; // = $18 POT7 shadow + unsigned char _free_1[0xE7]; // = $19-$FF User space /*Stack*/ unsigned char stack[0x100]; // = $100-$1FF Stack From aaec2a627092f4bad90aa408258559ec341a209a Mon Sep 17 00:00:00 2001 From: baktragh <zylon@post.cz> Date: Mon, 26 Jun 2023 16:46:42 +0200 Subject: [PATCH 358/360] Update _atari5200os.h - Remove dangling spaces --- include/_atari5200os.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/_atari5200os.h b/include/_atari5200os.h index 88636dc7f..2e861e797 100644 --- a/include/_atari5200os.h +++ b/include/_atari5200os.h @@ -54,14 +54,14 @@ struct __os { unsigned char color2; // = $0E PF color 2 unsigned char color3; // = $0F PF color 3 unsigned char color4; // = $10 PF color 4 - unsigned char pot0; // = $11 POT0 shadow - unsigned char pot1; // = $12 POT1 shadow - unsigned char pot2; // = $13 POT2 shadow - unsigned char pot3; // = $14 POT3 shadow - unsigned char pot4; // = $15 POT4 shadow - unsigned char pot5; // = $16 POT5 shadow - unsigned char pot6; // = $17 POT6 shadow - unsigned char pot7; // = $18 POT7 shadow + unsigned char pot0; // = $11 POT0 shadow + unsigned char pot1; // = $12 POT1 shadow + unsigned char pot2; // = $13 POT2 shadow + unsigned char pot3; // = $14 POT3 shadow + unsigned char pot4; // = $15 POT4 shadow + unsigned char pot5; // = $16 POT5 shadow + unsigned char pot6; // = $17 POT6 shadow + unsigned char pot7; // = $18 POT7 shadow unsigned char _free_1[0xE7]; // = $19-$FF User space /*Stack*/ From 6c127d6a836ee409f9839224cf74f35eeafb96d7 Mon Sep 17 00:00:00 2001 From: baktragh <zylon@post.cz> Date: Sun, 2 Jul 2023 14:59:00 +0200 Subject: [PATCH 359/360] Update _atari5200os.h Update the page 0 symbols, synchronize the names with the _atarios.h, add locations used by Atari 5200 conio --- include/_atari5200os.h | 44 ++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/include/_atari5200os.h b/include/_atari5200os.h index 2e861e797..d6f7d3875 100644 --- a/include/_atari5200os.h +++ b/include/_atari5200os.h @@ -44,25 +44,31 @@ struct __os { void* sdlst; // = $05,$06 Display list shadow }; - unsigned char sdmctl; // = $07 DMACTL shadow - unsigned char pcolr0; // = $08 PM color 0 - unsigned char pcolr1; // = $09 PM color 1 - unsigned char pcolr2; // = $0A PM color 2 - unsigned char pcolr3; // = $0B PM color 3 - unsigned char color0; // = $0C PF color 0 - unsigned char color1; // = $0D PF color 1 - unsigned char color2; // = $0E PF color 2 - unsigned char color3; // = $0F PF color 3 - unsigned char color4; // = $10 PF color 4 - unsigned char pot0; // = $11 POT0 shadow - unsigned char pot1; // = $12 POT1 shadow - unsigned char pot2; // = $13 POT2 shadow - unsigned char pot3; // = $14 POT3 shadow - unsigned char pot4; // = $15 POT4 shadow - unsigned char pot5; // = $16 POT5 shadow - unsigned char pot6; // = $17 POT6 shadow - unsigned char pot7; // = $18 POT7 shadow - unsigned char _free_1[0xE7]; // = $19-$FF User space + unsigned char sdmctl; // = $07 DMACTL shadow + unsigned char pcolr0; // = $08 PM color 0 + unsigned char pcolr1; // = $09 PM color 1 + unsigned char pcolr2; // = $0A PM color 2 + unsigned char pcolr3; // = $0B PM color 3 + unsigned char color0; // = $0C PF color 0 + unsigned char color1; // = $0D PF color 1 + unsigned char color2; // = $0E PF color 2 + unsigned char color3; // = $0F PF color 3 + unsigned char color4; // = $10 PF color 4 + unsigned char paddl0; // = $11 POT0 Shadow + unsigned char paddl1; // = $12 POT1 Shadow + unsigned char paddl2; // = $13 POT2 Shadow + unsigned char paddl3; // = $14 POT3 Shadow + unsigned char paddl4; // = $15 POT4 Shadow + unsigned char paddl5; // = $16 POT5 Shadow + unsigned char paddl6; // = $17 POT6 Shadow + unsigned char paddl7; // = $18 POT7 Shadow + + /*cc65 runtime zero page variables*/ + unsigned char rowcrs_5200; // = $19 Cursor row (conio) + unsigned char colcrs_5200; // = $1A Cursor column (conio) + unsigned char* savmsc; // = $1B/$1C Pointer to screen memory (conio) + + unsigned char _filler_1[0xE3]; // = $1D-$FF Filler /*Stack*/ unsigned char stack[0x100]; // = $100-$1FF Stack From 7a85473cb0dfcc180048c1c8892cb9bf039ca406 Mon Sep 17 00:00:00 2001 From: baktragh <zylon@post.cz> Date: Sun, 2 Jul 2023 15:16:33 +0200 Subject: [PATCH 360/360] Update _atari5200os.h Remove dangling spaces --- include/_atari5200os.h | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/include/_atari5200os.h b/include/_atari5200os.h index d6f7d3875..196b69e56 100644 --- a/include/_atari5200os.h +++ b/include/_atari5200os.h @@ -44,31 +44,31 @@ struct __os { void* sdlst; // = $05,$06 Display list shadow }; - unsigned char sdmctl; // = $07 DMACTL shadow - unsigned char pcolr0; // = $08 PM color 0 - unsigned char pcolr1; // = $09 PM color 1 - unsigned char pcolr2; // = $0A PM color 2 - unsigned char pcolr3; // = $0B PM color 3 - unsigned char color0; // = $0C PF color 0 - unsigned char color1; // = $0D PF color 1 - unsigned char color2; // = $0E PF color 2 - unsigned char color3; // = $0F PF color 3 - unsigned char color4; // = $10 PF color 4 - unsigned char paddl0; // = $11 POT0 Shadow - unsigned char paddl1; // = $12 POT1 Shadow - unsigned char paddl2; // = $13 POT2 Shadow - unsigned char paddl3; // = $14 POT3 Shadow - unsigned char paddl4; // = $15 POT4 Shadow - unsigned char paddl5; // = $16 POT5 Shadow - unsigned char paddl6; // = $17 POT6 Shadow - unsigned char paddl7; // = $18 POT7 Shadow - - /*cc65 runtime zero page variables*/ - unsigned char rowcrs_5200; // = $19 Cursor row (conio) - unsigned char colcrs_5200; // = $1A Cursor column (conio) - unsigned char* savmsc; // = $1B/$1C Pointer to screen memory (conio) - - unsigned char _filler_1[0xE3]; // = $1D-$FF Filler + unsigned char sdmctl; // = $07 DMACTL shadow + unsigned char pcolr0; // = $08 PM color 0 + unsigned char pcolr1; // = $09 PM color 1 + unsigned char pcolr2; // = $0A PM color 2 + unsigned char pcolr3; // = $0B PM color 3 + unsigned char color0; // = $0C PF color 0 + unsigned char color1; // = $0D PF color 1 + unsigned char color2; // = $0E PF color 2 + unsigned char color3; // = $0F PF color 3 + unsigned char color4; // = $10 PF color 4 + unsigned char paddl0; // = $11 POT0 Shadow + unsigned char paddl1; // = $12 POT1 Shadow + unsigned char paddl2; // = $13 POT2 Shadow + unsigned char paddl3; // = $14 POT3 Shadow + unsigned char paddl4; // = $15 POT4 Shadow + unsigned char paddl5; // = $16 POT5 Shadow + unsigned char paddl6; // = $17 POT6 Shadow + unsigned char paddl7; // = $18 POT7 Shadow + + /*cc65 runtime zero page variables*/ + unsigned char rowcrs_5200; // = $19 Cursor row (conio) + unsigned char colcrs_5200; // = $1A Cursor column (conio) + unsigned char* savmsc; // = $1B/$1C Pointer to screen memory (conio) + + unsigned char _filler_1[0xE3]; // = $1D-$FF Filler /*Stack*/ unsigned char stack[0x100]; // = $100-$1FF Stack