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 TXTPTR := $85 ; Far pointer into BASIC source code
FNAM := $90 ; Far pointer to LOAD/SAVE file-name 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 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 TXTPTR := $85 ; Far pointer into BASIC source code
FNAM := $90 ; Far pointer to LOAD/SAVE file-name 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 FNAM_LEN := $9D ; Holds length of file-name
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------

View File

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

View File

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

View File

@@ -107,6 +107,7 @@ Short options:
Long options: Long options:
--auto-import Mark unresolved symbols as import --auto-import Mark unresolved symbols as import
--bin-include-dir dir Set a search path for binary includes --bin-include-dir dir Set a search path for binary includes
--color [on|auto|off] Color diagnostics (default: auto)
--cpu type Set cpu type --cpu type Set cpu type
--create-dep name Create a make dependency file --create-dep name Create a make dependency file
--create-full-dep name Create a full make dependency file --create-full-dep name Create a full make dependency file
@@ -120,6 +121,7 @@ Long options:
--listing name Create a listing file if assembly was ok --listing name Create a listing file if assembly was ok
--list-bytes n Maximum number of bytes per listing line --list-bytes n Maximum number of bytes per listing line
--memory-model model Set the memory model --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 --pagelength n Set the page length for the listing
--relax-checks Disables some error checks --relax-checks Disables some error checks
--segment-list Generate segment offsets in listing --segment-list Generate segment offsets in listing
@@ -148,6 +150,14 @@ Here is a description of all the command line options:
name="search paths">. 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"> <label id="option--cpu">
<tag><tt>--cpu type</tt></tag> <tag><tt>--cpu type</tt></tag>
@@ -261,6 +271,14 @@ Here is a description of all the command line options:
huge. 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"> <label id="option-o">
<tag><tt>-o name</tt></tag> <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. directive for more information.
<label id=cheap-locals>
<sect1>Cheap local labels<p> <sect1>Cheap local labels<p>
Cheap local labels are defined like standard labels, but the name of the Cheap local labels are defined like standard labels, but the name of the
@@ -1435,38 +1454,6 @@ constant is defined:
CPU_ISET_M740 CPU_ISET_M740
</verb></tscreen> </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 <tt/.CPU/ may be used to replace the .IFPxx pseudo instructions or to
construct even more complex expressions. construct even more complex expressions.
@@ -1484,8 +1471,43 @@ see section <ref id="6502-mode" name="6502 format"> and following.
.endif .endif
</verb></tscreen> </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> <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> <sect1><tt>.LOCAL</tt><label id=".LOCAL"><p>
This command may only be used inside a macro definition. It declares a This command may only be used inside a macro definition. It declares a list
list of identifiers as local to the macro expansion. 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, 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. 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 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. invocation.
Some other assemblers start a new lexical block inside a macro expansion. Please note that while the generated names are unique and guaranteed to not
This has some drawbacks however, since that will not allow <em/any/ symbol clash with any user generated names, they are still regular symbols and
to be visible outside a macro, a feature that is sometimes useful. The added to the current scope. This means that a local macro label will start a
<tt><ref id=".LOCAL" name=".LOCAL"></tt> command is in my eyes a better way new scope for cheap locals whenever the macro is expanded. To avoid that,
to address the problem. 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 You get an error when using <tt><ref id=".LOCAL" name=".LOCAL"></tt> outside
a macro. a macro.
@@ -3805,7 +3830,6 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
<tscreen><verb> <tscreen><verb>
atari Defines the scrcode macro. atari Defines the scrcode macro.
cbm 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. generic Defines generic macros like add, sub, and blt.
longbranch Defines conditional long-jump macros. longbranch Defines conditional long-jump macros.
</verb></tscreen> </verb></tscreen>
@@ -5119,6 +5143,7 @@ For better orthogonality, the assembler defines similar symbols as the
compiler, depending on the target system selected: compiler, depending on the target system selected:
<itemize> <itemize>
<item><tt/__AGAT__/ - Target system is <tt/agat/
<item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/ <item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/
<item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/ <item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/
<item><tt/__ATARI2600__/ - Target system is <tt/atari2600/ <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/__C128__/ - Target system is <tt/c128/
<item><tt/__C16__/ - Target system is <tt/c16/ or <tt/plus4/ <item><tt/__C16__/ - Target system is <tt/c16/ or <tt/plus4/
<item><tt/__C64__/ - Target system is <tt/c64/ <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/__CBM__/ - Target is a Commodore or Commodore-alike system
<item><tt/__CBM510__/ - Target system is <tt/cbm510/ <item><tt/__CBM510__/ - Target system is <tt/cbm510/
<item><tt/__CBM610__/ - Target system is <tt/cbm610/ <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/__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__/ - Target is a GEOS system
<item><tt/__GEOS_APPLE__/ - Target system is <tt/geos-apple/ <item><tt/__GEOS_APPLE__/ - Target system is <tt/geos-apple/
<item><tt/__GEOS_CBM__/ - Target system is <tt/geos-cbm/ <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/__LUNIX__/ - Target system is <tt/lunix/
<item><tt/__LYNX__/ - Target system is <tt/lynx/ <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/__NES__/ - Target system is <tt/nes/
<item><tt/__OSIC1P__/ - Target system is <tt/osic1p/ <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/__PET__/ - Target system is <tt/pet/
<item><tt/__PLUS4__/ - Target system is <tt/plus4/ <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/__SIM6502__/ - Target system is <tt/sim6502/
<item><tt/__SIM65C02__/ - Target system is <tt/sim65c02/ <item><tt/__SIM65C02__/ - Target system is <tt/sim65c02/
<item><tt/__SUPERVISION__/ - Target system is <tt/supervision/ <item><tt/__SUPERVISION__/ - Target system is <tt/supervision/
<item><tt/__SYM1__/ - Target system is <tt/sym1/ <item><tt/__SYM1__/ - Target system is <tt/sym1/
<item><tt/__TELESTRAT__/ - Target system is <tt/telestrat/
<item><tt/__VIC20__/ - Target system is <tt/vic20/ <item><tt/__VIC20__/ - Target system is <tt/vic20/
</itemize> </itemize>

View File

