Merge branch 'master' into seglist
This commit is contained in:
122
Code_of_Conduct.md
Normal file
122
Code_of_Conduct.md
Normal 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
|
||||||
@@ -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
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
117
doc/ca65.sgml
117
doc/ca65.sgml
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
21
libsrc/cbm510/status.s
Normal 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
21
libsrc/cbm610/status.s
Normal 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
53
libsrc/common/strndup.s
Normal 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
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 ();
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
222
src/ca65/error.c
222
src/ca65/error.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
116
src/ca65/expect.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
124
src/ca65/macro.c
124
src/ca65/macro.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
304
src/ca65/token.c
304
src/ca65/token.c
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
156
src/ca65/token.h
156
src/ca65/token.h
@@ -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 */
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user