Use specific entry of an X macro - c

I am using X macros to generate functions setting GPIOs to 0 or 1 (I generate around 60 functions to set around 30 GPIOs). Here is an example (I have just written this example, so the syntax may be wrong):
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs \
X(Pin0, 0) \
X(Pin1, 1) \
X(Pin2, 2) \
X(Pin3, 3)
I generate the functions to access to these GPIOs:
#define X(pin_name, pin_nb) \
static void SetOn_GPIO##pin_name (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
The same process exists for SetOff_GPIOXXX functions.
Is there a way I can access the function generated above by the compiler as SetOn_GPIOPin2 in an other part of the program without directly writing the function name? (In order to keep the code as global as possible)
At the end of preprocessing, we should only have SetOn_GPIOPin2(); (and not every X-macro entries) generated from X-Macro.
Before pre-processing:
void foo ()
{
/* some code */
/*
* Macro to generate the desired function.
* For e.g: SetOn_GPIOPin2();
*/
/* some code */
}
After pre-processing:
void foo ()
{
/* some code */
/* Function resulting of the pre-processing */
SetOn_GPIOPin2();
/* some code */
}

From comments on the question, your objective appears to be to protect against the case in which your X macro is modified to produce differently-named functions. If that's so, then I think you're making unnecessary work for yourself: whether those names are changed is under your (and any other project developers') control, and a name change such as you are concerned about will not go unnoticed very long. So don't change them.
But if you're determined to go this route then no, there is no way to make the preprocessor extract the function names generated by your macros from their larger replacement text. Instead, you would need to inject them, via the same macro, into both the X macros and your other code. Like this, perhaps:
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs(gen) \
X(Pin0, 0, gen) \
X(Pin1, 1, gen) \
X(Pin2, 2, gen) \
X(Pin3, 3, gen)
// Generates the wanted function names:
#define GPIO_ON(pin_name, pin_nb) SetOn_GPIO##pin_name
#define X(pin_name, pin_nb, gen) \
static void gen(pin_name, pin_nb) (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
// ...
void some_function(void) {
GPIO_ON(pin_name, pin_nb)();
}
But note well that although this technique might have other applications, such as to generating multiple sets of functions with the same set of X macros, it just kicks the can down the road with respect to the specific objective you described. You can rely on the name-generator macro to produce the same names for function declarations and function calls, but you still have the problem that the X macro can be modified to generate function declarations with different names.

Using our trusty Boost.Preprocessor rocket launcher, this is preatty easy:
#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#define X_SELECT_PIN(pin_nb, selected_pin_nb, ...) \
BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_IF( \
BOOST_PP_EQUAL(pin_nb, selected_pin_nb), \
(__VA_ARGS__), \
() \
))
// Usage
#define X(pin_name, pin_nb)\
X_SELECT_PIN(pin_nb, 2, SetOn_GPIO##pin_name (void);)
CPLD_GPIOs
#undef X
This uses BOOST_PP_IF to expand your pattern only for the selected pin. The added parentheses and BOOST_PP_TUPLE_REM_CTOR are there to protect the macro from expansions containing commas.

Related

Default arguments to C macros

Suppose I have function bshow() with signature
void bshow(int arg0, int arg1, int arg2);
but for arbitrary reasons I want to implement it as a macro.
Furthermore, I want the function have default arguments
int arg0=0x10;
int arg1=0x11;
int arg2=0x12;
I've already done this for the case that bshow() is a function, using the standard tricks.
But how can I do it as a macro?
Eg. suppose I have a macro nargs() that uses the C Preprocessor to count the number of arguments. Eg.
nargs() // get replaced by 0 by the preprocessor
nargs(a) // get replaced by 1 by the preprocessor
nargs(a,b) // get replaced by 2 by the preprocessor
I'd like to do something like (which doesn't work):
#define arg0_get(a0,...) a0
#define arg1_get(a0,a1,...) a1
#define arg2_get(a0,a1,a2,...) a2
#define bshow(...) do{ \
int arg0=0x10; if(0<nargs(__VA_ARGS__)) arg0 = arg0_get(__VA_ARGS__); \
int arg1=0x11; if(1<nargs(__VA_ARGS__)) arg1 = arg1_get(__VA_ARGS__); \
int arg2=0x12; if(2<nargs(__VA_ARGS__)) arg2 = arg2_get(__VA_ARGS__); \
/* do stuff here */ \
}while(0)
Actually I've already implemented the bshow() function as a macro, as follows (here it has the actual number of arguments):
#define __bshow(bdim,data, nbits,ncols,base)({ \
bdim,data, nbits,ncols,base; \
putchar(0x0a); \
printf("nbits %d\n",nbits); \
printf("ncols %d\n",ncols); \
printf("base %d\n",base); \
})
#define _bshow(bdim,data, nbits,ncols,base, ...) __bshow(bdim,data, nbits,ncols,base)
#define bshow(...) \
if( 2==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 32,24,16,0,__VA_ARGS__); \
else if(3==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 24,16,0,__VA_ARGS__); \
else if(4==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 16,0,__VA_ARGS__); \
else if(5==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 0,__VA_ARGS__); \
// test
bshow(0,1);
bshow(0,1, 10);
bshow(0,1, 10,11);
bshow(0,1, 10,11,12);
EDIT:
The proposed solution doesn't have the intended effect because it seems to "instantiate" all instances of the macro, which in general has unintended consequences.
But I wonder if there's a more elegant way to do it.
It'd also be nice to abstract away the entire construction inside its own macro, so that one can apply it to other functions easily, as opposed to having to write the boilerplate manually for each function/macro.
Also this wasn't too helpful.
I found a nice answer.
What you do is you call the vfn() macro, which is (I think) a higher-order macro that returns a macro that returns the token concatenated with the number of args (in hex base, no 0-padding) and then evaluates it at the args. Or something.
Eg. supposed you want to overload a macro called bshow(). You #define the macro bshow() as #define bshow() vfn(bshow,__VA_ARGS__), and you define 1 instance of bshow for each argument count (eg. #define bshow0(...), for 0 arguments, #define bshow1(...) for 1 argument, #define bshow2(...) for 2 arguments, etc.). So now, eg., bshow(0,1) returns bshow2() (because you called it with 2 arguments) evaluated at (0,1), which is _bshow(0,1, 16,32,16), and then _bshow(0,1, 16,32,16) gets evaluated too. You can check the final preprocessor output by running gcc with the -E option, but the intermediate steps are hard to understand (for me).
You also need to decide on the mandatory args and the optional args.
That's almost all I (sort of) understand about what's going on, although I did upload a YT tutorial a while ago on how the argument-counting works.
// ----------------------------------------------------------------
// library
#define __nargs100__(a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a0a,a0b,a0c,a0d,a0e,a0f,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a1a,a1b,a1c,a1d,a1e,a1f,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a2a,a2b,a2c,a2d,a2e,a2f,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a3a,a3b,a3c,a3d,a3e,a3f,a40,a41,a42,a43,a44,a45,a46,a47,a48,a49,a4a,a4b,a4c,a4d,a4e,a4f,a50,a51,a52,a53,a54,a55,a56,a57,a58,a59,a5a,a5b,a5c,a5d,a5e,a5f,a60,a61,a62,a63,a64,a65,a66,a67,a68,a69,a6a,a6b,a6c,a6d,a6e,a6f,a70,a71,a72,a73,a74,a75,a76,a77,a78,a79,a7a,a7b,a7c,a7d,a7e,a7f,a80,a81,a82,a83,a84,a85,a86,a87,a88,a89,a8a,a8b,a8c,a8d,a8e,a8f,a90,a91,a92,a93,a94,a95,a96,a97,a98,a99,a9a,a9b,a9c,a9d,a9e,a9f,aa0,aa1,aa2,aa3,aa4,aa5,aa6,aa7,aa8,aa9,aaa,aab,aac,aad,aae,aaf,ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7,ab8,ab9,aba,abb,abc,abd,abe,abf,ac0,ac1,ac2,ac3,ac4,ac5,ac6,ac7,ac8,ac9,aca,acb,acc,acd,ace,acf,ad0,ad1,ad2,ad3,ad4,ad5,ad6,ad7,ad8,ad9,ada,adb,adc,add,ade,adf,ae0,ae1,ae2,ae3,ae4,ae5,ae6,ae7,ae8,ae9,aea,aeb,aec,aed,aee,aef,af0,af1,af2,af3,af4,af5,af6,af7,af8,af9,afa,afb,afc,afd,afe,aff,a100,...) a100
#define __nargs__(...) __nargs100__(,##__VA_ARGS__, ff,fe,fd,fc,fb,fa,f9,f8,f7,f6,f5,f4,f3,f2,f1,f0,ef,ee,ed,ec,eb,ea,e9,e8,e7,e6,e5,e4,e3,e2,e1,e0,df,de,dd,dc,db,da,d9,d8,d7,d6,d5,d4,d3,d2,d1,d0,cf,ce,cd,cc,cb,ca,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0,bf,be,bd,bc,bb,ba,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0,af,ae,ad,ac,ab,aa,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0,9f,9e,9d,9c,9b,9a,99,98,97,96,95,94,93,92,91,90,8f,8e,8d,8c,8b,8a,89,88,87,86,85,84,83,82,81,80,7f,7e,7d,7c,7b,7a,79,78,77,76,75,74,73,72,71,70,6f,6e,6d,6c,6b,6a,69,68,67,66,65,64,63,62,61,60,5f,5e,5d,5c,5b,5a,59,58,57,56,55,54,53,52,51,50,4f,4e,4d,4c,4b,4a,49,48,47,46,45,44,43,42,41,40,3f,3e,3d,3c,3b,3a,39,38,37,36,35,34,33,32,31,30,2f,2e,2d,2c,2b,2a,29,28,27,26,25,24,23,22,21,20,1f,1e,1d,1c,1b,1a,19,18,17,16,15,14,13,12,11,10,f,e,d,c,b,a,9,8,7,6,5,4,3,2,1,0)
#define __vfn(name, n) name##n
#define _vfn( name, n) __vfn(name, n)
#define vfn( fn, ...) _vfn(fn, __nargs__(__VA_ARGS__))(__VA_ARGS__)
// ----------------------------------------------------------------
// example
// backend: actual implementation, 2 mandatory args, 3 optional args
#define _bshow(bdim,data, ncols,nbits,base)({ \
/* do stuff here */ \
})
// "frontend", default arguments get implemented here. the suffix is the number of arguments, in hexadecimal base
#define bshow2(...) _bshow(__VA_ARGS__, 16,32,16)
#define bshow3(...) _bshow(__VA_ARGS__, 32,16)
#define bshow4(...) _bshow(__VA_ARGS__, 16)
#define bshow5(...) _bshow(__VA_ARGS__)
#define bshow(...) vfn(bshow,__VA_ARGS__)
// test
bshow(0x100,data0);
bshow(0x100,data0, 14);
bshow(0x100,data0, 12,16);
bshow(0x100,data0, 10, 8,2);

