using macros for configuration - c

I'm writing firmware in C for an embedded processor. I want to have all the configuration information in one header file called config.h. This is causing problems with the ADC initialization, where simple #defines won't do the trick. Right now the code is like so:
config.h
#define NUMBER_OF_POTS 1
#define POT_1_CHANNEL 27
adc.c
#define MAKE_CSS(channel) _CSS##channel
#define CALL_MAKE_CSS(channel) MAKE_CSS(channel)
void initialize_adc() {
CALL_MAKE_CSS(POT_1_CHANNEL);
}
What I want to do is not have to touch adc.c if I change config.h to:
#define NUMBER_OF_POTS 2
#define POT_1_CHANNEL 27
#define POT_2_CHANNEL 29
adc.c should just automatically add a second CALL_MAKE_CSS with some macro trickery.
I guess the question is: is there a trick that gives you for loop capability with a macro?
Thanks,
Steve.

I didn't test this:
// config.h
#define NUMBER_OF_POTS 2
extern int pots[];
// config.c
int pots[NUMBER_OF_POTS] = {
27,
29
};
// adc.c
void initialize_adc() {
for (int i = 0; i < NUMBER_OF_POTS; i++) {
CALL_MAKE_CSS(pots[i]);
}
}

You don't have to rely entirely on macros. Just define your 'magic numbers' as #defines.
For example:
In config.h:
#define NUMBER_OF_POTS 2
#define POT_1_CHANNEL 27
#define POT_2_CHANNEL 29
unsigned int PotChannelList[NUMBER_OF_POTS] = {POT_1_CHANNEL, POT_2_CHANNEL};
In adc.c:
for(i = 0; i < NUMBER_OF_CHANNELS; i++)
{
initialize_adc(PotChannelList[i]);
}
You still define the setup in config.h and don't have to change adc.c when you add a channel. You just add it to the list. The list order also defines the order of initialization.
EDIT: Sorry about the formatting mess...

Have a look at boost.preprocessor. Although boost is usually for C++, the preprocessor metaprogramming lib works, well, just with the CPP, so it may do what you want. It provides a few datastructures (lists, tuples) and iteration macros.
Sorry, I can't give you any example if it really does what you want, or at least provides another way, because I seldom needed it, and it's too long ago.
Note Just saw Schroeder's answer. Not relying on the PP if it is not necessary is still the best option...

The C preprocessor cannot do loops. You'll either have to do the looping in C code, or if you really need to do something loop-like at compile time, you can write your own preprocessor (which can just be a simple shell script, e.g.) that generates the necessary code.

Although you can't do loops with the preprocessor, you can do unrolled loops. So if you know you're never going to have more than 4 pots you could do this;
void initialize_adc() {
#if NUMBER_OF_POTS > 0
CALL_MAKE_CSS(POT_1_CHANNEL);
#endif
#if NUMBER_OF_POTS > 1
CALL_MAKE_CSS(POT_2_CHANNEL);
#endif
#if NUMBER_OF_POTS > 2
CALL_MAKE_CSS(POT_3_CHANNEL);
#endif
#if NUMBER_OF_POTS > 3
CALL_MAKE_CSS(POT_4_CHANNEL);
#endif
}
The only benefit of this compared to other solutions here is that there is no runtime overhead at all. Extra inline code "magically" appears if and only if another channel is added, just as the questioner wanted. To extract the ugliness from within the function call (at the cost of putting it earlier in your code instead), define 4 new macros each using the same #if NUMBER_OF_POTS > x technique. Then you'd be able to go simply;
void initialize_adc() {
INIT_CSS_1();
INIT_CSS_2();
INIT_CSS_3();
INIT_CSS_4();
}

Related

How to pass string as prefix of defined macro

