]> git.sur5r.net Git - cc65/commitdiff
Fixed the ca65 Assembly-code variable ".paramcount". 232/head
authorGreg King <gregdk@users.sf.net>
Tue, 17 Nov 2015 19:11:30 +0000 (14:11 -0500)
committerGreg King <gregdk@users.sf.net>
Tue, 17 Nov 2015 19:21:40 +0000 (14:21 -0500)
Fixed how it's described in the ca65 document.

doc/ca65.sgml
src/ca65/macro.c
testcode/assembler/paramcount.s [new file with mode: 0644]

index 278a81d1bef9ca1ce780203e7e7d12ba11e7e065..213033cd4b3ef100ad8bbf6ac3eeb4dea3fecb47 100644 (file)
@@ -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
@@ -1320,8 +1321,8 @@ either a string or an expression.
 
 <sect1><tt>.ADDRSIZE</tt><label id=".ADDRSIZE"><p>
 
-  The <tt/.ADDRSIZE/ function is used to return the interal address size 
-  associated with a symbol. This can be helpful in macros when knowing the address 
+  The <tt/.ADDRSIZE/ function is used to return the interal address size
+  associated with a symbol. This can be helpful in macros when knowing the address
   size of symbol can help with custom instructions.
 
   Example:
@@ -2358,8 +2359,8 @@ Here's a list of all control commands and a description, what they do:
 <sect1><tt>.DEFINEDMACRO</tt><label id=".DEFINEDMACRO"><p>
 
   Builtin function. The function expects an identifier as argument in braces.
-  The argument is evaluated, and the function yields "true" if the identifier 
-  has already been defined as the name of a macro. Otherwise the function yields 
+  The argument is evaluated, and the function yields "true" if the identifier
+  has already been defined as the name of a macro. Otherwise the function yields
   false. Example:
 
   <tscreen><verb>
@@ -2367,7 +2368,7 @@ Here's a list of all control commands and a description, what they do:
                 clc
                 adc foo
         .endmacro
-                 
+
        .if     .definedmacro(add)
                 add #$01
         .else
@@ -3935,10 +3936,10 @@ In its simplest form, a macro does not have parameters. Here's an
 example:
 
 <tscreen><verb>
-               .macro  asr             ; Arithmetic shift right
-               cmp     #$80    ; Put bit 7 into carry
-               ror             ; Rotate right with carry
-       .endmacro
+.macro  asr             ; Arithmetic shift right
+        cmp     #$80    ; Put bit 7 into carry
+        ror             ; Rotate right with carry
+.endmacro
 </verb></tscreen>
 
 The macro above consists of two real instructions, that are inserted into
@@ -3946,9 +3947,9 @@ the code, whenever the macro is expanded. Macro expansion is simply done
 by using the name, like this:
 
 <tscreen><verb>
-       lda     $2010
-       asr
-       sta     $2010
+        lda     $2010
+        asr
+        sta     $2010
 </verb></tscreen>
 
 
@@ -3957,15 +3958,15 @@ by using the name, like this:
 When using macro parameters, macros can be even more useful:
 
 <tscreen><verb>
-       .macro  inc16   addr
-               clc
-               lda     addr
-               adc     #$01
-               sta     addr
-               lda     addr+1
-               adc     #$00
-               sta     addr+1
-       .endmacro
+.macro  inc16   addr
+        clc
+        lda     addr
+        adc     #<$0001
+        sta     addr
+        lda     addr+1
+        adc     #>$0001
+        sta     addr+1
+.endmacro
 </verb></tscreen>
 
 When calling the macro, you may give a parameter, and each occurrence of
@@ -3973,19 +3974,19 @@ the name "addr" in the macro definition will be replaced by the given
 parameter. So
 
 <tscreen><verb>
-       inc16   $1000
+        inc16   $1000
 </verb></tscreen>
 
 will be expanded to
 
 <tscreen><verb>
-               clc
-               lda     $1000
-               adc     #$01
-               sta     $1000
-               lda     $1000+1
-               adc     #$00
-               sta     $1000+1
+        clc
+        lda     $1000
+        adc     #<$0001
+        sta     $1000
+        lda     $1000+1
+        adc     #>$0001
+        sta     $1000+1
 </verb></tscreen>
 
 A macro may have more than one parameter, in this case, the parameters
@@ -4006,40 +4007,40 @@ opposite.
 Look at this example:
 
 <tscreen><verb>
-       .macro  ldaxy   a, x, y
-       .ifnblank       a
-               lda     #a
-       .endif
-       .ifnblank       x
-               ldx     #x
-       .endif
-       .ifnblank       y
-               ldy     #y
-       .endif
-       .endmacro
+.macro  ldaxy   a, x, y
+.ifnblank       a
+        lda     #a
+.endif
+.ifnblank       x
+        ldx     #x
+.endif
+.ifnblank       y
+        ldy     #y
+.endif
+.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
+        ldaxy   1, 2, 3         ; Load all three registers
 
