Merge branch 'master' into seglist

This commit is contained in:
Bob Andrews
2025-07-10 20:48:28 +02:00
committed by GitHub
226 changed files with 2847 additions and 2118 deletions

122
Code_of_Conduct.md Normal file
View File

@@ -0,0 +1,122 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
groepaz@gmx.net.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -15,6 +15,8 @@ IndReg := $01 ; Controls indirect indexed load-store bank
TXTPTR := $85 ; Far pointer into BASIC source code
FNAM := $90 ; Far pointer to LOAD/SAVE file-name
FNAM_SEG := $92
STATUS := $9C ; Kernal I/O completion status
FNAM_LEN := $9D ; Holds length of file-name
; ---------------------------------------------------------------------------

View File

@@ -15,6 +15,8 @@ IndReg := $01 ; Controls indirect indexed load-store bank
TXTPTR := $85 ; Far pointer into BASIC source code
FNAM := $90 ; Far pointer to LOAD/SAVE file-name
FNAM_SEG := $92
STATUS := $9C ; Kernal I/O completion status
FNAM_LEN := $9D ; Holds length of file-name
; ---------------------------------------------------------------------------

View File

@@ -38,8 +38,6 @@
; iax = ($0000,X)
; rel = $0000 (PC-relative) (supressed here)
.macpack cpu
OPC_BRK = $00
OPC_ORA_izx = $01
OPC_ORA_zp = $05

View File

@@ -10,6 +10,7 @@ VARTAB := $2A ; Pointer to start of BASIC variables
MEMSIZE := $34 ; Size of memory installed
TXTPTR := $77 ; Pointer into BASIC source code
TIME := $8D ; 60HZ clock
STATUS := $96 ; IEC status byte
KEY_COUNT := $9E ; Number of keys in input buffer
RVS := $9F ; Reverse flag
CURS_FLAG := $A7 ; 1 = cursor off

View File

@@ -107,6 +107,7 @@ Short options:
Long options:
--auto-import Mark unresolved symbols as import
--bin-include-dir dir Set a search path for binary includes
--color [on|auto|off] Color diagnostics (default: auto)
--cpu type Set cpu type
--create-dep name Create a make dependency file
--create-full-dep name Create a full make dependency file
@@ -120,6 +121,7 @@ Long options:
--listing name Create a listing file if assembly was ok
--list-bytes n Maximum number of bytes per listing line
--memory-model model Set the memory model
--no-utf8 Disable use of UTF-8 in diagnostics
--pagelength n Set the page length for the listing
--relax-checks Disables some error checks
--segment-list Generate segment offsets in listing
@@ -148,6 +150,14 @@ Here is a description of all the command line options:
name="search paths">.
<label id="option--color">
<tag><tt>--color</tt></tag>
This option controls if the assembler will use colors when printing
diagnostics. The default is "auto" which will enable colors if the output
goes to a terminal (not to a file).
<label id="option--cpu">
<tag><tt>--cpu type</tt></tag>
@@ -261,6 +271,14 @@ Here is a description of all the command line options:
huge.
<label id="option--no-utf8">
<tag><tt>--no-utf8</tt></tag>
Disable the use of UTF-8 characters in diagnostics. This might be necessary
if auto detection fails or if the output is captured for processing with a
tool that is not UTF-8 capable.
<label id="option-o">
<tag><tt>-o name</tt></tag>
@@ -920,6 +938,7 @@ See the description of the <tt><ref id=".PROC" name=".PROC"></tt>
directive for more information.
<label id=cheap-locals>
<sect1>Cheap local labels<p>
Cheap local labels are defined like standard labels, but the name of the
@@ -1435,38 +1454,6 @@ constant is defined:
CPU_ISET_M740
</verb></tscreen>
<!-- Sorry but explaining these with the changes from #2751 is too cringy for
me - must be done by someone else. The remainder is from the old
".macpack cpu" section"
The value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable may
be checked with <tt/<ref id="operators" name=".BITAND">/ to determine if the
currently enabled CPU supports a specific instruction set. For example the
65C02 supports all instructions of the 65SC02 CPU, so it has the
<tt/CPU_ISET_65SC02/ bit set in addition to its native <tt/CPU_ISET_65C02/
bit. Using
<tscreen><verb>
.if (.cpu .bitand CPU_ISET_65SC02)
lda (c_sp)
.else
ldy #$00
lda (c_sp),y
.endif
</verb></tscreen>
it is possible to determine if the
<tscreen><verb>
lda (c_sp)
</verb></tscreen>
instruction is supported, which is the case for the 65SC02, 65C02 and 65816
CPUs (the latter two are upwards compatible to the 65SC02).
see section <ref id="6502-mode" name="6502 format"> and following.
-->
<tt/.CPU/ may be used to replace the .IFPxx pseudo instructions or to
construct even more complex expressions.
@@ -1484,8 +1471,43 @@ see section <ref id="6502-mode" name="6502 format"> and following.
.endif
</verb></tscreen>
See also: <tt><ref id=".CAP" name=".CAP"></tt>
<bf>The dilemma:</bf>
The original design of this feature was made under the assumption, that any
"higher" CPU will support the entire instruction set of the "lower" CPU. For
example: the WDC W65C02 supports all instructions of the 65C02, which again
support all instructions of the 65SC02. Unfortunately this is not true for all
CMOS CPUs - when the 65CE02 was made, some instructions were changed, and a new
addressingmode was added. As a result all CPUS after (and including) 65CE02
are no more (source code) compatible with all instructions originally introduced
by the 65SC02.
Because of this, the .CPU function and the ISET* macros were repurposed to
indicate <em>groups of instructions</em> only, ie only the set of instructions
that was added by that particular CPU. In the value returned by .CPU only the
bits will be set, that refer to the groups of instructions that are completely
supported by that CPU.
The advantage of this is, that the mechanism keeps working for all new CPUs
added. The inevitable disadvantage is that you now have to know exactly which
CPU added which instructions (look <htmlurl url="cpus.html" name="here"> for reference).
<tscreen><verb>
.if (.cpu .bitand CPU_ISET_65SC02)
; This will be assembled for the W65C02, 65C02, 65SC02, 65816, HUC6820
lda (c_sp)
.elseif (.cpu .bitand CPU_ISET_65CE02)
; This will be assembled for the 65CE02, 4510, 45GS02
ldz #$00
lda (c_sp),z
.else
ldy #$00
lda (c_sp),y
.endif
</verb></tscreen>
See also: <tt><ref id=".CAP" name=".CAP"></tt>, which is a similar mechanism,
but without the problem outlined above.
<sect1><tt>.ISIZE</tt><label id=".ISIZE"><p>
@@ -3753,20 +3775,23 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
<sect1><tt>.LOCAL</tt><label id=".LOCAL"><p>
This command may only be used inside a macro definition. It declares a
list of identifiers as local to the macro expansion.
This command may only be used inside a macro definition. It declares a list
of identifiers as local to the macro expansion. The identifers may be
standard identifiers or cheap local identifiers depending on the planed use.
A problem when using macros are labels: Since they don't change their name,
you get a "duplicate symbol" error if the macro is expanded the second time.
Labels declared with <tt><ref id=".LOCAL" name=".LOCAL"></tt> have their
name mapped to an internal unique name (<tt/___ABCD__/) with each macro
name replaced by an internally generated unique name for each macro
invocation.
Some other assemblers start a new lexical block inside a macro expansion.
This has some drawbacks however, since that will not allow <em/any/ symbol
to be visible outside a macro, a feature that is sometimes useful. The
<tt><ref id=".LOCAL" name=".LOCAL"></tt> command is in my eyes a better way
to address the problem.
Please note that while the generated names are unique and guaranteed to not
clash with any user generated names, they are still regular symbols and
added to the current scope. This means that a local macro label will start a
new scope for cheap locals whenever the macro is expanded. To avoid that,
you may also use a <ref id="cheap-locals" name="cheap local symbol"> for the
name. In this case the assembler will generate unique cheap local
identifiers instead of standard ones.
You get an error when using <tt><ref id=".LOCAL" name=".LOCAL"></tt> outside
a macro.
@@ -3805,7 +3830,6 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
<tscreen><verb>
atari Defines the scrcode macro.
cbm Defines the scrcode macro.
cpu Defines constants for the .CPU variable.
generic Defines generic macros like add, sub, and blt.
longbranch Defines conditional long-jump macros.
</verb></tscreen>
@@ -5119,6 +5143,7 @@ For better orthogonality, the assembler defines similar symbols as the
compiler, depending on the target system selected:
<itemize>
<item><tt/__AGAT__/ - Target system is <tt/agat/
<item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/
<item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/
<item><tt/__ATARI2600__/ - Target system is <tt/atari2600/
@@ -5131,23 +5156,31 @@ compiler, depending on the target system selected:
<item><tt/__C128__/ - Target system is <tt/c128/
<item><tt/__C16__/ - Target system is <tt/c16/ or <tt/plus4/
<item><tt/__C64__/ - Target system is <tt/c64/
<item><tt/__C65__/ - Target system is <tt/c65/
<item><tt/__CBM__/ - Target is a Commodore or Commodore-alike system
<item><tt/__CBM510__/ - Target system is <tt/cbm510/
<item><tt/__CBM610__/ - Target system is <tt/cbm610/
<item><tt/__CREATIVISION__/ - Target system is <tt/creativision/
<item><tt/__CX16__/ - Target system is <tt/cx16/
<item><tt/__GAMATE__/ - Target system is <tt/gamate/
<item><tt/__GEOS__/ - Target is a GEOS system
<item><tt/__GEOS_APPLE__/ - Target system is <tt/geos-apple/
<item><tt/__GEOS_CBM__/ - Target system is <tt/geos-cbm/
<item><tt/__KIM1__/ - Target system is <tt/kim1/
<item><tt/__LUNIX__/ - Target system is <tt/lunix/
<item><tt/__LYNX__/ - Target system is <tt/lynx/
<item><tt/__MEGA65__/ - Target system is <tt/mega65/
<item><tt/__NES__/ - Target system is <tt/nes/
<item><tt/__OSIC1P__/ - Target system is <tt/osic1p/
<item><tt/__PCE__/ - Target system is <tt/pce/
<item><tt/__PET__/ - Target system is <tt/pet/
<item><tt/__PLUS4__/ - Target system is <tt/plus4/
<item><tt/__RP6502__/ - Target system is <tt/rp6502/
<item><tt/__SIM6502__/ - Target system is <tt/sim6502/
<item><tt/__SIM65C02__/ - Target system is <tt/sim65c02/
<item><tt/__SUPERVISION__/ - Target system is <tt/supervision/
<item><tt/__SYM1__/ - Target system is <tt/sym1/
<item><tt/__TELESTRAT__/ - Target system is <tt/telestrat/
<item><tt/__VIC20__/ - Target system is <tt/vic20/
</itemize>

View File