C header declaration for generics (macro)

I am unsure about where to write the declaration and the call of a macro that replaces the code with a function. I do not really know if I should write the macro to the .h or .c file.
Before reading some stuff on the best ways to create libraries, I was just putting all the code in a header file and including it on my main, i.e.
#ifndef LIB
#define LIB
#define def_func(type) \
type func(type x) \
{ \
// Do something
}
func(int)
#endif
Some other functions use these defined functions so I had to call the macro to the .h file.
Firstly, I think that a few small edits are needed in the code from the question:
#ifndef LIB
#define LIB
#define def_func(type) \
type func(type x) \
{ \
/* Do something */ \
}
def_func(int)
#endif
The question does not detail what objective is being achieved, but I would assume that the goal is to create something that behaves like a template in C++, where the code is defined in one place and instances are created for different types by using the macro def_func.
One thing to be aware of is if you are using def_func more than once in your project, then you are going to have linker errors due to the same global symbol being used in multiple places, even if def_func is used in separate files. This could be avoided by making the function static if def_func is used multiple times but never more than once in the same file. Although, this would restrict the function from being called from multiple files.
Global symbol redefinition could also be avoided by adding another argument to the #define as follows:
#define def_func(func, type) \
type func(type x) \
{ \
/* Do something */ \
}
This would allow the function identifier to be specified uniquely. For example:
def_func(func_int, int)
would expand to:
int func_int(int x)
{
/* Do something */
}
This way a unique identifier would be created for each instance.
The #define should be placed in the header file if you intend to use the macro from multiple C source files. The macro should be used within C source files only, since using this in the header file would instantiate an object with the same global symbol in each case the header file is included. Although, this would be allowable if the functions are defined as static.
Lastly, if you plan to call the function created from multiple locations, you will need a macro that can be used in a header file associated with the module defining the function to prototype the function. For example:
#define def_func_proto(func, type) \
type func(type x)
So to sum it up, your library .h file would contain:
#define def_func(func, type) \
type func(type x) \
{ \
/* Do something */ \
}
#define def_func_proto(func, type) \
type func(type x)
Then using the integer case as an example, the C source file may include:
def_func(func_int, int)
Which would expand to (note that the actual expansion will not have line breaks):
int func_int(int x)
{
/* Do something */
}
In this case, the header file may contain:
def_func_proto(func_int, int);
Which would expand to:
int func_int(int x);
Finally, I would note that am not certain that this is a good programming practice, in general. You will want to be very cautious in implementing this in your program.

