Use macro expansion to create multiple #define constants - c

I am working on an open gl driver and need to define a set of constants using #define. The names of these constants iterate along with the value they represent. They are also bounded by a max value set by another #define which is hardware specific. I would like to define the these constants using the max value if possible.
Currently I have defined them as follows:
#define GL_MAX_TEXTURE_UNITS 24
#define GL_TEXTURE0 0
#define GL_TEXTURE1 1
...
#define GL_TEXTURE24 24
I would like to have something along the lines of the following:
#define GL_MAX_TEXTURE_UNITS 24
#define GL_TEXTURE(SOMETRICKYMACRO)
Where the macro is defined in such a way that at compilation I end up with an expansion equivalent to the first case but if I wanted to change the number of constants I would only need to modify GL_MAX_TEXTURE_UNITS.

The C preprocessor cannot produce new preprocessing directives itself. If you want to do something like this, you would need to generate the header file with a separate utility (perhaps a shell or awk script) as part of your build process.
If you find yourself really needing something like this (programmatically variable range of values), it might be an indication that referring to them symbolically via macro names is a bad design choice.

Related

Computed Includes in C

I was reading the C Preprocessor guide page on gnu.org on computed includes which has the following explanation:
2.6 Computed Includes
Sometimes it is necessary to select one of several different header
files to be included into your program. They might specify
configuration parameters to be used on different sorts of operating
systems, for instance. You could do this with a series of
conditionals,
#if SYSTEM_1
# include "system_1.h"
#elif SYSTEM_2
# include "system_2.h"
#elif SYSTEM_3 …
#endif
That rapidly becomes tedious. Instead, the preprocessor offers the
ability to use a macro for the header name. This is called a computed
include. Instead of writing a header name as the direct argument of
‘#include’, you simply put a macro name there instead:
#define SYSTEM_H "system_1.h"
…
#include SYSTEM_H
This doesn't make sense to me. The first code snippet allows for optionality based on which system type you encounter by using branching if elifs. The second seems to have no optionality as a macro is used to define a particular system type and then the macro is placed into the include statement without any code that would imply its definition can be changed. Yet, the text implies these are equivalent and that the second is a shorthand for the first. Can anyone explain how the optionality of the first code snippet exists in the second? I also don't know what code is implied to be contained in the "..." in the second code snippet.
There's some other places in the code or build system that define or don't define the macros that are being tested in the conditionals. What's suggested is that instead of those places defining lots of different SYSTEM_1, SYSTEM_2, etc. macros, they'll just define SYSTEM_H to the value that's desired.
Most likely this won't actually be in an explicit #define, instead of will be in a compiler option, e.g.
gcc -DSYSTEM_H='"system_1.h"' ...
And this will most likely actually come from a setting in a makefile or other configuration file.

Dynamically prefix macro names with a variadic macro

