Reputation: 2852
I've got a list of definitions: MASTER
, SLAVE0
, SLAVE1
, ... SLAVE9
to control which array of audio data is programmed into a microcontroller. The micro can hold no more than one sound file, so I have included the following definitions at the top of my main.c file:
#define MASTER
#define SLAVE0
#define SLAVE1
....
#define SLAVE9
Then, I write the following in my audio array:
#if defined(MASTER)
uint8_t sound[4096] PROGMEM = {127,126, ... }
#elif defined(SLAVE0)
uint8_t sound[4096] PROGMEM = {126,128, ... }
....
#else
#ERROR "One of MASTER-SLAVE9 must be defined!"
#endif
The person wishing to compile must then go through and comment out one and only one of the #define
lines. This is not only tedious, but also error-prone. So, I'm looking to simplify the process. Any pointers for any of the following tasks would be helpful:
if defined(MASTER) && !(defined(SLAVE0) || defined(SLAVE1) ...)
would require 11 such tests, each with 11 subtly different conditions. It's a one time expense, but it's kinda ugly. It feels like this might be a common need, and that there ought to be a better way.Upvotes: 0
Views: 120
Reputation: 3898
You are need an error message when you deined mre than one macro? Well, just write:
#ifdef MASTER
uint8_t sound = { ... };
#endif
#ifdef SLAVE0
uint8_t sound = { ... };
#endif
#ifdef SLAVE1
uint8_t sound = { ... };
#endif
And compiler will complain that one identifier defined multiple times.
Also why not use this?
#define SLAVE <n>
uint8_t sound_master = { ... };
uint8_t sound_slave_0 = { ... };
uint8_t sound_slave_1 = { ... };
uint8_t sound_slave_2 = { ... };
#define XCAT(a,b) a##b
#define CAT(a,b) XCAT(a,b)
#ifdef SLAVE
#define sound CAT(sound_slave_,SLAVE)
#endif
#ifdef MASTER
#ifdef sound
/* warnin or so. but if you need an error just remove this ifdef **/
#endif
#define sound sound_master
#endif
Upvotes: 0
Reputation: 652
I would just make a block comment with the name of all possible constants, and follow it with a single define. Who wants to compile just writes what he wants. First time he will check the comment to see the list, then he will just write.
Or even better, keep this list in a comment (for reference) and use the -D option that most compilers have (-DMASTER to define master for example) and if your tool supports it, make a build configuration for each where you change the -D value. Using a different build configuration i guess you could also change the output file name, so that would kill two birds with a stone.
Upvotes: 1
Reputation: 272607
Why not something like:
#define ARRAY_NAME (SLAVE0)
...
#if (ARRAY_NAME == MASTER)
// blah
#elif (ARRAY_NAME == SLAVE0)
// blah
// etc.
or even better, just:
#define ARRAY_MASTER { 1, 2, 3, 4 }
#define ARRAY_SLAVE0 { 5, 6, 7, 8 }
// etc.
...
const uint8_t sound[] = ARRAY_MASTER;
Upvotes: 0
Reputation: 355107
You can use a single test to ensure that only one of the macros is defined.
#if (defined(MASTER) + defined(SLAVE1) + defined(SLAVE2)) != 1
#error "Too many macros defined"
#endif
As for the definition itself, most compilers allow you to define a macro using a command line option; this might be cleaner than a file with a "configurable options list." You would then be able to create multiple build configurations, each of which defines a different macro, and build them each in sequence (I'm not familiar with your build system to be able to explain how exactly you need to do that).
Upvotes: 2