Multiple definition of function in the same place

I am trying to simulate generics in C by having some preprocessor definitions for a matrix type. Here is an excerpt of that:
#define __matrix_struct(TYPE) \
struct { \
uint32_t sz; \
TYPE **ptr; \
}
#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *
#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)
#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
__matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
uint32_t i; \
__matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
for (i = 0; i < sz; ++i) { \
m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
} \
return m; \
}
#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
uint32_t i; \
for (i = 0; i < m->sz; i++) { \
free(m->ptr[i]); \
} \
free(m->ptr); \
free(m); \
}
#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)
In another file, byte_matrix.h, I am trying to define a matrix of uint8_t values, as follows:
#include "matrix.h"
typedef uint8_t byte;
__matrix_typedef(byte);
__matrix_allocator(byte)
__matrix_deallocator(byte)
When I try to compile, I get the following errors:
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here
I cannot understand why it would point to times to the same line and complain about that definition, since every header I wrote has include guards. Could you please explain this to me? Also if you know of a better approach to my problem, please let me know. Thanks.
Also I need to compile with -std=c99 if that matters in this case.
A quick fix would be to add static to your function definitions. This will create a static copy of these functions in each compilation unit which references the header. If you want the functions to be inlined every time, this is the way to go.
An alternative way to do it would be to keep function declarations in a .h file, and actual definitions in a single .c file. This approach will avoid duplication, and the compiler will not inline them (unless your linker supports link time optimization).
The reason is that you are including this header file in multiple compilation units. After the preprocessor does all the textual replacements, you end up with actual separate function definitions inside your .c files. And if you don't specify that you want them to be static, they are by default extern, which means that now the compiler doesn't know how to differentiate them if some other part of the code wants to call them.
This is what you basically do whenever you create a header file: you create a list of declarations which will be included in many compilation units, but there is always a single extern definition in a single .c file.
Another way (relative to the proposed by Groo) is to create two macros.
__matrix_allocator_declare with just prototype of function -- for h-file(s)
__matrix_allocator_define with function body -- for one (selected by you) c-file
This way requires to handle two macros and to not forget add function-body macro in some file, but (and it is more important for embedded applications on small microcontrollers) it guarantees that only one function instance will consume memory.

