mirror of
https://github.com/cc65/cc65.git
synced 2025-01-10 19:29:45 +00:00
Merge pull request #232 from greg-king5/arg-count
Fix ca65's ".paramcount" Assembly-code read-only variable.
This commit is contained in:
commit
d54e515e08
@ -2,8 +2,9 @@
|
||||
|
||||
<article>
|
||||
<title>ca65 Users Guide
|
||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
||||
<date>2015-08-01
|
||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">
|
||||
<date>2015-11-17
|
||||
|
||||
<abstract>
|
||||
ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is
|
||||
@ -3960,10 +3961,10 @@ When using macro parameters, macros can be even more useful:
|
||||
.macro inc16 addr
|
||||
clc
|
||||
lda addr
|
||||
adc #$01
|
||||
adc #<$0001
|
||||
sta addr
|
||||
lda addr+1
|
||||
adc #$00
|
||||
adc #>$0001
|
||||
sta addr+1
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
@ -3981,10 +3982,10 @@ will be expanded to
|
||||
<tscreen><verb>
|
||||
clc
|
||||
lda $1000
|
||||
adc #$01
|
||||
adc #<$0001
|
||||
sta $1000
|
||||
lda $1000+1
|
||||
adc #$00
|
||||
adc #>$0001
|
||||
sta $1000+1
|
||||
</verb></tscreen>
|
||||
|
||||
@ -4019,7 +4020,7 @@ Look at this example:
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
|
||||
This macro may be called as follows:
|
||||
That macro may be called as follows:
|
||||
|
||||
<tscreen><verb>
|
||||
ldaxy 1, 2, 3 ; Load all three registers
|
||||
@ -4029,9 +4030,9 @@ This macro may be called as follows:
|
||||
ldaxy , , 3 ; Load y only
|
||||
</verb></tscreen>
|
||||
|
||||
There's another helper command for determining, which macro parameters are
|
||||
valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt> This command is
|
||||
replaced by the parameter count given, <em/including/ intermediate empty macro
|
||||
There's another helper command for determining which macro parameters are
|
||||
valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt>. That command is
|
||||
replaced by the parameter count given, <em/including/ explicitly empty
|
||||
parameters:
|
||||
|
||||
<tscreen><verb>
|
||||
@ -4056,10 +4057,10 @@ case of a macro parameter).
|
||||
</verb></tscreen>
|
||||
|
||||
In the first case, the macro is called with two parameters: '<tt/($00/'
|
||||
and 'x)'. The comma is not passed to the macro, since it is part of the
|
||||
and '<tt/x)/'. The comma is not passed to the macro, because it is part of the
|
||||
calling sequence, not the parameters.
|
||||
|
||||
In the second case, '($00,x)' is passed to the macro, this time
|
||||
In the second case, '<tt/($00,x)/' is passed to the macro; this time,
|
||||
including the comma.
|
||||
|
||||
|
||||
@ -4112,15 +4113,15 @@ Macros may be used recursively:
|
||||
.macro push r1, r2, r3
|
||||
lda r1
|
||||
pha
|
||||
.if .paramcount > 1
|
||||
.ifnblank r2
|
||||
push r2, r3
|
||||
.endif
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
|
||||
There's also a special macro to help writing recursive macros: <tt><ref
|
||||
id=".EXITMACRO" name=".EXITMACRO"></tt> This command will stop macro expansion
|
||||
immediately:
|
||||
There's also a special macro command to help with writing recursive macros:
|
||||
<tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>. That command will stop macro
|
||||
expansion immediately:
|
||||
|
||||
<tscreen><verb>
|
||||
.macro push r1, r2, r3, r4, r5, r6, r7
|
||||
@ -4135,7 +4136,7 @@ immediately:
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
|
||||
When expanding this macro, the expansion will push all given parameters
|
||||
When expanding that macro, the expansion will push all given parameters
|
||||
until an empty one is encountered. The macro may be called like this:
|
||||
|
||||
<tscreen><verb>
|
||||
@ -4154,10 +4155,10 @@ Have a look at the inc16 macro above. Here is it again:
|
||||
.macro inc16 addr
|
||||
clc
|
||||
lda addr
|
||||
adc #$01
|
||||
adc #<$0001
|
||||
sta addr
|
||||
lda addr+1
|
||||
adc #$00
|
||||
adc #>$0001
|
||||
sta addr+1
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
@ -4288,7 +4289,7 @@ don't like that, use classic macros instead:
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
|
||||
(This is an example where a problem can be solved with both macro types).
|
||||
(That is an example where a problem can be solved with both macro types).
|
||||
|
||||
|
||||
<sect1>Characters in macros<p>
|
||||
@ -4308,7 +4309,7 @@ be sure to take the translation into account.
|
||||
<sect1>Deleting macros<p>
|
||||
|
||||
Macros can be deleted. This will not work if the macro that should be deleted
|
||||
is currently expanded as in the following non working example:
|
||||
is currently expanded as in the following non-working example:
|
||||
|
||||
<tscreen><verb>
|
||||
.macro notworking
|
||||
@ -4348,6 +4349,7 @@ argument to <tt>.UNDEFINE</tt> is not allowed to come from another
|
||||
different commands increases flexibility.
|
||||
|
||||
|
||||
|
||||
<sect>Macro packages<label id="macropackages"><p>
|
||||
|
||||
Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined
|
||||
@ -4862,6 +4864,3 @@ freely, subject to the following restrictions:
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
|
@ -147,7 +147,7 @@ static int DoMacAbort = 0;
|
||||
/* Counter to create local names for symbols */
|
||||
static unsigned LocalName = 0;
|
||||
|
||||
/* Define style macros disabled if != 0 */
|
||||
/* Define-style macros disabled if != 0 */
|
||||
static unsigned DisableDefines = 0;
|
||||
|
||||
|
||||
@ -422,8 +422,8 @@ void MacDef (unsigned Style)
|
||||
EnterRawTokenMode ();
|
||||
NextTok ();
|
||||
|
||||
/* If we have a DEFINE style macro, we may have parameters in braces,
|
||||
** otherwise we may have parameters without braces.
|
||||
/* If we have a DEFINE-style macro, we may have parameters in parentheses;
|
||||
** otherwise, we may have parameters without parentheses.
|
||||
*/
|
||||
if (Style == MAC_STYLE_CLASSIC) {
|
||||
HaveParams = 1;
|
||||
@ -475,7 +475,7 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
}
|
||||
|
||||
/* For class macros, we expect a separator token, for define style macros,
|
||||
/* For classic macros, we expect a separator token, for define-style macros,
|
||||
** we expect the closing paren.
|
||||
*/
|
||||
if (Style == MAC_STYLE_CLASSIC) {
|
||||
@ -485,9 +485,9 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
|
||||
/* Preparse the macro body. We will read the tokens until we reach end of
|
||||
** file, or a .endmacro (or end of line for DEFINE style macros) and store
|
||||
** them into an token list internal to the macro. For classic macros, there
|
||||
** the .LOCAL command is detected and removed at this time.
|
||||
** file, or a .endmacro (or end of line for DEFINE-style macros) and store
|
||||
** them into a token list internal to the macro. For classic macros,
|
||||
** the .LOCAL command is detected and removed, at this time.
|
||||
*/
|
||||
while (1) {
|
||||
|
||||
@ -752,11 +752,11 @@ ExpandParam:
|
||||
FreeTokNode (Mac->Final);
|
||||
Mac->Final = 0;
|
||||
|
||||
/* Problem: When a .define style macro is expanded within the call
|
||||
/* Problem: When a .define-style macro is expanded within the call
|
||||
** of a classic one, the latter may be terminated and removed while
|
||||
** the expansion of the .define style macro is still active. Because
|
||||
** the expansion of the .define-style macro is still active. Because
|
||||
** line info slots are "stacked", this runs into a CHECK FAILED. For
|
||||
** now, we will fix that by removing the .define style macro expansion
|
||||
** now, we will fix that by removing the .define-style macro expansion
|
||||
** immediately, once the final token is placed. The better solution
|
||||
** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
|
||||
** to be called in FIFO order, but this is a bigger change.
|
||||
@ -790,9 +790,11 @@ static void StartExpClassic (MacExp* E)
|
||||
/* Skip the macro name */
|
||||
NextTok ();
|
||||
|
||||
/* Read the actual parameters */
|
||||
while (!TokIsSep (CurTok.Tok)) {
|
||||
/* Does this invocation have any arguments? */
|
||||
if (!TokIsSep (CurTok.Tok)) {
|
||||
|
||||
/* Read the actual parameters */
|
||||
while (1) {
|
||||
TokNode* Last;
|
||||
|
||||
/* Check for maximum parameter count */
|
||||
@ -801,13 +803,12 @@ static void StartExpClassic (MacExp* E)
|
||||
break;
|
||||
}
|
||||
|
||||
/* The macro may optionally be enclosed in curly braces */
|
||||
/* The macro argument optionally may be enclosed in curly braces */
|
||||
Term = GetTokListTerm (TOK_COMMA);
|
||||
|
||||
/* Read tokens for one parameter, accept empty params */
|
||||
Last = 0;
|
||||
while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
|
||||
|
||||
TokNode* T;
|
||||
|
||||
/* Check for end of file */
|
||||
@ -853,6 +854,7 @@ static void StartExpClassic (MacExp* E)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We must be at end of line now, otherwise something is wrong */
|
||||
ExpectSep ();
|
||||
@ -864,9 +866,9 @@ static void StartExpClassic (MacExp* E)
|
||||
|
||||
|
||||
static void StartExpDefine (MacExp* E)
|
||||
/* Start expanding a DEFINE style macro */
|
||||
/* Start expanding a DEFINE-style macro */
|
||||
{
|
||||
/* A define style macro must be called with as many actual parameters
|
||||
/* A define-style macro must be called with as many actual parameters
|
||||
** as there are formal ones. Get the parameter count.
|
||||
*/
|
||||
unsigned Count = E->M->ParamCount;
|
||||
@ -876,10 +878,9 @@ static void StartExpDefine (MacExp* E)
|
||||
|
||||
/* Read the actual parameters */
|
||||
while (Count--) {
|
||||
|
||||
TokNode* Last;
|
||||
|
||||
/* The macro may optionally be enclosed in curly braces */
|
||||
/* The macro argument optionally may be enclosed in curly braces */
|
||||
token_t Term = GetTokListTerm (TOK_COMMA);
|
||||
|
||||
/* Check if there is really a parameter */
|
||||
@ -892,7 +893,6 @@ static void StartExpDefine (MacExp* E)
|
||||
/* Read tokens for one parameter */
|
||||
Last = 0;
|
||||
do {
|
||||
|
||||
TokNode* T;
|
||||
|
||||
/* Get the next token in a node */
|
||||
@ -936,7 +936,7 @@ static void StartExpDefine (MacExp* E)
|
||||
}
|
||||
|
||||
/* Macro expansion will overwrite the current token. This is a problem
|
||||
** for define style macros since these are called from the scanner level.
|
||||
** for define-style macros since these are called from the scanner level.
|
||||
** To avoid it, remember the current token and re-insert it, once macro
|
||||
** expansion is done.
|
||||
*/
|
||||
@ -1007,8 +1007,8 @@ Macro* FindMacro (const StrBuf* Name)
|
||||
|
||||
|
||||
Macro* FindDefine (const StrBuf* Name)
|
||||
/* Try to find the define style macro with the given name and return it. If no
|
||||
** such macro was found, return NULL.
|
||||
/* Try to find the define-style macro with the given name; and, return it.
|
||||
** If no such macro was found, return NULL.
|
||||
*/
|
||||
{
|
||||
Macro* M;
|
||||
@ -1034,7 +1034,7 @@ int InMacExpansion (void)
|
||||
|
||||
|
||||
void DisableDefineStyleMacros (void)
|
||||
/* Disable define style macros until EnableDefineStyleMacros is called */
|
||||
/* Disable define-style macros until EnableDefineStyleMacros() is called */
|
||||
{
|
||||
++DisableDefines;
|
||||
}
|
||||
@ -1042,8 +1042,8 @@ void DisableDefineStyleMacros (void)
|
||||
|
||||
|
||||
void EnableDefineStyleMacros (void)
|
||||
/* Re-enable define style macros previously disabled with
|
||||
** DisableDefineStyleMacros.
|
||||
/* Re-enable define-style macros previously disabled with
|
||||
** DisableDefineStyleMacros().
|
||||
*/
|
||||
{
|
||||
PRECONDITION (DisableDefines > 0);
|
||||
|
20
testcode/assembler/paramcount.s
Normal file
20
testcode/assembler/paramcount.s
Normal file
@ -0,0 +1,20 @@
|
||||
; Test ca65's handling of the .paramcount read-only variable.
|
||||
; .paramcount should see all given arguments, even when they are empty.
|
||||
|
||||
.macro push r1, r2, r3, r4, r5, r6
|
||||
.out .sprintf(" .paramcount = %u", .paramcount)
|
||||
.if .paramcount <> 0
|
||||
.ifblank r1
|
||||
.warning "r1 is blank!"
|
||||
.exitmacro
|
||||
.endif
|
||||
lda r1
|
||||
pha
|
||||
|
||||
push r2, r3, r4, r5, r6
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
push 1, , {}
|
||||
push 1, ,
|
||||
push 1
|
Loading…
x
Reference in New Issue
Block a user