-       ldaxy   1, , 3          ; Load only a and y
+        ldaxy   1, , 3          ; Load only a and y
 
-       ldaxy   , , 3           ; Load y only
+        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>
-       ldaxy   1               ; .PARAMCOUNT = 1
-       ldaxy   1,,3            ; .PARAMCOUNT = 3
-       ldaxy   1,2             ; .PARAMCOUNT = 2
-       ldaxy   1,              ; .PARAMCOUNT = 2
-       ldaxy   1,2,3           ; .PARAMCOUNT = 3
+        ldaxy   1       ; .PARAMCOUNT = 1
+        ldaxy   1,,3    ; .PARAMCOUNT = 3
+        ldaxy   1,2     ; .PARAMCOUNT = 2
+        ldaxy   1,      ; .PARAMCOUNT = 2
+        ldaxy   1,2,3   ; .PARAMCOUNT = 3
 </verb></tscreen>
 
 Macro parameters may optionally be enclosed into curly braces. This allows the
@@ -4047,19 +4048,19 @@ inclusion of tokens that would otherwise terminate the parameter (the comma in
 case of a macro parameter).
 
 <tscreen><verb>
-        .macro  foo     arg1, arg2
-                ...
-        .endmacro
+.macro  foo     arg1, arg2
+        ...
+.endmacro
 
-                foo     ($00,x)         ; Two parameters passed
-                foo     {($00,x)}       ; One parameter passed
+        foo     ($00,x)         ; Two parameters passed
+        foo     {($00,x)}       ; One parameter passed
 </verb></tscreen>
 
 In the first case, the macro is called with two parameters: '<tt/(&dollar;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, '(&dollar;00,x)' is passed to the macro, this time
+In the second case, '<tt/(&dollar;00,x)/' is passed to the macro; this time,
 including the comma.
 
 
@@ -4072,17 +4073,17 @@ id=".MATCH" name=".MATCH">/ and <tt/<ref id=".XMATCH" name=".XMATCH">/
 functions will allow you to do exactly this:
 
 <tscreen><verb>