@@ -641,7 +641,7 @@ Here is a description of all the command line options:
<item>pce (PC engine) <item>pce (PC engine)
<item>pet (all CBM PET systems except the 2001) <item>pet (all CBM PET systems except the 2001)
<item>plus4 <item>plus4
<item>p6502 <item>rp6502
<item>sim6502 <item>sim6502
<item>sim65c02 <item>sim65c02
<item>supervision <item>supervision
@@ -1112,6 +1112,10 @@ This cc65 version has some extensions to the ISO C standard.
The compiler defines several macros at startup: The compiler defines several macros at startup:
<descrip> <descrip>
<tag><tt>__AGAT__</tt></tag>
This macro is defined if the target is the Agat (-t agat).
<tag><tt>__APPLE2__</tt></tag> <tag><tt>__APPLE2__</tt></tag>
This macro is defined if the target is the Apple ][ (-t apple2) or the enhanced Apple //e (-t apple2enh). 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> <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> <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> <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). 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> <tag><tt>__C128__</tt></tag>
This macro is defined if the target is the Commodore 128 (-t c128). 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). 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> <tag><tt>__CBM__</tt></tag>
This macro is defined if the target system is one of the CBM targets. 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"> <label id="macro-CPU">
<tag><tt>__CPU__</tt></tag> <tag><tt>__CPU__</tt></tag>
This macro contains a bitset that allows to check if a specific instruction This macro contains a bitset that allows to check if a specific group of
set is supported. For example, the 65C02 CPU supports all instructions of the instructions is supported.
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).
<tscreen><verb> <tscreen><verb>
#if (__CPU__ & __CPU_ISET_65SC02__) #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">/ given, but can be changed using the <tt/<ref id="option--cpu" name="--cpu">/
command line option. 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> <tag><tt>__CPU_4510__</tt></tag>
This macro is defined if the code is compiled for a 4510 CPU. 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 <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the W65C02 CPU. 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> <tag><tt>__CX16__</tt></tag>
This macro is defined if the target is the Commander X16 (-t cx16). 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. 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> <tag><tt>__GEOS__</tt></tag>
This macro is defined if you are compiling for one of the GEOS systems. 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). 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> <tag><tt>__LINE__</tt></tag>
This macro expands to the current line number. 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). 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> <tag><tt>__NES__</tt></tag>
This macro is defined if the target is the Nintendo Entertainment System (-t nes). 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 This macro is defined if the target is the Ohio Scientific Challenger 1P
(-t osic1p). (-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> <tag><tt>__PET__</tt></tag>
This macro is defined if the target is the PET family of computers (-t pet). 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). 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> <tag><tt>__SIM6502__</tt></tag>
This macro is defined if the target is sim65 in 6502 mode (-t sim6502). 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="strcpy" name="strcpy">
<item><ref id="strcspn" name="strcspn"> <item><ref id="strcspn" name="strcspn">
<item><ref id="strdup" name="strdup"> <item><ref id="strdup" name="strdup">
<item><ref id="strndup" name="strndup">
<item><ref id="strerror" name="strerror"> <item><ref id="strerror" name="strerror">
<item><ref id="stricmp" name="stricmp"> <item><ref id="stricmp" name="stricmp">
<item><ref id="strlen" name="strlen"> <item><ref id="strlen" name="strlen">
@@ -5621,6 +5622,7 @@ be used in presence of a prototype.
<ref id="free" name="free">, <ref id="free" name="free">,
<ref id="realloc" name="realloc">, <ref id="realloc" name="realloc">,
<ref id="strdup" name="strdup"> <ref id="strdup" name="strdup">
<ref id="strndup" name="strndup">
<tag/Example/None. <tag/Example/None.
</descrip> </descrip>
</quote> </quote>
@@ -7774,6 +7776,35 @@ be used in presence of a prototype.
<tag/See also/ <tag/See also/
<ref id="free" name="free">, <ref id="free" name="free">,
<ref id="malloc" name="malloc"> <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. <tag/Example/None.
</descrip> </descrip>
</quote> </quote>

View File

@@ -79,6 +79,7 @@ void* __fastcall__ __bzero (void* ptr, size_t n);
#if __CC65_STD__ == __CC65_STD_CC65__ #if __CC65_STD__ == __CC65_STD_CC65__
void __fastcall__ bzero (void* ptr, size_t n); /* BSD */ void __fastcall__ bzero (void* ptr, size_t n); /* BSD */
char* __fastcall__ strdup (const char* s); /* SYSV/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__ stricmp (const char* s1, const char* s2); /* DOS/Windows */
int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */ int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */
char* __fastcall__ strcasestr (const char* str, const char* substr); 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__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (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 .import COUT
.export _cputcxy, _cputc, newline, putchar,putchardirect .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__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (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 .constructor initconio
.export _cputcxy, _cputc .export _cputcxy, _cputc

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc
.export plot, cputdirect, putchar .export plot, cputdirect, putchar

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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" .include "atari5200.inc"

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 .export _cputc
.import gotox, gotoy, pusha0 .import gotox, gotoy, pusha0

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc
.export setscrptr, cputdirect, putchar .export setscrptr, cputdirect, putchar

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

@@ -9,7 +9,6 @@
.import push0, callmain .import push0, callmain
.import RESTOR, BSOUT, CLRCH .import RESTOR, BSOUT, CLRCH
.import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__ .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__
.importzp ST
.include "zeropage.inc" .include "zeropage.inc"
.include "c128.inc" .include "c128.inc"
@@ -65,6 +64,15 @@ L1: lda c_sp,x
jsr initlib 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 ; 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 ; *after* calling the constructors because some of them might depend on
; the original value of this register. ; the original value of this register.
@@ -89,10 +97,15 @@ L2: lda zpsave,x
dex dex
bpl L2 bpl L2
; Enable the BASIC interrupt again
lda initsave
sta INIT_STATUS
; Place the program return code into BASIC's status variable. ; Place the program return code into BASIC's status variable.
pla pla
sta ST sta STATUS
; Reset the stack and the memory configuration. ; Reset the stack and the memory configuration.
@@ -116,5 +129,6 @@ zpsave: .res zpspace
.bss .bss
spsave: .res 1 spsave: .res 1
mmusave:.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 initlib, donelib
.import callmain, zerobss .import callmain, zerobss
.import MEMTOP, RESTOR, BSOUT, CLRCH .import MEMTOP, RESTOR, BSOUT, CLRCH
.importzp ST
.include "zeropage.inc" .include "zeropage.inc"
.include "c16.inc"
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; Startup code ; Startup code
@@ -76,7 +76,7 @@ L2: lda zpsave,x
; Store the return code into BASIC's status variable. ; Store the return code into BASIC's status variable.
pla pla
sta ST sta STATUS
; Restore the stack pointer. ; Restore the stack pointer.

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); ; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

@@ -10,9 +10,9 @@
.import BSOUT .import BSOUT
.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; from configure file .import __STACKSIZE__ ; from configure file
.importzp ST
.include "zeropage.inc" .include "zeropage.inc"
.include "c64.inc"
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
@@ -62,7 +62,7 @@ L2: lda zpsave,x
; Place the program return code into BASIC's status variable. ; Place the program return code into BASIC's status variable.
pla pla
sta ST sta STATUS
; Restore the system stuff. ; 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__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .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 isdisk
.import opencmdchannel .import opencmdchannel
.import closecmdchannel .import closecmdchannel
.importzp ST .import initst
.import READST
.importzp tmp2 .importzp tmp2
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
@@ -33,26 +34,25 @@ next: inx
; interpret a non-disk as a no-op while we need to interpret it ; interpret a non-disk as a no-op while we need to interpret it
; as an error here ; as an error here
jsr isdisk jsr isdisk ; carry clear if the unit number in X is a disk
bcs next bcs next
; [open|close]cmdchannel don't call into the Kernal at all if they ; [open|close]cmdchannel don't call into the Kernal at all if they
; only [in|de]crement the reference count of the shared cmdchannel ; only [in|de]crement the reference count of the shared cmdchannel
; so we need to explicitly initialize ST here ; so we need to explicitly initialize ST here
lda #$00 stx tmp2 ; further calls my use X
sta ST
stx tmp2 jsr initst
ldx tmp2 ; get unit number back
jsr opencmdchannel jsr opencmdchannel
ldx tmp2 ldx tmp2 ; get unit number back
jsr closecmdchannel jsr closecmdchannel
ldx tmp2
; As we had to reference ST above anyway we can as well do so ldx tmp2 ; get unit number back
; here too (instead of calling READST)
lda ST jsr READST ; preserves X, returns A and Flags
; Either the Kernal calls above were successful or there was ; Either the Kernal calls above were successful or there was
; already a cmdchannel to the device open - which is a pretty ; 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 cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

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

View File

@@ -22,7 +22,7 @@
sty ktmp sty ktmp
txa txa
ldy #$90 ; FNAM ldy #FNAM
sta (sysp0),y sta (sysp0),y
lda ktmp lda ktmp
@@ -33,13 +33,10 @@
ldy #$92 ; FNAM_SEG ldy #$92 ; FNAM_SEG
sta (sysp0),y sta (sysp0),y
ldy #$9D ; FNAM_LEN ldy #FNAM_LEN
pla pla
sta (sysp0),y sta (sysp0),y
ldy ktmp ldy ktmp
jmp restore_bank jmp restore_bank
.endproc .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 cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .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. ; Place the program return code into BASIC's status variable.
pla pla
ldy #$9C ; ST ldy #STATUS
sta (sysp0),y sta (sysp0),y
; Set up the welcome code at the stack bottom in the system bank. ; Set up the welcome code at the stack bottom in the system bank.

View File

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

View File

@@ -22,7 +22,7 @@
sty ktmp sty ktmp
txa txa
ldy #$90 ; FNAM ldy #FNAM
sta (sysp0),y sta (sysp0),y
lda ktmp lda ktmp
@@ -30,14 +30,13 @@
sta (sysp0),y sta (sysp0),y
lda ExecReg ; Assume name is always in this segment lda ExecReg ; Assume name is always in this segment
ldy #$92 ; FNAM_SEG ldy #FNAM_SEG
sta (sysp0),y sta (sysp0),y
ldy #$9D ; FNAM_LEN ldy #FNAM_LEN
pla pla
sta (sysp0),y sta (sysp0),y
ldy ktmp ldy ktmp
jmp restore_bank jmp restore_bank
.endproc .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 _cputs: sta ptr1 ; Save s
stx ptr1+1 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: L0:
.if .cap(CPU_HAS_ZPIND) .if .cap(CPU_HAS_ZPIND)
lda (ptr1) ; (5) lda (ptr1) ; (5)

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline .export newline

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); ; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

