1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-10 13:29:50 +00:00

Compare commits

...

10 Commits

Author SHA1 Message Date
Movax12
32e48f0d1d
Merge 6bcce49d5d into 2c4d4d3314 2024-05-16 19:06:09 +02:00
mrdudz
2c4d4d3314 add -j2 to make test invocations 2024-05-16 18:57:29 +02:00
mrdudz
86e5acd679 fix race condition as proposed in #2420 2024-05-16 18:57:08 +02:00
Bob Andrews
84153e809e
Merge pull request #2438 from ops/exehdr
Add missing EXEHDR
2024-05-15 14:11:08 +02:00
Bob Andrews
90723d7dd1
Merge pull request #2132 from vrubleg/ulabel
Add support of unnamed labels with @ (.localchar) prefix
2024-05-14 20:10:06 +02:00
Evgeny Vrublevsky
f789316f86 Add a test for the unnamed labels. 2024-04-07 13:34:49 +03:00
Evgeny Vrublevsky
270f3544b5 Document changes in unnamed labels. 2024-04-07 13:34:48 +03:00
Evgeny Vrublevsky
c500cb9086 Add support of unnamed labels with @ (.localchar) prefix. 2024-04-07 13:34:48 +03:00
Olli Savia
074ec82126 Added missing EXEHDR 2024-04-02 19:25:15 +03:00
mvax
6bcce49d5d Remove MacSkipDef, capture all MacDef errors 2023-04-28 17:16:16 -04:00
14 changed files with 129 additions and 87 deletions

View File

@ -35,7 +35,7 @@ jobs:
run: make -j2 lib QUIET=1
- name: Run the regression tests.
shell: bash
run: make test QUIET=1
run: make -j2 test QUIET=1
- name: Test that the samples can be built.
run: make -C samples platforms
- name: Test that the targettest programs can be built.
@ -89,4 +89,4 @@ jobs:
- name: Run the regression tests (make test)
shell: cmd
run: make test QUIET=1 SHELL=cmd
run: make -j2 test QUIET=1 SHELL=cmd

View File

@ -59,7 +59,7 @@ jobs:
run: make -j2 lib QUIET=1
- name: Run the regression tests.
shell: bash
run: make test QUIET=1
run: make -j2 test QUIET=1
- name: Test that the samples can be built.
shell: bash
run: make -j2 samples

View File

@ -70,7 +70,7 @@ jobs:
- name: Run the regression tests (make test)
if: steps.check-sha.outputs.cache-hit != 'true'
shell: cmd
run: make test QUIET=1 SHELL=cmd
run: make -j2 test QUIET=1 SHELL=cmd
- name: Test that the samples can be built (make samples)
if: steps.check-sha.outputs.cache-hit != 'true'

View File