-        .macro  ldax    arg
-                .if (.match (.left (1, {arg}), #))
-                    ; immediate mode
-                    lda     #<(.right (.tcount ({arg})-1, {arg}))
-                    ldx     #>(.right (.tcount ({arg})-1, {arg}))
-                .else
-                    ; assume absolute or zero page
-                    lda     arg
-                    ldx     1+(arg)
-                .endif
-        .endmacro
+.macro  ldax    arg
+        .if (.match (.left (1, {arg}), #))
+            ; immediate mode
+            lda     #<(.right (.tcount ({arg})-1, {arg}))
+            ldx     #>(.right (.tcount ({arg})-1, {arg}))
+        .else
+            ; assume absolute or zero page
+            lda     arg
+            ldx     1+(arg)
+        .endif
+.endmacro
 </verb></tscreen>
 
 Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to
@@ -4096,11 +4097,11 @@ as end-of-list.
 The macro can be used as
 
 <tscreen><verb>
-        foo:    .word   $5678
-        ...
-                ldax    #$1234          ; X=$12, A=$34
-        ...
-                ldax    foo             ; X=$56, A=$78
+foo:    .word   $5678
+...
+        ldax    #$1234          ; X=$12, A=$34
+...
+        ldax    foo             ; X=$56, A=$78
 </verb></tscreen>
 
 
@@ -4109,38 +4110,38 @@ The macro can be used as
 Macros may be used recursively:
 
 <tscreen><verb>
-       .macro  push    r1, r2, r3
-               lda     r1
-               pha
-       .if     .paramcount > 1
-               push    r2, r3
-       .endif
-       .endmacro
+.macro  push    r1, r2, r3
+        lda     r1
+        pha
+.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
-       .ifblank        r1
-               ; First parameter is empty
-               .exitmacro
-       .else
-               lda     r1
-               pha
-       .endif
-               push    r2, r3, r4, r5, r6, r7
-       .endmacro
+.macro  push    r1, r2, r3, r4, r5, r6, r7
+.ifblank        r1
+        ; First parameter is empty
+        .exitmacro
+.else
+        lda     r1
+        pha
+.endif
+        push    r2, r3, r4, r5, r6, r7
+.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>
-       push    $20, $21, $32           ; Push 3 ZP locations
-       push    $21                     ; Push one ZP location
+        push    $20, $21, $32   ; Push 3 ZP locations
+        push    $21             ; Push one ZP location
 </verb></tscreen>
 
 
@@ -4151,27 +4152,27 @@ Now, with recursive macros, <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> and
 Have a look at the inc16 macro above. Here is it again:
 
 <tscreen><verb>
-               .macro  inc16   addr
-                       clc
-                       lda     addr
-                       adc     #$01
-                       sta     addr
-                       lda     addr+1
-                       adc     #$00
-                       sta     addr+1
-               .endmacro
+.macro  inc16   addr
+        clc
+        lda     addr
+        adc     #<$0001
+        sta     addr
+        lda     addr+1
+        adc     #>$0001
+        sta     addr+1
+.endmacro
 </verb></tscreen>
 
 If you have a closer look at the code, you will notice, that it could be
 written more efficiently, like this:
 
 <tscreen><verb>
-               .macro  inc16   addr
-                       inc     addr
-                       bne     Skip
-                       inc     addr+1
-               Skip:
-               .endmacro
+.macro  inc16   addr
+        inc     addr
+        bne     Skip
+        inc     addr+1
+Skip:
+.endmacro
 </verb></tscreen>
 
 But imagine what happens, if you use this macro twice? Since the label "Skip"
@@ -4183,27 +4184,27 @@ local variables are replaced by a unique name in each separate macro
 expansion. So we can solve the problem above by using <tt/.LOCAL/:
 
 <tscreen><verb>
-       .macro  inc16   addr
-                       .local  Skip            ; Make Skip a local symbol
-               inc     addr
-                       bne     Skip
-               inc     addr+1
-       Skip:                           ; Not visible outside
-       .endmacro
+.macro  inc16   addr
+        .local  Skip            ; Make Skip a local symbol
+        inc     addr
+        bne     Skip
+        inc     addr+1
+Skip:                           ; Not visible outside
+.endmacro
 </verb></tscreen>
 
 Another solution is of course to start a new lexical block inside the macro
 that hides any labels:
 
 <tscreen><verb>
-       .macro  inc16   addr
-       .proc
-                       inc     addr
-                       bne     Skip
-                       inc     addr+1
-       Skip:
-       .endproc
-       .endmacro
+.macro  inc16   addr
+.proc
+        inc     addr
+        bne     Skip
+        inc     addr+1
+Skip:
+.endproc
+.endmacro
 </verb></tscreen>
 
 
@@ -4240,7 +4241,7 @@ different:
        be omitted.
 
 <item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not
-       contain end-of-line tokens, there are things that cannot be done. They
+       contain end-of-line tokens, there are things that cannot be done. They
        may not contain several processor instructions for example. So, while
        some things may be done with both macro types, each type has special
        usages. The types complement each other.
@@ -4254,27 +4255,27 @@ To emulate assemblers that use "<tt/EQU/" instead of "<tt/=/" you may use the
 following <tt/.DEFINE/:
 
 <tscreen><verb>
-       .define EQU     =
+.define EQU     =
 
-       foo     EQU     $1234           ; This is accepted now
+foo     EQU     $1234           ; This is accepted now
 </verb></tscreen>
 
 You may use the directive to define string constants used elsewhere:
 
 <tscreen><verb>
-       ; Define the version number
-       .define VERSION         "12.3a"
+; Define the version number
+.define VERSION "12.3a"
 
-       ; ... and use it
-       .asciiz VERSION
+        ; ... and use it
+        .asciiz VERSION
 </verb></tscreen>
 
 Macros with parameters may also be useful:
 
 <tscreen><verb>
-       .define DEBUG(message)  .out    message
+.define DEBUG(message)  .out    message
 
-       DEBUG   "Assembling include file #3"
+        DEBUG   "Assembling include file #3"
 </verb></tscreen>
 
 Note that, while formal parameters have to be placed in braces, this is
@@ -4283,12 +4284,12 @@ detect the end of one parameter, only the first token is used. If you
 don't like that, use classic macros instead:
 
 <tscreen><verb>
-       .macro  DEBUG   message
-               .out    message
-       .endmacro
+.macro  DEBUG   message
+        .out    message
+.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,12 +4309,12 @@ 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
-               .delmacro       notworking
-       .endmacro
+.macro  notworking
+        .delmacro       notworking
+.endmacro
 
         notworking              ; Will not work
 </verb></tscreen>
@@ -4324,19 +4325,19 @@ for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros, <tt><ref
 id=".UNDEFINE" name=".UNDEFINE"></tt> must be used. Example:
 
 <tscreen><verb>
-        .define value   1
-       .macro  mac
-               .byte   2
-       .endmacro
+.define value   1
+.macro  mac
+        .byte   2
+.endmacro
 
-                .byte   value           ; Emit one byte with value 1
-                mac                     ; Emit another byte with value 2
+        .byte   value           ; Emit one byte with value 1
+        mac                     ; Emit another byte with value 2
 
-        .undefine value
-        .delmacro mac
+.undefine value
+.delmacro mac
 
-                .byte   value           ; Error: Unknown identifier
-                mac                     ; Error: Missing ":"
+        .byte   value           ; Error: Unknown identifier
+        mac                     ; Error: Missing ":"
 </verb></tscreen>
 
 A separate command for <tt>.DEFINE</tt> style macros was necessary, because
@@ -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
@@ -4497,7 +4499,7 @@ it is possible to determine if the
 instruction is supported, which is the case for the 65SC02, 65C02 and 65816
 CPUs (the latter two are upwards compatible to the 65SC02).
 
-  
+
 <sect1><tt>.MACPACK module</tt><p>
 
 This macro package defines a macro named <tt/module_header/. It takes an
@@ -4862,6 +4864,3 @@ freely, subject to the following restrictions:
 
 
 </article>
-
-
-
index 634f2107ef32219b264df0064d29835965b4ecc7..1f6812ce03c5a29df32b52ec8a8cbc3c4cea2ac8 100644 (file)
@@ -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.
@@ -785,72 +785,74 @@ MacEnd:
 static void StartExpClassic (MacExp* E)
 /* Start expanding a classic macro */
 {
-    token_t     Term;
+    token_t Term;
 
     /* Skip the macro name */
     NextTok ();
 
-    /* Read the actual parameters */
-    while (!TokIsSep (CurTok.Tok)) {
+    /* Does this invocation have any arguments? */
+    if (!TokIsSep (CurTok.Tok)) {
 
-        TokNode* Last;
+        /* Read the actual parameters */
+        while (1) {
+            TokNode* Last;
 
-        /* Check for maximum parameter count */
-        if (E->ParamCount >= E->M->ParamCount) {
-            ErrorSkip ("Too many macro parameters");
-            break;
-        }
+            /* Check for maximum parameter count */
+            if (E->ParamCount >= E->M->ParamCount) {
+                ErrorSkip ("Too many macro parameters");
+                break;
+            }
 
-        /* The macro may optionally be enclosed in curly braces */
-        Term = GetTokListTerm (TOK_COMMA);
+            /* 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) {
+            /* Read tokens for one parameter, accept empty params */
+            Last = 0;
+            while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
+                TokNode* T;
 
-            TokNode* T;
+                /* Check for end of file */
+                if (CurTok.Tok == TOK_EOF) {
+                    Error ("Unexpected end of file");
+                    FreeMacExp (E);
+                    return;
+                }
 
-            /* Check for end of file */
-            if (CurTok.Tok == TOK_EOF) {
-                Error ("Unexpected end of file");
-                FreeMacExp (E);
-                return;
-            }
+                /* Get the next token in a node */
+                T = NewTokNode ();
 
-            /* Get the next token in a node */
-            T = NewTokNode ();
+                /* Insert it into the list */
+                if (Last == 0) {
+                    E->Params [E->ParamCount] = T;
+                } else {
+                    Last->Next = T;
+                }
+                Last = T;
 
-            /* Insert it into the list */
-            if (Last == 0) {
-                E->Params [E->ParamCount] = T;
-            } else {
-                Last->Next = T;
+                /* And skip it... */
+                NextTok ();
             }
-            Last = T;
 
-            /* And skip it... */
-            NextTok ();
-        }
+            /* One parameter more */
+            ++E->ParamCount;
 
-        /* One parameter more */
-        ++E->ParamCount;
+            /* If the macro argument was enclosed in curly braces, end-of-line
+            ** is an error. Skip the closing curly brace.
+            */
+            if (Term == TOK_RCURLY) {
+                if (CurTok.Tok == TOK_SEP) {
+                    Error ("End of line encountered within macro argument");
+                    break;
+                }
+                NextTok ();
+            }
 
-        /* If the macro argument was enclosed in curly braces, end-of-line
-        ** is an error. Skip the closing curly brace.
-        */
-        if (Term == TOK_RCURLY) {
-            if (CurTok.Tok == TOK_SEP) {
-                Error ("End of line encountered within macro argument");
+            /* Check for a comma */
+            if (CurTok.Tok == TOK_COMMA) {
+                NextTok ();
+            } else {
                 break;
             }
-            NextTok ();
-        }
-
-        /* Check for a comma */
-        if (CurTok.Tok == TOK_COMMA) {
-            NextTok ();
-        } else {
-            break;
         }
     }
 
@@ -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;
 
-        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);
diff --git a/testcode/assembler/paramcount.s b/testcode/assembler/paramcount.s
new file mode 100644 (file)
index 0000000..4e9190d
--- /dev/null
@@ -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