Is there any idea to pass C string as part of the defined macro like below code?
#define AAA_NUM 10
#define BBB_NUM 20
#define PREFIX_NUM(string) string##_NUM
int main()
{
char *name_a = "AAA";
char *name_b = "AAA";
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
Expected output
AAA_NUM: 10
BBB_NUM: 20
As mentioned in other posts, you can't use run-time variables in the pre-processor. You could however create enum that way. Though it is usually not a good idea to generate identifiers with macros either, save for special cases like when maintaining an existing code base and you are limited in how much of the existing code you can/want to change. So it should be used as a last resort only.
The least bad way to write such macros would be by using a common design pattern called "X macros". These are used when it is important that code repetition should be reduced to a single place in the project. They tend to make the code look rather alien though... Example:
#define PREFIX_LIST(X) \
/* pre val */ \
X(AAA, 10) \
X(BBB, 20) \
X(CCC, 30) \
enum // used to generate constants like AAA_NUM = 10,
{
#define PREFIX_ENUMS(pre, val) pre##_NUM = (val),
PREFIX_LIST(PREFIX_ENUMS)
};
#include <stdio.h>
int main (void)
{
// one way to print
#define prefix_to_val(pre) pre##_NUM
printf("AAA_NUM: %d\n", prefix_to_val(AAA));
printf("BBB_NUM: %d\n", prefix_to_val(BBB));
// another alternative
#define STR(s) #s
#define print_all_prefixes(pre, val) printf("%s: %d\n", STR(pre##_NUM), val);
PREFIX_LIST(print_all_prefixes)
return 0;
}
A macro is only processed before compilation and not at runtime. Your code example does not work as you can see here.
Good practice (for example MISRA coding rules) recommend to use macros as little as possible since it is error prone.
Preprocessor works at compile time and here name_a and name_b are non constant, and even if they were (i.e. const char *str is a real constant in C++ but not in C), there is a literal substitution and the preprocessor does not know the contents of variables.
This works (notice that the parameter should be expanded by another macro in order to get a valid token):
#include <stdio.h>
#define AAA_NUM 10
#define BBB_NUM 20
#define _PREFIX_NUM(string) string##_NUM
#define PREFIX_NUM(string) _PREFIX_NUM(string)
int main(void)
{
#define name_a AAA
#define name_b BBB
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
There is no way in C to create runtime symbols and use them. C is a compiled language and all symbols have to be known before the compilation.
The preprocessor (which do changes on the text level before the compilation) does not know anything about the C language.

Are there directives in C/C++ preprocessor to convert string to number?

I wish to add some conditional directive in my code to control different build, for example:
#if VERSION > 100
/* Compiling here */
#endif
The problem is that 'VERSION' is in other's code where I can't change. It was defined as a string:
#define VERSION "101"
I'm wondering if there's some sort of macro or directive which converts the string to number so I can simply do
#if STRING_TO_NUMBER(VERSION) > 100
/* Compiling here */
#endif
Is that possible please?
PS.
It seems my description is not quite clear. The main purpose of this requirement is to control the version branch. For example, in old version, pre-version 100, this program would like old_function(). After this version, all functions have been migrated to new_function. So I need to write codes like that:
#if VERSION >= 100
old_function();
#else
new_function();
#endif
#if VERSION >= 100
int old_function()
{
...
}
#else
int new_function()
{
...
}
#endif
You can see that only one of the function will be compiled. Therefore the condition must be decided in preprocessing stage, not in the runtime.
The tricky part is, the VERSION had been defined as a string, which brought this question.
If you need to interact with the pre-processor to set other #defines or conditionally #include different headers. Until you can get VERSION to be "fixed" to be an integer...
The only thing that I can think of for you to do is to create a tiny header file defining PROPER_VERSION and include it by naming each file as the version number. So here you would create:
100:
#define PROPER_VERSION 100
101:
#define PROPER_VERSION 101
102:
#define PROPER_VERSION 102
and then you would need to add the following:
#include VERSION
And then use PROPER_VERSION as you need
#if PROPER_VERSION > 100
...
Its not elegant, but I cannot see anything else you can do. You can auto-generate the VERSION file.
As long as you don't need to make declarations or preprocessor defines conditional on VERSION, and as long as you are confident that the VERSION string will just be an integer with no leading zeros, (both of which might be too much to ask for), you might be able to do this at compile time if your compiler has a reasonably effective constant expression evaluator.
For example, gcc 4.8 will optimize away the following if test, leaving only the appropriate arm:
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
} else {
// code if VERSION is "100" or less
}
The fact that only one of the branches of the if statement survives the compilation is easily demonstrated by inserting a call to an undefined function in the non-used branch. With gcc (and clang), and with optimization enabled, no linker error is produced:
#include <stdio.h>
#include <string.h>
#define VERSION "101"
// This function is not available for linking
int unknown_function();
// This one is in standard library
int rand();
int main(void) {
int x;
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
x = rand();
} else {
// code if VERSION is "100" or less
x = unknown_function();
}
printf("%d\n", x);
return 0;
}
(See it at http://ideone.com/nGLGTH)
In C++11, there is an even more clearly compile-time version. You can create a constexpr version of atoi. Combined with what some might call an abuse of templates, that allows for conditional declarations:
constexpr int const_atoi(const char* num, int accum=0) {
return *num ? const_atoi(num+1, accum*10 + (*num - '0')) : accum;
}
template<bool V_GT_100> struct MoreOrLess_Impl;
template<> struct MoreOrLess_Impl<false> {
// Old prototype
void doit(double x) {...}
};
template<> struct MoreOrLess_Impl<true> {
// New prototype
void doit(long double x) {...}
};
using MoreOrLess = MoreOrLess_Impl<(const_atoi(VERSION) > 100)>;
// ...
// ... MoreOrLess::doit(x) ...
(Silly example at http://ideone.com/H1sdNg)

Temporarily overwrite a macro in C preprocessor

I need to temporarily overwrite a macro and then restore it. Like:
#define FOO X
#save FOO
#define FOO Y
...
#restore FOO
Is it possible in standard C preprocessor? In GCC?
ADDED. About real world example. I use a global macro for error exception. It acts like assert, but for persistent usage, not only for debug versions; so, for example, I usually call functions (with side-effect) inside the macro. It's defined once, but the definition isn't persistent; therefore I don't know it a-priori. For some piece of code I need its own, modified version of the macro, but I want to save general style of code. It's looks ugly when one part of code uses the one macro, other part uses other macro -- both macros have the same purpose, but slightly different implementation.
So, it's good for me to save original macro temporarily, use different version for a part of code, after that restore original macro.
This is possible with #pragma push_macro and #pragma pop_macro. These are not standard C—they're originally an MSVC extension—but clang supports them, and so does GCC.
Example usage:
int main() {
#define SOME_MACRO 1
printf("SOME_MACRO = %d\n", SOME_MACRO);
#pragma push_macro("SOME_MACRO")
#define SOME_MACRO 2
printf("SOME_MACRO = %d\n", SOME_MACRO);
#pragma pop_macro("SOME_MACRO")
printf("SOME_MACRO = %d\n", SOME_MACRO);
return 0;
}
prints:
SOME_MACRO = 1
SOME_MACRO = 2
SOME_MACRO = 1
You can also #undef a macro inside a push_macro / pop_macro pair, and the pop_macro call will redefine it.
As already said, it is not really possible. Depending on the situation, this might be a workaround:
#include "generalmacrodefs.h" // put them in here or include them indirectly
#undef macro1
#define macro1 "specialized temporary value"
#undef macro1
#include "generalmacrodefs.h" // restores
This requires that generalmacrodefs.h uses a pattern like this at least for the definitions you might temporarily overwrite:
#ifndef macro1
#define macro1 "original value"
#endif
The closest you can come in C is the #undef directive, which simply undefines the macro, allowing it to be replaced:
#define FOO X
...
#undef FOO
#define FOO Y
...
#undef FOO
#define FOO X
The problem is that you cannot know the 'old' value of FOO once you redefine it - so your values must be hard-coded in one place.
You cannot create a macro to save the values for you either, as it isn't possible to have a macro that creates other preprocessor directives in standard C.

displaying #define values in C

I have a series of #defines from a library file header of this sort:
typedef int Lib_error;
#define LIB_ERROR_A ((Lib_error) 0x0000)
#define LIB_ERROR_D ((Lib_error) 0x0100)
#define LIB_ERROR_F ((Lib_error) 0x0200)
#define LIB_ERROR_K ((Lib_error) 0x0300)
#define LIB_ERROR_O ((Lib_error) 0x0400)
#define LIB_ERROR_P ((Lib_error) 0x0500)
#define LIB_ERROR_R ((Lib_error) 0x0600)
#define LIB_ERROR_X ((Lib_error) 0x0700)
#define LIB_ERROR_Y ((Lib_error) 0x0800)
#define LIB_ERROR_M ((Lib_error) 0x0900)
/* and so on */
Is there any way apart I can print these values so if for example
uint MyError;
/* printf("Error = %s",MyError); It should print the string LIB_ERROR_F instead of say 0x200 */
I could use lot's of if else for this but I was wondering if there was a cleverer way. Please note that I can't change the contents of library header file in anyway.
People seem to have mixed feelings about them, but X-macros are one possible solution.
But if you can't change the header, then your only two options (AFAIK) are:
Doing it manually
Some form of code generation step in your build process. In your case, it should probably be possible by parsing the header file with sed (assuming you're working on Linux).
There isn't a simple or automatic way to do it. You have to generate the list of numbers and names yourself, and provide a lookup function to map between number and name.
You might take a look at the ideas in the blog post 'Enums, Strings and Laziness'; it has some ideas that might help you. (That's closely related to the X-Macros at Dr Dobbs mentioned by Oli Charlesworth; the article there claims the technique goes back to the 60s, albeit that it must have been in a language other than C since C didn't exist back then.)
Warning: The below code piece is just a sample. It can be improvised a lot which is for you to do. : )
Define a structure like below:
typedef struct ErrorStorage
{
Lib_error err;
char err_string[100];
}ErrNoStore;
ErrNoStore arrErr[25];
arrErr[0].err = LIB_ERROR_A;
strcpy(arrErr[0].err_string, "LIB_ERROR_A");
/... and so on .../
and later down in the code define a function like this and call it
void display_error(Lib_error errnum)
{
int i = 0;
for(i=0; i<25;i++)
{
if(errnum == arrErr[i].err)
{
printf("%s\n", arrErr[i].err_string);
}
}
}
}
Just generate a table by parsing those defines in some scripting language. Should be easy-ish to translate those defines to the declaration of a constant array of code, string structs which you can then iterate.
Assuming the library doesn't change often, you'll only need to do this once so you don't need to bother much with script corectness etc.

Simplifying compilation with each of a list of options

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:
How can I test a list of macros for the presence of one and only one of these options? A simple 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.
How can I simplify the compilation process? I've been using AVRStudio with WinAVR t0 compile. It has an 'export makefile' option, but I have no experience with it. I'm stuck doing this on Windows. An ideal process would build all 11 configurations in a single command, and then I could go through and program each one to the microcontroller individually. The current, very much less-than-ideal build process involves editing the source each time I want to build, and renaming/moving the output file.
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).
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.
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;
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

Resources