@@ -641,7 +641,7 @@ Here is a description of all the command line options:
<item>pce (PC engine)
<item>pet (all CBM PET systems except the 2001)
<item>plus4
<item>p6502
<item>rp6502
<item>sim6502
<item>sim65c02
<item>supervision
@@ -1112,6 +1112,10 @@ This cc65 version has some extensions to the ISO C standard.
The compiler defines several macros at startup:
<descrip>
<tag><tt>__AGAT__</tt></tag>
This macro is defined if the target is the Agat (-t agat).
<tag><tt>__APPLE2__</tt></tag>
This macro is defined if the target is the Apple ][ (-t apple2) or the enhanced Apple //e (-t apple2enh).
@@ -1122,11 +1126,15 @@ The compiler defines several macros at startup:
<tag><tt>__ATARI2600__</tt></tag>
This macro is defined if the target is the Atari 2600 game console.
This macro is defined if the target is the Atari 2600 game console (-t atari2600).
<tag><tt>__ATARI5200__</tt></tag>
This macro is defined if the target is the Atari 5200 game console.
This macro is defined if the target is the Atari 5200 game console (-t atari5200).
<tag><tt>__ATARI7800__</tt></tag>
This macro is defined if the target is the Atari 7800 game console (-t atari7800).
<tag><tt>__ATARI__</tt></tag>
@@ -1140,6 +1148,10 @@ The compiler defines several macros at startup:
This macro is defined if the target is the Oric Atmos (-t atmos).
<tag><tt>__BBC__</tt></tag>
This macro is defined if the target is the BBC (-t bbc).
<tag><tt>__C128__</tt></tag>
This macro is defined if the target is the Commodore 128 (-t c128).
@@ -1152,6 +1164,10 @@ The compiler defines several macros at startup:
This macro is defined if the target is the Commodore 64 (-t c64).
<tag><tt>__C65__</tt></tag>
This macro is defined if the target is the Commodore 65 (-t c65).
<tag><tt>__CBM__</tt></tag>
This macro is defined if the target system is one of the CBM targets.
@@ -1196,10 +1212,8 @@ The compiler defines several macros at startup:
<label id="macro-CPU">
<tag><tt>__CPU__</tt></tag>
This macro contains a bitset that allows to check if a specific instruction
set is supported. For example, the 65C02 CPU supports all instructions of the
65SC02. So testing for the instruction set of the 65SC02 using the following
check will succeed for both CPUs (and also for the 65816 and HUC6280).
This macro contains a bitset that allows to check if a specific group of
instructions is supported.
<tscreen><verb>
#if (__CPU__ & __CPU_ISET_65SC02__)
@@ -1212,6 +1226,13 @@ The compiler defines several macros at startup:
given, but can be changed using the <tt/<ref id="option--cpu" name="--cpu">/
command line option.
Note that, since the different CMOS instruction sets are not orthogonal, the
following test macros only test for the group of instructions <bf>added</bf>
by this particular CPU.
see <htmlurl url="ca65.html#.CPU" name=".CPU"> for details on the ISET*
dilemma.
<tag><tt>__CPU_4510__</tt></tag>
This macro is defined if the code is compiled for a 4510 CPU.
@@ -1321,6 +1342,10 @@ The compiler defines several macros at startup:
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the W65C02 CPU.
<tag><tt>__CREATIVISION__</tt></tag>
This macro is defined if the target is the VTech Creativision game console (-t creativision).
<tag><tt>__CX16__</tt></tag>
This macro is defined if the target is the Commander X16 (-t cx16).
@@ -1339,6 +1364,10 @@ The compiler defines several macros at startup:
This macro expands to a string containing the name of the C source file.
<tag><tt>__GAMATE__</tt></tag>
This macro is defined if the target is the Gamate handheld (-t gamate).
<tag><tt>__GEOS__</tt></tag>
This macro is defined if you are compiling for one of the GEOS systems.
@@ -1351,6 +1380,10 @@ The compiler defines several macros at startup:
This macro is defined if you are compiling for the GEOS 64/128 system (-t geos-cbm).
<tag><tt>__KIM1__</tt></tag>
This macro is defined if the target is the KIM-1 (-t kmi1).
<tag><tt>__LINE__</tt></tag>
This macro expands to the current line number.
@@ -1363,6 +1396,10 @@ The compiler defines several macros at startup:
This macro is defined if the target is the Atari Lynx (-t lynx).
<tag><tt>__MEGA65__</tt></tag>
This macro is defined if the target is the Mega 65 (-t mega65).
<tag><tt>__NES__</tt></tag>
This macro is defined if the target is the Nintendo Entertainment System (-t nes).
@@ -1388,6 +1425,10 @@ The compiler defines several macros at startup:
This macro is defined if the target is the Ohio Scientific Challenger 1P
(-t osic1p).
<tag><tt>__PCE__</tt></tag>
This macro is defined if the target is the PC Engine game console (-t pce).
<tag><tt>__PET__</tt></tag>
This macro is defined if the target is the PET family of computers (-t pet).
@@ -1396,6 +1437,10 @@ The compiler defines several macros at startup:
This macro is defined if the target is the Commodore Plus/4 (-t plus4).
<tag><tt>__RP6502__</tt></tag>
This macro is defined if the target is the Picocomputer 6502 (-t rp6502).
<tag><tt>__SIM6502__</tt></tag>
This macro is defined if the target is sim65 in 6502 mode (-t sim6502).

View File

@@ -785,6 +785,7 @@ communication, see also <tt>testcode/lib/ser-test.c</tt>.
<item><ref id="strcpy" name="strcpy">
<item><ref id="strcspn" name="strcspn">
<item><ref id="strdup" name="strdup">
<item><ref id="strndup" name="strndup">
<item><ref id="strerror" name="strerror">
<item><ref id="stricmp" name="stricmp">
<item><ref id="strlen" name="strlen">
@@ -5621,6 +5622,7 @@ be used in presence of a prototype.
<ref id="free" name="free">,
<ref id="realloc" name="realloc">,
<ref id="strdup" name="strdup">
<ref id="strndup" name="strndup">
<tag/Example/None.
</descrip>
</quote>
@@ -7774,6 +7776,35 @@ be used in presence of a prototype.
<tag/See also/
<ref id="free" name="free">,
<ref id="malloc" name="malloc">
<ref id="strndup" name="strndup">
<tag/Example/None.
</descrip>
</quote>
<sect1>strndup<label id="strndup"><p>
<quote>
<descrip>
<tag/Function/Allocate a copy of a string on the heap, of a given maximum length.
<tag/Header/<tt/<ref id="string.h" name="string.h">/
<tag/Declaration/<tt/char* __fastcall__ strndup (const char* s, size_t maxlen);/
<tag/Description/<tt/strndup/ allocates a memory block on the heap, big enough
to hold a copy of <tt/s/ including the terminating zero. If the allocation
fails, <tt/NULL/ is returned, otherwise <tt/s/ is copied into the allocated
memory block, maxlen characters are kept, and a pointer to the block is returned.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>It is up to the caller to free the allocated memory block.
</itemize>
<tag/Availability/ISO 9899
<tag/See also/
<ref id="free" name="free">,
<ref id="malloc" name="malloc">
<ref id="strndup" name="strndup">
<tag/Example/None.
</descrip>
</quote>

View File

@@ -79,6 +79,7 @@ void* __fastcall__ __bzero (void* ptr, size_t n);
#if __CC65_STD__ == __CC65_STD_CC65__
void __fastcall__ bzero (void* ptr, size_t n); /* BSD */
char* __fastcall__ strdup (const char* s); /* SYSV/BSD */
char* __fastcall__ strndup (const char* s, size_t maxlen); /* SYSV/BSD */
int __fastcall__ stricmp (const char* s1, const char* s2); /* DOS/Windows */
int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */
char* __fastcall__ strcasestr (const char* str, const char* substr);

View File

@@ -5,6 +5,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.import COUT
.export _cputcxy, _cputc, newline, putchar,putchardirect

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.constructor initconio
.export _cputcxy, _cputc

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc
.export plot, cputdirect, putchar

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.include "atari5200.inc"

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputc
.import gotox, gotoy, pusha0

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc
.export setscrptr, cputdirect, putchar

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -9,7 +9,6 @@
.import push0, callmain
.import RESTOR, BSOUT, CLRCH
.import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__
.importzp ST
.include "zeropage.inc"
.include "c128.inc"
@@ -65,6 +64,15 @@ L1: lda c_sp,x
jsr initlib
; Disable the BASIC part of the IRQ handler. It would usually (once per frame)
; copy the VIC shadow register, move sprites, play music. This would only get
; in the way, so we turn it off.
lda INIT_STATUS
sta initsave
and #$fe
sta INIT_STATUS
; Set the bank for the file name to our execution bank. We must do this
; *after* calling the constructors because some of them might depend on
; the original value of this register.
@@ -89,10 +97,15 @@ L2: lda zpsave,x
dex
bpl L2
; Enable the BASIC interrupt again
lda initsave
sta INIT_STATUS
; Place the program return code into BASIC's status variable.
pla
sta ST
sta STATUS
; Reset the stack and the memory configuration.
@@ -116,5 +129,6 @@ zpsave: .res zpspace
.bss
spsave: .res 1
mmusave:.res 1
spsave: .res 1
mmusave: .res 1
initsave: .res 1

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $90 ; IEC status byte
.export initst
.include "c128.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -10,9 +10,9 @@
.import initlib, donelib
.import callmain, zerobss
.import MEMTOP, RESTOR, BSOUT, CLRCH
.importzp ST
.include "zeropage.inc"
.include "c16.inc"
; ------------------------------------------------------------------------
; Startup code
@@ -76,7 +76,7 @@ L2: lda zpsave,x
; Store the return code into BASIC's status variable.
pla
sta ST
sta STATUS
; Restore the stack pointer.

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -10,9 +10,9 @@
.import BSOUT
.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; from configure file
.importzp ST
.include "zeropage.inc"
.include "c64.inc"
; ------------------------------------------------------------------------
@@ -62,7 +62,7 @@ L2: lda zpsave,x
; Place the program return code into BASIC's status variable.
pla
sta ST
sta STATUS
; Restore the system stuff.

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $90 ; IEC status byte
.export initst
.include "c64.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $90 ; IEC status byte
.export initst
.include "c65.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -10,7 +10,8 @@
.import isdisk
.import opencmdchannel
.import closecmdchannel
.importzp ST
.import initst
.import READST
.importzp tmp2
;------------------------------------------------------------------------------
@@ -33,26 +34,25 @@ next: inx
; interpret a non-disk as a no-op while we need to interpret it
; as an error here
jsr isdisk
jsr isdisk ; carry clear if the unit number in X is a disk
bcs next
; [open|close]cmdchannel don't call into the Kernal at all if they
; only [in|de]crement the reference count of the shared cmdchannel
; so we need to explicitly initialize ST here
lda #$00
sta ST
stx tmp2 ; further calls my use X
stx tmp2
jsr initst
ldx tmp2 ; get unit number back
jsr opencmdchannel
ldx tmp2
ldx tmp2 ; get unit number back
jsr closecmdchannel
ldx tmp2
; As we had to reference ST above anyway we can as well do so
; here too (instead of calling READST)
ldx tmp2 ; get unit number back
lda ST
jsr READST ; preserves X, returns A and Flags
; Either the Kernal calls above were successful or there was
; already a cmdchannel to the device open - which is a pretty

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -16,11 +16,9 @@
jsr sys_bank
sty ktmp ; Save Y register
ldy #$9C ; STATUS
ldy #STATUS
lda (sysp0),y ; Load STATUS from system bank
ldy ktmp
jmp restore_bank ; Will set condition codes on A
.endproc

View File

@@ -22,7 +22,7 @@
sty ktmp
txa
ldy #$90 ; FNAM
ldy #FNAM
sta (sysp0),y
lda ktmp
@@ -33,13 +33,10 @@
ldy #$92 ; FNAM_SEG
sta (sysp0),y
ldy #$9D ; FNAM_LEN
ldy #FNAM_LEN
pla
sta (sysp0),y
ldy ktmp
jmp restore_bank
.endproc

21
libsrc/cbm510/status.s Normal file
View File

@@ -0,0 +1,21 @@
;
; Stefan Haubenthal, 2023-01-16
;
.export initst
.include "extzp.inc"
.include "cbm510.inc"
.proc initst
ldx IndReg
ldy #$0F
sty IndReg ; Switch to the system bank
ldy #STATUS
lda #$00 ; Initialize value
sta (sysp0),y
stx IndReg
rts
.endproc

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -394,7 +394,7 @@ _exit: pha ; Save the return code
; Place the program return code into BASIC's status variable.
pla
ldy #$9C ; ST
ldy #STATUS
sta (sysp0),y
; Set up the welcome code at the stack bottom in the system bank.

View File

@@ -11,16 +11,14 @@
.include "cbm610.inc"
; preserves X and Y, returns status in A and in status flags
.proc READST
jsr sys_bank
sty ktmp ; Save Y register
ldy #$9C ; STATUS
ldy #STATUS
lda (sysp0),y ; Load STATUS from system bank
ldy ktmp
jmp restore_bank ; Will set condition codes on A
.endproc

View File

@@ -22,7 +22,7 @@
sty ktmp
txa
ldy #$90 ; FNAM
ldy #FNAM
sta (sysp0),y
lda ktmp
@@ -30,14 +30,13 @@
sta (sysp0),y
lda ExecReg ; Assume name is always in this segment
ldy #$92 ; FNAM_SEG
ldy #FNAM_SEG
sta (sysp0),y
ldy #$9D ; FNAM_LEN
ldy #FNAM_LEN
pla
sta (sysp0),y
ldy ktmp
jmp restore_bank
.endproc

21
libsrc/cbm610/status.s Normal file
View File

@@ -0,0 +1,21 @@
;
; Stefan Haubenthal, 2023-01-16
;
.export initst
.include "extzp.inc"
.include "cbm610.inc"
.proc initst
ldx IndReg
ldy #$0F
sty IndReg ; Switch to the system bank
ldy #STATUS
lda #$00 ; Initialize value
sta (sysp0),y
stx IndReg
rts
.endproc

53
libsrc/common/strndup.s Normal file
View File

@@ -0,0 +1,53 @@
;
; Colin Leroy-Mira, 03.07.2025
;
; char* __fastcall__ strndup (const char* S, size_t maxlen);
;
.importzp tmp1, tmp2, ptr2
.import _strncpy, _strlen, _malloc
.import pushax, popax, incsp2, incax1, swapstk
.import ___errno
.export _strndup
.include "errno.inc"
.proc _strndup
sta tmp1 ; Remember maxlen
stx tmp1+1
jsr popax ; Get string
jsr pushax ; Keep it in TOS
jsr _strlen ; Get string length,
cpx tmp1+1 ; Compare to max,
bcc alloc
bne :+
cmp tmp1
bcc alloc
: lda tmp1 ; Use maxlen if shorter
ldx tmp1+1
alloc: jsr incax1 ; Add 1 for terminator
jsr _malloc ; Allocate output
cpx #$00 ; Check allocation
beq errmem
jsr swapstk ; Put dest in TOS and get string back
jsr pushax ; Put src in TOS
lda tmp1 ; Get length for strncpy
ldx tmp1+1
jsr _strncpy ; Copy
pha ; Terminate
lda #$00
sta (ptr2),y
pla
rts
errmem: ldy #ENOMEM
sty ___errno
jmp incsp2 ; Pop string and return
.endproc

View File

@@ -22,6 +22,10 @@ _cputsxy:
_cputs: sta ptr1 ; Save s
stx ptr1+1
; Important note: The implementation below relies on the _cputc() function not
; clobbering ptr1. This might not be the case when rewriting this function so
; beware!
L0:
.if .cap(CPU_HAS_ZPIND)
lda (ptr1) ; (5)

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -2,6 +2,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -21,6 +21,9 @@
; note that there are conflicts between control characters and keyboard:
; HOME = KEY_ENTER, KEY_HOME = REV_ON,
; UPLINE = ?, KEY_UPARROW = GOTOY, ...
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc
.import gotoxy, fixcursor

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $90 ; IEC status byte
.export initst
.include "mega65.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline

View File

@@ -2,6 +2,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -6,12 +6,12 @@
;
.export checkst
.importzp ST
.include "pet.inc"
.proc checkst
lda ST
lda STATUS
beq @L1
lda #5 ; ### Device not present
sec

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -8,7 +8,6 @@
.import zerobss, push0
.import callmain
.import CLRCH, BSOUT
.importzp ST
.include "zeropage.inc"
.include "pet.inc"
@@ -80,7 +79,7 @@ L2: lda zpsave,x
; Store the program return code into BASIC's status variable.
pla
sta ST
sta STATUS
; Restore the stack pointer.

View File

@@ -5,14 +5,12 @@
;
.export READST
.importzp ST
.include "pet.inc"
.proc READST
lda ST
lda STATUS
rts
.endproc

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $96 ; IEC status byte
.export initst
.include "pet.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -10,7 +10,6 @@
.import callmain, zerobss
.import __INTERRUPTOR_COUNT__
.import __HIMEM__ ; Linker generated
.importzp ST
.include "zeropage.inc"
.include "plus4.inc"
@@ -121,7 +120,7 @@ L2: lda zpsave,x
; Place the program return code into BASIC's status variable.
pla
sta ST
sta STATUS
; Restore the stack pointer.

View File

@@ -7,12 +7,11 @@
.export READST
.include "plus4.inc"
.importzp ST
; Read the status byte from the zero page instead of banking in the ROM
.proc READST
lda ST ; Load status
lda STATUS ; Load status
rts ; Return to caller
.endproc

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $90 ; IEC status byte
.export initst
.include "plus4.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -1,8 +1,10 @@
; 2018-04-13, Jede (jede@oric.org)
;
;
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputc, _cputcxy, cputdirect, display_conio
.export CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
; Important note: The implementation of cputs() relies on the cputc() function
; not clobbering ptr1. Beware when rewriting or changing this function!
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot

View File

@@ -10,9 +10,9 @@
.import RESTOR, BSOUT, CLRCH
.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; Linker generated
.importzp ST
.include "zeropage.inc"
.include "vic20.inc"
; ------------------------------------------------------------------------
; Startup code
@@ -72,7 +72,7 @@ L2: lda zpsave,x
; Place the program return code into BASIC's status variable.
pla
sta ST
sta STATUS
; Restore the stack pointer.

View File

@@ -1,5 +1,15 @@
;
; Oliver Schmidt, 2012-09-30
; Stefan Haubenthal, 2023-01-16
;
.exportzp ST := $90 ; IEC status byte
.export initst
.include "vic20.inc"
.proc initst
lda #$00
sta STATUS
rts
.endproc

View File

@@ -297,6 +297,7 @@ EXELIST_c16 = \
EXELIST_cbm510 = \
ascii \
checkversion \
enumdevdir \
gunzip65 \
hello \
joydemo \
@@ -308,6 +309,7 @@ EXELIST_cbm510 = \
EXELIST_cbm610 = \
ascii \
checkversion \
enumdevdir \
gunzip65 \
hello \
terminal \

View File

@@ -57,7 +57,7 @@ ifdef QUIET
PQ = "QUIET=1"
PD = --no-print-directory
ifndef CMD_EXE
CATERR = 2> ../wrk/common/$$@.errlog || (cat ../wrk/common/$$@.errlog && false)
CATERR = 2> $@.errlog || (cat $@.errlog && false)
endif
endif

View File

@@ -91,6 +91,7 @@
<ClInclude Include="ca65\easw16.h" />
<ClInclude Include="ca65\enum.h" />
<ClInclude Include="ca65\error.h" />
<ClInclude Include="ca65\expect.h" />
<ClInclude Include="ca65\expr.h" />
<ClInclude Include="ca65\feature.h" />
<ClInclude Include="ca65\filetab.h" />
@@ -132,6 +133,7 @@
<ClCompile Include="ca65\easw16.c" />
<ClCompile Include="ca65\enum.c" />
<ClCompile Include="ca65\error.c" />
<ClCompile Include="ca65\expect.c" />
<ClCompile Include="ca65\expr.c" />
<ClCompile Include="ca65\feature.c" />
<ClCompile Include="ca65\filetab.c" />
@@ -168,4 +170,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@@ -35,6 +35,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "instr.h"
#include "lineinfo.h"
@@ -194,7 +195,7 @@ static void FreeIf (void)
{
int Done;
do {
IfDesc* ID = GetCurrentIf();
IfDesc* ID = GetCurrentIf ();
if (ID == 0) {
Error (" Unexpected .ENDIF");
Done = 1;
@@ -318,7 +319,7 @@ void DoConditionals (void)
D = AllocIf (".IFCONST", 1);
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
ExprNode* Expr = Expression ();
SetIfCond (D, IsConstExpr (Expr, 0));
FreeExpr (Expr);
ExpectSep ();
@@ -354,7 +355,7 @@ void DoConditionals (void)
D = AllocIf (".IFNCONST", 1);
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
ExprNode* Expr = Expression ();
SetIfCond (D, !IsConstExpr (Expr, 0));
FreeExpr (Expr);
ExpectSep ();
@@ -388,7 +389,7 @@ void DoConditionals (void)
D = AllocIf (".IFP02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502);
SetIfCond (D, GetCPU () == CPU_6502);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -398,7 +399,7 @@ void DoConditionals (void)
D = AllocIf (".IFP02X", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502X);
SetIfCond (D, GetCPU () == CPU_6502X);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -408,7 +409,7 @@ void DoConditionals (void)
D = AllocIf (".IFP4510", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_4510);
SetIfCond (D, GetCPU () == CPU_4510);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -418,7 +419,7 @@ void DoConditionals (void)
D = AllocIf (".IFP45GS02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_45GS02);
SetIfCond (D, GetCPU () == CPU_45GS02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -428,7 +429,7 @@ void DoConditionals (void)
D = AllocIf (".IFP6280", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_HUC6280);
SetIfCond (D, GetCPU () == CPU_HUC6280);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -438,7 +439,7 @@ void DoConditionals (void)
D = AllocIf (".IFP816", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65816);
SetIfCond (D, GetCPU () == CPU_65816);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -448,7 +449,7 @@ void DoConditionals (void)
D = AllocIf (".IFPC02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65C02);
SetIfCond (D, GetCPU () == CPU_65C02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -458,7 +459,7 @@ void DoConditionals (void)
D = AllocIf (".IFPCE02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65CE02);
SetIfCond (D, GetCPU () == CPU_65CE02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -468,7 +469,7 @@ void DoConditionals (void)
D = AllocIf (".IFPDTV", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502DTV);
SetIfCond (D, GetCPU () == CPU_6502DTV);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -478,7 +479,7 @@ void DoConditionals (void)
D = AllocIf (".IFPM740", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_M740);
SetIfCond (D, GetCPU () == CPU_M740);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -488,7 +489,7 @@ void DoConditionals (void)
D = AllocIf (".IFPSC02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65SC02);
SetIfCond (D, GetCPU () == CPU_65SC02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -498,7 +499,7 @@ void DoConditionals (void)
D = AllocIf (".IFPSWEET16", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_SWEET16);
SetIfCond (D, GetCPU () == CPU_SWEET16);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -508,7 +509,7 @@ void DoConditionals (void)
D = AllocIf (".IFPWC02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_W65C02);
SetIfCond (D, GetCPU () == CPU_W65C02);
}
ExpectSep ();
CalcOverallIfCond ();

View File

@@ -46,6 +46,7 @@
/* ca65 */
#include "dbginfo.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "filetab.h"
#include "global.h"
@@ -238,8 +239,7 @@ void DbgInfoFunc (void)
ConsumeComma ();
/* Type */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
Type = ValidateType (&CurTok.SVal);
@@ -267,8 +267,7 @@ void DbgInfoFunc (void)
ConsumeComma ();
/* Assembler name follows */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
AsmName = GetStrBufId (&CurTok.SVal);
@@ -321,8 +320,7 @@ void DbgInfoLine (void)
ConsumeComma ();
/* The name of the file follows */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
@@ -371,8 +369,7 @@ void DbgInfoSym (void)
ConsumeComma ();
/* Name */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
Name = GetStrBufId (&CurTok.SVal);
@@ -382,8 +379,7 @@ void DbgInfoSym (void)
ConsumeComma ();
/* Type */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
Type = ValidateType (&CurTok.SVal);
@@ -418,8 +414,7 @@ void DbgInfoSym (void)
Offs = ConstExpression ();
} else {
/* Register, extern or static: Assembler name follows */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
AsmName = GetStrBufId (&CurTok.SVal);
@@ -468,7 +463,7 @@ void DbgInfoCheck (void)
/* Search for the symbol name */
S->Sym = SymFindAny (S->Scope, GetStrBuf (S->AsmName));
if (S->Sym == 0) {
PError (&S->Pos, "Assembler symbol '%s' not found",
PError (&S->Pos, "Assembler symbol `%s' not found",
GetString (S->AsmName));
} else {
/* Set the backlink */

View File

@@ -37,6 +37,7 @@
#include "ea.h"
#include "ea65.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "instr.h"
#include "nexttok.h"
@@ -62,11 +63,11 @@ void GetEA (EffAddr* A)
if (BracketAsIndirect) {
IndirectEnter = TOK_LBRACK;
IndirectLeave = TOK_RBRACK;
IndirectExpect = "']' expected";
IndirectExpect = "Expected `]'";
} else {
IndirectEnter = TOK_LPAREN;
IndirectLeave = TOK_RPAREN;
IndirectExpect = "')' expected";
IndirectExpect = "Expected `)'";
}
/* Clear the output struct */
@@ -136,16 +137,22 @@ void GetEA (EffAddr* A)
/* (adr,x) */
NextTok ();
A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
Consume (IndirectLeave, IndirectExpect);
if (!Consume (IndirectLeave, IndirectExpect)) {
SkipUntilSep ();
}
} else if (CurTok.Tok == TOK_S) {
/* (rel,s),y */
NextTok ();
A->AddrModeSet = AM65_STACK_REL_IND_Y;
Consume (IndirectLeave, IndirectExpect);
ConsumeComma ();
Consume (TOK_Y, "'Y' expected");
if (!Consume (IndirectLeave, IndirectExpect) ||
!ConsumeComma () ||
!Consume (TOK_Y, "Expected `Y'")) {
/* In case of errors skip anything else on the line */
SkipUntilSep ();
}
} else {
Error ("Syntax error");
ErrorExpect ("Expected `X' or `S'");
SkipUntilSep ();
}
} else {
@@ -162,7 +169,9 @@ void GetEA (EffAddr* A)
A->AddrModeSet = AM65_DIR_IND;
break;
default:
Consume (TOK_Y, "'Y' expected");
if (!Consume (TOK_Y, "Expected `Y'")) {
SkipUntilSep ();
}
A->AddrModeSet = AM65_DIR_IND_Y;
break;
}
@@ -190,16 +199,22 @@ void GetEA (EffAddr* A)
/* [dir] or [dir],y */
NextTok ();
A->Expr = Expression ();
Consume (TOK_RBRACK, "']' expected");
if (!Consume (TOK_RBRACK, "Expected `]'")) {
SkipUntilSep ();
}
if (CurTok.Tok == TOK_COMMA) {
/* [dir],y */
NextTok ();
if (GetCPU () == CPU_45GS02) {
Consume (TOK_Z, "'Z' expected");
if (!Consume (TOK_Z, "Expected `Z'")) {
SkipUntilSep ();
}
A->AddrModeSet = AM65_32BIT_BASE_IND_Z;
}
else {
Consume (TOK_Y, "'Y' expected");
if (!Consume (TOK_Y, "Expected `Y'")) {
SkipUntilSep ();
}
A->AddrModeSet = AM65_DIR_IND_LONG_Y;
}
} else {

View File

@@ -37,6 +37,7 @@
#include "ea.h"
#include "ea65.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "instr.h"
#include "nexttok.h"
@@ -96,7 +97,7 @@ void GetSweet16EA (EffAddr* A)
/* Register number */
A->Reg = (unsigned) Reg;
} else {
ErrorSkip ("Register or register number expected");
ErrorExpect ("Expected register or register number");
A->Reg = 0;
}

View File

@@ -41,6 +41,7 @@
#include "condasm.h"
#include "enum.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "macro.h"
#include "nexttok.h"
@@ -87,12 +88,13 @@ void DoEnum (void)
continue;
}
/* Allow conditionals within an enum */
if (CheckConditionals ()) {
continue;
}
/* The format is "identifier [ = value ]" */
if (CurTok.Tok != TOK_IDENT) {
/* Maybe it's a conditional? */
if (!CheckConditionals ()) {
ErrorSkip ("Identifier expected");
}
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
continue;
}
@@ -146,7 +148,7 @@ void DoEnum (void)
}
/* End of enum definition */
Consume (TOK_ENDENUM, "'.ENDENUM' expected");
Consume (TOK_ENDENUM, "`.ENDENUM' expected");
/* Free the base expression */
FreeExpr (BaseExpr);

View File

@@ -38,6 +38,8 @@
#include <stdarg.h>
/* common */
#include "cmdline.h"
#include "consprop.h"
#include "strbuf.h"
/* ca65 */
@@ -45,6 +47,7 @@
#include "filetab.h"
#include "lineinfo.h"
#include "nexttok.h"
#include "spool.h"
@@ -64,6 +67,14 @@ unsigned WarningCount = 0;
/* Maximum number of additional notifications */
#define MAX_NOTES 8
/* Diagnostic category */
typedef enum { DC_NOTE, DC_WARN, DC_ERR, DC_FATAL, DC_COUNT } DiagCat;
/* Descriptions for diagnostic categories */
const char* DiagCatDesc[DC_COUNT] = {
"Note", "Warning", "Error", "Fatal error"
};
/*****************************************************************************/
@@ -72,27 +83,144 @@ unsigned WarningCount = 0;
static void VPrintMsg (const FilePos* Pos, const char* Desc,
const char* Format, va_list ap)
static void ReplaceQuotes (StrBuf* Msg)
/* Replace opening and closing single quotes in Msg by their typographically
** correct UTF-8 counterparts for better readbility. A closing quote will
** only get replaced if an opening quote has been seen before.
** To handle some special cases, the function will also treat \xF0 as
** opening and \xF1 as closing quote. These are replaced without the need for
** correct ordering (open/close).
** The function will change the quotes in place, so after the call Msg will
** contain the changed string. If UTF-8 is not available, the function will
** replace '`' by '\'' since that was the default behavior before. It will
** also replace \xF0 and \xF1 by '\''.
**/
{
/* UTF-8 characters for single quotes */
static const char QuoteStart[] = "\xE2\x80\x98";
static const char QuoteEnd[] = "\xE2\x80\x99";
/* ANSI color sequences */
const char* ColorStart = CP_BrightGreen ();
const char* ColorEnd = CP_White ();
/* Remember a few things */
int IsUTF8 = CP_IsUTF8 ();
/* We create a new string in T and will later copy it back to Msg */
StrBuf T = AUTO_STRBUF_INITIALIZER;
/* Parse the string and create a modified copy */
SB_Reset (Msg);
int InQuote = 0;
while (1) {
char C = SB_Get (Msg);
switch (C) {
case '`':
if (!InQuote) {
InQuote = 1;
if (IsUTF8) {
SB_AppendStr (&T, QuoteStart);
} else {
/* ca65 uses \' for opening and closing quotes */
SB_AppendChar (&T, '\'');
}
SB_AppendStr (&T, ColorStart);
} else {
/* Found two ` without closing quote - don't replace */
SB_AppendChar (&T, '`');
}
break;
case '\'':
if (InQuote) {
InQuote = 0;
SB_AppendStr (&T, ColorEnd);
if (IsUTF8) {
SB_AppendStr (&T, QuoteEnd);
} else {
SB_AppendChar (&T, C);
}
} else {
SB_AppendChar (&T, C);
}
break;
case '\xF0':
if (IsUTF8) {
SB_AppendStr (&T, QuoteStart);
} else {
SB_AppendChar (&T, '\'');
}
break;
case '\xF1':
if (IsUTF8) {
SB_AppendStr (&T, QuoteEnd);
} else {
SB_AppendChar (&T, '\'');
}
break;
case '\0':
goto Done;
default:
SB_AppendChar (&T, C);
break;
}
}
Done:
/* Copy the string back, then terminate it */
SB_Move (Msg, &T);
SB_Terminate (Msg);
}
static void VPrintMsg (const FilePos* Pos, DiagCat Cat, const char* Format,
va_list ap)
/* Format and output an error/warning message. */
{
StrBuf S = STATIC_STRBUF_INITIALIZER;
StrBuf S = AUTO_STRBUF_INITIALIZER;
StrBuf Msg = AUTO_STRBUF_INITIALIZER;
StrBuf Loc = AUTO_STRBUF_INITIALIZER;
/* Format the actual message */
StrBuf Msg = STATIC_STRBUF_INITIALIZER;
/* Determine the description for the category and its color */
const char* Desc = DiagCatDesc[Cat];
const char* Color;
switch (Cat) {
case DC_NOTE: Color = CP_Cyan (); break;
case DC_WARN: Color = CP_Yellow (); break;
case DC_ERR: Color = CP_BrightRed (); break;
case DC_FATAL: Color = CP_BrightRed (); break;
default: FAIL ("Unexpected Cat value"); break;
}
/* Format the actual message, then replace quotes */
SB_VPrintf (&Msg, Format, ap);
SB_Terminate (&Msg);
ReplaceQuotes (&Msg);
/* Format the message header */
SB_Printf (&S, "%s:%u: %s: ",
SB_GetConstBuf (GetFileName (Pos->Name)),
Pos->Line,
Desc);
/* Format the location. If the file position is valid, we use the file
** position, otherwise the program name. This allows to print fatal
** errors in the startup phase.
*/
if (Pos->Name == EMPTY_STRING_ID) {
SB_CopyStr (&Loc, ProgName);
} else {
SB_Printf (&Loc, "%s:%u", SB_GetConstBuf (GetFileName (Pos->Name)),
Pos->Line);
}
SB_Terminate (&Loc);
/* Append the message to the message header */
SB_Append (&S, &Msg);
/* Format the full message */
SB_Printf (&S, "%s%s: %s%s:%s %s%s",
CP_White (),
SB_GetConstBuf (&Loc),
Color,
Desc,
CP_White (),
SB_GetConstBuf (&Msg),
CP_Reset ());
/* Delete the formatted message */
/* Delete the formatted message and the location string */
SB_Done (&Loc);
SB_Done (&Msg);
/* Add a new line and terminate the generated full message */
@@ -108,18 +236,6 @@ static void VPrintMsg (const FilePos* Pos, const char* Desc,
static void PrintMsg (const FilePos* Pos, const char* Desc,
const char* Format, ...)
/* Format and output an error/warning message. */
{
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, Desc, Format, ap);
va_end (ap);
}
static void AddNotifications (const Collection* LineInfos)
/* Output additional notifications for an error or warning */
{
@@ -165,7 +281,7 @@ static void AddNotifications (const Collection* LineInfos)
/* Output until an upper limit of messages is reached */
if (Msg) {
if (Output < MAX_NOTES) {
PrintMsg (GetSourcePos (LI), "Note", "%s", Msg);
PNotification (GetSourcePos (LI), "%s", Msg);
++Output;
} else {
++Skipped;
@@ -176,13 +292,43 @@ static void AddNotifications (const Collection* LineInfos)
/* Add a note if we have more stuff that we won't output */
if (Skipped > 0) {
const LineInfo* LI = CollConstAt (LineInfos, 0);
PrintMsg (GetSourcePos (LI), "Note",
"Dropping %u additional line infos", Skipped);
PNotification (GetSourcePos (LI), "Dropping %u additional line infos",
Skipped);
}
}
/*****************************************************************************/
/* Notifications */
/*****************************************************************************/
void Notification (const char* Format, ...)
/* Print a notification message. */
{
/* Output the message */
va_list ap;
va_start (ap, Format);
VPrintMsg (&CurTok.Pos, DC_NOTE, Format, ap);
va_end (ap);
}
void PNotification (const FilePos* Pos, const char* Format, ...)
/* Print a notification message. */
{
/* Output the message */
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, DC_NOTE, Format, ap);
va_end (ap);
}
/*****************************************************************************/
/* Warnings */
/*****************************************************************************/
@@ -196,7 +342,7 @@ static void WarningMsg (const Collection* LineInfos, const char* Format, va_list
const LineInfo* LI = CollConstAt (LineInfos, 0);
/* Output a warning for this position */
VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
VPrintMsg (GetSourcePos (LI), DC_WARN, Format, ap);
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
@@ -237,7 +383,7 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
if (Level <= WarnLevel) {
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, "Warning", Format, ap);
VPrintMsg (Pos, DC_WARN, Format, ap);
va_end (ap);
/* Count warnings */
@@ -274,7 +420,7 @@ void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
const LineInfo* LI = CollConstAt (LineInfos, 0);
/* Output an error for this position */
VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
VPrintMsg (GetSourcePos (LI), DC_ERR, Format, ap);
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
@@ -311,7 +457,7 @@ void PError (const FilePos* Pos, const char* Format, ...)
{
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, "Error", Format, ap);
VPrintMsg (Pos, DC_ERR, Format, ap);
va_end (ap);
/* Count errors */
@@ -365,18 +511,12 @@ void ErrorSkip (const char* Format, ...)
void Fatal (const char* Format, ...)
/* Print a message about a fatal error and die */
{
/* Output the message ... */
va_list ap;
StrBuf S = STATIC_STRBUF_INITIALIZER;
va_start (ap, Format);
SB_VPrintf (&S, Format, ap);
SB_Terminate (&S);
VPrintMsg (&CurTok.Pos, DC_FATAL, Format, ap);
va_end (ap);
fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
SB_Done (&S);
/* And die... */
exit (EXIT_FAILURE);
}

View File

@@ -72,6 +72,12 @@ extern unsigned WarningCount;
void Notification (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print a notification message. */
void PNotification (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print a notification message. */
void Warning (unsigned Level, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print warning message. */

116
src/ca65/expect.c Normal file
View File

@@ -0,0 +1,116 @@
/*****************************************************************************/
/* */
/* expect.c */
/* */
/* Print errors about expected tokens */
/* */
/* */
/* */
/* (C) 2025, Kugelfuhr */
/* */
/* */
/* 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. */
/* */
/*****************************************************************************/
/* ca65 */
#include "error.h"
#include "expect.h"
#include "nexttok.h"
#include "scanner.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ErrorExpect (const char* Msg)
/* Output an error message about some expected token using Msg and the
* description of the following token. This means that Msg should contain
* something like "xyz expected". The actual error message would then be
* "xyz expected but found zyx".
*/
{
StrBuf S = AUTO_STRBUF_INITIALIZER;
TokenDesc (&CurTok, &S);
Error ("%s but found `%s'", Msg, SB_GetConstBuf (&S));
SB_Done (&S);
}
int Expect (token_t Expected, const char* Msg)
/* Check if the next token is the expected one. If not, print Msg plus some
* information about the token that was actually found. This means that Msg
* should contain something like "xyz expected". The actual error message would
* then be "xyz expected but found zyx".
* Returns true if the token was found, otherwise false.
*/
{
if (CurTok.Tok == Expected) {
return 1;
}
ErrorExpect (Msg);
return 0;
}
int ExpectSkip (token_t Expected, const char* Msg)
/* Check if the next token is the expected one. If not, print Msg plus some
* information about the token that was actually found and skip the remainder
* of the line. This means that Msg should contain something like "xyz
* expected". The actual error message would then be "xyz expected but found
* zyx".
* Returns true if the token was found, otherwise false.
*/
{
if (CurTok.Tok == Expected) {
return 1;
}
ErrorExpect (Msg);
SkipUntilSep ();
return 0;
}
int ExpectSep (void)
/* Check if we've reached a line separator. If so, return true. If not, output
** an error and skip all tokens until the line separator is reached. Then
** return false.
*/
{
if (!TokIsSep (CurTok.Tok)) {
/* Try to be helpful by giving information about the token that was
* unexpected.
*/
ErrorExpect ("Expected `end-of-line'");
SkipUntilSep ();
return 0;
} else {
return 1;
}
}

View File

@@ -1,15 +1,12 @@
/*****************************************************************************/
/* */
/* inline.h */
/* expect.h */
/* */
/* Definitions to use the inline compiler feature */
/* Print errors about expected tokens */
/* */
/* */
/* */
/* (C) 2001-2005 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2025, Kugelfuhr */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -33,24 +30,54 @@
#ifndef INLINE_H
#define INLINE_H
#ifndef EXPECT_H
#define EXPECT_H
/* ca65 */
#include "token.h"
/*****************************************************************************/
/* Defines */
/* Code */
/*****************************************************************************/
#if defined(__GNUC__) && !defined(DISABLE_INLINE)
# define HAVE_INLINE 1
# define INLINE static __inline__
#endif
void ErrorExpect (const char* Msg);
/* Output an error message about some expected token using Msg and the
* description of the following token. This means that Msg should contain
* something like "xyz expected". The actual error message would then be
* "xyz expected but found zyx".
*/
int Expect (token_t Expected, const char* Msg);
/* Check if the next token is the expected one. If not, print Msg plus some
* information about the token that was actually found. This means that Msg
* should contain something like "xyz expected". The actual error message would
* then be "xyz expected but found zyx".
* Returns true if the token was found, otherwise false.
*/
int ExpectSkip (token_t Expected, const char* Msg);
/* Check if the next token is the expected one. If not, print Msg plus some
* information about the token that was actually found and skip the remainder
* of the line. This means that Msg should contain something like "xyz
* expected". The actual error message would then be "xyz expected but found
* zyx".
* Returns true if the token was found, otherwise false.
*/
int ExpectSep (void);
/* Check if we've reached a line separator. If so, return true. If not, output
** an error and skip all tokens until the line separator is reached. Then
** return false.
*/
/* End of inline.h */
/* End of expect.h */
#endif

View File

@@ -51,6 +51,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "global.h"
#include "instr.h"
@@ -421,8 +422,7 @@ static ExprNode* FuncCapability (void)
capability_t Cap;
/* We must have an identifier */
if (CurTok.Tok != TOK_IDENT) {
Error ("Arguments to .CAPABILITY must be identifiers");
if (!Expect (TOK_IDENT, "Expected a capability name")) {
/* Skip tokens until closing paren or end of line */
while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) {
NextTok ();
@@ -779,7 +779,7 @@ static ExprNode* FuncAddrSize (void)
/* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Unknown symbol or scope: '%m%p'", &CurTok.SVal);
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
AddrSize = Sym->AddrSize;
}
@@ -819,13 +819,13 @@ static ExprNode* FuncAddrSize (void)
if (Sym) {
AddrSize = Sym->AddrSize;
} else {
Error ("Unknown symbol or scope: '%m%p%m%p'", &ScopeName, &Name);
Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name);
}
}
if (AddrSize == 0) {
Warning (1, "Unknown address size: '%m%p%m%p'", &ScopeName, &Name);
Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name);
}
/* Free the string buffers */
@@ -860,7 +860,7 @@ static ExprNode* FuncSizeOf (void)
/* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Unknown symbol or scope: '%m%p'", &CurTok.SVal);
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
SizeSym = GetSizeOfSymbol (Sym);
}
@@ -912,7 +912,7 @@ static ExprNode* FuncSizeOf (void)
if (Sym) {
SizeSym = GetSizeOfSymbol (Sym);
} else {
Error ("Unknown symbol or scope: '%m%p%m%p'",
Error ("Unknown symbol or scope: `%m%p%m%p'",
&ScopeName, &Name);
}
}
@@ -920,7 +920,7 @@ static ExprNode* FuncSizeOf (void)
/* Check if we have a size */
if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
Error ("Size of '%m%p%m%p' is unknown", &ScopeName, &Name);
Error ("Size of `%m%p%m%p' is unknown", &ScopeName, &Name);
Size = 0;
}
@@ -942,8 +942,7 @@ static ExprNode* FuncStrAt (void)
unsigned char C = 0;
/* String constant expected */
if (CurTok.Tok != TOK_STRCON) {
Error ("String constant expected");
if (!Expect (TOK_STRCON, "Expected a string constant")) {
NextTok ();
goto ExitPoint;
}
@@ -985,9 +984,8 @@ static ExprNode* FuncStrLen (void)
int Len;
/* String constant expected */
if (CurTok.Tok != TOK_STRCON) {
if (!Expect (TOK_STRCON, "Expected a string constant")) {
Error ("String constant expected");
/* Smart error recovery */
if (CurTok.Tok != TOK_RPAREN) {
NextTok ();
@@ -1062,9 +1060,7 @@ static ExprNode* Function (ExprNode* (*F) (void))
NextTok ();
/* Expression must be enclosed in braces */
if (CurTok.Tok != TOK_LPAREN) {
Error ("'(' expected");
SkipUntilSep ();
if (!ExpectSkip (TOK_LPAREN, "Expected `('")) {
return GenLiteral0 ();
}
NextTok ();
@@ -1296,7 +1292,7 @@ static ExprNode* Factor (void)
NextTok ();
} else {
N = GenLiteral0 (); /* Dummy */
Error ("Syntax error");
ErrorExpect ("Expected an expression");
}
break;
}
@@ -1957,9 +1953,8 @@ ExprNode* GenNearAddrExpr (ExprNode* Expr)
if (IsEasyConst (Expr, &Val)) {
FreeExpr (Expr);
Expr = GenLiteralExpr (Val & 0xFFFF);
if (Val > 0xFFFF)
{
Error("Range error: constant too large for assumed near address.");
if (Val > 0xFFFF) {
Error ("Range error: constant too large for assumed near address.");
}
} else {
ExprNode* Operand = Expr;

View File

@@ -211,7 +211,7 @@ unsigned GetFileIndex (const StrBuf* Name)
/* If we don't have this index, print a diagnostic and use the main file */
if (F == 0) {
Error ("File name '%m%p' not found in file table", Name);
Error ("File name `%m%p' not found in file table", Name);
return 0;
} else {
return F->Index;
@@ -316,7 +316,7 @@ static void CreateDepFile (const char* Name, FileType Types)
/* Open the file */
FILE* F = fopen (Name, "w");
if (F == 0) {
Fatal ("Cannot open dependency file '%s': %s", Name, strerror (errno));
Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
}
/* Print the output file followed by a tab char */

View File

@@ -1961,7 +1961,7 @@ static void PutLDM_m740 (const InsDesc* Ins)
}
Emit0 (Ins->BaseCode);
EmitByte (A.Expr);
Consume (TOK_HASH, "'#' expected");
Consume (TOK_HASH, "`#' expected");
EmitByte (Expression ());
}
@@ -2091,7 +2091,7 @@ static void PutBitBranch_m740 (const InsDesc* Ins)
EffAddr A;
/* Evaluate the addressing mode used */
GetEA(&A);
GetEA (&A);
/* From the possible addressing modes, remove the ones that are invalid
** for this instruction or CPU.
@@ -2375,7 +2375,7 @@ static void PutJSR_m740 (const InsDesc* Ins)
/* direct page */
A.Opcode = 0x22;
Emit0 (A.Opcode);
EmitByte(GenByteExpr(A.Expr));
EmitByte (GenByteExpr (A.Expr));
return;
}
}

View File

@@ -316,7 +316,7 @@ void CreateListing (void)
/* Open the real listing file */
F = fopen (SB_GetConstBuf (&ListingName), "w");
if (F == 0) {
Fatal ("Cannot open listing file '%s': %s",
Fatal ("Cannot open listing file `%s': %s",
SB_GetConstBuf (&ListingName),
strerror (errno));
}

View File

@@ -45,6 +45,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "global.h"
#include "instr.h"
#include "istack.h"
@@ -102,10 +103,12 @@ struct Macro {
unsigned TokCount; /* Number of tokens for this macro */
TokNode* TokRoot; /* Root of token list */
TokNode* TokLast; /* Pointer to last token in list */
FilePos DefPos; /* Position of definition */
StrBuf Name; /* Macro name, dynamically allocated */
unsigned Expansions; /* Number of active macro expansions */
unsigned char Style; /* Macro style */
unsigned char Incomplete; /* Macro is currently built */
unsigned char HasError; /* Macro has errors */
};
/* Hash table functions */
@@ -232,7 +235,7 @@ static void FreeIdDescList (IdDesc* ID)
static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
static Macro* NewMacro (const StrBuf* Name, const FilePos* P, unsigned char Style)
/* Generate a new macro entry, initialize and return it */
{
/* Allocate memory */
@@ -247,11 +250,14 @@ static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
M->TokCount = 0;
M->TokRoot = 0;
M->TokLast = 0;
M->DefPos = *P;
SB_Init (&M->Name);
SB_Copy (&M->Name, Name);
SB_Terminate (&M->Name); /* So the name can be used with %s */
M->Expansions = 0;
M->Style = Style;
M->Incomplete = 1;
M->HasError = 0;
/* Insert the macro into the hash table */
HT_Insert (&MacroTab, &M->Node);
@@ -364,19 +370,28 @@ static void FreeMacExp (MacExp* E)
static void MacSkipDef (unsigned Style)
static void MacSkipDef (unsigned Style, const FilePos* StartPos)
/* Skip a macro definition */
{
if (Style == MAC_STYLE_CLASSIC) {
/* Skip tokens until we reach the final .endmacro */
while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
/* Skip tokens until we reach the final .endmacro. Implement the same
** behavior as when parsing the macro regularily: .endmacro needs to
** be at the start of the line to end the macro definition.
*/
int LastWasSep = 0;
while (1) {
if (CurTok.Tok == TOK_EOF) {
ErrorExpect ("Expected `.ENDMACRO'");
PNotification (StartPos, "Macro definition started here");
break;
}
if (CurTok.Tok == TOK_ENDMACRO && LastWasSep) {
NextTok ();
break;
}
LastWasSep = (CurTok.Tok == TOK_SEP);
NextTok ();
}
if (CurTok.Tok != TOK_EOF) {
SkipUntilSep ();
} else {
Error ("'.ENDMACRO' expected");
}
} else {
/* Skip until end of line */
SkipUntilSep ();
@@ -388,48 +403,49 @@ static void MacSkipDef (unsigned Style)
void MacDef (unsigned Style)
/* Parse a macro definition */
{
Macro* Existing;
Macro* M;
TokNode* N;
FilePos Pos;
int HaveParams;
int LastTokWasSep;
/* Remember the current file position */
FilePos StartPos = CurTok.Pos;
/* 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
*/
Pos = CurTok.Pos;
int LastTokWasSep = 1;
/* We expect a macro name here */
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
MacSkipDef (Style);
if (!Expect (TOK_IDENT, "Expected an identifier")) {
MacSkipDef (Style, &StartPos);
return;
} else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
}
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, &StartPos);
return;
}
/* Did we already define that macro? */
if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
Existing = HT_Find (&MacroTab, &CurTok.SVal);
if (Existing != 0) {
/* Macro is already defined */
Error ("A macro named '%m%p' is already defined", &CurTok.SVal);
Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
PNotification (&Existing->DefPos,
"Previous definition of macro `%s' was here",
SB_GetConstBuf (&Existing->Name));
/* Skip tokens until we reach the final .endmacro */
MacSkipDef (Style);
MacSkipDef (Style, &StartPos);
return;
}
/* Define the macro */
M = NewMacro (&CurTok.SVal, Style);
M = NewMacro (&CurTok.SVal, &StartPos, Style);
/* Switch to raw token mode and skip the macro name */
EnterRawTokenMode ();
@@ -439,7 +455,7 @@ void MacDef (unsigned Style)
** otherwise, we may have parameters without parentheses.
*/
if (Style == MAC_STYLE_CLASSIC) {
HaveParams = 1;
HaveParams = (CurTok.Tok != TOK_SEP);
} else {
if (CurTok.Tok == TOK_LPAREN) {
HaveParams = 1;
@@ -451,7 +467,7 @@ void MacDef (unsigned Style)
/* Parse the parameter list */
if (HaveParams) {
while (CurTok.Tok == TOK_IDENT) {
while (Expect (TOK_IDENT, "Expected a parameter name")) {
/* Create a struct holding the identifier */
IdDesc* I = NewIdDesc (&CurTok.SVal);
@@ -463,7 +479,8 @@ void MacDef (unsigned Style)
while (1) {
if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
Error ("Duplicate symbol '%m%p'", &CurTok.SVal);
Error ("Duplicate macro parameter `%m%p'", &CurTok.SVal);
M->HasError = 1;
}
if (List->Next == 0) {
break;
@@ -513,7 +530,10 @@ void MacDef (unsigned Style)
}
/* May not have end of file in a macro definition */
if (CurTok.Tok == TOK_EOF) {
PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name);
Error ("Missing `.ENDMACRO' for definition of macro `%s'",
SB_GetConstBuf (&M->Name));
PNotification (&StartPos, "Macro definition started here");
M->HasError = 1;
goto Done;
}
} else {
@@ -533,8 +553,9 @@ void MacDef (unsigned Style)
/* Need an identifer */
if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
Error ("Identifier expected");
ErrorExpect ("Expected an identifier");
SkipUntilSep ();
M->HasError = 1;
break;
}
@@ -553,7 +574,10 @@ void MacDef (unsigned Style)
}
/* We need end of line after the locals */
ConsumeSep ();
if (!ExpectSep ()) {
M->HasError = 1;
}
NextTok ();
continue;
}
@@ -591,7 +615,7 @@ void MacDef (unsigned Style)
/* Save if last token was a separator to know if .endmacro is at
** the start of a line
*/
LastTokWasSep = TokIsSep(CurTok.Tok);
LastTokWasSep = TokIsSep (CurTok.Tok);
/* Read the next token */
NextTok ();
@@ -622,11 +646,12 @@ void MacUndef (const StrBuf* Name, unsigned char Style)
/* Don't let the user kid with us */
if (M == 0 || M->Style != Style) {
Error ("No such macro: %m%p", Name);
Error ("No such macro: `%m%p'", Name);
return;
}
if (M->Expansions > 0) {
Error ("Cannot delete a macro that is currently expanded");
Error ("Cannot delete macro `%s' which is currently expanded",
SB_GetConstBuf (&M->Name));
return;
}
@@ -813,7 +838,11 @@ static void StartExpClassic (MacExp* E)
/* Check for maximum parameter count */
if (E->ParamCount >= E->M->ParamCount) {
ErrorSkip ("Too many macro parameters");
ErrorSkip ("Too many parameters for macro `%s'",
SB_GetConstBuf (&E->M->Name));
PNotification (&E->M->DefPos,
"See definition of macro `%s' which was here",
SB_GetConstBuf (&E->M->Name));
break;
}
@@ -827,7 +856,7 @@ static void StartExpClassic (MacExp* E)
/* Check for end of file */
if (CurTok.Tok == TOK_EOF) {
Error ("Unexpected end of file");
Error ("Unexpected end of file in macro parameter list");
FreeMacExp (E);
return;
}
@@ -938,10 +967,8 @@ static void StartExpDefine (MacExp* E)
/* Check for a comma */
if (Count > 0) {
if (CurTok.Tok == TOK_COMMA) {
if (Expect (TOK_COMMA, "Expected `,'")) {
NextTok ();
} else {
Error ("',' expected");
}
}
}
@@ -972,9 +999,21 @@ void MacExpandStart (Macro* M)
Pos = CurTok.Pos;
NextTok ();
/* We cannot expand a macro with errors */
if (M->HasError) {
PError (&Pos, "Macro `%s' contains errors and cannot be expanded",
SB_GetConstBuf (&M->Name));
PNotification (&M->DefPos, "Definition of macro `%s' was here",
SB_GetConstBuf (&M->Name));
return;
}
/* We cannot expand an incomplete macro */
if (M->Incomplete) {
PError (&Pos, "Cannot expand an incomplete macro");
PError (&Pos, "Macro `%s' is incomplete and cannot be expanded",
SB_GetConstBuf (&M->Name));
PNotification (&M->DefPos, "Definition of macro `%s' was here",
SB_GetConstBuf (&M->Name));
return;
}
@@ -982,7 +1021,8 @@ void MacExpandStart (Macro* M)
** to force an endless loop and assembler crash.
*/
if (MacExpansions >= MAX_MACEXPANSIONS) {
PError (&Pos, "Too many nested macro expansions");
PError (&Pos, "Too many nested macro expansions for macro `%s'",
SB_GetConstBuf (&M->Name));
return;
}

View File

@@ -42,6 +42,7 @@
#include "addrsize.h"
#include "chartype.h"
#include "cmdline.h"
#include "consprop.h"
#include "debugflag.h"
#include "mmodel.h"
#include "print.h"
@@ -56,6 +57,7 @@
#include "asserts.h"
#include "dbginfo.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "feature.h"
#include "filetab.h"
@@ -112,6 +114,7 @@ static void Usage (void)
"Long options:\n"
" --auto-import\t\t\tMark unresolved symbols as import\n"
" --bin-include-dir dir\t\tSet a search path for binary includes\n"
" --color [on|auto|off]\t\tColor diagnostics (default: auto)\n"
" --cpu type\t\t\tSet cpu type\n"
" --create-dep name\t\tCreate a make dependency file\n"
" --create-full-dep name\tCreate a full make dependency file\n"
@@ -125,13 +128,15 @@ static void Usage (void)
" --listing name\t\tCreate a listing file if assembly was ok\n"
" --list-bytes n\t\tMaximum number of bytes per listing line\n"
" --memory-model model\t\tSet the memory model\n"
" --no-utf8\t\t\tDisable use of UTF-8 in diagnostics\n"
" --pagelength n\t\tSet the page length for the listing\n"
" --relax-checks\t\tRelax some checks (see docs)\n"
" --segment-list\t\tEnable segment offset listing\n"
" --smart\t\t\tEnable smart mode\n"
" --target sys\t\t\tSet the target system\n"
" --verbose\t\t\tIncrease verbosity\n"
" --version\t\t\tPrint the assembler version\n",
" --version\t\t\tPrint the assembler version\n"
" --warnings-as-errors\t\tTreat warnings as errors\n",
ProgName);
}
@@ -147,7 +152,7 @@ static void SetOptions (void)
OptTranslator (&Buf);
/* Set date and time */
OptDateTime ((unsigned long) time(0));
OptDateTime ((unsigned long) time (0));
/* Release memory for the string */
SB_Done (&Buf);
@@ -494,6 +499,22 @@ static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char*
static void OptColor(const char* Opt, const char* Arg)
/* Handle the --color option */
{
if (strcmp (Arg, "off") == 0 || strcmp (Arg, "false") == 0) {
CP_SetColorMode (CM_OFF);
} else if (strcmp (Arg, "auto") == 0) {
CP_SetColorMode (CM_AUTO);
} else if (strcmp (Arg, "on") == 0 || strcmp (Arg, "true") == 0) {
CP_SetColorMode (CM_ON);
} else {
AbEnd ("Invalid argument to %s: %s", Opt, Arg);
}
}
static void OptCPU (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --cpu option */
{
@@ -624,7 +645,7 @@ static void OptListing (const char* Opt, const char* Arg)
** the filename is empty or begins with the option char.
*/
if (Arg == 0 || *Arg == '\0' || *Arg == '-') {
Fatal ("The meaning of '%s' has changed. It does now "
Fatal ("The meaning of `%s' has changed. It does now "
"expect a file name as argument.", Opt);
}
@@ -658,6 +679,15 @@ static void OptMemoryModel (const char* Opt, const char* Arg)
static void OptNoUtf8 (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --no-utf8 option */
{
CP_DisableUTF8 ();
}
static void OptPageLength (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --pagelength option */
{
@@ -710,7 +740,7 @@ static void OptVersion (const char* Opt attribute ((unused)),
/* Print the assembler version */
{
fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
exit(EXIT_SUCCESS);
exit (EXIT_SUCCESS);
}
static void OptSeglist (const char* Opt attribute ((unused)),
@@ -734,7 +764,7 @@ static void DoPCAssign (void)
{
long PC = ConstExpression ();
if (PC < 0 || PC > 0xFFFFFF) {
Error ("Range error");
Error ("Program counter value is out of valid range");
} else {
EnterAbsoluteMode (PC);
}
@@ -778,7 +808,7 @@ static void OneLine (void)
if (CurTok.Tok == TOK_COLON) {
NextTok ();
} else if (CurTok.WS || !NoColonLabels) {
Error ("':' expected");
Error ("`:' expected");
}
}
@@ -827,11 +857,10 @@ static void OneLine (void)
NextTok ();
/* Define the symbol with the expression following the '=' */
SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
SymDef (Sym, Expression (), ADDR_SIZE_DEFAULT, Flags);
/* Don't allow anything after a symbol definition */
ConsumeSep ();
return;
goto Done;
} else if (CurTok.Tok == TOK_SET) {
@@ -849,8 +878,7 @@ static void OneLine (void)
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
/* Don't allow anything after a symbol definition */
ConsumeSep ();
return;
goto Done;
} else {
@@ -860,26 +888,24 @@ static void OneLine (void)
Seg = ActiveSeg;
PC = GetPC ();
/* Define the label */
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
/* Skip the colon. If NoColonLabels is enabled, allow labels
** without a colon if there is no whitespace before the
** identifier.
*/
if (CurTok.Tok != TOK_COLON) {
if (HadWS || !NoColonLabels) {
Error ("':' expected");
/* Try some smart error recovery */
if (CurTok.Tok == TOK_NAMESPACE) {
NextTok ();
}
ErrorExpect ("Expected `:' after identifier to form a label");
SkipUntilSep ();
goto Done;
}
} else {
/* Skip the colon */
NextTok ();
}
/* Define the label */
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
/* If we come here, a new identifier may be waiting, which may
** be a macro or instruction.
*/
@@ -913,17 +939,23 @@ static void OneLine (void)
HandleInstruction (Instr);
} else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) {
NextTok ();
if (CurTok.Tok != TOK_EQ) {
Error ("'=' expected");
SkipUntilSep ();
} else {
/* Skip the equal sign */
NextTok ();
/* Enter absolute mode */
DoPCAssign ();
if (!ExpectSkip (TOK_EQ, "Expected `='")) {
goto Done;
}
/* Skip the equal sign */
NextTok ();
/* Enter absolute mode */
DoPCAssign ();
} else if ((CurTok.Tok >= TOK_FIRSTOP && CurTok.Tok <= TOK_LASTOP) ||
(CurTok.Tok >= TOK_FIRSTREG && CurTok.Tok <= TOK_LASTREG) ||
CurTok.Tok == TOK_INTCON || CurTok.Tok == TOK_CHARCON ||
CurTok.Tok == TOK_STRCON) {
ErrorExpect ("Expected a mnemonic");
SkipUntilSep ();
goto Done;
}
/* If we have defined a label, remember its size. Sym is also set by
** a symbol assignment, but in this case Done is false, so we don't
** come here.
@@ -945,6 +977,7 @@ static void OneLine (void)
}
}
Done:
/* Line separator must come here */
ConsumeSep ();
}
@@ -1017,6 +1050,7 @@ int main (int argc, char* argv [])
static const LongOpt OptTab[] = {
{ "--auto-import", 0, OptAutoImport },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--color", 1, OptColor },
{ "--cpu", 1, OptCPU },
{ "--create-dep", 1, OptCreateDep },
{ "--create-full-dep", 1, OptCreateFullDep },
@@ -1030,6 +1064,7 @@ int main (int argc, char* argv [])
{ "--list-bytes", 1, OptListBytes },
{ "--listing", 1, OptListing },
{ "--memory-model", 1, OptMemoryModel },
{ "--no-utf8", 0, OptNoUtf8 },
{ "--pagelength", 1, OptPageLength },
{ "--relax-checks", 0, OptRelaxChecks },
{ "--segment-list", 0, OptSeglist },
@@ -1045,6 +1080,9 @@ int main (int argc, char* argv [])
unsigned I;
/* Initialize console output */
CP_Init ();
/* Initialize the cmdline module */
InitCmdLine (&argc, &argv, "ca65");
@@ -1247,7 +1285,7 @@ int main (int argc, char* argv [])
}
if (WarningCount > 0 && WarningsAsErrors) {
Error("Warnings as errors");
Error ("Warnings as errors");
}
/* If we didn't have an errors, finish off the line infos */

View File

@@ -44,6 +44,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "global.h"
#include "scanner.h"
@@ -179,7 +180,7 @@ static void FuncConcat (void)
** by the string token just created.
*/
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = TOK_STRCON;
SB_Copy (&CurTok.SVal, &Buf);
@@ -253,7 +254,7 @@ static void FuncIdent (void)
SB_Copy (&Buf, &CurTok.SVal);
NextTok ();
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = Id;
SB_Copy (&CurTok.SVal, &Buf);
@@ -600,7 +601,7 @@ static void FuncSPrintF (void)
** by the string token just created.
*/
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = TOK_STRCON;
SB_Copy (&CurTok.SVal, &R);
@@ -660,7 +661,7 @@ static void FuncString (void)
** by the string token just created.
*/
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = TOK_STRCON;
SB_Copy (&CurTok.SVal, &Buf);
@@ -725,52 +726,65 @@ void NextTok (void)
void Consume (token_t Expected, const char* ErrMsg)
/* Consume Expected, print an error if we don't find it */
int Consume (token_t Expected, const char* ErrMsg)
/* Consume Token, print an error if we don't find it. Return true if the token
** was found and false otherwise.
*/
{
if (CurTok.Tok == Expected) {
if (Expect (Expected, ErrMsg)) {
NextTok ();
return 1;
} else {
Error ("%s", ErrMsg);
return 0;
}
}
void ConsumeSep (void)
/* Consume a separator token */
int ConsumeSep (void)
/* Consume a separator token. Return true if the token was found and false
* otherwise.
*/
{
/* We expect a separator token */
ExpectSep ();
int Found = ExpectSep ();
/* If we are at end of line, skip it */
if (CurTok.Tok == TOK_SEP) {
NextTok ();
}
return Found;
}
void ConsumeLParen (void)
/* Consume a left paren */
int ConsumeLParen (void)
/* Consume a left paren. Return true if the token was found and false
** otherwise.
*/
{
Consume (TOK_LPAREN, "'(' expected");
return Consume (TOK_LPAREN, "Expected `('");
}
void ConsumeRParen (void)
/* Consume a right paren */
int ConsumeRParen (void)
/* Consume a right paren. Return true if the token was found and false
** otherwise.
*/
{
Consume (TOK_RPAREN, "')' expected");
return Consume (TOK_RPAREN, "Expected `)'");
}
void ConsumeComma (void)
/* Consume a comma */
int ConsumeComma (void)
/* Consume a comma. Return true if the token was found and false
** otherwise.
*/
{
Consume (TOK_COMMA, "',' expected");
return Consume (TOK_COMMA, "Expected `,'");
}
@@ -785,18 +799,6 @@ void SkipUntilSep (void)
void ExpectSep (void)
/* Check if we've reached a line separator, and output an error if not. Do
** not skip the line separator.
*/
{
if (!TokIsSep (CurTok.Tok)) {
ErrorSkip ("Unexpected trailing garbage characters");
}
}
void EnterRawTokenMode (void)
/* Enter raw token mode. In raw mode, token handling functions are not
** executed, but the function tokens are passed untouched to the upper

View File

@@ -51,29 +51,34 @@
void NextTok (void);
/* Get next token and handle token level functions */
void Consume (token_t Expected, const char* ErrMsg);
/* Consume Token, print an error if we don't find it */
int Consume (token_t Expected, const char* ErrMsg);
/* Consume Token, print an error if we don't find it. Return true if the token
** was found and false otherwise.
*/
void ConsumeSep (void);
/* Consume a separator token */
int ConsumeSep (void);
/* Consume a separator token. Return true if the token was found and false
* otherwise.
*/
void ConsumeLParen (void);
/* Consume a left paren */
int ConsumeLParen (void);
/* Consume a left paren. Return true if the token was found and false
** otherwise.
*/
void ConsumeRParen (void);
/* Consume a right paren */
int ConsumeRParen (void);
/* Consume a right paren. Return true if the token was found and false
** otherwise.
*/
void ConsumeComma (void);
/* Consume a comma */
int ConsumeComma (void);
/* Consume a comma. Return true if the token was found and false
** otherwise.
*/
void SkipUntilSep (void);
/* Skip tokens until we reach a line separator or end of file */
void ExpectSep (void);
/* Check if we've reached a line separator, and output an error if not. Do
** not skip the line separator.
*/
void EnterRawTokenMode (void);
/* Enter raw token mode. In raw mode, token handling functions are not
** executed, but the function tokens are passed untouched to the upper

View File

@@ -113,7 +113,7 @@ static void ObjWriteError (void)
remove (OutFile);
/* Now abort with a fatal error */
Fatal ("Cannot write to output file '%s': %s", OutFile, strerror (Error));
Fatal ("Cannot write to output file `%s': %s", OutFile, strerror (Error));
}
@@ -170,7 +170,7 @@ void ObjOpen (void)
/* Create the output file */
F = fopen (OutFile, "w+b");
if (F == 0) {
Fatal ("Cannot open output file '%s': %s", OutFile, strerror (errno));
Fatal ("Cannot open output file `%s': %s", OutFile, strerror (errno));
}
/* Write a dummy header */

View File

@@ -60,6 +60,7 @@
#include "dbginfo.h"
#include "enum.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "feature.h"
#include "filetab.h"
@@ -167,13 +168,17 @@ static void SetBoolOption (unsigned char* Flag)
switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
case 0: *Flag = 0; NextTok (); break;
case 1: *Flag = 1; NextTok (); break;
default: ErrorSkip ("'on' or 'off' expected"); break;
default:
ErrorExpect ("Expected ON or OFF");
SkipUntilSep ();
break;
}
} else if (TokIsSep (CurTok.Tok)) {
/* Without anything assume switch on */
*Flag = 1;
} else {
ErrorSkip ("'on' or 'off' expected");
ErrorExpect ("Expected ON or OFF");
SkipUntilSep ();
}
}
@@ -216,8 +221,7 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
while (1) {
/* We need an identifier here */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
@@ -283,7 +287,7 @@ static void ConDes (const StrBuf* Name, unsigned Type)
Prio = ConstExpression ();
if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) {
/* Value out of range */
Error ("Range error");
Error ("Given priority is out of range");
return;
}
} else {
@@ -333,7 +337,7 @@ static StrBuf* GenArrayType (StrBuf* Type, unsigned SpanSize,
static void DoA16 (void)
/* Switch the accu to 16 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has two extension bytes */
@@ -346,7 +350,7 @@ static void DoA16 (void)
static void DoA8 (void)
/* Switch the accu to 8 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has one extension byte */
@@ -400,7 +404,7 @@ static void DoAlign (void)
/* Read the alignment value */
Alignment = ConstExpression ();
if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) {
ErrorSkip ("Range error");
ErrorSkip ("Alignment is out of range");
return;
}
@@ -410,7 +414,7 @@ static void DoAlign (void)
FillVal = ConstExpression ();
/* We need a byte value here */
if (!IsByteRange (FillVal)) {
ErrorSkip ("Range error");
ErrorSkip ("Fill value is not in byte range");
return;
}
} else {
@@ -428,8 +432,7 @@ static void DoASCIIZ (void)
{
while (1) {
/* Must have a string constant */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
@@ -463,11 +466,10 @@ static void DoAssert (void)
/* First we have the expression that has to evaluated */
ExprNode* Expr = Expression ();
ConsumeComma ();
/* Action follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
/* Followed by comma and action */
if (!ConsumeComma () || !Expect (TOK_IDENT, "Expected an identifier")) {
SkipUntilSep ();
return;
}
switch (GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]))) {
@@ -496,9 +498,8 @@ static void DoAssert (void)
default:
Error ("Illegal assert action specifier");
/* Use lderror - there won't be an .o file anyway */
Action = ASSERT_ACT_LDERROR;
break;
SkipUntilSep ();
return;
}
NextTok ();
@@ -512,8 +513,7 @@ static void DoAssert (void)
NextTok ();
/* Read the message */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
@@ -642,20 +642,23 @@ static void DoCharMap (void)
/* Read the index as numerical value */
Index = ConstExpression ();
if (Index < 0 || Index > 255) {
if (IsByteRange (Index)) {
/* Value out of range */
ErrorSkip ("Index range error");
ErrorSkip ("Index must be in byte range");
return;
}
/* Comma follows */
ConsumeComma ();
if (!ConsumeComma ()) {
SkipUntilSep ();
return;
}
/* Read the character code */
Code = ConstExpression ();
if (Code < 0 || Code > 255) {
if (!IsByteRange (Code)) {
/* Value out of range */
ErrorSkip ("Code range error");
ErrorSkip ("Replacement character code must be in byte range");
return;
}
@@ -685,15 +688,17 @@ static void DoConDes (void)
long Type;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
NextTok ();
/* Type follows. May be encoded as identifier or numerical */
ConsumeComma ();
if (!ConsumeComma ()) {
SkipUntilSep ();
goto ExitPoint;
}
if (CurTok.Tok == TOK_IDENT) {
/* Map the following keyword to a number, then skip it */
@@ -702,7 +707,8 @@ static void DoConDes (void)
/* Check if we got a valid keyword */
if (Type < 0) {
ErrorSkip ("Syntax error");
ErrorExpect ("Expected CONSTRUCTOR, DESTRUCTOR or INTERRUPTOR");
SkipUntilSep ();
goto ExitPoint;
}
@@ -712,7 +718,7 @@ static void DoConDes (void)
Type = ConstExpression ();
if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
/* Value out of range */
ErrorSkip ("Range error");
ErrorSkip ("Numeric condes type is out of range");
goto ExitPoint;
}
@@ -734,8 +740,7 @@ static void DoConstructor (void)
StrBuf Name = STATIC_STRBUF_INITIALIZER;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -771,8 +776,7 @@ static void DoDbg (void)
/* We expect a subkey */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
@@ -788,7 +792,10 @@ static void DoDbg (void)
case 1: DbgInfoFunc (); break;
case 2: DbgInfoLine (); break;
case 3: DbgInfoSym (); break;
default: ErrorSkip ("Syntax error"); break;
default:
ErrorExpect ("Expected FILE, FUNC, LINE or SYM");
SkipUntilSep ();
break;
}
}
@@ -853,9 +860,7 @@ static void DoDelMac (void)
/* Delete a classic macro */
{
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
MacUndef (&CurTok.SVal, MAC_STYLE_CLASSIC);
NextTok ();
}
@@ -869,8 +874,7 @@ static void DoDestructor (void)
StrBuf Name = STATIC_STRBUF_INITIALIZER;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -938,9 +942,7 @@ static void DoEndScope (void)
static void DoError (void)
/* User error */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
Error ("User error: %m%p", &CurTok.SVal);
SkipUntilSep ();
}
@@ -1010,9 +1012,7 @@ static void DoFarAddr (void)
static void DoFatal (void)
/* Fatal user error */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
Fatal ("User error: %m%p", &CurTok.SVal);
SkipUntilSep ();
}
@@ -1030,22 +1030,22 @@ static void DoFeature (void)
while (1) {
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
/* Make the string attribute lower case */
LocaseSVal ();
Feature = FindFeature(&CurTok.SVal);
Feature = FindFeature (&CurTok.SVal);
if (Feature == FEAT_UNKNOWN) {
/* Not found */
ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal);
ErrorSkip ("Invalid feature: `%m%p'", &CurTok.SVal);
return;
}
if (Feature == FEAT_ADDRSIZE) {
Warning (1, "Deprecated feature: '.feature addrsize'. Pseudo function .addrsize is always available.");
Warning (1, "Deprecated feature `addrsize'");
Notification ("Pseudo function `.addrsize' is always available");
}
NextTok ();
@@ -1053,7 +1053,7 @@ static void DoFeature (void)
/* Optional +/- or ON/OFF */
On = 1;
if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) {
SetBoolOption(&On);
SetBoolOption (&On);
}
/* Apply feature setting. */
@@ -1087,19 +1087,17 @@ static void DoFileOpt (void)
OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
if (OptNum < 0) {
/* Not found */
ErrorSkip ("File option keyword expected");
ErrorExpect ("Expected a file option keyword");
SkipUntilSep ();
return;
}
/* Skip the keyword */
NextTok ();
/* Must be followed by a comma */
ConsumeComma ();
/* We accept only string options for now */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
/* Must be followed by a comma and a string option */
if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) {
SkipUntilSep ();
return;
}
@@ -1134,16 +1132,13 @@ static void DoFileOpt (void)
/* Option given as number */
OptNum = ConstExpression ();
if (!IsByteRange (OptNum)) {
ErrorSkip ("Range error");
ErrorSkip ("Option number must be in byte range");
return;
}
/* Must be followed by a comma */
ConsumeComma ();
/* We accept only string options for now */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
/* Must be followed by a comma plus a string constant */
if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) {
SkipUntilSep ();
return;
}
@@ -1198,7 +1193,7 @@ static void DoHiBytes (void)
static void DoI16 (void)
/* Switch the index registers to 16 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has two extension bytes */
@@ -1211,7 +1206,7 @@ static void DoI16 (void)
static void DoI8 (void)
/* Switch the index registers to 16 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has one extension byte */
@@ -1248,8 +1243,7 @@ static void DoIncBin (void)
FILE* F;
/* Name must follow */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -1277,7 +1271,7 @@ static void DoIncBin (void)
char* PathName = SearchFile (BinSearchPath, SB_GetConstBuf (&Name));
if (PathName == 0 || (F = fopen (PathName, "rb")) == 0) {
/* Not found or cannot open, print an error and bail out */
ErrorSkip ("Cannot open include file '%m%p': %s", &Name, strerror (errno));
ErrorSkip ("Cannot open include file `%m%p': %s", &Name, strerror (errno));
xfree (PathName);
goto ExitPoint;
}
@@ -1303,7 +1297,7 @@ static void DoIncBin (void)
*/
SB_Terminate (&Name);
if (FileStat (SB_GetConstBuf (&Name), &StatBuf) != 0) {
Fatal ("Cannot stat input file '%m%p': %s", &Name, strerror (errno));
Fatal ("Cannot stat input file `%m%p': %s", &Name, strerror (errno));
}
/* Add the file to the input file table */
@@ -1314,13 +1308,16 @@ static void DoIncBin (void)
Count = Size - Start;
if (Count < 0) {
/* Nothing to read - flag this as a range error */
ErrorSkip ("Range error");
ErrorSkip ("Start offset is larger than file size");
goto Done;
}
} else {
/* Count was given, check if it is valid */
if (Start + Count > Size) {
ErrorSkip ("Range error");
if (Start > Size) {
ErrorSkip ("Start offset is larger than file size");
goto Done;
} else if (Start + Count > Size) {
ErrorSkip ("Not enough bytes left in file at offset %ld", Start);
goto Done;
}
}
@@ -1340,7 +1337,7 @@ static void DoIncBin (void)
size_t BytesRead = fread (Buf, 1, BytesToRead, F);
if (BytesToRead != BytesRead) {
/* Some sort of error */
ErrorSkip ("Cannot read from include file '%m%p': %s",
ErrorSkip ("Cannot read from include file `%m%p': %s",
&Name, strerror (errno));
break;
}
@@ -1367,9 +1364,7 @@ static void DoInclude (void)
/* Include another file */
{
/* Name must follow */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
SB_Terminate (&CurTok.SVal);
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
/* Error opening the file, skip remainder of line */
@@ -1386,8 +1381,7 @@ static void DoInterruptor (void)
StrBuf Name = STATIC_STRBUF_INITIALIZER;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -1474,9 +1468,7 @@ static void DoListBytes (void)
static void DoLocalChar (void)
/* Define the character that starts local labels */
{
if (CurTok.Tok != TOK_CHARCON) {
ErrorSkip ("Character constant expected");
} else {
if (ExpectSkip (TOK_CHARCON, "Expected a character constant")) {
if (CurTok.IVal != '@' && CurTok.IVal != '?') {
Error ("Invalid start character for locals");
} else {
@@ -1492,15 +1484,14 @@ static void DoMacPack (void)
/* Insert a macro package */
{
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
SB_AppendStr (&CurTok.SVal, ".mac");
SB_Terminate (&CurTok.SVal);
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
/* Error opening the file, skip remainder of line */
SkipUntilSep ();
}
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_AppendStr (&CurTok.SVal, ".mac");
SB_Terminate (&CurTok.SVal);
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
/* Error opening the file, skip remainder of line */
SkipUntilSep ();
}
}
@@ -1538,12 +1529,10 @@ static void DoOrg (void)
static void DoOut (void)
/* Output a string */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
/* Output the string and be sure to flush the output to keep it in
** sync with any error messages if the output is redirected to a file.
*/
* sync with any error messages if the output is redirected to a file.
*/
printf ("%.*s\n",
(int) SB_GetLen (&CurTok.SVal),
SB_GetConstBuf (&CurTok.SVal));
@@ -1835,7 +1824,7 @@ static void DoRes (void)
Count = ConstExpression ();
if (Count > 0xFFFF || Count < 0) {
ErrorSkip ("Range error");
ErrorSkip ("Invalid number of bytes specified");
return;
}
if (CurTok.Tok == TOK_COMMA) {
@@ -1843,7 +1832,7 @@ static void DoRes (void)
Val = ConstExpression ();
/* We need a byte value here */
if (!IsByteRange (Val)) {
ErrorSkip ("Range error");
ErrorSkip ("Fill value is not in byte range");
return;
}
@@ -1903,12 +1892,10 @@ static void DoScope (void)
static void DoSegment (void)
/* Switch to another segment */
{
StrBuf Name = STATIC_STRBUF_INITIALIZER;
SegDef Def;
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
SegDef Def;
StrBuf Name = AUTO_STRBUF_INITIALIZER;
/* Save the name of the segment and skip it */
SB_Copy (&Name, &CurTok.SVal);
@@ -1923,10 +1910,10 @@ static void DoSegment (void)
/* Set the segment */
UseSeg (&Def);
}
/* Free memory for Name */
SB_Done (&Name);
/* Free memory for Name */
SB_Done (&Name);
}
}
@@ -1935,9 +1922,7 @@ static void DoSetCPU (void)
/* Switch the CPU instruction set */
{
/* We expect an identifier */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
cpu_t CPU;
/* Try to find the CPU */
@@ -1948,8 +1933,8 @@ static void DoSetCPU (void)
SetCPU (CPU);
/* Skip the identifier. If the CPU switch was successful, the scanner
** will treat the input now correctly for the new CPU.
*/
* will treat the input now correctly for the new CPU.
*/
NextTok ();
}
}
@@ -2024,9 +2009,7 @@ static void DoUnDef (void)
EnableDefineStyleMacros ();
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
MacUndef (&CurTok.SVal, MAC_STYLE_DEFINE);
NextTok ();
}
@@ -2037,7 +2020,7 @@ static void DoUnDef (void)
static void DoUnexpected (void)
/* Got an unexpected keyword */
{
Error ("Unexpected '%m%p'", &Keyword);
Error ("Unexpected `%m%p'", &Keyword);
SkipUntilSep ();
}
@@ -2046,9 +2029,7 @@ static void DoUnexpected (void)
static void DoWarning (void)
/* User warning */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
Warning (0, "User warning: %m%p", &CurTok.SVal);
SkipUntilSep ();
}
@@ -2255,7 +2236,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoUnexpected }, /* .REF, .REFERENCED */
{ ccNone, DoReferTo }, /* .REFTO, .REFERTO */
{ ccNone, DoReloc }, /* .RELOC */
{ ccNone, DoRepeat }, /* .REPEAT */
{ ccKeepToken, DoRepeat }, /* .REPEAT */
{ ccNone, DoRes }, /* .RES */
{ ccNone, DoInvalid }, /* .RIGHT */
{ ccNone, DoROData }, /* .RODATA */

View File

@@ -40,6 +40,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "nexttok.h"
#include "toklist.h"
@@ -53,7 +54,7 @@
static TokList* CollectRepeatTokens (void)
static TokList* CollectRepeatTokens (const FilePos* StartPos)
/* Collect all tokens inside the .REPEAT body in a token list and return
** this list. In case of errors, NULL is returned.
*/
@@ -67,7 +68,8 @@ static TokList* CollectRepeatTokens (void)
/* Check for end of input */
if (CurTok.Tok == TOK_EOF) {
Error ("Unexpected end of file");
ErrorExpect ("Expected `.ENDREPEAT'");
PNotification (StartPos, "For this `.REPEAT' command");
FreeTokList (List);
return 0;
}
@@ -117,10 +119,14 @@ void ParseRepeat (void)
char* Name;
TokList* List;
/* Remember the position of the .REPEAT token, then skip it */
FilePos StartPos = CurTok.Pos;
NextTok ();
/* Repeat count follows */
long RepCount = ConstExpression ();
if (RepCount < 0) {
Error ("Range error");
Error ("Repeat count must be positive or zero");
RepCount = 0;
}
@@ -132,9 +138,7 @@ void ParseRepeat (void)
NextTok ();
/* Check for an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
/* Remember the name and skip it */
SB_Terminate (&CurTok.SVal);
Name = xstrdup (SB_GetConstBuf (&CurTok.SVal));
@@ -147,7 +151,7 @@ void ParseRepeat (void)
ConsumeSep ();
/* Read the token list */
List = CollectRepeatTokens ();
List = CollectRepeatTokens (&StartPos);
/* If we had an error, bail out */
if (List == 0) {

View File

@@ -52,6 +52,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "filetab.h"
#include "global.h"
#include "incpath.h"
@@ -545,7 +546,7 @@ int NewInputFile (const char* Name)
/* Main file */
F = fopen (Name, "r");
if (F == 0) {
Fatal ("Cannot open input file '%s': %s", Name, strerror (errno));
Fatal ("Cannot open input file `%s': %s", Name, strerror (errno));
}
} else {
/* We are on include level. Search for the file in the include
@@ -554,7 +555,7 @@ int NewInputFile (const char* Name)
PathName = SearchFile (IncSearchPath, Name);
if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
/* Not found or cannot open, print an error and bail out */
Error ("Cannot open include file '%s': %s", Name, strerror (errno));
Error ("Cannot open include file `%s': %s", Name, strerror (errno));
goto ExitPoint;
}
@@ -571,7 +572,7 @@ int NewInputFile (const char* Name)
** here.
*/
if (FileStat (Name, &Buf) != 0) {
Fatal ("Cannot stat input file '%s': %s", Name, strerror (errno));
Fatal ("Cannot stat input file `%s': %s", Name, strerror (errno));
}
/* Add the file to the input file table and remember the index */
@@ -818,7 +819,7 @@ static void ReadStringConst (int StringTerm)
int Cooked = 1;
NeedNext = 1;
if (StringTerm == 0 && SB_GetLen(&CurTok.SVal) == 1) {
if (StringTerm == 0 && SB_GetLen (&CurTok.SVal) == 1) {
if (C == '\'') {
break;
}
@@ -901,12 +902,12 @@ static void ReadStringConst (int StringTerm)
case '7':
{ /* brace needed for scoping */
int Count = 1;
int Final = DigitVal(C);
int Final = DigitVal (C);
Cooked = 0;
NextChar ();
while (IsODigit (C) && Count++ < 3) {
Final = (Final << 3) | DigitVal(C);
NextChar();
Final = (Final << 3) | DigitVal (C);
NextChar ();
}
if (C >= 256)
Error ("Octal character constant out of range");
@@ -1196,7 +1197,7 @@ Again:
/* Not found */
if (!LeadingDotInIdents) {
/* Invalid pseudo instruction */
Error ("'%m%p' is not a recognized control command", &CurTok.SVal);
Error ("`%m%p' is not a recognized control command", &CurTok.SVal);
goto Again;
}
@@ -1587,8 +1588,8 @@ CharAgain:
/* Always a character constant
** Hack: Pass 0 to ReadStringConst for special handling.
*/
ReadStringConst(0);
if (SB_GetLen(&CurTok.SVal) != 1) {
ReadStringConst (0);
if (SB_GetLen (&CurTok.SVal) != 1) {
Error ("Illegal character constant");
goto CharAgain;
}
@@ -1686,14 +1687,14 @@ unsigned char ParseAddrSize (void)
/* Check for an identifier */
if (CurTok.Tok != TOK_IDENT) {
Error ("Address size specifier expected");
ErrorExpect ("Expected an address size specifier");
return ADDR_SIZE_DEFAULT;
}
/* Convert the attribute */
AddrSize = AddrSizeFromStr (SB_GetConstBuf (&CurTok.SVal));
if (AddrSize == ADDR_SIZE_INVALID) {
Error ("Address size specifier expected");
ErrorExpect ("Expected an address size specifier");
AddrSize = ADDR_SIZE_DEFAULT;
}

View File

@@ -134,7 +134,7 @@ static Segment* NewSegment (const char* Name, unsigned char AddrSize)
/* Check the segment name for invalid names */
if (!ValidSegName (Name)) {
Error ("Illegal segment name: '%s'", Name);
Error ("Illegal segment name: `%s'", Name);
}
/* Create a new segment and return it */

View File

@@ -41,7 +41,6 @@
/* common */
#include "coll.h"
#include "fragdefs.h"
#include "inline.h"
/* ca65 */
#include "fragment.h"
@@ -102,35 +101,23 @@ void ListSegments (FILE* destination);
void UseSeg (const SegDef* D);
/* Use the given segment */
#if defined(HAVE_INLINE)
INLINE const SegDef* GetCurrentSegDef (void)
static inline const SegDef* GetCurrentSegDef (void)
/* Get a pointer to the segment defininition of the current segment */
{
return ActiveSeg->Def;
}
#else
# define GetCurrentSegDef() (ActiveSeg->Def)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned GetCurrentSegNum (void)
static inline unsigned GetCurrentSegNum (void)
/* Get the number of the current segment */
{
return ActiveSeg->Num;
}
#else
# define GetCurrentSegNum() (ActiveSeg->Num)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned char GetCurrentSegAddrSize (void)
static inline unsigned char GetCurrentSegAddrSize (void)
/* Get the address size of the current segment */
{
return ActiveSeg->Def->AddrSize;
}
#else
# define GetCurrentSegAddrSize() (ActiveSeg->Def->AddrSize)
#endif
void SegAlign (unsigned long Alignment, int FillVal);
/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments

View File

@@ -42,7 +42,6 @@
#include "coll.h"
#include "gentype.h"
#include "hashtab.h"
#include "inline.h"
#include "strbuf.h"
@@ -75,15 +74,11 @@ struct Span{
#if defined(HAVE_INLINE)
INLINE unsigned long GetSpanSize (const Span* R)
static inline unsigned long GetSpanSize (const Span* R)
/* Return the span size in bytes */
{
return (R->End - R->Start);
}
#else
# define GetSpanSize(R) ((R)->End - (R)->Start)
#endif
void SetSpanType (Span* S, const StrBuf* Type);
/* Set the generic type of the span to Type */

View File

@@ -63,45 +63,29 @@ extern StringPool* StrPool;
#if defined(HAVE_INLINE)
INLINE unsigned GetStrBufId (const StrBuf* S)
static inline unsigned GetStrBufId (const StrBuf* S)
/* Return the id of the given string buffer */
{
return SP_Add (StrPool, S);
}
#else
# define GetStrBufId(S) SP_Add (StrPool, (S))
#endif
#if defined(HAVE_INLINE)
INLINE unsigned GetStringId (const char* S)
static inline unsigned GetStringId (const char* S)
/* Return the id of the given string */
{
return SP_AddStr (StrPool, S);
}
#else
# define GetStringId(S) SP_AddStr (StrPool, (S))
#endif
#if defined(HAVE_INLINE)
INLINE const StrBuf* GetStrBuf (unsigned Index)
static inline const StrBuf* GetStrBuf (unsigned Index)
/* Convert a string index into a string */
{
return SP_Get (StrPool, Index);
}
#else
# define GetStrBuf(Index) SP_Get (StrPool, (Index))
#endif
#if defined(HAVE_INLINE)
INLINE const char* GetString (unsigned Index)
static inline const char* GetString (unsigned Index)
/* Convert a string index into a string */
{
return SB_GetConstBuf (SP_Get (StrPool, Index));
}
#else
# define GetString(Index) SB_GetConstBuf (SP_Get (StrPool, (Index)))
#endif
void WriteStrPool (void);
/* Write the string pool to the object file */

View File

@@ -39,6 +39,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "macro.h"
#include "nexttok.h"
@@ -105,14 +106,21 @@ static long DoStructInternal (long Offs, unsigned Type)
** union, the struct may be anonymous; in which case, no new lexical level
** is started.
*/
int Anon = (CurTok.Tok != TOK_IDENT);
int Anon = (CurTok.Tok == TOK_SEP);
if (!Anon) {
/* Enter a new scope, then skip the name */
SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
NextTok ();
/* Start at zero offset in the new scope */
Offs = 0;
/* Non anonymous structs must have an identifier as name */
if (Expect (TOK_IDENT, "Expected a struct/union name")) {
/* Enter a new scope, then skip the name */
SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
NextTok ();
/* Start at zero offset in the new scope */
Offs = 0;
} else {
/* Skip the junk on the line before proceeding */
SkipUntilSep ();
Anon = 1;
}
}
/* Test for end of line */
@@ -183,7 +191,7 @@ static long DoStructInternal (long Offs, unsigned Type)
case TOK_RES:
NextTok ();
if (CurTok.Tok == TOK_SEP) {
ErrorSkip ("Size is missing");
ErrorExpect ("Expected a byte count");
} else {
MemberSize = Member (1);
}
@@ -192,7 +200,7 @@ static long DoStructInternal (long Offs, unsigned Type)
case TOK_ORG:
NextTok ();
if (CurTok.Tok == TOK_SEP) {
ErrorSkip ("Address is missing");
ErrorExpect ("Expected an address");
} else {
Offs = ConstExpression ();
@@ -233,7 +241,12 @@ static long DoStructInternal (long Offs, unsigned Type)
default:
if (!CheckConditionals ()) {
/* Not a conditional directive */
ErrorSkip ("Invalid storage allocator in struct/union");
if (Sym) {
ErrorExpect ("Expected a storage allocator after the field name");
} else {
ErrorExpect ("Expected a storage allocator");
}
SkipUntilSep ();
}
}
@@ -275,9 +288,9 @@ static long DoStructInternal (long Offs, unsigned Type)
/* End of struct/union definition */
if (Type == STRUCT) {
Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected");
Consume (TOK_ENDSTRUCT, "Expected `.ENDSTRUCT'");
} else {
Consume (TOK_ENDUNION, "'.ENDUNION' expected");
Consume (TOK_ENDUNION, "Expected `.ENDUNION'");
}
/* Return the size of the struct */

View File

@@ -593,7 +593,7 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
if (SymHasUserMark (Sym)) {
LIError (&Sym->DefLines,
"Circular reference in definition of symbol '%m%p'",
"Circular reference in definition of symbol `%m%p'",
GetSymName (Sym));
ED_SetError (D);
} else {
@@ -1359,8 +1359,7 @@ static void StudyNearAddr (ExprNode* Expr, ExprDesc* D)
}
/* Promote to absolute if smaller. */
if (D->AddrSize < ADDR_SIZE_ABS)
{
if (D->AddrSize < ADDR_SIZE_ABS) {
D->AddrSize = ADDR_SIZE_ABS;
}
}

View File

@@ -40,6 +40,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "nexttok.h"
#include "scanner.h"
#include "symbol.h"
@@ -73,7 +74,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
/* Start from the root scope */
Scope = RootScope;
} else if (CurTok.Tok == TOK_IDENT) {
} else if (Expect (TOK_IDENT, "Expected an identifier")) {
/* Remember the name and skip it */
SB_Copy (Name, &CurTok.SVal);
@@ -95,7 +96,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
if (Scope == 0) {
/* Scope not found */
SB_Terminate (FullName);
Error ("No such scope: '%m%p'", FullName);
Error ("No such scope: `%m%p'", FullName);
return 0;
}
@@ -115,8 +116,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
while (1) {
/* Next token must be an identifier. */
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
if (!Expect (TOK_IDENT, "Expected an identifier")) {
return 0;
}
@@ -139,7 +139,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
if (Scope == 0) {
/* Scope not found */
Error ("No such scope: '%m%p'", FullName);
Error ("No such scope: `%m%p'", FullName);
return 0;
}

View File

@@ -215,24 +215,32 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
Error ("Symbol '%m%p' is already an import", GetSymName (S));
Error ("Symbol `%m%p' is already an import", GetSymName (S));
if (CollCount (&S->DefLines) > 0) {
PNotification (GetSourcePos (CollAt(&S->DefLines, 0)),
"The symbol was previously imported here");
}
return;
}
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
/* Variable symbols cannot be exports or globals */
Error ("Var symbol '%m%p' cannot be an export or global symbol", GetSymName (S));
Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S));
return;
}
if (S->Flags & SF_DEFINED) {
/* Multiple definition. In case of a variable, this is legal. */
if ((S->Flags & SF_VAR) == 0) {
Error ("Symbol '%m%p' is already defined", GetSymName (S));
Error ("Symbol `%m%p' is already defined", GetSymName (S));
if (CollCount (&S->DefLines) > 0) {
PNotification (GetSourcePos (CollAt(&S->DefLines, 0)),
"The symbol was previously defined here");
}
S->Flags |= SF_MULTDEF;
return;
} else {
/* Redefinition must also be a variable symbol */
if ((Flags & SF_VAR) == 0) {
Error ("Symbol '%m%p' is already different kind", GetSymName (S));
Error ("Symbol `%m%p' is already different kind", GetSymName (S));
return;
}
/* Delete the current symbol expression, since it will get
@@ -288,7 +296,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
Warning (1, "Symbol '%m%p' is %s but exported %s",
Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
@@ -320,13 +328,13 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */
{
if (S->Flags & SF_DEFINED) {
Error ("Symbol '%m%p' is already defined", GetSymName (S));
Error ("Symbol `%m%p' is already defined", GetSymName (S));
S->Flags |= SF_MULTDEF;
return;
}
if (S->Flags & SF_EXPORT) {
/* The symbol is already marked as exported symbol */
Error ("Cannot import exported symbol '%m%p'", GetSymName (S));
Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
return;
}
@@ -342,16 +350,16 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if (S->Flags & SF_IMPORT) {
if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S));
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
}
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
if (S->Flags & SF_GLOBAL) {
S->Flags &= ~SF_GLOBAL;
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
@@ -374,12 +382,12 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Check if it's ok to export the symbol */
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
Error ("Symbol '%m%p' is already an import", GetSymName (S));
Error ("Symbol `%m%p' is already an import", GetSymName (S));
return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported */
Error ("Var symbol '%m%p' cannot be exported", GetSymName (S));
Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
return;
}
@@ -388,7 +396,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
@@ -403,7 +411,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
S->ExportSize = AddrSize;
@@ -417,7 +425,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
Warning (1, "Symbol '%m%p' is %s but exported %s",
Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
@@ -439,7 +447,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
{
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
Error ("Var symbol '%m%p' cannot be made global", GetSymName (S));
Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
return;
}
@@ -452,7 +460,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
AddrSize = GetCurrentSegAddrSize ();
}
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
return;
}
@@ -464,12 +472,12 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
if ((S->Flags & SF_DEFINED) == 0) {
/* Symbol is undefined */
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
} else if (AddrSize != ADDR_SIZE_DEFAULT) {
/* Symbol is defined and address size given */
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
return;
@@ -481,7 +489,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
return;
}
@@ -499,7 +507,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
Warning (1, "Symbol '%m%p' is %s but exported %s",
Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
@@ -542,12 +550,12 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
/* Check for errors */
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
Error ("Symbol '%m%p' is already an import", GetSymName (S));
Error ("Symbol `%m%p' is already an import", GetSymName (S));
return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
Error ("Var symbol '%m%p' cannot be exported", GetSymName (S));
Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
return;
}
@@ -559,7 +567,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
/* Use the real size of the symbol */
AddrSize = S->AddrSize;
} else if (S->AddrSize != AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
@@ -569,7 +577,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
*/
if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
}
@@ -580,7 +588,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
*/
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
if (S->ConDesPrio[Type] != Prio) {
Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S));
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
}
}
S->ConDesPrio[Type] = Prio;

View File

@@ -42,7 +42,6 @@
#include "cddefs.h"
#include "coll.h"
#include "filepos.h"
#include "inline.h"
#include "strbuf.h"
/* ca65 */
@@ -137,25 +136,17 @@ int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E);
** inserted on the right side.
*/
#if defined(HAVE_INLINE)
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
static inline void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add an expression reference to this symbol */
{
CollAppend (&Sym->ExprRefs, Expr);
}
#else
#define SymAddExprRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
#endif
#if defined(HAVE_INLINE)
INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
static inline void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Delete an expression reference to this symbol */
{
CollDeleteItem (&Sym->ExprRefs, Expr);
}
#else
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
void SymTransferExprRefs (SymEntry* From, SymEntry* To);
/* Transfer all expression references from one symbol to another. */
@@ -199,107 +190,71 @@ void SymImportFromGlobal (SymEntry* S);
** into an import.
*/
#if defined(HAVE_INLINE)
INLINE int SymIsDef (const SymEntry* S)
static inline int SymIsDef (const SymEntry* S)
/* Return true if the given symbol is already defined */
{
return (S->Flags & SF_DEFINED) != 0;
}
#else
# define SymIsDef(S) (((S)->Flags & SF_DEFINED) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsRef (const SymEntry* S)
static inline int SymIsRef (const SymEntry* S)
/* Return true if the given symbol has been referenced */
{
return (S->Flags & SF_REFERENCED) != 0;
}
#else
# define SymIsRef(S) (((S)->Flags & SF_REFERENCED) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsImport (const SymEntry* S)
static inline int SymIsImport (const SymEntry* S)
/* Return true if the given symbol is marked as import */
{
/* Check the import flag */
return (S->Flags & SF_IMPORT) != 0;
}
#else
# define SymIsImport(S) (((S)->Flags & SF_IMPORT) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsExport (const SymEntry* S)
static inline int SymIsExport (const SymEntry* S)
/* Return true if the given symbol is marked as export */
{
/* Check the export flag */
return (S->Flags & SF_EXPORT) != 0;
}
#else
# define SymIsExport(S) (((S)->Flags & SF_EXPORT) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsVar (const SymEntry* S)
static inline int SymIsVar (const SymEntry* S)
/* Return true if the given symbol is marked as variable */
{
/* Check the variable flag */
return (S->Flags & SF_VAR) != 0;
}
#else
# define SymIsVar(S) (((S)->Flags & SF_VAR) != 0)
#endif
int SymIsConst (const SymEntry* Sym, long* Val);
/* Return true if the given symbol has a constant value. If Val is not NULL
** and the symbol has a constant value, store it's value there.
*/
#if defined(HAVE_INLINE)
INLINE int SymHasExpr (const SymEntry* S)
static inline int SymHasExpr (const SymEntry* S)
/* Return true if the given symbol has an associated expression */
{
/* Check the expression */
return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED);
}
#else
# define SymHasExpr(S) (((S)->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED)
#endif
#if defined(HAVE_INLINE)
INLINE void SymMarkUser (SymEntry* S)
static inline void SymMarkUser (SymEntry* S)
/* Set a user mark on the specified symbol */
{
/* Set the bit */
S->Flags |= SF_USER;
}
#else
# define SymMarkUser(S) ((S)->Flags |= SF_USER)
#endif
#if defined(HAVE_INLINE)
INLINE void SymUnmarkUser (SymEntry* S)
static inline void SymUnmarkUser (SymEntry* S)
/* Remove a user mark from the specified symbol */
{
/* Reset the bit */
S->Flags &= ~SF_USER;
}
#else
# define SymUnmarkUser(S) ((S)->Flags &= ~SF_USER)
#endif
#if defined(HAVE_INLINE)
INLINE int SymHasUserMark (SymEntry* S)
static inline int SymHasUserMark (SymEntry* S)
/* Return the state of the user mark for the specified symbol */
{
/* Check the bit */
return (S->Flags & SF_USER) != 0;
}
#else
# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0)
#endif
struct SymTable* GetSymParentScope (SymEntry* S);
/* Get the parent scope of the symbol (not the one it is defined in). Return
@@ -314,27 +269,19 @@ const struct ExprNode* SymResolve (const SymEntry* Sym);
** NULL. Do not call in other contexts!
*/
#if defined(HAVE_INLINE)
INLINE const StrBuf* GetSymName (const SymEntry* S)
static inline const StrBuf* GetSymName (const SymEntry* S)
/* Return the name of the symbol */
{
return GetStrBuf (S->Name);
}
#else
# define GetSymName(S) GetStrBuf ((S)->Name)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned char GetSymAddrSize (const SymEntry* S)
static inline unsigned char GetSymAddrSize (const SymEntry* S)
/* Return the address size of the symbol. Beware: This function will just
** return the AddrSize member, it will not look at the expression!
*/
{
return S->AddrSize;
}
#else
# define GetSymAddrSize(S) ((S)->AddrSize)
#endif
long GetSymVal (SymEntry* Sym);
/* Return the value of a symbol assuming it's constant. FAIL will be called

View File

@@ -178,7 +178,7 @@ static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
}
} else {
/* Duplicate scope name */
Internal ("Duplicate scope name: '%m%p'", Name);
Internal ("Duplicate scope name: `%m%p'", Name);
}
}
}
@@ -216,7 +216,7 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
/* Check if the scope has been defined before */
if (CurrentScope->Flags & ST_DEFINED) {
Error ("Duplicate scope '%m%p'", ScopeName);
Error ("Duplicate scope `%m%p'", ScopeName);
}
} else {
@@ -502,7 +502,7 @@ static void SymCheckUndefined (SymEntry* S)
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as import */
LIError (&S->RefLines,
"Symbol '%s' is already an import",
"Symbol `%s' is already an import",
GetString (Sym->Name));
}
if ((Sym->Flags & SF_EXPORT) == 0) {
@@ -516,7 +516,7 @@ static void SymCheckUndefined (SymEntry* S)
if (Sym->AddrSize > Sym->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
LIWarning (&Sym->DefLines, 1,
"Symbol '%m%p' is %s but exported %s",
"Symbol `%m%p' is %s but exported %s",
GetSymName (Sym),
AddrSizeToStr (Sym->AddrSize),
AddrSizeToStr (Sym->ExportSize));
@@ -541,7 +541,7 @@ static void SymCheckUndefined (SymEntry* S)
if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */
LIError (&S->RefLines,
"Exported symbol '%m%p' was never defined",
"Exported symbol `%m%p' was never defined",
GetSymName (S));
} else {
if (AutoImport) {
@@ -554,7 +554,7 @@ static void SymCheckUndefined (SymEntry* S)
} else {
/* Error */
LIError (&S->RefLines,
"Symbol '%m%p' is undefined",
"Symbol `%m%p' is undefined",
GetSymName (S));
}
}
@@ -573,13 +573,13 @@ void SymCheck (void)
if (CurrentScope->Label) {
/* proc has a label indicating the line it was opened. */
LIError (&CurrentScope->Label->DefLines,
"Local proc '%s' was not closed",
"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",
Error ("Local scope `%s' was not closed",
GetString (CurrentScope->Name));
}
}
@@ -627,7 +627,7 @@ void SymCheck (void)
ReleaseFullLineInfo (&S->RefLines);
} else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
LIWarning (&S->DefLines, 2,
"Symbol '%m%p' is defined but never used",
"Symbol `%m%p' is defined but never used",
GetSymName (S));
}
@@ -636,7 +636,7 @@ void SymCheck (void)
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
/* Imported symbol is not referenced */
LIWarning (&S->DefLines, 2,
"Symbol '%m%p' is imported but never used",
"Symbol `%m%p' is imported but never used",
GetSymName (S));
} else {
/* Give the import an id, count imports */
@@ -664,7 +664,7 @@ void SymCheck (void)
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
LIWarning (&S->DefLines, 1,
"Symbol '%m%p' is %s but exported %s",
"Symbol `%m%p' is %s but exported %s",
GetSymName (S),
AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
@@ -684,7 +684,7 @@ void SymCheck (void)
const FilePos* P = S->GuessedUse[S->AddrSize - 1];
if (P) {
PWarning (P, 0,
"Didn't use %s addressing for '%m%p'",
"Didn't use %s addressing for `%m%p'",
AddrSizeToStr (S->AddrSize),
GetSymName (S));
}

View File

@@ -42,7 +42,6 @@
/* common */
#include "exprdefs.h"
#include "inline.h"
/* ca65 */
#include "symentry.h"
@@ -135,25 +134,17 @@ SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name);
** scope.
*/
#if defined(HAVE_INLINE)
INLINE unsigned char GetSymTabType (const SymTable* S)
static inline unsigned char GetSymTabType (const SymTable* S)
/* Return the type of the given symbol table */
{
return S->Type;
}
#else
# define GetSymTabType(S) ((S)->Type)
#endif
#if defined(HAVE_INLINE)
INLINE int SymTabIsClosed (const SymTable* S)
static inline int SymTabIsClosed (const SymTable* S)
/* Return true if the symbol table has been closed */
{
return (S->Flags & ST_CLOSED) != 0;
}
#else
# define SymTabIsClosed(S) (((S)->Flags & ST_CLOSED) != 0)
#endif
void SymCheck (void);
/* Run through all symbols and check for anomalies and errors */

View File

@@ -33,30 +33,261 @@
#include <stdio.h>
/* ca65 */
#include "token.h"
/*****************************************************************************/
/* Code */
/* Data */
/*****************************************************************************/
int TokHasSVal (token_t Tok)
/* Return true if the given token has an attached SVal */
{
return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON);
}
/* Use a struct so we can extend it if required */
typedef struct TokDescEntry TokDescEntry;
struct TokDescEntry {
const char* Desc;
};
static const TokDescEntry TokDesc[] = {
{ "none", },
{ "end-of-file", },
{ "end-of-line", },
{ "{s}", },
{ "{s}", },
{ "{i}", },
{ "'{c}'", },
{ "\"{s}\"", },
{ "A", },
{ "Q", },
{ "S", },
{ "X", },
{ "Y", },
{ "Z", },
{ "R{i}", },
{ ":=", },
{ "unnamed label", },
{ "=", },
{ "<>", },
{ "<", },
{ ">", },
{ "<=", },
{ ">=", },
{ ".AND", },
{ ".OR", },
{ ".XOR", },
{ ".NOT", },
{ "+", },
{ "-", },
{ "*", },
{ "/", },
{ "!", },
{ "|", },
{ "^", },
{ "&", },
{ "<<", },
{ ">>", },
{ "~", },
{ "$", },
{ "::", },
{ ".", },
{ ",", },
{ "#", },
{ ":", },
{ "(", },
{ ")", },
{ "[", },
{ "]", },
{ "{", },
{ "}", },
{ "@", },
{ "z:", },
{ "a:", },
{ "f:", },
{ "macro parameter", },
{ "repeat counter", },
{ ".A16" },
{ ".A8" },
{ ".ADDR" },
{ ".ADDRSIZE" },
{ ".ALIGN" },
{ ".ASCIIZ" },
{ ".ASIZE" },
{ ".ASSERT" },
{ ".AUTOIMPORT" },
{ ".BANK" },
{ ".BANKBYTE" },
{ ".BANKBYTES" },
{ ".BLANK" },
{ ".BSS" },
{ ".BYTE" },
{ ".CAP" },
{ ".CASE" },
{ ".CHARMAP" },
{ ".CODE" },
{ ".CONCAT" },
{ ".CONDES" },
{ ".CONST" },
{ ".CONSTRUCTOR" },
{ ".CPU" },
{ ".DATA" },
{ ".DBG" },
{ ".DBYT" },
{ ".DEBUGINFO" },
{ ".DEFINE" },
{ ".DEFINED" },
{ ".DEFINEDMACRO" },
{ ".DELMAC" },
{ ".DESTRUCTOR" },
{ ".DWORD" },
{ ".ELSE" },
{ ".ELSEIF" },
{ ".END" },
{ ".ENDENUM" },
{ ".ENDIF" },
{ ".ENDMACRO" },
{ ".ENDPROC" },
{ ".ENDREP" },
{ ".ENDSCOPE" },
{ ".ENDSTRUCT" },
{ ".ENDUNION" },
{ ".ENUM" },
{ ".ERROR" },
{ ".EXITMACRO" },
{ ".EXPORT" },
{ ".EXPORTZP" },
{ ".FARADDR" },
{ ".FATAL" },
{ ".FEATURE" },
{ ".FILEOPT" },
{ ".FORCEIMPORT" },
{ ".FORCEWORD" },
{ ".GLOBAL" },
{ ".GLOBALZP" },
{ ".HIBYTE" },
{ ".HIBYTES" },
{ ".HIWORD" },
{ ".I16" },
{ ".I8" },
{ ".MAKEIDENT" },
{ ".IF" },
{ ".IFBLANK" },
{ ".IFCONST" },
{ ".IFDEF" },
{ ".IFNBLANK" },
{ ".IFNCONST" },
{ ".IFNDEF" },
{ ".IFNREF" },
{ ".IFP02" },
{ ".IFP02X" },
{ ".IFP4510" },
{ ".IFP45GS02" },
{ ".IFP6280" },
{ ".IFP816" },
{ ".IFPC02" },
{ ".IFPCE02" },
{ ".IFPDTV" },
{ ".IFPM740" },
{ ".IFPSC02" },
{ ".IFPSWEET16" },
{ ".IFPWC02" },
{ ".IFREF" },
{ ".IMPORT" },
{ ".IMPORTZP" },
{ ".INCBIN" },
{ ".INCLUDE" },
{ ".INTERRUPTOR" },
{ ".ISIZE" },
{ ".ISMNEMONIC" },
{ ".LEFT" },
{ ".LINECONT" },
{ ".LIST" },
{ ".LISTBYTES" },
{ ".LITERAL" },
{ ".LOBYTE" },
{ ".LOBYTES" },
{ ".LOCAL" },
{ ".LOCALCHAR" },
{ ".LOWORD" },
{ ".MACPACK" },
{ ".MACRO" },
{ ".MATCH" },
{ ".MAX" },
{ ".MID" },
{ ".MIN" },
{ ".NULL" },
{ ".ORG" },
{ ".OUT" },
{ ".P02" },
{ ".P02X" },
{ ".P4510" },
{ ".P45GS02" },
{ ".P6280" },
{ ".P816" },
{ ".PAGELENGTH" },
{ ".PARAMCOUNT" },
{ ".PC02" },
{ ".PCE02" },
{ ".PDTV" },
{ ".PM740" },
{ ".POPCHARMAP" },
{ ".POPCPU" },
{ ".POPSEG" },
{ ".PROC" },
{ ".PSC02" },
{ ".PSWEET16" },
{ ".PUSHCHARMAP" },
{ ".PUSHCPU" },
{ ".PUSHSEG" },
{ ".PWC02" },
{ ".REFERENCED" },
{ ".REFERTO" },
{ ".RELOC" },
{ ".REPEAT" },
{ ".RES" },
{ ".RIGHT" },
{ ".RODATA" },
{ ".SCOPE" },
{ ".SEGMENT" },
{ ".SET" },
{ ".SETCPU" },
{ ".SIZEOF" },
{ ".SMART" },
{ ".SPRINTF" },
{ ".STRAT" },
{ ".STRING" },
{ ".STRLEN" },
{ ".STRUCT" },
{ ".TAG" },
{ ".TCOUNT" },
{ ".TIME" },
{ ".UNDEF" },
{ ".UNION" },
{ ".VERSION" },
{ ".WARNING" },
{ ".WORD" },
{ ".XMATCH" },
{ ".ZEROPAGE" },
};
int TokHasIVal (token_t Tok)
/* Return true if the given token has an attached IVal */
{
return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@@ -72,3 +303,54 @@ void CopyToken (Token* Dst, const Token* Src)
SB_Copy (&Dst->SVal, &Src->SVal);
Dst->Pos = Src->Pos;
}
StrBuf* TokenDesc (const Token* T, StrBuf* S)
/* Place a textual description of the given token into S. */
{
PRECONDITION (sizeof (TokDesc) / sizeof (TokDesc[0]) == TOK_COUNT);
/* Clear the target buffer */
SB_Clear (S);
/* Get the description for the token */
const char* Desc = TokDesc[T->Tok].Desc;
/* Repeatedly replace {c}, {i} and {s} */
size_t Start = 0;
while (1) {
const char* P = strchr (Desc + Start, '{');
if (P) {
/* Check if this is really {c}, {i} or {s} */
if ((P[1] != 'c' &&
P[1] != 'i' &&
P[1] != 's') ||
P[2] != '}') {
++Start;
continue;
}
/* Append the text before the replacement token */
SB_AppendBuf (S, Desc + Start, P - (Desc + Start));
Start += P - (Desc + Start) + 3;
/* Append the replacement text */
if (P[1] == 'c') {
SB_AppendChar (S, (char)T->IVal);
} else if (P[1] == 'i') {
char Buf[64];
snprintf (Buf, sizeof (Buf), "%ld", T->IVal);
SB_AppendStr (S, Buf);
} else {
SB_Append (S, &T->SVal);
}
} else {
/* No more replacements found, append remainder */
SB_AppendStr (S, Desc + Start);
break;
}
}
/* Zero-terminate the buffer and return it */
SB_Terminate (S);
return S;
}

View File

@@ -40,7 +40,6 @@
/* common */
#include "filepos.h"
#include "inline.h"
#include "strbuf.h"
@@ -53,76 +52,80 @@
/* Tokens */
typedef enum token_t {
TOK_NONE, /* Start value, invalid */
TOK_EOF, /* End of input file */
TOK_SEP, /* Separator (usually newline) */
TOK_IDENT, /* An identifier */
TOK_LOCAL_IDENT, /* A cheap local identifier */
TOK_NONE, /* Start value, invalid */
TOK_EOF, /* End of input file */
TOK_SEP, /* Separator (usually newline) */
TOK_IDENT, /* An identifier */
TOK_LOCAL_IDENT, /* A cheap local identifier */
TOK_INTCON, /* Integer constant */
TOK_CHARCON, /* Character constant */
TOK_STRCON, /* String constant */
TOK_INTCON, /* Integer constant */
TOK_CHARCON, /* Character constant */
TOK_STRCON, /* String constant */
TOK_A, /* A)ccumulator */
TOK_X, /* X register */
TOK_Y, /* Y register */
TOK_Z, /* Z register */
TOK_S, /* S register */
TOK_Q, /* Q pseudo register */
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_FIRSTREG, /* First register name token */
TOK_A = TOK_FIRSTREG, /* A)ccumulator */
TOK_Q, /* Q pseudo register */
TOK_S, /* S register */
TOK_X, /* X register */
TOK_Y, /* Y register */
TOK_Z, /* Z register */
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_LASTREG = TOK_REG, /* Last register name token */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* An unnamed label */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* An unnamed label */
TOK_EQ, /* = */
TOK_NE, /* <> */
TOK_LT, /* < */
TOK_GT, /* > */
TOK_LE, /* <= */
TOK_GE, /* >= */
TOK_FIRSTOP, /* First operator token */
TOK_EQ = TOK_FIRSTOP, /* = */
TOK_NE, /* <> */
TOK_LT, /* < */
TOK_GT, /* > */
TOK_LE, /* <= */
TOK_GE, /* >= */
TOK_BOOLAND, /* .and */
TOK_BOOLOR, /* .or */
TOK_BOOLXOR, /* .xor */
TOK_BOOLNOT, /* .not */
TOK_BOOLAND, /* .and */
TOK_BOOLOR, /* .or */
TOK_BOOLXOR, /* .xor */
TOK_BOOLNOT, /* .not */
TOK_PLUS, /* + */
TOK_MINUS, /* - */
TOK_MUL, /* * */
TOK_STAR = TOK_MUL, /* Alias */
TOK_DIV, /* / */
TOK_MOD, /* ! */
TOK_OR, /* | */
TOK_XOR, /* ^ */
TOK_AND, /* & */
TOK_SHL, /* << */
TOK_SHR, /* >> */
TOK_NOT, /* ~ */
TOK_PLUS, /* + */
TOK_MINUS, /* - */
TOK_MUL, /* * */
TOK_STAR = TOK_MUL, /* Alias */
TOK_DIV, /* / */
TOK_MOD, /* ! */
TOK_OR, /* | */
TOK_XOR, /* ^ */
TOK_AND, /* & */
TOK_SHL, /* << */
TOK_SHR, /* >> */
TOK_NOT, /* ~ */
TOK_LASTOP = TOK_NOT, /* Last operator token */
TOK_PC, /* $ if enabled */
TOK_NAMESPACE, /* :: */
TOK_DOT, /* . */
TOK_COMMA, /* , */
TOK_HASH, /* # */
TOK_COLON, /* : */
TOK_LPAREN, /* ( */
TOK_RPAREN, /* ) */
TOK_LBRACK, /* [ */
TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
TOK_AT, /* @ - in Sweet16 mode */
TOK_PC, /* $ if enabled */
TOK_NAMESPACE, /* :: */
TOK_DOT, /* . */
TOK_COMMA, /* , */
TOK_HASH, /* # */
TOK_COLON, /* : */
TOK_LPAREN, /* ( */
TOK_RPAREN, /* ) */
TOK_LBRACK, /* [ */
TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
TOK_AT, /* @ - in Sweet16 mode */
TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */
TOK_OVERRIDE_FAR, /* f: */
TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */
TOK_OVERRIDE_FAR, /* f: */
TOK_MACPARAM, /* Macro parameter, not generated by scanner */
TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */
TOK_MACPARAM, /* Macro parameter, not generated by scanner */
TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */
/* The next ones are tokens for the pseudo instructions. Keep together! */
TOK_FIRSTPSEUDO,
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A8,
TOK_ADDR,
TOK_ADDRSIZE,
@@ -284,9 +287,9 @@ typedef enum token_t {
TOK_WORD,
TOK_XMATCH,
TOK_ZEROPAGE,
TOK_LASTPSEUDO = TOK_ZEROPAGE,
TOK_LASTPSEUDO = TOK_ZEROPAGE,
TOK_COUNT /* Count of tokens */
TOK_COUNT /* Count of tokens */
} token_t;
@@ -318,27 +321,42 @@ struct Token {
int TokHasSVal (token_t Tok);
#if defined(HAVE_INLINE)
INLINE int TokHasSVal (token_t Tok)
/* Return true if the given token has an attached SVal */
int TokHasIVal (token_t Tok);
/* Return true if the given token has an attached IVal */
{
return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON);
}
#else
# define TokHasSVal(T) \
((T) == TOK_IDENT || (T) == TOK_LOCAL_IDENT || (T) == TOK_STRCON)
#endif
#if defined(HAVE_INLINE)
INLINE int TokIsSep (enum token_t T)
INLINE int TokHasIVal (token_t Tok)
/* Return true if the given token has an attached IVal */
{
return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
}
#else
# define TokHasIVal(T) \
((T) == TOK_INTCON || (T) == TOK_CHARCON || (T) == TOK_REG)
#endif
static inline int TokIsSep (enum token_t T)
/* Return true if this is a separator token */
{
return (T == TOK_SEP || T == TOK_EOF);
}
#else
# define TokIsSep(T) ((T) == TOK_SEP || (T) == TOK_EOF)
#endif
void CopyToken (Token* Dst, const Token* Src);
/* Copy a token. The current value of Dst.SVal is free'd, so Dst must be
** initialized.
*/
StrBuf* TokenDesc (const Token* T, StrBuf* S);
/* Place a textual description of the given token into S. */
/* End of token.h */

View File

@@ -111,7 +111,7 @@ ExprNode* ULabRef (int Which)
if (Which == 0) {
Error ("Invalid unnamed label reference");
/* We must return something valid */
return GenCurrentPC();
return GenCurrentPC ();
}
/* Get the index of the referenced label */
@@ -125,7 +125,7 @@ ExprNode* ULabRef (int Which)
/* Label does not exist */
Error ("Undefined label");
/* We must return something valid */
return GenCurrentPC();
return GenCurrentPC ();
}
/* Check if the label exists. If not, generate enough forward labels. */

View File

@@ -70,45 +70,29 @@ CaseNode* NewCaseNode (unsigned char Value);
void FreeCaseNode (CaseNode* N);
/* Delete a case node plus all sub nodes */
#if defined(HAVE_INLINE)
INLINE CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index)
static inline CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index)
/* Get a sub node of the given node */
{
return CollAt (N->Nodes, Index);
}
#else
# define CN_GetSubNode(N, Index) CollAt (&(N)->Nodes, Index)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned char CN_GetValue (const CaseNode* N)
static inline unsigned char CN_GetValue (const CaseNode* N)
/* Return the value for a case node */
{
return N->Value;
}
#else
# define CN_GetValue(N) ((N)->Value)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned CN_GetLabel (const CaseNode* N)
static inline unsigned CN_GetLabel (const CaseNode* N)
/* Return the label for a case node */
{
return N->Label;
}
#else
# define CN_GetLabel(N) ((N)->Label)
#endif
#if defined(HAVE_INLINE)
INLINE int CN_IsLeafNode (const CaseNode* N)
static inline int CN_IsLeafNode (const CaseNode* N)
/* Return true if this is a leaf node */
{
return (N->Nodes == 0);
}
#else
# define CN_IsLeafNode(N) ((N)->Nodes == 0)
#endif
void FreeCaseNodeColl (Collection* Nodes);
/* Free a collection of case nodes */

View File

@@ -42,7 +42,6 @@
/* common */
#include "coll.h"
#include "inline.h"
/* cc65 */
#include "codelab.h"
@@ -150,88 +149,56 @@ void CE_ClearJumpTo (CodeEntry* E);
** so use it with care.
*/
#if defined(HAVE_INLINE)
INLINE int CE_HasLabel (const CodeEntry* E)
static inline int CE_HasLabel (const CodeEntry* E)
/* Check if the given code entry has labels attached */
{
return (CollCount (&E->Labels) > 0);
}
#else
# define CE_HasLabel(E) (CollCount (&(E)->Labels) > 0)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned CE_GetLabelCount (const CodeEntry* E)
static inline unsigned CE_GetLabelCount (const CodeEntry* E)
/* Get the number of labels attached to this entry */
{
return CollCount (&E->Labels);
}
#else
# define CE_GetLabelCount(E) CollCount (&(E)->Labels)
#endif
#if defined(HAVE_INLINE)
INLINE CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index)
static inline CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index)
/* Get a label from this code entry */
{
return CollAt (&E->Labels, Index);
}
#else
# define CE_GetLabel(E, Index) CollAt (&(E)->Labels, (Index))
#endif
#if defined(HAVE_INLINE)
INLINE void CE_ReplaceLabel (CodeEntry* E, CodeLabel* L, unsigned Index)
static inline void CE_ReplaceLabel (CodeEntry* E, CodeLabel* L, unsigned Index)
/* Replace the code label at the specified index with L */
{
CollReplace (&E->Labels, L, Index);
}
#else
# define CE_ReplaceLabel(E, L, Index) CollReplace (&(E)->Labels, (L), (Index))
#endif
void CE_MoveLabel (CodeLabel* L, CodeEntry* E);
/* Move the code label L from it's former owner to the code entry E. */
#if defined(HAVE_INLINE)
INLINE int CE_HasMark (const CodeEntry* E)
static inline int CE_HasMark (const CodeEntry* E)
/* Return true if the given code entry has the CEF_USERMARK flag set */
{
return (E->Flags & CEF_USERMARK) != 0;
}
#else
# define CE_HasMark(E) (((E)->Flags & CEF_USERMARK) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE void CE_SetMark (CodeEntry* E)
static inline void CE_SetMark (CodeEntry* E)
/* Set the CEF_USERMARK flag for the given entry */
{
E->Flags |= CEF_USERMARK;
}
#else
# define CE_SetMark(E) ((E)->Flags |= CEF_USERMARK)
#endif
#if defined(HAVE_INLINE)
INLINE void CE_ResetMark (CodeEntry* E)
static inline void CE_ResetMark (CodeEntry* E)
/* Reset the CEF_USERMARK flag for the given entry */
{
E->Flags &= ~CEF_USERMARK;
}
#else
# define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK)
#endif
#if defined(HAVE_INLINE)
INLINE int CE_HasNumArg (const CodeEntry* E)
static inline int CE_HasNumArg (const CodeEntry* E)
/* Return true if the instruction has a numeric argument */
{
return (E->Flags & CEF_NUMARG) != 0;
}
#else
# define CE_HasNumArg(E) (((E)->Flags & CEF_NUMARG) != 0)
#endif
void CE_SetArg (CodeEntry* E, const char* Arg);
/* Replace the argument by the new one. */
@@ -271,15 +238,11 @@ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num);
** equal to Num.
*/
#if defined(HAVE_INLINE)
INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name)
static inline int CE_IsCallTo (const CodeEntry* E, const char* Name)
/* Check if this is a call to the given function */
{
return (E->OPC == OP65_JSR && strcmp (E->Arg, Name) == 0);
}
#else
# define CE_IsCallTo(E, Name) ((E)->OPC == OP65_JSR && strcmp ((E)->Arg, (Name)) == 0)
#endif
int CE_UseLoadFlags (CodeEntry* E);
/* Return true if the instruction uses any flags that are set by a load of

View File

@@ -83,25 +83,17 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
void FreeCodeLabel (CodeLabel* L);
/* Free the given code label */
#if defined(HAVE_INLINE)
INLINE unsigned CL_GetRefCount (const CodeLabel* L)
static inline unsigned CL_GetRefCount (const CodeLabel* L)
/* Get the number of references for this label */
{
return CollCount (&L->JumpFrom);
}
#else
# define CL_GetRefCount(L) CollCount (&(L)->JumpFrom)
#endif
#if defined(HAVE_INLINE)
INLINE struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
static inline struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
/* Get a code entry referencing this label */
{
return CollAt (&L->JumpFrom, Index);
}
#else
# define CL_GetRef(L, Index) CollAt (&(L)->JumpFrom, (Index))
#endif
void CL_AddRef (CodeLabel* L, struct CodeEntry* E);
/* Let the CodeEntry E reference the label L */

View File

@@ -113,6 +113,8 @@ static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 65, 0,
static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd6 = { OptAdd6, "OptAdd6", 40, 0, 0, 0, 0, 0 };
static OptFunc DOptAXLoad = { OptAXLoad, "OptAXLoad", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptAXOps = { OptAXOps, "OptAXOps", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0, 0, 0, 0, 0 };
@@ -236,6 +238,7 @@ static OptFunc* OptFuncs[] = {
&DOptAdd4,
&DOptAdd5,
&DOptAdd6,
&DOptAXOps,
&DOptBNegA1,
&DOptBNegA2,
&DOptBNegAX1,
@@ -629,6 +632,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
Changes += RunOptFunc (S, &DOptGotoSPAdj, 1);
Changes += RunOptFunc (S, &DOptStackPtrOps, 5);
Changes += RunOptFunc (S, &DOptAXOps, 5);
Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */
Changes += RunOptFunc (S, &DOptPtrStore1, 1);
Changes += RunOptFunc (S, &DOptPtrStore2, 1);
@@ -871,6 +875,7 @@ static unsigned RunOptGroup7 (CodeSeg* S)
** may have opened new oportunities.
*/
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
Changes += RunOptFunc (S, &DOptAXLoad, 5);
Changes += RunOptFunc (S, &DOptUnusedStores, 1);
Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
Changes += RunOptFunc (S, &DOptStore5, 1);
@@ -907,6 +912,11 @@ static unsigned RunOptGroup7 (CodeSeg* S)
between branches */
C += RunOptFunc (S, &DOptBranchDist, 3);
/* Re-optimize inc/decsp that may now be grouped */
C += RunOptFunc (S, &DOptStackPtrOps, 5);
/* Re-optimize JSR/RTS that may now be grouped */
C += RunOptFunc (S, &DOptRTS, 1);
Changes += C;
/* If we had changes, we must run dead code elimination again,
** since the changes may have introduced dead code.

View File

@@ -43,7 +43,6 @@
/* common */
#include "attrib.h"
#include "coll.h"
#include "inline.h"
/* cc65 */
#include "codelab.h"
@@ -106,15 +105,11 @@ void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) attr
void CS_AddLine (CodeSeg* S, LineInfo* LI, const char* Format, ...) attribute ((format(printf,3,4)));
/* Add a line to the given code segment */
#if defined(HAVE_INLINE)
INLINE unsigned CS_GetEntryCount (const CodeSeg* S)
static inline unsigned CS_GetEntryCount (const CodeSeg* S)
/* Return the number of entries for the given code segment */
{
return CollCount (&S->Entries);
}
#else
# define CS_GetEntryCount(S) CollCount (&(S)->Entries)
#endif
void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
/* Insert the code entry at the index given. Following code entries will be
@@ -145,27 +140,19 @@ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos
** current code end)
*/
#if defined(HAVE_INLINE)
INLINE void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos)
static inline void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos)
/* Move an entry from one position to another. OldPos is the current position
** of the entry, NewPos is the new position of the entry.
*/
{
CollMove (&S->Entries, OldPos, NewPos);
}
#else
# define CS_MoveEntry(S, OldPos, NewPos) CollMove (&(S)->Entries, OldPos, NewPos)
#endif
#if defined(HAVE_INLINE)
INLINE struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index)
static inline struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index)
/* Get an entry from the given code segment */
{
return CollAt (&S->Entries, Index);
}
#else
# define CS_GetEntry(S, Index) ((struct CodeEntry*) CollAt(&(S)->Entries, (Index)))
#endif
struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index);
/* Get the code entry preceeding the one with the index Index. If there is no
@@ -192,17 +179,13 @@ int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count);
** possible span instead.
*/
#if defined(HAVE_INLINE)
INLINE int CS_HavePendingLabel (const CodeSeg* S)
static inline int CS_HavePendingLabel (const CodeSeg* S)
/* Return true if there are open labels that will get attached to the next
** instruction that is added.
*/
{
return (CollCount (&S->Labels) > 0);
}
#else
# define CS_HavePendingLabel(S) (CollCount (&(S)->Labels) > 0)
#endif
CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name);
/* Add a code label for the next instruction to follow */
@@ -253,18 +236,13 @@ void CS_DelCodeAfter (CodeSeg* S, unsigned Last);
void CS_ResetMarks (CodeSeg* S, unsigned First, unsigned Last);
/* Remove all user marks from the entries in the given range */
#if defined(HAVE_INLINE)
INLINE void CS_ResetAllMarks (CodeSeg* S)
static inline void CS_ResetAllMarks (CodeSeg* S)
/* Remove all user marks from the code segment */
{
if (CS_GetEntryCount (S) > 0) {
CS_ResetMarks (S, 0, CS_GetEntryCount (S));
}
}
#else
# define CS_ResetAllMarks(S) \
((CS_GetEntryCount (S) > 0)? CS_ResetMarks (S, 0, CS_GetEntryCount (S)) : (void) 0)
#endif
int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last);
/* Check if the given code segment range is a basic block. That is, check if

Some files were not shown because too many files have changed in this diff Show More