Background
I've utilized a set of preprocessor macros from another question that allows me to prefix symbol names (enums, function names, struct names, etc) in my source, i.e.:
#include <stdio.h>
#define VARIABLE 3
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define NAME(fun) EVALUATOR(fun, VARIABLE)
void NAME(func)(int i);
int main(void)
{
NAME(func)(123);
return 0;
}
void NAME(func)(int i)
{
printf("i is %d in %s.\n", i, __func__);
}
Problem
This works as expected, with the following output: i is 123 in func_3.
Edit
I would like this code:
#define NAME(SOME_MACRO_CONST) (123)
#define NAME(SOME_MACRO_CONST2) (123)
To expand to:
#define 3SOME_MACRO_CONST (123)
#define 3SOME_MACRO_CONST2 (123)
I realize the macro shouldn't start with a digit. In the final code I'll be using names like LIB_A_ and LIB_B_ as prefixes.
/Edit
However, if I attempt to do the same with macros as the arguments to my NAME variadic macro, it fails like so:
Re-using NAME macro:
Code
#define NAME(MY_CONST) (3)
Output
test.c:7:0: warning: "NAME" redefined
#define NAME(MY_CONST) 3
Manually pasting prefix:
Code:
#define VARIABLE ## MY_CONST (3)
Output:
test.c:8:18: error: '##' cannot appear at either end of a macro expansion
#define VARIABLE ## MY_CONST (3)
Question
How can I create simple macro definitions (name + value) that has a common prefix for all the macros? The goal is to be able to make multiple copies of the source file and compile them with different flags so all versions can be linked together into the same final binary without symbol/macro name collisions (the macros will later be moved into header files). The final file will be too big to write in something like M4 or a template language. Ideally, the solution would involve being able to use a single macro-function/variadic-macro for all use cases, but I'm OK with one macro for symbol prefixing, and another for macro-name prefixing.
I would like this code:
#define NAME(SOME_MACRO_CONST) (123)
#define NAME(SOME_MACRO_CONST2) (124)
To expand to:
#define 3SOME_MACRO_CONST (123)
#define 3SOME_MACRO_CONST2 (124)
(I corrected the second number to 124 to make it different from the first one, for readability purposes)
This is impossible with the C preprocessor
for several reasons:
3SOME_MACRO_CONST is not a valid identifier (both for the preprocessor, and for the C compiler itself) since it does not start with a letter or an underscore. So let's assume you want your code to be expanded to:
/// new desired expansion
#define THREE_SOME_MACRO_CONST (123)
#define THREE_SOME_MACRO_CONST2 (124)
this is still impossible, because the preprocessor works before anything else and cannot generate any preprocessor directive (e.g. #define).
A workaround, if you only want to #define some numbers (computable at compile-time !!!) might be to expand to some anonymous enum like
enum {
THREE_SOME_MACRO_CONST= 123,
THREE_SOME_MACRO_CONST2= 124,
};
and you know how to do that in the details. Read also about X-macros.
However, even if you can change your requirement to something that is possible, it might be not recommendable, because your code becomes very unreadable (IMHO). You could sometimes consider writing some simple script (e.g. in sed or awk ...), or use some other preprocessor like GPP, to generate a C file from something else.
Notice that most serious build automation tools (like GNU make or ninja) -or even IDEs (they can be configured to) permit quite easily (by adding extra targets, recipes, commands, etc...) to generate some C (or C++) code from some other file, and that meta-programming practice has been routinely used since decades (e.g. bison, flex, autoconf, rpcgen, Qt moc, SWIG ...) so I am surprised you cannot do so. Generating a header file containing many #define-s is so common a practice that I am surprised you are forbidden to do so. Perhaps you just need to discuss with your manager or colleagues. Maybe you need to look for some more interesting job.
Personally, I am very fond of such meta-programming approaches (I did my PhD on these in 1990, and I would discuss them at every job interview; a job where metaprogramming is forbidden is not for me. Look for example at my past GCC MELT project, and my future project also will have metaprogramming). Another way of promoting that approach is to defend domain specific languages (and the ability to make your DSL inside some large software project; for example the GCC compiler has about a dozen of such DSLs inside it....). Then, your DSL can (naturally) be compiled to C which is a common practice. On modern operating systems that generated C code could be compiled at runtime and dynamically loaded as a (generated) plugin (using dlopen on POSIX...)
Sometimes, you can trick the compiler. For a project compiled by GCC, you could consider writing your GCC plugin..... (that is a lot more work than adding a command generating C code; your plugin could provide extra magic pragmas or builtins or attributes used by some other macros).
You could also configure the spec file of your gcc to handle specifically some C files. Beware, that could affect every future compilation!

How do I create a sophisitcated macro check for resources in a static embedded OS?

I have an embedded OS that needs its resources to be defined statically by compile time.
So e.g.
#define NUM_TASKS 200
At the moment, I have one header file where every developer needs to declare the tasks he/she needs, kind of like this:
#define ALL_TASKS ( \
1 + \ /* need one task in module A */
2 \ /* need two tasks in module B */
)
and during compilation of the OS, there is a check:
#if (ALL_TASKS > NUM_TASKS)
#error Please increase NUM_TASKS in CONF.H
#endif
So when I compile and more Tasks are needed the compilation stops and gives explicit notice that the static OS won't have enough tasks for this to work.
So far so good.
Enter the lazy programmer that forgets to add the tasks he added in module A to the global declaration file in directory x/y/z/foo/bar/baz/.
What I would like is the following construct, which I can't seem to achieve with any macro tricks I tried:
Have macros to declare the resources needed in a module like so:
OS_RESERVE_NUMBER_OF_TASKS(2)
in the modules adds 2 to the global number of Tasks.
my first rough idea was something like this:
#define OS_RESERVE_NUMBER_OF_TASKS(max_tasks) #undef RESOURCE_CALC_TEMP_MAX_NUM_TASKS \
#define RESOURCE_CALC_TEMP_MAX_NUM_TASKS RESOURCE_CALC_MAX_NUM_TASKS + max_tasks \
#undef RESOURCE_CALC_MAX_NUM_TASKS \
#define RESOURCE_CALC_MAX_NUM_TASKS RESOURCE_CALC_TEMP_MAX_NUM_TASKS \
#undef RESOURCE_CALC_TEMP_MAX_NUM_TASKS
but that doesn't work because a #define in a #define does not work.
So the question basically is:
Do you have an idea how it would be possible to split the calculation of the number of tasks into multiple files (namely the modules themselves) and have that number comapred to the defined max number of tasks during compile time?
If this isn't solvable with pure C preprocessor, I'll have to wait until we change the make system to scons...
Can you require that tasks have some ID or similar which all task users must use?
tasks.h
enum {
TASK_ID_TASK_A_1,
TASK_ID_TASK_B_1,
TASK_ID_TASK_B_2,
NUM_TASKS
};
void * giveResource(int taskId, int resourceId);
user_module_B.c
#include "tasks.h"
...
resource = giveResource(TASK_ID_TASK_B_1, resource_id_B_needs);
You can update the value of a macro in the course of translating one unit using the Boost Preprocessor library's evaluated slots functionality. It defines several "slots" that can be treated as mutable global variables by preprocessor code, which will let you add to a value as you go along rather than defining it with a single expression.
(It's pure standard C, but the code that implements it is rather complicated)
You can't do it in one line, because it relies on calls to #include, and that means you can't wrap it up into a pretty one-liner macro, but it would look something like this:
#define TASK_SLOT 2 //just pick one
#define ALL_TASKS BOOST_PP_SLOT(TASK_SLOT)
#define BOOST_PP_VALUE 1 + 2
#include BOOST_PP_ASSIGN_SLOT(TASK_SLOT) // ALL_TASKS now evals to 3
#define BOOST_PP_VALUE 3 + ALL_TASKS
#include BOOST_PP_ASSIGN_SLOT(TASK_SLOT) // ALL_TASKS now evals to 6
As Drew comments (I may have misunderstood your req.), this is only valid for one translation unit. Which is fine if you have a central NUM_TASKS and each unit is allowed to add up its own ALL_TASKS figure.
If you need the value to increment across multiple .c files (so that the final ALL_TASKS is the total across all modules, not for one), you'd need to wrap them up into a unity build for this technique to work, which most people reckon is a bad idea. A more advanced build system would then probably be appropriate, because the preprocessor is only designed to work on single units.

Evaluate constant before displaying it in preprocessor

On this site I found tricks to display constant values in preprocessor, like:
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
#define A 5
#pragma display(VAR_NAME_VALUE(A))
that generates the output A=5
and they work well, but when I need to evaluate something like:
#define A 5
#define B (A*5)
#pragma display(B)
it displays the output B=5*5.
What if I wanted to display B=25? How should I write the preprocessor directive to do this?
You can not, the macro replacement mechanism does not involve doing calculations, but you can take a look to GNU M4:
Besides just doing macro expansion, m4 has built-in functions for including named files, running shell commands, doing integer arithmetic, manipulating text in various ways, performing recursion, etc....
at built-in eval
http://www.gnu.org/software/m4/manual/m4.html#Eval

Do preprocessor macro definitions need to be in CAPS in a header file?

In the code I'm writing, I have been told to define a variable in a header file in the following way:
#define CLR_BLACK 0x0000
and since this is the only example I've been given, I was wondering whether all variables defined in a header file with the #define command need to be in caps. For example, would the following be valid?
#define videoBuffer (u16*)0x6000000
No. You can use any combination of alphanumeric characters and underscores. Don't start with a number.
However a variable name like videoBuffer would be difficult to distinguish from regular variables (without syntax coloring). That's why most people either use all caps for preprocessor macros or start them with a lower case k, like this: kMyPreprocessorMacro
EDIT: Those are not "global variables" by the way (as you tagged). They're preprocessor macros. Basically an automatic find and replace mechanism that is run at compile time.
No.
#define is a pre-processor macro. It replaces every occurrence of the first string after it with whatever comes after the string. The first string does not need to be in caps.
No, but it's a common and useful convention so if you're reading the code you can see what's a macro and what isn't. See C++ #ifndef for include files, why is all caps used for the header file?

Resources