@ -14,6 +14,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -14,6 +14,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -14,6 +14,7 @@ MEMORY {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -829,49 +829,42 @@ names like "Loop". Here is an example:
bne @Loop ; ERROR: Unknown identifier!
</verb></tscreen>
<sect1>Unnamed labels<p>
If you really want to write messy code, there are also unnamed labels. These
labels do not have a name (you guessed that already, didn't you?). A colon is
used to mark the absence of the name.
If you really want to write messy code, there are also unnamed labels. To define
an unnamed label, use either <tt>@:</tt> (<tt>.LOCALCHAR</tt> is respected if it
is set) or sole <tt>:</tt>.
Unnamed labels may be accessed by using the colon plus several minus or plus
characters as a label designator. Using the '-' characters will create a back
reference (use the n'th label backwards), using '+' will create a forward
reference (use the n'th label in forward direction). An example will help to
understand this:
To reference an unnamed label, use <tt>@</tt> (<tt>.LOCALCHAR</tt> is respected
if it is set) or <tt>:</tt> with several <tt>-</tt> or <tt>+</tt> characters.
The <tt>-</tt> characters will create a back reference (n'th label backwards),
the <tt>+</tt> will create a forward reference (n'th label in forward direction).
As an alternative, angle brackets <tt>&lt;</tt> and <tt>&gt;</tt> may be used
instead of <tt>-</tt> and <tt>+</tt> with the same meaning.
Example:
<tscreen><verb>
: lda (ptr1),y ; #1
cmp (ptr2),y
bne :+ ; -> #2
tax
beq :+++ ; -> #4
iny
bne :- ; -> #1
inc ptr1+1
inc ptr2+1
bne :- ; -> #1
: bcs :+ ; #2 -> #3
ldx #$FF
rts
: ldx #$01 ; #3
: rts ; #4
cpy #0
beq @++
@:
sta $2007
dey
bne @-
@:
rts
</verb></tscreen>
As you can see from the example, unnamed labels will make even short
sections of code hard to understand, because you have to count labels
to find branch targets (this is the reason why I for my part do
prefer the "cheap" local labels). Nevertheless, unnamed labels are
convenient in some situations, so it's your decision.
Unnamed labels may make even short sections of code hard to understand, because
you have to count labels to find branch targets. It's better to prefer the
"cheap" local labels. Nevertheless, unnamed labels are convenient in some
situations, so it's up to your discretion.
<em/Note:/ <ref id="scopes" name="Scopes"> organize named symbols, not
unnamed ones, so scopes don't have an effect on unnamed labels.
<sect1>Using macros to define labels and constants<p>
While there are drawbacks with this approach, it may be handy in a few rare

View File

@ -364,27 +364,6 @@ static void FreeMacExp (MacExp* E)
static void MacSkipDef (unsigned Style)
/* Skip a macro definition */
{
if (Style == MAC_STYLE_CLASSIC) {
/* Skip tokens until we reach the final .endmacro */
while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
NextTok ();
}
if (CurTok.Tok != TOK_EOF) {
SkipUntilSep ();
} else {
Error ("'.ENDMACRO' expected");
}
} else {
/* Skip until end of line */
SkipUntilSep ();
}
}
void MacDef (unsigned Style)
/* Parse a macro definition */
{
@ -393,6 +372,7 @@ void MacDef (unsigned Style)
FilePos Pos;
int HaveParams;
int LastTokWasSep;
unsigned MacroErrorCount;
/* 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
@ -405,27 +385,23 @@ void MacDef (unsigned Style)
*/
Pos = CurTok.Pos;
/* Remember current error count */
MacroErrorCount = ErrorCount;
/* We expect a macro name here */
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
MacSkipDef (Style);
return;
} else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
/* The identifier is a name of a 6502 instruction, which is not
** allowed if not explicitly enabled.
*/
Error ("Cannot use an instruction as macro name");
MacSkipDef (Style);
return;
}
/* Did we already define that macro? */
if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
/* Macro is already defined */
Error ("A macro named '%m%p' is already defined", &CurTok.SVal);
/* Skip tokens until we reach the final .endmacro */
MacSkipDef (Style);
return;
}
/* Define the macro */
@ -508,13 +484,14 @@ void MacDef (unsigned Style)
** it will be added to the macro definition instead of closing it.
*/
if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) {
/* Done */
/* Done: Skip the .endmacro token */
NextTok ();
break;
}
/* May not have end of file in a macro definition */
if (CurTok.Tok == TOK_EOF) {
PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name);
goto Done;
break;
}
} else {
/* Accept a newline or end of file for new style macros */
@ -597,15 +574,11 @@ void MacDef (unsigned Style)
NextTok ();
}
/* Skip the .endmacro for a classic macro */
if (Style == MAC_STYLE_CLASSIC) {
NextTok ();
}
/* Set the Incomplete flag now that parsing is done. Any errors
** generated in this routine will result in an incomplete macro
*/
M->Incomplete = (MacroErrorCount != ErrorCount);
/* Reset the Incomplete flag now that parsing is done */
M->Incomplete = 0;
Done:
/* Switch out of raw token mode */
LeaveRawTokenMode ();
}

View File

