C seems to be very nitpicky about spaces. I tried adding spaces in the macro and it refused to compile. Is there a rule about where spaces can and cannot go?
That's absolutely incorrect. Almost all spaces in a C program can be removed with no ill effect, and more whitespace than the minimum can never hurt at all.
The place where you *need* a space is between two tokens that would look like one token without a space e.g. "int i".
That's C. That's not the pre-processor, which has its own rules. And you can screw things up by not being careful with pre-processor macros.
Note that a macro definition such as ...
#define MASKIN(reg,mask,x) (reg = (mask & x)|(~mask & reg))
... is very dangerous. It can do quite unexpected things if reg, mask, or x are not simple variables names or constants.
For example, what if you call it as:
#define PIN(n) (1<<n)
MASKIN(sGPIO, PIN(1) | PIN(4), PIN(4));
... to set pin 4 and clear pin 1.
It's not going to do what you want AT ALL because after the macros are expanded you're going to have...
(sGPIO = ((1<<1)|(1<<4) & (1<<4))|(~(1<<1)|(1<<4) & sGPIO))
... which is going to be parsed as ...
(sGPIO = ((1<<1) | ((1<<4) & (1<<4))) | (~(1<<1) | ((1<<4) & sGPIO)))
(sGPIO = (2 | ((16 & 16))) | (~2 | (16 & sGPIO)))
(sGPIO = (2 | 16) | (~2 | (16 & sGPIO)))
sGPIO = 2 | 16 | ~2 | (16 & sGPIO)
sGPIO = (2 | ~2) | (16 | (16 & sGPIO))
sGPIO = -1 | 16
sGPIO = -1
ALWAYS PUT PARENS AROUND MACRO ARGUMENTS IN THE EXPANSION
#define MASKIN(reg,mask,x) ((reg) = ((mask) & (x))|(~(mask) & (reg)))
Now it will do AND #-3; OR #16 as intended. (or the AND might be with #-19, depending on the optimiser .. same thing)