@@ -2,6 +2,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

@@ -21,6 +21,9 @@
; note that there are conflicts between control characters and keyboard: ; note that there are conflicts between control characters and keyboard:
; HOME = KEY_ENTER, KEY_HOME = REV_ON, ; HOME = KEY_ENTER, KEY_HOME = REV_ON,
; UPLINE = ?, KEY_UPARROW = GOTOY, ... ; 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 .export _cputcxy, _cputc
.import gotoxy, fixcursor .import gotoxy, fixcursor

View File

@@ -4,6 +4,8 @@
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); ; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .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 cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline .export newline

View File

@@ -2,6 +2,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

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

View File

@@ -4,6 +4,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

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

View File

@@ -5,14 +5,12 @@
; ;
.export READST .export READST
.importzp ST
.include "pet.inc"
.proc READST .proc READST
lda ST lda STATUS
rts rts
.endproc .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 cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

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

View File

@@ -7,12 +7,11 @@
.export READST .export READST
.include "plus4.inc" .include "plus4.inc"
.importzp ST
; Read the status byte from the zero page instead of banking in the ROM ; Read the status byte from the zero page instead of banking in the ROM
.proc READST .proc READST
lda ST ; Load status lda STATUS ; Load status
rts ; Return to caller rts ; Return to caller
.endproc .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) ; 2018-04-13, Jede (jede@oric.org)
; ;
;
; void cputc (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, _cputcxy, cputdirect, display_conio .export _cputc, _cputcxy, cputdirect, display_conio
.export CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR .export CHARCOLOR, OLD_CHARCOLOR, BGCOLOR, OLD_BGCOLOR

View File

@@ -5,6 +5,8 @@
; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (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 _cputcxy, _cputc, cputdirect, putchar
.export newline, plot .export newline, plot

View File

@@ -10,9 +10,9 @@
.import RESTOR, BSOUT, CLRCH .import RESTOR, BSOUT, CLRCH
.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; Linker generated .import __STACKSIZE__ ; Linker generated
.importzp ST
.include "zeropage.inc" .include "zeropage.inc"
.include "vic20.inc"
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; Startup code ; Startup code
@@ -72,7 +72,7 @@ L2: lda zpsave,x
; Place the program return code into BASIC's status variable. ; Place the program return code into BASIC's status variable.
pla pla
sta ST sta STATUS
; Restore the stack pointer. ; 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 = \ EXELIST_cbm510 = \
ascii \ ascii \
checkversion \ checkversion \
enumdevdir \
gunzip65 \ gunzip65 \
hello \ hello \
joydemo \ joydemo \
@@ -308,6 +309,7 @@ EXELIST_cbm510 = \
EXELIST_cbm610 = \ EXELIST_cbm610 = \
ascii \ ascii \
checkversion \ checkversion \
enumdevdir \
gunzip65 \ gunzip65 \
hello \ hello \
terminal \ terminal \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -38,6 +38,8 @@
#include <stdarg.h> #include <stdarg.h>
/* common */ /* common */
#include "cmdline.h"
#include "consprop.h"
#include "strbuf.h" #include "strbuf.h"
/* ca65 */ /* ca65 */
@@ -45,6 +47,7 @@
#include "filetab.h" #include "filetab.h"
#include "lineinfo.h" #include "lineinfo.h"
#include "nexttok.h" #include "nexttok.h"
#include "spool.h"
@@ -64,6 +67,14 @@ unsigned WarningCount = 0;
/* Maximum number of additional notifications */ /* Maximum number of additional notifications */
#define MAX_NOTES 8 #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, static void ReplaceQuotes (StrBuf* Msg)
const char* Format, va_list ap) /* 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. */ /* 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 */ /* Determine the description for the category and its color */
StrBuf Msg = STATIC_STRBUF_INITIALIZER; 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_VPrintf (&Msg, Format, ap);
SB_Terminate (&Msg); ReplaceQuotes (&Msg);
/* Format the message header */ /* Format the location. If the file position is valid, we use the file
SB_Printf (&S, "%s:%u: %s: ", ** position, otherwise the program name. This allows to print fatal
SB_GetConstBuf (GetFileName (Pos->Name)), ** errors in the startup phase.
Pos->Line, */
Desc); 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 */ /* Format the full message */
SB_Append (&S, &Msg); 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); SB_Done (&Msg);
/* Add a new line and terminate the generated full message */ /* 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) static void AddNotifications (const Collection* LineInfos)
/* Output additional notifications for an error or warning */ /* 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 */ /* Output until an upper limit of messages is reached */
if (Msg) { if (Msg) {
if (Output < MAX_NOTES) { if (Output < MAX_NOTES) {
PrintMsg (GetSourcePos (LI), "Note", "%s", Msg); PNotification (GetSourcePos (LI), "%s", Msg);
++Output; ++Output;
} else { } else {
++Skipped; ++Skipped;
@@ -176,13 +292,43 @@ static void AddNotifications (const Collection* LineInfos)
/* Add a note if we have more stuff that we won't output */ /* Add a note if we have more stuff that we won't output */
if (Skipped > 0) { if (Skipped > 0) {
const LineInfo* LI = CollConstAt (LineInfos, 0); const LineInfo* LI = CollConstAt (LineInfos, 0);
PrintMsg (GetSourcePos (LI), "Note", PNotification (GetSourcePos (LI), "Dropping %u additional line infos",
"Dropping %u additional line infos", Skipped); 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 */ /* Warnings */
/*****************************************************************************/ /*****************************************************************************/
@@ -196,7 +342,7 @@ static void WarningMsg (const Collection* LineInfos, const char* Format, va_list
const LineInfo* LI = CollConstAt (LineInfos, 0); const LineInfo* LI = CollConstAt (LineInfos, 0);
/* Output a warning for this position */ /* Output a warning for this position */
VPrintMsg (GetSourcePos (LI), "Warning", Format, ap); VPrintMsg (GetSourcePos (LI), DC_WARN, Format, ap);
/* Add additional notifications if necessary */ /* Add additional notifications if necessary */
AddNotifications (LineInfos); AddNotifications (LineInfos);
@@ -237,7 +383,7 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
if (Level <= WarnLevel) { if (Level <= WarnLevel) {
va_list ap; va_list ap;
va_start (ap, Format); va_start (ap, Format);
VPrintMsg (Pos, "Warning", Format, ap); VPrintMsg (Pos, DC_WARN, Format, ap);
va_end (ap); va_end (ap);
/* Count warnings */ /* Count warnings */
@@ -274,7 +420,7 @@ void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
const LineInfo* LI = CollConstAt (LineInfos, 0); const LineInfo* LI = CollConstAt (LineInfos, 0);
/* Output an error for this position */ /* Output an error for this position */
VPrintMsg (GetSourcePos (LI), "Error", Format, ap); VPrintMsg (GetSourcePos (LI), DC_ERR, Format, ap);
/* Add additional notifications if necessary */ /* Add additional notifications if necessary */
AddNotifications (LineInfos); AddNotifications (LineInfos);
@@ -311,7 +457,7 @@ void PError (const FilePos* Pos, const char* Format, ...)
{ {
va_list ap; va_list ap;
va_start (ap, Format); va_start (ap, Format);
VPrintMsg (Pos, "Error", Format, ap); VPrintMsg (Pos, DC_ERR, Format, ap);
va_end (ap); va_end (ap);
/* Count errors */ /* Count errors */
@@ -365,18 +511,12 @@ void ErrorSkip (const char* Format, ...)
void Fatal (const char* Format, ...) void Fatal (const char* Format, ...)
/* Print a message about a fatal error and die */ /* Print a message about a fatal error and die */
{ {
/* Output the message ... */
va_list ap; va_list ap;
StrBuf S = STATIC_STRBUF_INITIALIZER;
va_start (ap, Format); va_start (ap, Format);
SB_VPrintf (&S, Format, ap); VPrintMsg (&CurTok.Pos, DC_FATAL, Format, ap);
SB_Terminate (&S);
va_end (ap); va_end (ap);
fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
SB_Done (&S);
/* And die... */ /* And die... */
exit (EXIT_FAILURE); 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))); void Warning (unsigned Level, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print warning message. */ /* 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 */ /* (C) 2025, Kugelfuhr */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -33,24 +30,54 @@
#ifndef INLINE_H #ifndef EXPECT_H
#define INLINE_H #define EXPECT_H
/* ca65 */
#include "token.h"
/*****************************************************************************/ /*****************************************************************************/
/* Defines */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
#if defined(__GNUC__) && !defined(DISABLE_INLINE) void ErrorExpect (const char* Msg);
# define HAVE_INLINE 1 /* Output an error message about some expected token using Msg and the
# define INLINE static __inline__ * description of the following token. This means that Msg should contain
#endif * 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 #endif

View File

@@ -51,6 +51,7 @@
/* ca65 */ /* ca65 */
#include "error.h" #include "error.h"
#include "expect.h"
#include "expr.h" #include "expr.h"
#include "global.h" #include "global.h"
#include "instr.h" #include "instr.h"
@@ -421,8 +422,7 @@ static ExprNode* FuncCapability (void)
capability_t Cap; capability_t Cap;
/* We must have an identifier */ /* We must have an identifier */
if (CurTok.Tok != TOK_IDENT) { if (!Expect (TOK_IDENT, "Expected a capability name")) {
Error ("Arguments to .CAPABILITY must be identifiers");
/* Skip tokens until closing paren or end of line */ /* Skip tokens until closing paren or end of line */
while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) { while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) {
NextTok (); NextTok ();
@@ -779,7 +779,7 @@ static ExprNode* FuncAddrSize (void)
/* Cheap local symbol */ /* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING); Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) { if (Sym == 0) {
Error ("Unknown symbol or scope: '%m%p'", &CurTok.SVal); Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else { } else {
AddrSize = Sym->AddrSize; AddrSize = Sym->AddrSize;
} }
@@ -819,13 +819,13 @@ static ExprNode* FuncAddrSize (void)
if (Sym) { if (Sym) {
AddrSize = Sym->AddrSize; AddrSize = Sym->AddrSize;
} else { } 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) { 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 */ /* Free the string buffers */
@@ -860,7 +860,7 @@ static ExprNode* FuncSizeOf (void)
/* Cheap local symbol */ /* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING); Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) { if (Sym == 0) {
Error ("Unknown symbol or scope: '%m%p'", &CurTok.SVal); Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else { } else {
SizeSym = GetSizeOfSymbol (Sym); SizeSym = GetSizeOfSymbol (Sym);
} }
@@ -912,7 +912,7 @@ static ExprNode* FuncSizeOf (void)
if (Sym) { if (Sym) {
SizeSym = GetSizeOfSymbol (Sym); SizeSym = GetSizeOfSymbol (Sym);
} else { } else {
Error ("Unknown symbol or scope: '%m%p%m%p'", Error ("Unknown symbol or scope: `%m%p%m%p'",
&ScopeName, &Name); &ScopeName, &Name);
} }
} }
@@ -920,7 +920,7 @@ static ExprNode* FuncSizeOf (void)
/* Check if we have a size */ /* Check if we have a size */
if (SizeSym == 0 || !SymIsConst (SizeSym, &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; Size = 0;
} }
@@ -942,8 +942,7 @@ static ExprNode* FuncStrAt (void)
unsigned char C = 0; unsigned char C = 0;
/* String constant expected */ /* String constant expected */
if (CurTok.Tok != TOK_STRCON) { if (!Expect (TOK_STRCON, "Expected a string constant")) {
Error ("String constant expected");
NextTok (); NextTok ();
goto ExitPoint; goto ExitPoint;
} }
@@ -985,9 +984,8 @@ static ExprNode* FuncStrLen (void)
int Len; int Len;
/* String constant expected */ /* String constant expected */
if (CurTok.Tok != TOK_STRCON) { if (!Expect (TOK_STRCON, "Expected a string constant")) {
Error ("String constant expected");
/* Smart error recovery */ /* Smart error recovery */
if (CurTok.Tok != TOK_RPAREN) { if (CurTok.Tok != TOK_RPAREN) {
NextTok (); NextTok ();
@@ -1062,9 +1060,7 @@ static ExprNode* Function (ExprNode* (*F) (void))
NextTok (); NextTok ();
/* Expression must be enclosed in braces */ /* Expression must be enclosed in braces */
if (CurTok.Tok != TOK_LPAREN) { if (!ExpectSkip (TOK_LPAREN, "Expected `('")) {
Error ("'(' expected");
SkipUntilSep ();
return GenLiteral0 (); return GenLiteral0 ();
} }
NextTok (); NextTok ();
@@ -1296,7 +1292,7 @@ static ExprNode* Factor (void)
NextTok (); NextTok ();
} else { } else {
N = GenLiteral0 (); /* Dummy */ N = GenLiteral0 (); /* Dummy */
Error ("Syntax error"); ErrorExpect ("Expected an expression");
} }
break; break;
} }
@@ -1957,9 +1953,8 @@ ExprNode* GenNearAddrExpr (ExprNode* Expr)
if (IsEasyConst (Expr, &Val)) { if (IsEasyConst (Expr, &Val)) {
FreeExpr (Expr); FreeExpr (Expr);
Expr = GenLiteralExpr (Val & 0xFFFF); Expr = GenLiteralExpr (Val & 0xFFFF);
if (Val > 0xFFFF) if (Val > 0xFFFF) {
{ Error ("Range error: constant too large for assumed near address.");
Error("Range error: constant too large for assumed near address.");
} }
} else { } else {
ExprNode* Operand = Expr; 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 we don't have this index, print a diagnostic and use the main file */
if (F == 0) { 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; return 0;
} else { } else {
return F->Index; return F->Index;
@@ -316,7 +316,7 @@ static void CreateDepFile (const char* Name, FileType Types)
/* Open the file */ /* Open the file */
FILE* F = fopen (Name, "w"); FILE* F = fopen (Name, "w");
if (F == 0) { 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 */ /* 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); Emit0 (Ins->BaseCode);
EmitByte (A.Expr); EmitByte (A.Expr);
Consume (TOK_HASH, "'#' expected"); Consume (TOK_HASH, "`#' expected");
EmitByte (Expression ()); EmitByte (Expression ());
} }
@@ -2091,7 +2091,7 @@ static void PutBitBranch_m740 (const InsDesc* Ins)
EffAddr A; EffAddr A;
/* Evaluate the addressing mode used */ /* Evaluate the addressing mode used */
GetEA(&A); GetEA (&A);
/* From the possible addressing modes, remove the ones that are invalid /* From the possible addressing modes, remove the ones that are invalid
** for this instruction or CPU. ** for this instruction or CPU.
@@ -2375,7 +2375,7 @@ static void PutJSR_m740 (const InsDesc* Ins)
/* direct page */ /* direct page */
A.Opcode = 0x22; A.Opcode = 0x22;
Emit0 (A.Opcode); Emit0 (A.Opcode);
EmitByte(GenByteExpr(A.Expr)); EmitByte (GenByteExpr (A.Expr));
return; return;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -113,7 +113,7 @@ static void ObjWriteError (void)
remove (OutFile); remove (OutFile);
/* Now abort with a fatal error */ /* 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 */ /* Create the output file */
F = fopen (OutFile, "w+b"); F = fopen (OutFile, "w+b");
if (F == 0) { 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 */ /* Write a dummy header */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -215,24 +215,32 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
if (S->Flags & SF_IMPORT) { if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */ /* 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; return;
} }
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) { if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
/* Variable symbols cannot be exports or globals */ /* 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; return;
} }
if (S->Flags & SF_DEFINED) { if (S->Flags & SF_DEFINED) {
/* Multiple definition. In case of a variable, this is legal. */ /* Multiple definition. In case of a variable, this is legal. */
if ((S->Flags & SF_VAR) == 0) { 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; S->Flags |= SF_MULTDEF;
return; return;
} else { } else {
/* Redefinition must also be a variable symbol */ /* Redefinition must also be a variable symbol */
if ((Flags & SF_VAR) == 0) { 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; return;
} }
/* Delete the current symbol expression, since it will get /* 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; S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) { } else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */ /* 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), GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize)); AddrSizeToStr (S->ExportSize));
} }
@@ -320,13 +328,13 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */ /* Mark the given symbol as an imported symbol */
{ {
if (S->Flags & SF_DEFINED) { 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; S->Flags |= SF_MULTDEF;
return; return;
} }
if (S->Flags & SF_EXPORT) { if (S->Flags & SF_EXPORT) {
/* The symbol is already marked as exported symbol */ /* 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; return;
} }
@@ -342,16 +350,16 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/ */
if (S->Flags & SF_IMPORT) { if (S->Flags & SF_IMPORT) {
if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) { 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) { 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) { if (S->Flags & SF_GLOBAL) {
S->Flags &= ~SF_GLOBAL; S->Flags &= ~SF_GLOBAL;
if (AddrSize != S->AddrSize) { 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 */ /* Check if it's ok to export the symbol */
if (S->Flags & SF_IMPORT) { if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */ /* 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; return;
} }
if (S->Flags & SF_VAR) { if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported */ /* 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; return;
} }
@@ -388,7 +396,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/ */
if (S->Flags & SF_GLOBAL) { if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) { 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; 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->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
if (S->ExportSize != AddrSize) { 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; S->ExportSize = AddrSize;
@@ -417,7 +425,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
S->ExportSize = S->AddrSize; S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) { } else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */ /* 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), GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize)); AddrSizeToStr (S->ExportSize));
} }
@@ -439,7 +447,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
{ {
if (S->Flags & SF_VAR) { if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */ /* 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; return;
} }
@@ -452,7 +460,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
AddrSize = GetCurrentSegAddrSize (); AddrSize = GetCurrentSegAddrSize ();
} }
if (AddrSize != S->AddrSize) { 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; return;
} }
@@ -464,12 +472,12 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
if ((S->Flags & SF_DEFINED) == 0) { if ((S->Flags & SF_DEFINED) == 0) {
/* Symbol is undefined */ /* Symbol is undefined */
if (AddrSize != S->ExportSize) { 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) { } else if (AddrSize != ADDR_SIZE_DEFAULT) {
/* Symbol is defined and address size given */ /* Symbol is defined and address size given */
if (AddrSize != S->ExportSize) { 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; return;
@@ -481,7 +489,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/ */
if (S->Flags & SF_GLOBAL) { if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) { 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; return;
} }
@@ -499,7 +507,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
S->ExportSize = S->AddrSize; S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) { } else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */ /* 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), GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize)); AddrSizeToStr (S->ExportSize));
} }
@@ -542,12 +550,12 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
/* Check for errors */ /* Check for errors */
if (S->Flags & SF_IMPORT) { if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */ /* 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; return;
} }
if (S->Flags & SF_VAR) { if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */ /* 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; return;
} }
@@ -559,7 +567,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
/* Use the real size of the symbol */ /* Use the real size of the symbol */
AddrSize = S->AddrSize; AddrSize = S->AddrSize;
} else if (S->AddrSize != 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->Flags & (SF_EXPORT | SF_GLOBAL)) {
if (S->ExportSize != AddrSize) { 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; 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] != CD_PRIO_NONE) {
if (S->ConDesPrio[Type] != Prio) { 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; S->ConDesPrio[Type] = Prio;

View File

@@ -42,7 +42,6 @@
#include "cddefs.h" #include "cddefs.h"
#include "coll.h" #include "coll.h"
#include "filepos.h" #include "filepos.h"
#include "inline.h"
#include "strbuf.h" #include "strbuf.h"
/* ca65 */ /* ca65 */
@@ -137,25 +136,17 @@ int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E);
** inserted on the right side. ** inserted on the right side.
*/ */
#if defined(HAVE_INLINE) static inline void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add an expression reference to this symbol */ /* Add an expression reference to this symbol */
{ {
CollAppend (&Sym->ExprRefs, Expr); CollAppend (&Sym->ExprRefs, Expr);
} }
#else
#define SymAddExprRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
#endif
#if defined(HAVE_INLINE) static inline void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Delete an expression reference to this symbol */ /* Delete an expression reference to this symbol */
{ {
CollDeleteItem (&Sym->ExprRefs, Expr); CollDeleteItem (&Sym->ExprRefs, Expr);
} }
#else
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
void SymTransferExprRefs (SymEntry* From, SymEntry* To); void SymTransferExprRefs (SymEntry* From, SymEntry* To);
/* Transfer all expression references from one symbol to another. */ /* Transfer all expression references from one symbol to another. */
@@ -199,107 +190,71 @@ void SymImportFromGlobal (SymEntry* S);
** into an import. ** into an import.
*/ */
#if defined(HAVE_INLINE) static inline int SymIsDef (const SymEntry* S)
INLINE int SymIsDef (const SymEntry* S)
/* Return true if the given symbol is already defined */ /* Return true if the given symbol is already defined */
{ {
return (S->Flags & SF_DEFINED) != 0; return (S->Flags & SF_DEFINED) != 0;
} }
#else
# define SymIsDef(S) (((S)->Flags & SF_DEFINED) != 0)
#endif
#if defined(HAVE_INLINE) static inline int SymIsRef (const SymEntry* S)
INLINE int SymIsRef (const SymEntry* S)
/* Return true if the given symbol has been referenced */ /* Return true if the given symbol has been referenced */
{ {
return (S->Flags & SF_REFERENCED) != 0; return (S->Flags & SF_REFERENCED) != 0;
} }
#else
# define SymIsRef(S) (((S)->Flags & SF_REFERENCED) != 0)
#endif
#if defined(HAVE_INLINE) static inline int SymIsImport (const SymEntry* S)
INLINE int SymIsImport (const SymEntry* S)
/* Return true if the given symbol is marked as import */ /* Return true if the given symbol is marked as import */
{ {
/* Check the import flag */ /* Check the import flag */
return (S->Flags & SF_IMPORT) != 0; return (S->Flags & SF_IMPORT) != 0;
} }
#else
# define SymIsImport(S) (((S)->Flags & SF_IMPORT) != 0)
#endif
#if defined(HAVE_INLINE) static inline int SymIsExport (const SymEntry* S)
INLINE int SymIsExport (const SymEntry* S)
/* Return true if the given symbol is marked as export */ /* Return true if the given symbol is marked as export */
{ {
/* Check the export flag */ /* Check the export flag */
return (S->Flags & SF_EXPORT) != 0; return (S->Flags & SF_EXPORT) != 0;
} }
#else
# define SymIsExport(S) (((S)->Flags & SF_EXPORT) != 0)
#endif
#if defined(HAVE_INLINE) static inline int SymIsVar (const SymEntry* S)
INLINE int SymIsVar (const SymEntry* S)
/* Return true if the given symbol is marked as variable */ /* Return true if the given symbol is marked as variable */
{ {
/* Check the variable flag */ /* Check the variable flag */
return (S->Flags & SF_VAR) != 0; return (S->Flags & SF_VAR) != 0;
} }
#else
# define SymIsVar(S) (((S)->Flags & SF_VAR) != 0)
#endif
int SymIsConst (const SymEntry* Sym, long* Val); int SymIsConst (const SymEntry* Sym, long* Val);
/* Return true if the given symbol has a constant value. If Val is not NULL /* 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. ** and the symbol has a constant value, store it's value there.
*/ */
#if defined(HAVE_INLINE) static inline int SymHasExpr (const SymEntry* S)
INLINE int SymHasExpr (const SymEntry* S)
/* Return true if the given symbol has an associated expression */ /* Return true if the given symbol has an associated expression */
{ {
/* Check the expression */ /* Check the expression */
return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED); 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) static inline void SymMarkUser (SymEntry* S)
INLINE void SymMarkUser (SymEntry* S)
/* Set a user mark on the specified symbol */ /* Set a user mark on the specified symbol */
{ {
/* Set the bit */ /* Set the bit */
S->Flags |= SF_USER; S->Flags |= SF_USER;
} }
#else
# define SymMarkUser(S) ((S)->Flags |= SF_USER)
#endif
#if defined(HAVE_INLINE) static inline void SymUnmarkUser (SymEntry* S)
INLINE void SymUnmarkUser (SymEntry* S)
/* Remove a user mark from the specified symbol */ /* Remove a user mark from the specified symbol */
{ {
/* Reset the bit */ /* Reset the bit */
S->Flags &= ~SF_USER; S->Flags &= ~SF_USER;
} }
#else
# define SymUnmarkUser(S) ((S)->Flags &= ~SF_USER)
#endif
#if defined(HAVE_INLINE) static inline int SymHasUserMark (SymEntry* S)
INLINE int SymHasUserMark (SymEntry* S)
/* Return the state of the user mark for the specified symbol */ /* Return the state of the user mark for the specified symbol */
{ {
/* Check the bit */ /* Check the bit */
return (S->Flags & SF_USER) != 0; return (S->Flags & SF_USER) != 0;
} }
#else
# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0)
#endif
struct SymTable* GetSymParentScope (SymEntry* S); struct SymTable* GetSymParentScope (SymEntry* S);
/* Get the parent scope of the symbol (not the one it is defined in). Return /* 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! ** NULL. Do not call in other contexts!
*/ */
#if defined(HAVE_INLINE) static inline const StrBuf* GetSymName (const SymEntry* S)
INLINE const StrBuf* GetSymName (const SymEntry* S)
/* Return the name of the symbol */ /* Return the name of the symbol */
{ {
return GetStrBuf (S->Name); return GetStrBuf (S->Name);
} }
#else
# define GetSymName(S) GetStrBuf ((S)->Name)
#endif
#if defined(HAVE_INLINE) static inline unsigned char GetSymAddrSize (const SymEntry* S)
INLINE unsigned char GetSymAddrSize (const SymEntry* S)
/* Return the address size of the symbol. Beware: This function will just /* Return the address size of the symbol. Beware: This function will just
** return the AddrSize member, it will not look at the expression! ** return the AddrSize member, it will not look at the expression!
*/ */
{ {
return S->AddrSize; return S->AddrSize;
} }
#else
# define GetSymAddrSize(S) ((S)->AddrSize)
#endif
long GetSymVal (SymEntry* Sym); long GetSymVal (SymEntry* Sym);
/* Return the value of a symbol assuming it's constant. FAIL will be called /* 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 { } else {
/* Duplicate scope name */ /* 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 */ /* Check if the scope has been defined before */
if (CurrentScope->Flags & ST_DEFINED) { if (CurrentScope->Flags & ST_DEFINED) {
Error ("Duplicate scope '%m%p'", ScopeName); Error ("Duplicate scope `%m%p'", ScopeName);
} }
} else { } else {
@@ -502,7 +502,7 @@ static void SymCheckUndefined (SymEntry* S)
if (Sym->Flags & SF_IMPORT) { if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as import */ /* The symbol is already marked as import */
LIError (&S->RefLines, LIError (&S->RefLines,
"Symbol '%s' is already an import", "Symbol `%s' is already an import",
GetString (Sym->Name)); GetString (Sym->Name));
} }
if ((Sym->Flags & SF_EXPORT) == 0) { if ((Sym->Flags & SF_EXPORT) == 0) {
@@ -516,7 +516,7 @@ static void SymCheckUndefined (SymEntry* S)
if (Sym->AddrSize > Sym->ExportSize) { if (Sym->AddrSize > Sym->ExportSize) {
/* We're exporting a symbol smaller than it actually is */ /* We're exporting a symbol smaller than it actually is */
LIWarning (&Sym->DefLines, 1, LIWarning (&Sym->DefLines, 1,
"Symbol '%m%p' is %s but exported %s", "Symbol `%m%p' is %s but exported %s",
GetSymName (Sym), GetSymName (Sym),
AddrSizeToStr (Sym->AddrSize), AddrSizeToStr (Sym->AddrSize),
AddrSizeToStr (Sym->ExportSize)); AddrSizeToStr (Sym->ExportSize));
@@ -541,7 +541,7 @@ static void SymCheckUndefined (SymEntry* S)
if (S->Flags & SF_EXPORT) { if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */ /* We will not auto-import an export */
LIError (&S->RefLines, LIError (&S->RefLines,
"Exported symbol '%m%p' was never defined", "Exported symbol `%m%p' was never defined",
GetSymName (S)); GetSymName (S));
} else { } else {
if (AutoImport) { if (AutoImport) {
@@ -554,7 +554,7 @@ static void SymCheckUndefined (SymEntry* S)
} else { } else {
/* Error */ /* Error */
LIError (&S->RefLines, LIError (&S->RefLines,
"Symbol '%m%p' is undefined", "Symbol `%m%p' is undefined",
GetSymName (S)); GetSymName (S));
} }
} }
@@ -573,13 +573,13 @@ void SymCheck (void)
if (CurrentScope->Label) { if (CurrentScope->Label) {
/* proc has a label indicating the line it was opened. */ /* proc has a label indicating the line it was opened. */
LIError (&CurrentScope->Label->DefLines, LIError (&CurrentScope->Label->DefLines,
"Local proc '%s' was not closed", "Local proc `%s' was not closed",
GetString (CurrentScope->Name)); GetString (CurrentScope->Name));
} else { } else {
/* scope has no label to track a line number, uses end-of-document line instead. /* scope has no label to track a line number, uses end-of-document line instead.
** Anonymous scopes will reveal their internal automatic name. ** 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)); GetString (CurrentScope->Name));
} }
} }
@@ -627,7 +627,7 @@ void SymCheck (void)
ReleaseFullLineInfo (&S->RefLines); ReleaseFullLineInfo (&S->RefLines);
} else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) { } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
LIWarning (&S->DefLines, 2, LIWarning (&S->DefLines, 2,
"Symbol '%m%p' is defined but never used", "Symbol `%m%p' is defined but never used",
GetSymName (S)); GetSymName (S));
} }
@@ -636,7 +636,7 @@ void SymCheck (void)
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) { if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
/* Imported symbol is not referenced */ /* Imported symbol is not referenced */
LIWarning (&S->DefLines, 2, LIWarning (&S->DefLines, 2,
"Symbol '%m%p' is imported but never used", "Symbol `%m%p' is imported but never used",
GetSymName (S)); GetSymName (S));
} else { } else {
/* Give the import an id, count imports */ /* Give the import an id, count imports */
@@ -664,7 +664,7 @@ void SymCheck (void)
} else if (S->AddrSize > S->ExportSize) { } else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */ /* We're exporting a symbol smaller than it actually is */
LIWarning (&S->DefLines, 1, LIWarning (&S->DefLines, 1,
"Symbol '%m%p' is %s but exported %s", "Symbol `%m%p' is %s but exported %s",
GetSymName (S), GetSymName (S),
AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize)); AddrSizeToStr (S->ExportSize));
@@ -684,7 +684,7 @@ void SymCheck (void)
const FilePos* P = S->GuessedUse[S->AddrSize - 1]; const FilePos* P = S->GuessedUse[S->AddrSize - 1];
if (P) { if (P) {
PWarning (P, 0, PWarning (P, 0,
"Didn't use %s addressing for '%m%p'", "Didn't use %s addressing for `%m%p'",
AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->AddrSize),
GetSymName (S)); GetSymName (S));
} }

View File

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

View File

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

View File

@@ -111,7 +111,7 @@ ExprNode* ULabRef (int Which)
if (Which == 0) { if (Which == 0) {
Error ("Invalid unnamed label reference"); Error ("Invalid unnamed label reference");
/* We must return something valid */ /* We must return something valid */
return GenCurrentPC(); return GenCurrentPC ();
} }
/* Get the index of the referenced label */ /* Get the index of the referenced label */
@@ -125,7 +125,7 @@ ExprNode* ULabRef (int Which)
/* Label does not exist */ /* Label does not exist */
Error ("Undefined label"); Error ("Undefined label");
/* We must return something valid */ /* We must return something valid */
return GenCurrentPC(); return GenCurrentPC ();
} }
/* Check if the label exists. If not, generate enough forward labels. */ /* 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); void FreeCaseNode (CaseNode* N);
/* Delete a case node plus all sub nodes */ /* Delete a case node plus all sub nodes */
#if defined(HAVE_INLINE) static inline CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index)
INLINE CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index)
/* Get a sub node of the given node */ /* Get a sub node of the given node */
{ {
return CollAt (N->Nodes, Index); return CollAt (N->Nodes, Index);
} }
#else
# define CN_GetSubNode(N, Index) CollAt (&(N)->Nodes, Index)
#endif
#if defined(HAVE_INLINE) static inline unsigned char CN_GetValue (const CaseNode* N)
INLINE unsigned char CN_GetValue (const CaseNode* N)
/* Return the value for a case node */ /* Return the value for a case node */
{ {
return N->Value; return N->Value;
} }
#else
# define CN_GetValue(N) ((N)->Value)
#endif
#if defined(HAVE_INLINE) static inline unsigned CN_GetLabel (const CaseNode* N)
INLINE unsigned CN_GetLabel (const CaseNode* N)
/* Return the label for a case node */ /* Return the label for a case node */
{ {
return N->Label; return N->Label;
} }
#else
# define CN_GetLabel(N) ((N)->Label)
#endif
#if defined(HAVE_INLINE) static inline int CN_IsLeafNode (const CaseNode* N)
INLINE int CN_IsLeafNode (const CaseNode* N)
/* Return true if this is a leaf node */ /* Return true if this is a leaf node */
{ {
return (N->Nodes == 0); return (N->Nodes == 0);
} }
#else
# define CN_IsLeafNode(N) ((N)->Nodes == 0)
#endif
void FreeCaseNodeColl (Collection* Nodes); void FreeCaseNodeColl (Collection* Nodes);
/* Free a collection of case nodes */ /* Free a collection of case nodes */

View File

@@ -42,7 +42,6 @@
/* common */ /* common */
#include "coll.h" #include "coll.h"
#include "inline.h"
/* cc65 */ /* cc65 */
#include "codelab.h" #include "codelab.h"
@@ -150,88 +149,56 @@ void CE_ClearJumpTo (CodeEntry* E);
** so use it with care. ** so use it with care.
*/ */
#if defined(HAVE_INLINE) static inline int CE_HasLabel (const CodeEntry* E)
INLINE int CE_HasLabel (const CodeEntry* E)
/* Check if the given code entry has labels attached */ /* Check if the given code entry has labels attached */
{ {
return (CollCount (&E->Labels) > 0); return (CollCount (&E->Labels) > 0);
} }
#else
# define CE_HasLabel(E) (CollCount (&(E)->Labels) > 0)
#endif
#if defined(HAVE_INLINE) static inline unsigned CE_GetLabelCount (const CodeEntry* E)
INLINE unsigned CE_GetLabelCount (const CodeEntry* E)
/* Get the number of labels attached to this entry */ /* Get the number of labels attached to this entry */
{ {
return CollCount (&E->Labels); return CollCount (&E->Labels);
} }
#else
# define CE_GetLabelCount(E) CollCount (&(E)->Labels)
#endif
#if defined(HAVE_INLINE) static inline CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index)
INLINE CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index)
/* Get a label from this code entry */ /* Get a label from this code entry */
{ {
return CollAt (&E->Labels, Index); return CollAt (&E->Labels, Index);
} }
#else
# define CE_GetLabel(E, Index) CollAt (&(E)->Labels, (Index))
#endif
#if defined(HAVE_INLINE) static inline void CE_ReplaceLabel (CodeEntry* E, CodeLabel* L, unsigned Index)
INLINE void CE_ReplaceLabel (CodeEntry* E, CodeLabel* L, unsigned Index)
/* Replace the code label at the specified index with L */ /* Replace the code label at the specified index with L */
{ {
CollReplace (&E->Labels, L, Index); 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); void CE_MoveLabel (CodeLabel* L, CodeEntry* E);
/* Move the code label L from it's former owner to the code entry E. */ /* Move the code label L from it's former owner to the code entry E. */
#if defined(HAVE_INLINE) static inline int CE_HasMark (const CodeEntry* E)
INLINE int CE_HasMark (const CodeEntry* E)
/* Return true if the given code entry has the CEF_USERMARK flag set */ /* Return true if the given code entry has the CEF_USERMARK flag set */
{ {
return (E->Flags & CEF_USERMARK) != 0; return (E->Flags & CEF_USERMARK) != 0;
} }
#else
# define CE_HasMark(E) (((E)->Flags & CEF_USERMARK) != 0)
#endif
#if defined(HAVE_INLINE) static inline void CE_SetMark (CodeEntry* E)
INLINE void CE_SetMark (CodeEntry* E)
/* Set the CEF_USERMARK flag for the given entry */ /* Set the CEF_USERMARK flag for the given entry */
{ {
E->Flags |= CEF_USERMARK; E->Flags |= CEF_USERMARK;
} }
#else
# define CE_SetMark(E) ((E)->Flags |= CEF_USERMARK)
#endif
#if defined(HAVE_INLINE) static inline void CE_ResetMark (CodeEntry* E)
INLINE void CE_ResetMark (CodeEntry* E)
/* Reset the CEF_USERMARK flag for the given entry */ /* Reset the CEF_USERMARK flag for the given entry */
{ {
E->Flags &= ~CEF_USERMARK; E->Flags &= ~CEF_USERMARK;
} }
#else
# define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK)
#endif
#if defined(HAVE_INLINE) static inline int CE_HasNumArg (const CodeEntry* E)
INLINE int CE_HasNumArg (const CodeEntry* E)
/* Return true if the instruction has a numeric argument */ /* Return true if the instruction has a numeric argument */
{ {
return (E->Flags & CEF_NUMARG) != 0; 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); void CE_SetArg (CodeEntry* E, const char* Arg);
/* Replace the argument by the new one. */ /* Replace the argument by the new one. */
@@ -271,15 +238,11 @@ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num);
** equal to Num. ** equal to Num.
*/ */
#if defined(HAVE_INLINE) static inline int CE_IsCallTo (const CodeEntry* E, const char* Name)
INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name)
/* Check if this is a call to the given function */ /* Check if this is a call to the given function */
{ {
return (E->OPC == OP65_JSR && strcmp (E->Arg, Name) == 0); 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); int CE_UseLoadFlags (CodeEntry* E);
/* Return true if the instruction uses any flags that are set by a load of /* 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); void FreeCodeLabel (CodeLabel* L);
/* Free the given code label */ /* Free the given code label */
#if defined(HAVE_INLINE) static inline unsigned CL_GetRefCount (const CodeLabel* L)
INLINE unsigned CL_GetRefCount (const CodeLabel* L)
/* Get the number of references for this label */ /* Get the number of references for this label */
{ {
return CollCount (&L->JumpFrom); return CollCount (&L->JumpFrom);
} }
#else
# define CL_GetRefCount(L) CollCount (&(L)->JumpFrom)
#endif
#if defined(HAVE_INLINE) static inline struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
INLINE struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
/* Get a code entry referencing this label */ /* Get a code entry referencing this label */
{ {
return CollAt (&L->JumpFrom, Index); return CollAt (&L->JumpFrom, Index);
} }
#else
# define CL_GetRef(L, Index) CollAt (&(L)->JumpFrom, (Index))
#endif
void CL_AddRef (CodeLabel* L, struct CodeEntry* E); void CL_AddRef (CodeLabel* L, struct CodeEntry* E);
/* Let the CodeEntry E reference the label L */ /* 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 DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 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 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 DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 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 }; static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0, 0, 0, 0, 0 };
@@ -236,6 +238,7 @@ static OptFunc* OptFuncs[] = {
&DOptAdd4, &DOptAdd4,
&DOptAdd5, &DOptAdd5,
&DOptAdd6, &DOptAdd6,
&DOptAXOps,
&DOptBNegA1, &DOptBNegA1,
&DOptBNegA2, &DOptBNegA2,
&DOptBNegAX1, &DOptBNegAX1,
@@ -629,6 +632,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
Changes += RunOptFunc (S, &DOptGotoSPAdj, 1); Changes += RunOptFunc (S, &DOptGotoSPAdj, 1);
Changes += RunOptFunc (S, &DOptStackPtrOps, 5); Changes += RunOptFunc (S, &DOptStackPtrOps, 5);
Changes += RunOptFunc (S, &DOptAXOps, 5);
Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */ Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */
Changes += RunOptFunc (S, &DOptPtrStore1, 1); Changes += RunOptFunc (S, &DOptPtrStore1, 1);
Changes += RunOptFunc (S, &DOptPtrStore2, 1); Changes += RunOptFunc (S, &DOptPtrStore2, 1);
@@ -871,6 +875,7 @@ static unsigned RunOptGroup7 (CodeSeg* S)
** may have opened new oportunities. ** may have opened new oportunities.
*/ */
Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
Changes += RunOptFunc (S, &DOptAXLoad, 5);
Changes += RunOptFunc (S, &DOptUnusedStores, 1); Changes += RunOptFunc (S, &DOptUnusedStores, 1);
Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
Changes += RunOptFunc (S, &DOptStore5, 1); Changes += RunOptFunc (S, &DOptStore5, 1);
@@ -907,6 +912,11 @@ static unsigned RunOptGroup7 (CodeSeg* S)
between branches */ between branches */
C += RunOptFunc (S, &DOptBranchDist, 3); 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; Changes += C;
/* If we had changes, we must run dead code elimination again, /* If we had changes, we must run dead code elimination again,
** since the changes may have introduced dead code. ** since the changes may have introduced dead code.

View File

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