Since the inline assembler of cc65 doesn't accept anonymous labels (from my other answer), another approach is to provide a unique suffix to the labels, which can be applied by the macro. The stringizing operator of the C preprocessor, and the fact that C string literals written consecutively are automatically concatenated, might make this more convenient:
Your source is most likely in ISO 8859-1 (or -15) encoded (*1), so the compiler has to do code conversion between character literals in your source and the designated target. Without a specifying a target CL65 uses, unlike all other tools, the C64 target by default (*2). As specified in target.c line 193, the C64 Target uses the PETSCII table at line 113, ...
There is a pseudo variable __AX__ of type unsigned int that can be assigned a value that then ends up in register A (lo byte) and X (hi byte). So, the following macro definition works as intended:
#define set_bgcolor(C) (__AX__ = (C),asm("sta $D021"))
I found this under "Extensions" in the cc65 user guide.
Preface: I'm not the world greatest C expert - not at least as I dislike C quite a lot :))
The general issue here is that CC65 puts the address into a pointer variable, visible when looking at the generated source:
Later that variable gets loaded onto the stack - like CC65 does with ...
You can use anonymous labels in ca65. The equivalent to your example code using these, but without the C wrapping, would be:
: AND #$3F
You can also use :- to refer to an anonymous label preceding the current position. Increasing the number of + or - symbols increases the number of anonymous labels to skip over.
I would expect that the CC65 compiler, like most compilers, would output string literals using whatever sequence of bytes appears in the source file. If you want to ensure that particular byte values get included in a string, you can use a backslash followed by a three-digit octal number to include any byte value within a string. While one could use fewer ...