mirror of
https://github.com/cc65/cc65.git
synced 2025-04-12 00:37:12 +00:00
Merge pull request #2009 from bbbradsmith/ca65_feature_disable
ca65: allow .feature to both enable and disable
This commit is contained in:
commit
c0559dd931
@ -2758,15 +2758,19 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
|
||||
This directive may be used to enable one or more compatibility features
|
||||
of the assembler. While the use of <tt/.FEATURE/ should be avoided when
|
||||
possible, it may be useful when porting sources written for other
|
||||
assemblers. There is no way to switch a feature off, once you have
|
||||
enabled it, so using
|
||||
assemblers. After the feature name an optional '+' or '-' may specify whether
|
||||
to enable or disable the feature (enable if omitted). Multiple features may be
|
||||
enabled, separated by commas. Examples:
|
||||
|
||||
<tscreen><verb>
|
||||
.FEATURE xxx
|
||||
; enable c_comments
|
||||
.feature c_comments
|
||||
.feature c_comments +
|
||||
; enable force_range, disable underline_in_numbers, enable labels_without_colons
|
||||
.feature force_range, underline_in_numbers -, labels_without_colons +
|
||||
.feature force_range +, underline_in_numbers off, labels_without_colons on
|
||||
</verb></tscreen>
|
||||
|
||||
will enable the feature until end of assembly is reached.
|
||||
|
||||
The following features are available:
|
||||
|
||||
<descrip>
|
||||
|
@ -98,38 +98,30 @@ feature_t FindFeature (const StrBuf* Key)
|
||||
|
||||
|
||||
|
||||
feature_t SetFeature (const StrBuf* Key)
|
||||
/* Find the feature and set the corresponding flag if the feature is known.
|
||||
** In any case, return the feature found. An invalid Key will return
|
||||
** FEAT_UNKNOWN.
|
||||
void SetFeature (feature_t Feature, unsigned char On)
|
||||
/* Set the corresponding feature flag if Feature is valid.
|
||||
*/
|
||||
{
|
||||
/* Map the string to an enum value */
|
||||
feature_t Feature = FindFeature (Key);
|
||||
|
||||
/* Set the flags */
|
||||
switch (Feature) {
|
||||
case FEAT_DOLLAR_IS_PC: DollarIsPC = 1; break;
|
||||
case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = 1; break;
|
||||
case FEAT_LOOSE_STRING_TERM: LooseStringTerm = 1; break;
|
||||
case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = 1; break;
|
||||
case FEAT_AT_IN_IDENTIFIERS: AtInIdents = 1; break;
|
||||
case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = 1; break;
|
||||
case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= 1; break;
|
||||
case FEAT_ORG_PER_SEG: OrgPerSeg = 1; break;
|
||||
case FEAT_PC_ASSIGNMENT: PCAssignment = 1; break;
|
||||
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break;
|
||||
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break;
|
||||
case FEAT_C_COMMENTS: CComments = 1; break;
|
||||
case FEAT_FORCE_RANGE: ForceRange = 1; break;
|
||||
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break;
|
||||
case FEAT_ADDRSIZE: AddrSize = 1; break;
|
||||
case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break;
|
||||
case FEAT_STRING_ESCAPES: StringEscapes = 1; break;
|
||||
case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = 1; break;
|
||||
default: /* Keep gcc silent */ break;
|
||||
case FEAT_DOLLAR_IS_PC: DollarIsPC = On; break;
|
||||
case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = On; break;
|
||||
case FEAT_LOOSE_STRING_TERM: LooseStringTerm = On; break;
|
||||
case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = On; break;
|
||||
case FEAT_AT_IN_IDENTIFIERS: AtInIdents = On; break;
|
||||
case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = On; break;
|
||||
case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= On; break;
|
||||
case FEAT_ORG_PER_SEG: OrgPerSeg = On; break;
|
||||
case FEAT_PC_ASSIGNMENT: PCAssignment = On; break;
|
||||
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = On; break;
|
||||
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = On; break;
|
||||
case FEAT_C_COMMENTS: CComments = On; break;
|
||||
case FEAT_FORCE_RANGE: ForceRange = On; break;
|
||||
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= On; break;
|
||||
case FEAT_ADDRSIZE: AddrSize = On; break;
|
||||
case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = On; break;
|
||||
case FEAT_STRING_ESCAPES: StringEscapes = On; break;
|
||||
case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = On; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* Return the value found */
|
||||
return Feature;
|
||||
}
|
||||
|
@ -87,10 +87,8 @@ feature_t FindFeature (const StrBuf* Key);
|
||||
** feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
|
||||
feature_t SetFeature (const StrBuf* Key);
|
||||
/* Find the feature and set the corresponding flag if the feature is known.
|
||||
** In any case, return the feature found. An invalid Key will return
|
||||
** FEAT_UNKNOWN.
|
||||
void SetFeature (feature_t Feature, unsigned char On);
|
||||
/* Set the corresponding feature flag if Feature is valid.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -489,12 +489,15 @@ static void OptDebugInfo (const char* Opt attribute ((unused)),
|
||||
static void OptFeature (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Set an emulation feature */
|
||||
{
|
||||
/* Make a string buffer from Arg */
|
||||
StrBuf Feature;
|
||||
/* Make a string buffer from Arg and use it to find the feature. */
|
||||
StrBuf StrFeature;
|
||||
feature_t Feature = FindFeature (SB_InitFromString (&StrFeature, Arg));
|
||||
|
||||
/* Set the feature, check for errors */
|
||||
if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) {
|
||||
/* Enable the feature, check for errors */
|
||||
if (Feature == FEAT_UNKNOWN) {
|
||||
AbEnd ("Illegal emulation feature: '%s'", Arg);
|
||||
} else {
|
||||
SetFeature (Feature, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1023,7 +1023,10 @@ static void DoFatal (void)
|
||||
static void DoFeature (void)
|
||||
/* Switch the Feature option */
|
||||
{
|
||||
/* Allow a list of comma separated keywords */
|
||||
feature_t Feature;
|
||||
unsigned char On;
|
||||
|
||||
/* Allow a list of comma separated feature keywords with optional +/- or ON/OFF */
|
||||
while (1) {
|
||||
|
||||
/* We expect an identifier */
|
||||
@ -1034,18 +1037,24 @@ static void DoFeature (void)
|
||||
|
||||
/* Make the string attribute lower case */
|
||||
LocaseSVal ();
|
||||
|
||||
/* Set the feature and check for errors */
|
||||
if (SetFeature (&CurTok.SVal) == FEAT_UNKNOWN) {
|
||||
Feature = FindFeature(&CurTok.SVal);
|
||||
if (Feature == FEAT_UNKNOWN) {
|
||||
/* Not found */
|
||||
ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal);
|
||||
return;
|
||||
} else {
|
||||
/* Skip the keyword */
|
||||
NextTok ();
|
||||
}
|
||||
NextTok ();
|
||||
|
||||
/* Optional +/- or ON/OFF */
|
||||
On = 1;
|
||||
if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) {
|
||||
SetBoolOption(&On);
|
||||
}
|
||||
|
||||
/* Allow more than one keyword */
|
||||
/* Apply feature setting. */
|
||||
SetFeature (Feature, On);
|
||||
|
||||
/* Allow more than one feature separated by commas. */
|
||||
if (CurTok.Tok == TOK_COMMA) {
|
||||
NextTok ();
|
||||
} else {
|
||||
|
8
test/asm/listing/108-long-rts.s
Normal file
8
test/asm/listing/108-long-rts.s
Normal file
@ -0,0 +1,8 @@
|
||||
; test of long-rts promotion
|
||||
|
||||
.p816
|
||||
.feature long_jsr_jmp_rts
|
||||
.smart +
|
||||
.proc farproc : far
|
||||
rts ; should be $6B (RTL) and not $60 (RTS)
|
||||
.endproc
|
@ -6,22 +6,38 @@ The name of a test is everything in the form <test>.s.
|
||||
|
||||
The following reference files can be added:
|
||||
|
||||
- <test>.bin-ref:
|
||||
- ref/<test>.bin-ref:
|
||||
This is a reference for the resulting binary.
|
||||
The binary as binary tested against this file.
|
||||
If they are not equal, the test fails.
|
||||
|
||||
- <test>.list-ref
|
||||
- ref/<test>.list-ref
|
||||
This is a reference for the resulting listing output
|
||||
This file *must* have the first line of the listing removed, as that
|
||||
contains a ca65 version string, and almost always this will be changed!
|
||||
|
||||
- ref/<test>.err-ref
|
||||
This is a reference for the resulting ca65 stdout (>) output.
|
||||
|
||||
- ref/<test>.err2-ref
|
||||
This is a reference for the resulting ca65 stderr (2>) output.
|
||||
|
||||
- ref/<test>.ld65err-ref
|
||||
This is a reference for the resutling ld65 stdout (>) output.
|
||||
|
||||
- ref/<test>.ld65err2-ref
|
||||
This is a reference for the resulting ld65 stderr (2>) output.
|
||||
|
||||
The following control files can be added to control the tests.
|
||||
These files are empty (contents ignored), and only the filename is used:
|
||||
|
||||
- control/<test>.err
|
||||
Test is expected to produce an error.
|
||||
|
||||
- control/<test>.no-ld65
|
||||
Skip the ld65 step.
|
||||
|
||||
|
||||
Note that the resulting .bin file is generated twice: Once with no listing
|
||||
file, and once with listing file. This way, one can find out if the listing
|
||||
file generation changes anything with the resulting binary output.
|
||||
|
||||
|
||||
TODO:
|
||||
- add the possibility to test for specific error output that are to be
|
||||
expected
|
||||
|
1
test/asm/listing/ref/108-long-rts.bin-ref
Normal file
1
test/asm/listing/ref/108-long-rts.bin-ref
Normal file
@ -0,0 +1 @@
|
||||
k
|
147
test/asm/val/feature.s
Normal file
147
test/asm/val/feature.s
Normal file
@ -0,0 +1,147 @@
|
||||
; a simple test of every .feature
|
||||
|
||||
.export _main
|
||||
|
||||
.segment "ZEROPAGE"
|
||||
zplabel:
|
||||
|
||||
.segment "CODE"
|
||||
abslabel:
|
||||
|
||||
; exit with 0
|
||||
|
||||
_main:
|
||||
; if any feature needs a runtime test,
|
||||
; it can be added here.
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
|
||||
.feature addrsize +
|
||||
.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE"
|
||||
.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute"
|
||||
.feature addrsize -
|
||||
|
||||
|
||||
.feature at_in_identifiers on
|
||||
ident@with@at:
|
||||
rts
|
||||
.feature at_in_identifiers off
|
||||
|
||||
|
||||
.feature bracket_as_indirect
|
||||
lda [$82],y
|
||||
.feature bracket_as_indirect-
|
||||
|
||||
|
||||
.feature c_comments
|
||||
lda zplabel /* comment */
|
||||
/* comment */
|
||||
/* multiline
|
||||
** comment
|
||||
*/
|
||||
.feature c_comments -
|
||||
|
||||
|
||||
.feature dollar_in_identifiers
|
||||
ident$with$dollar:
|
||||
rts
|
||||
.feature dollar_in_identifiers -
|
||||
|
||||
|
||||
.feature dollar_is_pc
|
||||
.assert $ = *, error, "dollar_is_pc failure"
|
||||
.feature dollar_is_pc -
|
||||
|
||||
|
||||
.feature force_range
|
||||
lda #-1
|
||||
.feature force_range -
|
||||
|
||||
|
||||
.feature labels_without_colons
|
||||
labelwithoutcolon
|
||||
jmp labelwithoutcolon
|
||||
.feature labels_without_colons -
|
||||
|
||||
|
||||
.feature leading_dot_in_identifiers
|
||||
.identifierwithdot:
|
||||
rts
|
||||
.feature leading_dot_in_identifiers -
|
||||
|
||||
|
||||
.feature long_jsr_jmp_rts
|
||||
.p816
|
||||
; long addresses require alternate instruction names JSL, JML without this feature
|
||||
jsr $123456
|
||||
jmp $123456
|
||||
; smart + far + long_jsr_jmp_rts will promote rts to rtl
|
||||
.smart +
|
||||
.proc long_rts : far
|
||||
rts ; should become RTL ($6B) instead of RTS ($60)
|
||||
; the emitted opcode is not verified by this test,
|
||||
; see test/asm/listing/108-long-rts
|
||||
.endproc
|
||||
.smart -
|
||||
.p02
|
||||
.feature long_jsr_jmp_rts -
|
||||
|
||||
|
||||
.feature loose_char_term
|
||||
.byte 'a'
|
||||
.byte "a"
|
||||
.feature loose_char_term -
|
||||
|
||||
|
||||
.feature loose_string_term
|
||||
.asciiz "string"
|
||||
.asciiz 'string'
|
||||
.feature loose_string_term -
|
||||
|
||||
|
||||
.feature missing_char_term
|
||||
lda #'a
|
||||
.feature missing_char_term -
|
||||
|
||||
|
||||
.feature org_per_seg
|
||||
.segment "RODATA"
|
||||
.org $5678
|
||||
.assert * = $5678, error, "org_per_seg failed"
|
||||
.segment "CODE"
|
||||
.org $9ABC
|
||||
.assert * = $9ABC, error, "org_per_seg failed"
|
||||
.segment "RODATA"
|
||||
.assert * = $5678, error, "org_per_seg failed"
|
||||
.reloc
|
||||
.segment "CODE"
|
||||
.assert * = $9ABC, error, "org_per_seg failed"
|
||||
.reloc
|
||||
.feature org_per_seg -
|
||||
|
||||
|
||||
.feature pc_assignment
|
||||
* = $1234
|
||||
.assert * = $1234, error, "pc_assignment failed"
|
||||
.reloc
|
||||
.feature pc_assignment -
|
||||
|
||||
|
||||
.feature string_escapes
|
||||
.asciiz "quote:\""
|
||||
.feature string_escapes -
|
||||
|
||||
|
||||
.feature ubiquitous_idents
|
||||
.macro bit
|
||||
brk
|
||||
.endmacro
|
||||
bit
|
||||
.feature ubiquitous_idents -
|
||||
|
||||
|
||||
.feature underline_in_numbers
|
||||
.byte %10_10_10_10
|
||||
.feature underline_in_numbers -
|
Loading…
x
Reference in New Issue
Block a user