1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-04 18:29:31 +00:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Evgeny Vrublevsky
974f15ee05
Merge f789316f86 into b993d88339 2024-04-07 10:35:04 +00: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
6 changed files with 108 additions and 44 deletions

View File

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

View File

@ -707,6 +707,24 @@ static void OneLine (void)
NextTok (); 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 /* If the first token on the line is an identifier, check for a macro or
** an instruction. ** an instruction.
*/ */

View File

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

View File

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

View File

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

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