@ -707,6 +707,24 @@ static void OneLine (void)
NextTok ();
}
/* Handle @-style unnamed labels */
if (CurTok.Tok == TOK_ULABEL) {
if (CurTok.IVal != 0) {
Error ("Invalid unnamed label definition");
}
ULabDef ();
NextTok ();
/* Skip the colon. If NoColonLabels is enabled, allow labels without
** a colon if there is no whitespace before the identifier.
*/
if (CurTok.Tok == TOK_COLON) {
NextTok ();
} else if (CurTok.WS || !NoColonLabels) {
Error ("':' expected");
}
}
/* If the first token on the line is an identifier, check for a macro or
** an instruction.
*/

View File

@ -1124,17 +1124,33 @@ Again:
/* Local symbol? */
if (C == LocalStart) {
/* Read the identifier. */
ReadIdent ();
NextChar ();
/* Start character alone is not enough */
if (SB_GetLen (&CurTok.SVal) == 1) {
Error ("Invalid cheap local symbol");
goto Again;
if (IsIdChar (C)) {
/* Read a local identifier */
CurTok.Tok = TOK_LOCAL_IDENT;
SB_AppendChar (&CurTok.SVal, LocalStart);
ReadIdent ();
} else {
/* Read an unnamed label */
CurTok.IVal = 0;
CurTok.Tok = TOK_ULABEL;
if (C == '-' || C == '<') {
int PrevC = C;
do {
--CurTok.IVal;
NextChar ();
} while (C == PrevC);
} else if (C == '+' || C == '>') {
int PrevC = C;
do {
++CurTok.IVal;
NextChar ();
} while (C == PrevC);
}
}
/* A local identifier */
CurTok.Tok = TOK_LOCAL_IDENT;
return;
}
@ -1314,22 +1330,30 @@ CharAgain:
break;
case '-':
case '<':
{
int PrevC = C;
CurTok.IVal = 0;
do {
--CurTok.IVal;
NextChar ();
} while (C == '-');
} while (C == PrevC);
CurTok.Tok = TOK_ULABEL;
break;
}
case '+':
case '>':
{
int PrevC = C;
CurTok.IVal = 0;
do {
++CurTok.IVal;
NextChar ();
} while (C == '+');
} while (C == PrevC);
CurTok.Tok = TOK_ULABEL;
break;
}
case '=':
NextChar ();

View File

@ -71,7 +71,7 @@ typedef enum token_t {
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* :++ or :-- */
TOK_ULABEL, /* An unnamed label */
TOK_EQ, /* = */
TOK_NE, /* <> */

View File

@ -107,8 +107,12 @@ ExprNode* ULabRef (int Which)
int Index;
ULabel* L;
/* Which can never be 0 */
PRECONDITION (Which != 0);
/* Which should not be 0 */
if (Which == 0) {
Error ("Invalid unnamed label reference");
/* We must return something valid */
return GenCurrentPC();
}
/* Get the index of the referenced label */
if (Which > 0) {

View File

@ -14,7 +14,9 @@ WORKDIR = ../testwrk
.PHONY: test continue mostlyclean clean
test: mostlyclean continue
test:
@$(MAKE) mostlyclean
@$(MAKE) continue
continue:
@$(MAKE) -C asm all

View File

@ -0,0 +1,25 @@
; Test new-style (@:) and legacy-style (:) unnamed labels.
; Make sure that they have identical behavior.
.ORG $0000
@: nop
: nop
.ASSERT @<< = $0000, error
.ASSERT @-- = $0000, error
.ASSERT :<< = $0000, error
.ASSERT :-- = $0000, error
.ASSERT @< = $0001, error
.ASSERT @- = $0001, error
.ASSERT :< = $0001, error
.ASSERT :- = $0001, error
.ASSERT @> = $0002, error
.ASSERT @+ = $0002, error
.ASSERT :> = $0002, error
.ASSERT :+ = $0002, error
.ASSERT @>> = $0003, error
.ASSERT @++ = $0003, error
.ASSERT :>> = $0003, error
.ASSERT :++ = $0003, error
@: nop
: nop