X-macros: how to make the list of variables compile-time configurable?

I have code similar to
#define LIST_OF_VARIABLES \
X(value1) \
X(value2) \
X(value3)
as explained in https://en.wikipedia.org/wiki/X_Macro
Now I have the need to make the LIST_OF_VARIABLES configurable at compile time
So it could effectively be e.g.
#define LIST_OF_VARIABLES \
X(default_value1) \
X(cust_value2) \
X(default_value3)
or e.g.
#define LIST_OF_VARIABLES \
X(default_value1) \
X(default_value2) \
X(cust_value3)
depending on some macros previously defined. The LIST_OF_VARIABLES is long and the customizations are relatively small. I would not like to copy the long list for each customization, because that will cause maintenance issues (the DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). As a matter of fact the LIST_OF_VARIABLES should be in one file and the
customizations elsewhere (either another file or just -D options in the Makefile)
In pseudo-code I was thinking of something like
#define X(arg) \
#ifdef CUST_##arg \
Y(CUST_##arg) \
#else \
Y(DEFAULT_##arg) \
#endif
And then use the X-macros under the name Y.
But of course that does not work, because a macro cannot contain preprocessor
directives.
What would be a way to achieve this? C is a must (no templates or Boost
macros), gcc specific solutions are acceptable.
I think that what you have to do is along the lines of:
#ifdef USE_DEFAULT_VALUE1
#define X_DEFAULT_VALUE1 X(default_value1)
#else
#define X_DEFAULT_VALUE1 /* omitted */
#endif
#ifdef USE_DEFAULT_VALUE2
#define X_DEFAULT_VALUE2 X(default_value2)
#else
#define X_DEFAULT_VALUE2 /* omitted */
#endif
#ifdef USE_DEFAULT_VALUE3
#define X_DEFAULT_VALUE3 X(default_value3)
#else
#define X_DEFAULT_VALUE3 /* omitted */
#endif
#ifdef USE_CUST_VALUE1
#define X_CUST_VALUE1 X(cust_value1)
#else
#define X_CUST_VALUE1 /* omitted */
#endif
#ifdef USE_CUST_VALUE2
#define X_CUST_VALUE2 X(cust_value2)
#else
#define X_CUST_VALUE2 /* omitted */
#endif
#define LIST_OF_VARIABLES \
X_DEFAULT_VALUE1 \
X_DEFAULT_VALUE2 \
X_DEFAULT_VALUE3 \
X_CUST_VALUE1 \
X_CUST_VALUE2 \
You then need to define USE_DEFAULT_VALUE1 etc as required for the specific configuration you are after.
As long as you always need the items in the same order, this is sufficient. If you need them in different orders, then you conditionally define LIST_OF_VARIABLES in the different sequences.
Answering myself.
With help of the comments I came up with a solution that works and meets most
requirements I had mentioned
With the "main code"
$cat main.c
#ifndef VALUE1
#define VALUE1 value1
#endif
#ifndef VALUE2
#define VALUE2 value2
#endif
#ifndef VALUE3
#define VALUE3 value3
#endif
#define LIST_OF_VARIABLES \
X(VALUE1) \
X(VALUE2) \
X(VALUE3)
and a customization file like
$cat cust1
-DVALUE2=value2cust
the code can be compiled using (GNUmake pseudo syntax)
$(CC) $(CFLAGS) $(shell cat cust1) main.c
Actually having the extra indirection with every value defined on a single
line is good, because it allows commenting the values. That would not have
been possible with the continuation lines in the single LIST_OF_VARIABLES macro.
Edit: Not true. A COMMENT(foo) macro expanding to nothing would have solved that issue, too. (Credit: Got the idea from the answer posted by #Jonathan Leffer.)
However the approach does not yet meet the following requirements I hadn't mentioned
no ugly boilerplate code (all these #ifndef lines are not really nice)
customization should also make it possible to drop default values from the
list altogether or add completely new values (yes, this could probably be
done with some ugly dummy code already now)
So not really satisfied yet with my own answer. Need to think about the
approach from the Dr. Dobbs article a bit more, maybe that can be used.
Open for better answers.
Given further context, it appears you want to be able to cherry pick individual values from your list at compile time. I think you might be interested in a preprocessor switch, which can accomplish what you're using preprocessor conditionals for with a lot less boilerplate.
Generic preprocessor switch
Here's a brief framework:
#define GLUEI(A,B) A##B
#define GLUE(A,B) GLUEI(A,B)
#define SECONDI(A,B,...) B
#define SECOND(...) SECONDI(__VA_ARGS__,,)
#define SWITCH(NAME_, PATTERN_, DEFAULT_) SECOND(GLUE(NAME_,PATTERN_), DEFAULT_)
SWITCH macro usage
Invoke SWITCH(MY_PREFIX_,SPECIFIC_IDENTIFIER,DEFAULT_VALUE) to expand everything that is not a matching pattern to DEFAULT_VALUE. Things that are a matching pattern can expand to whatever you map them to.
To create a matching pattern, define an object like macro called MY_PREFIX_SPECIFIC_IDENTIFIER, whose replacement list consists of a single comma followed by the value you want the SWITCH to expand to in this case.
The magic here is simply that SWITCH builds a hidden token, giving it a chance to expand (well, in this implementation SECOND's indirection is also significant), and inject a new second argument to SECOND if it's defined. Nominally this new token isn't defined; in such cases, it simply becomes the first argument to SECOND, which just discards it, never to be seen again.
For example, given the above macros:
#define CONTRACT_IDENTIFIER_FOR_DEFAULT , overridden_id_for_default
#define CONTRACT_IDENTIFIER_FOR_SIGNED , overridden_id_for_signed
SWITCH(CONTRACT_IDENTIFIER_FOR_, DRAFT , draft )
SWITCH(CONTRACT_IDENTIFIER_FOR_, DRAWN , drawn )
SWITCH(CONTRACT_IDENTIFIER_FOR_, PROOFED , proofed )
SWITCH(CONTRACT_IDENTIFIER_FOR_, DELIVERED , delivered )
SWITCH(CONTRACT_IDENTIFIER_FOR_, SIGNED , signed )
SWITCH(CONTRACT_IDENTIFIER_FOR_, FULFILLED , fulfilled )
SWITCH(CONTRACT_IDENTIFIER_FOR_, DEFAULT , default )
...will expand to:
draft
drawn
proofed
delivered
overridden_id_for_signed
fulfilled
overridden_id_for_default
Decorated X Macros
Assuming you wish to give your values names, and simply replace cherry picked values from the command line, you can make use of SWITCH to do something like this:
#define VARVALUE(N_,V_) SWITCH(VALUE_FOR_, N_, V_)
#define LIST_OF_VARIABLES \
X(VARVALUE(value1, default_value1)) \
X(VARVALUE(value2, default_value2)) \
X(VARVALUE(value3, default_value3))
The VARVALUE macros will be applied first in this form. To override a specific value, you can define your pattern matcher using either a #define:
#define VALUE_FOR_value2 , custom_value2
...or on the command line/makefile:
CFLAGS += -DVALUE_FOR_value2=,custom_value2
Disable/insertion using switch macro
To support disabling individual items safely, nest two switches and add an EAT macro to catch the entry:
#define EAT(...)
#define SELECT_ITEM_MACRO_FOR_STATE_ON , X
#define X_IF_ENABLED(N_, V_) \
SWITCH(SELECT_ITEM_MACRO_FOR_STATE_, SWITCH(ENABLE_VALUE_, N_, ON), EAT) \
(SWITCH(VALUE_FOR_, N_, V_))
#define LIST_OF_VARIABLES \
X_IF_ENABLED(value1, default_value1) \
X_IF_ENABLED(value2, default_value2) \
X_IF_ENABLED(value3, default_value3)
Just as before, individual macros can be overridden using VALUE_FOR_valuex pattern macros, but this also allows disabling items using ENABLE_VALUE_valuex macros, which can be set to anything but ,ON to disable that item.
Similarly, one way to add support for inserting values is to flip the idea:
#define ADD_ITEM_MACRO_FOR_STATE_EAT , EAT
#define X_IF_ADDED(N_) \
SWITCH(ADD_ITEM_MACRO_FOR_STATE_, SWITCH(VALUE_FOR_, N_, EAT), X) \
(SECOND(GLUE(VALUE_FOR_,N_)))
#define LIST_OF_VARIABLES \
X_IF_ENABLED(value1, default_value1) \
X_IF_ENABLED(value2, default_value2) \
X_IF_ENABLED(value3, default_value3) \
X_IF_ADDED(value4) \
X_IF_ADDED(value5) \
X_IF_ADDED(value6)
...this allows you to define VALUE_FOR_value4 as a a pattern macro, but by default will expand to nothing.
Summary
The framework supporting setting, removing, or inserting values winds up being:
#define GLUEI(A,B) A##B
#define GLUE(A,B) GLUEI(A,B)
#define SECONDI(A,B,...) B
#define SECOND(...) SECONDI(__VA_ARGS__,,)
#define SWITCH(NAME_, PATTERN_, DEFAULT_) SECOND(GLUE(NAME_,PATTERN_), DEFAULT_)
#define EAT(...)
#define SELECT_ITEM_MACRO_FOR_STATE_ON , X
#define X_IF_ENABLED(N_, V_) \
SWITCH(SELECT_ITEM_MACRO_FOR_STATE_, SWITCH(ENABLE_VALUE_, N_, ON), EAT) \
(SWITCH(VALUE_FOR_, N_, V_))
#define ADD_ITEM_MACRO_FOR_STATE_EAT , EAT
#define X_IF_ADDED(N_) \
SWITCH(ADD_ITEM_MACRO_FOR_STATE_, SWITCH(VALUE_FOR_, N_, EAT), X) \
(SECOND(GLUE(VALUE_FOR_,N_)))
Given this framework, your list macro would be comprised of a series of X(value), X_IF_ENABLED(name,default_value), and/or X_IF_ADDED(name) values, where:
X(value) can be used to always insert a call to the X macro with value
X_IF_ENABLED(name,default_value) will call X with default_value, allowing you to override the default based on name.
X_IF_ADDED(name) will provide an "empty slot" with name, which will do nothing unless you override that slot.
Overriding slots is done by defining VALUE_FOR_name to expand to ,replacement. Disabling enabled slots is done by defining ENABLE_VALUE_name to expand to ,OFF.
Demo showing change, removal, addition using command line

Ways to ASSERT expressions at build time in C

I'm tidying up some older code that uses 'magic numbers' all over the place to set hardware registers, and I would like to use constants instead of these numbers to make the code somewhat more expressive (in fact they will map to the names/values used to document the registers).
However, I'm concerned that with the volume of changes I might break the magic numbers. Here is a simplified example (the register set is more complex):
const short mode0 = 0;
const short mode1 = 1;
const short mode2 = 2;
const short state0 = 0;
const short state1 = 4;
const short state2 = 8;
so instead of :
set_register(5);
we have:
set_register(state1|mode1);
What I'm looking for is a build time version of:
ASSERT(5==(state1|mode1));
Update
#Christian, thanks for the quick response, I'm interested on a C / non-boost environment answer too because this is driver/kernel code.
NEW ANSWER :
In my original answer (below), I had to have two different macros to support assertions in a function scope and at the global scope. I wondered if it was possible to come up with a single solution that would work in both scopes.
I was able to find a solution that worked for Visual Studio and Comeau compilers using extern character arrays. But I was able to find a more complex solution that works for GCC. But GCC's solution doesn't work for Visual Studio. :( But adding a '#ifdef __ GNUC __', it's easy to choose the right set of macros for a given compiler.
Solution:
#ifdef __GNUC__
#define STATIC_ASSERT_HELPER(expr, msg) \
(!!sizeof \ (struct { unsigned int STATIC_ASSERTION__##msg: (expr) ? 1 : -1; }))
#define STATIC_ASSERT(expr, msg) \
extern int (*assert_function__(void)) [STATIC_ASSERT_HELPER(expr, msg)]
#else
#define STATIC_ASSERT(expr, msg) \
extern char STATIC_ASSERTION__##msg[1]; \
extern char STATIC_ASSERTION__##msg[(expr)?1:2]
#endif /* #ifdef __GNUC__ */
Here are the error messages reported for STATIC_ASSERT(1==1, test_message); at line 22 of test.c:
GCC:
line 22: error: negative width in bit-field `STATIC_ASSERTION__test_message'
Visual Studio:
test.c(22) : error C2369: 'STATIC_ASSERTION__test_message' : redefinition; different subscripts
test.c(22) : see declaration of 'STATIC_ASSERTION__test_message'
Comeau:
line 22: error: declaration is incompatible with
"char STATIC_ASSERTION__test_message[1]" (declared at line 22)
ORIGINAL ANSWER :
I do something very similar to what Checkers does. But I include a message that'll show up in many compilers:
#define STATIC_ASSERT(expr, msg) \
{ \
char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
(void)STATIC_ASSERTION__##msg[0]; \
}
And for doing something at the global scope (outside a function) use this:
#define GLOBAL_STATIC_ASSERT(expr, msg) \
extern char STATIC_ASSERTION__##msg[1]; \
extern char STATIC_ASSERTION__##msg[(expr)?1:2]
There is an article by
Ralf Holly that examines different options for static asserts in C.
He presents three different approaches:
switch case values must be unique
arrays must not have negative dimensions
division by zero for constant expressions
His conclusion for the best implementation is this:
#define assert_static(e) \
do { \
enum { assert_static__ = 1/(e) }; \
} while (0)
Checkout boost's static assert
You can roll your own static assert if you don't have access to a third-party library static assert function (like boost):
#define STATIC_ASSERT(x) \
do { \
const static char dummy[(x)?1:-1] = {0};\
} while(0)
The downside is, of course, that error message is not going to be very helpful, but at least, it will give you the line number.
#define static_assert(expr) \
int __static_assert(int static_assert_failed[(expr)?1:-1])
It can be used anywhere, any times.
I think it is the easiest solution.
Before usage, test it with your compiler carefully.
Any of the techniques listed here should work and when C++0x becomes available you will be able to use the built-in static_assert keyword.
If you have Boost then using BOOST_STATIC_ASSERT is the way to go. If you're using C or don't want to get Boost
here's my c_assert.h file that defines (and explains the workings of) a few macros to handle static assertions.
It's a bit more convoluted that it should be because in ANSI C code you need 2 different macros - one that can work in the area where you have declarations and one that can work in the area where normal statements go. There is a also a bit of work that goes into making the macro work at global scope or in block scope and a bunch of gunk to ensure that there are no name collisions.
STATIC_ASSERT() can be used in the variable declaration block or global scope.
STATIC_ASSERT_EX() can be among regular statements.
For C++ code (or C99 code that allow declarations mixed with statements) STATIC_ASSERT() will work anywhere.
/*
Define macros to allow compile-time assertions.
If the expression is false, an error something like
test.c(9) : error XXXXX: negative subscript
will be issued (the exact error and its format is dependent
on the compiler).
The techique used for C is to declare an extern (which can be used in
file or block scope) array with a size of 1 if the expr is TRUE and
a size of -1 if the expr is false (which will result in a compiler error).
A counter or line number is appended to the name to help make it unique.
Note that this is not a foolproof technique, but compilers are
supposed to accept multiple identical extern declarations anyway.
This technique doesn't work in all cases for C++ because extern declarations
are not permitted inside classes. To get a CPP_ASSERT(), there is an
implementation of something similar to Boost's BOOST_STATIC_ASSERT(). Boost's
approach uses template specialization; when expr evaluates to 1, a typedef
for the type
::interslice::StaticAssert_test< sizeof( ::interslice::StaticAssert_failed<true>) >
which boils down to
::interslice::StaticAssert_test< 1>
which boils down to
struct StaticAssert_test
is declared. If expr is 0, the compiler will be unable to find a specialization for
::interslice::StaticAssert_failed<false>.
STATIC_ASSERT() or C_ASSERT should work in either C or C++ code (and they do the same thing)
CPP_ASSERT is defined only for C++ code.
Since declarations can only occur at file scope or at the start of a block in
standard C, the C_ASSERT() or STATIC_ASSERT() macros will only work there. For situations
where you want to perform compile-time asserts elsewhere, use C_ASSERT_EX() or
STATIC_ASSERT_X() which wrap an enum declaration inside it's own block.
*/
#ifndef C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546
#define C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546
/* first some utility macros to paste a line number or counter to the end of an identifier
* this will let us have some chance of generating names that are unique
* there may be problems if a static assert ends up on the same line number in different headers
* to avoid that problem in C++ use namespaces
*/
#if !defined( PASTE)
#define PASTE2( x, y) x##y
#define PASTE( x, y) PASTE2( x, y)
#endif /* PASTE */
#if !defined( PASTE_LINE)
#define PASTE_LINE( x) PASTE( x, __LINE__)
#endif /* PASTE_LINE */
#if!defined( PASTE_COUNTER)
#if (_MSC_VER >= 1300) /* __COUNTER__ introduced in VS 7 (VS.NET 2002) */
#define PASTE_COUNTER( x) PASTE( x, __COUNTER__) /* __COUNTER__ is a an _MSC_VER >= 1300 non-Ansi extension */
#else
#define PASTE_COUNTER( x) PASTE( x, __LINE__) /* since there's no __COUNTER__ use __LINE__ as a more or less reasonable substitute */
#endif
#endif /* PASTE_COUNTER */
#if __cplusplus
extern "C++" { // required in case we're included inside an extern "C" block
namespace interslice {
template<bool b> struct StaticAssert_failed;
template<> struct StaticAssert_failed<true> { enum {val = 1 }; };
template<int x> struct StaticAssert_test { };
}
}
#define CPP_ASSERT( expr) typedef ::interslice::StaticAssert_test< sizeof( ::interslice::StaticAssert_failed< (bool) (expr) >) > PASTE_COUNTER( IntersliceStaticAssertType_)
#define STATIC_ASSERT( expr) CPP_ASSERT( expr)
#define STATIC_ASSERT_EX( expr) CPP_ASSERT( expr)
#else
#define C_ASSERT_STORAGE_CLASS extern /* change to typedef might be needed for some compilers? */
#define C_ASSERT_GUID 4964f7ac50fa4661a1377e4c17509495 /* used to make sure our extern name doesn't collide with something else */
#define STATIC_ASSERT( expr) C_ASSERT_STORAGE_CLASS char PASTE( PASTE( c_assert_, C_ASSERT_GUID), [(expr) ? 1 : -1])
#define STATIC_ASSERT_EX(expr) do { enum { c_assert__ = 1/((expr) ? 1 : 0) }; } while (0)
#endif /* __cplusplus */
#if !defined( C_ASSERT) /* C_ASSERT() might be defined by winnt.h */
#define C_ASSERT( expr) STATIC_ASSERT( expr)
#endif /* !defined( C_ASSERT) */
#define C_ASSERT_EX( expr) STATIC_ASSERT_EX( expr)
#ifdef TEST_IMPLEMENTATION
C_ASSERT( 1 < 2);
C_ASSERT( 1 < 2);
int main( )
{
C_ASSERT( 1 < 2);
C_ASSERT( 1 < 2);
int x;
x = 1 + 4;
C_ASSERT_EX( 1 < 2);
C_ASSERT_EX( 1 < 2);
return( 0);
}
#endif /* TEST_IMPLEMENTATION */
#endif /* C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546 */
Try:
#define STATIC_ASSERT(x, error) \
do { \
static const char error[(x)?1:-1];\
} while(0)
Then you can write:
STATIC_ASSERT(a == b, a_not_equal_to_b);
Which may give you a better error message (depending on your compiler).
The common, portable option is
#if 5 != (state1|mode1)
# error "aaugh!"
#endif
but it doesn't work in this case, because they're C constants and not #defines.
You can see the Linux kernel's BUILD_BUG_ON macro for something that handles your case:
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
When condition is true, this becomes ((void)sizeof(char[-1])), which is illegal and should fail at compile time, and otherwise it becomes ((void)sizeof(char[1])), which is just fine.
Ensure you compile with a sufficiently recent compiler (e.g. gcc -std=c11).
Then your statement is simply:
_Static_assert(state1|mode1 == 5, "Unexpected change of bitflags");
#define MODE0 0
#define MODE1 1
#define MODE2 2
#define STATE0 0
#define STATE1 4
#define STATE2 8
set_register(STATE1|STATE1); //set_register(5);
#if (!(5==(STATE1|STATE1))) //MY_ASSERT(5==(state1|mode1)); note the !
#error "error blah blah"
#endif
This is not as elegant as a one line MY_ASSERT(expr) solution. You could use sed, awk, or m4 macro processor before compiling your C code to generate the DEBUG code expansion of MY_ASSERT(expr) to multiple lines or NODEBUG code which removes them for production.

Resources