C, Find the intermediate value of a define - macros

Given the following defines :
#define foo bar
#define bar 2
#define reg_bar 4
I'm trying to create a macro that given the define foo, find the value of the define reg_bar, 4.
I tried this:
#define foo_bar(value) reg_##value
foo_bar(foo)
But it doesn't work, as it returns reg_foo.
And this
#define foo_bar(value) reg_##value
#define foo_bar_2(value) foo_bar(value)
foo_bar_2(foo)
But it still doesn't work as it returns reg_2
Is there anyway to do it, only with macro and preprocessor?
Thanks for your help :)

Sadly, no. There is no such thing as an "intermediate value". A token sequence is either expanded or not; ## suppresses expansion, but there is nothing which suppressed "part of" the expansion.

Related

Concatenating an expanded macro and a word using the Fortran preprocessor

I'm trying to concatenate a word in the source code with the expansion of a preprocessor macro. Basically I have foo somewhere in the code, and with a #define EXPANSION bar I want to obtain foobar. However, I'm struggling to find a way to do this, which works with all compilers. For the moment I would be happy if it works with gfortran and ifort.
According to its documentation, the gfortran preprocessor is a C preprocessor running in "traditional mode", which does not have the ## token paste operator. However, the same effect can be obtained with an empty C-style /**/ comment. The ifort preprocessor seems to behave more like the normal C preprocessor, so normal token pasting does the trick in ifort. Unfortunately the empty /**/ comment does not work in ifort, as the comment is replaced by a single space instead.
Here is a little example:
#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#define PASTE(x,y) x ## y
foo/**/EXPANSION
CAT(foo,EXPANSION)
For which gfortran produces:
foobar
foo ## bar
While ifort gives me:
foo bar
foobar
Of course I could choose the right way by checking the predefined macros for both compilers:
#ifdef __GFORTRAN__
foo/**/EXPANSION
#else
CAT(foo,EXPANSION)
#endif
This works for both of them, but it's rather ugly to have the preprocessor conditional for every expansion. I would much rather avoid this and have some macro magic only once in the beginning.
I have seen this answer to another question, which would probably allow me to work around this issue, but I would rather find a solution that does not invoke the preprocessor separately.
I'm not too familiar with the C preprocessor. Maybe there is a simple way to do what I want. Any ideas?
EDIT: I've already tried something like this:
#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#ifdef __GFORTRAN__
#define PASTE(x,y) x/**/y
#else
#define PASTE(x,y) x ## y
#endif
CAT(foo,EXPANSION)
Unfortunately this does not work in gfortran where it produces fooEXPANSION. I'm not entirely sure how this works, but apparently the expansion of the CAT macro prevents the expansion of EXPANSION in the same line. I suspect that this is a feature of the "traditional" C preprocessor ...
I have done some research and it seems that basically most Fortran compilers (i.e. Intel and PGI) use a relatively normal C-preprocessor with a token pasting operator. We only need a special treatment for gfortran, which uses a C preprocessor in traditional mode without a token pasting operator.
Thanks to an entry on c-faq.com I found this definition of a CAT macro that works with all compilers I tested so far:
#ifdef __GFORTRAN__
#define PASTE(a) a
#define CAT(a,b) PASTE(a)b
#else
#define PASTE(a) a ## b
#define CAT(a,b) PASTE(a,b)
#endif
Another solution (that still uses the /**/ trick) was posted by Jonathan Leffler in this answer to a related question.

How to store a macro in another macro?

I have a macro DDLogDebug(...) and I would like to do the following
#define _DDLogDebug(arg...) DDLogDebug(args)
#undef DDLogDebug
#define DDLogDebug(args...) doSomething(); _DDLogDebug(arg...)
But it does not work. Instead of #define _DDLogDebug(arg...) DDLogDebug(args), I would need a command that "stores" the content of the macro DDLogDebug to _DDLogDebug.
Does something like that exist?
How should one do when one wants to modify a macro whose definition is not exposed?
You can't do something like this with the purely standard preprocessor.
The reason is that macro definition doesn't work like e.g. function definition in the main language: at the time when you define _DDLogDebug, it isn't actually linking to the definition of DDLogDebug - it's storing exactly what you wrote. It won't attempt to actually find an expansion for any names until the macro is being used in the program outside of any definitions. By that point, the definition for DDLogDebug is already gone.
This is actually a valuable and intended behaviour, because it allows the use of techniques like X-macros: one definition can provide a framework and let different calling contexts decide how to actually use it in different ways. Not only is the outer macro not dependent on definitions available at the time it was written, but meaning of its contents can change throughout the program without having to change its structure.
If you can't work around this problem, you might have some luck with the non-standard but widely-supported push_macro and pop_macro directives.
Example of the use of push and pop:
#define FOO 123
#pragma push_macro("FOO")
#undef FOO
FOO
#pragma pop_macro("FOO")
FOO
Run this through gcc -E and you'll see it emits FOO (newline) 123. Works with Clang.

Comparing Strings in C Macros (for MODULE_LICENSE)

I'd like to be able to ensure I don't accidentally statically link any proprietary modules into the kernel. I was thinking of making MODULE_LICENSE("Proprietary") fail at compile time if MODULE was not defined. (or even better, fail if MODULE_LICENSE("GPL") was not defined...).
But I can't find a good way to compare strings within a macro -- anyone have any good solutions to this?
I don't think you can do this.
The way it's usually done is by defining preprocessor symbols, and comparing their (integer) values:
#define LICENSE_PROPRIETARY 1
#define LICENSE_GPL 2
#define LICENSE_MIT 3
#define MODULE_LICENSE LICENSE_GPL
#if MODULE_LICENSE != LICENSE_GPL
#error "Not GPL, fail fail"
#endif

Availability.h -like macro

Is it possible to have a custom availability macro like the __OSX_AVAILABLE_STARTING for instance. I need it to perform in the same way, I just need to change its name and the versions and number of parameters?
Yes, certainly. Objective-C is a strict superset of C, so C macros are very much at your disposal, and that facility is simply a set of C macros that eventually expand to
gcc's __attribute__ keyword to declare special attributes of a function.
The relevant declarations are all in
Availability.h
AvailabilityInternal.h
To refresh, you use the __OSX_AVAILABLE_STARTING macro to tag a function declaration as being supported for a particular version, like this:
extern void mymacfunc() __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_NA);
So what do we need to implement this ourselves? If you strip their
support for two different OS (mac, iphone), the availability facility boils down to:
A macro that takes a version argument like __MY_AVAILABLE_STARTING(<version>):
#define __MY_AVAILABLE_STARTING(_myversion) __MY_AVAILABILITY_INTERNAL##_myversion
Set of version arguments, like those in Availability.h, that are valid arguments for the above:
#define __MYVER_2_0 20000
#define __MYVER_2_1 20100
#define __MYVER_2_2 20200
#define __MYVER_3_0 30000
Another set of macros, like thos in AvailabilityInternal.h that specifies what should happen for each version (regular support, deprecated, unavailable, weak, etc). Again, this is a function of the compiler, see gcc docs (there are lots of other interesting options):
#define __MY_AVAILABILITY_INTERNAL__MYVER_2_0 __AVAILABILITY_INTERNAL_UNAVAILABLE
#define __MY_AVAILABILITY_INTERNAL__MYVER_2_1 __AVAILABILITY_INTERNAL_WEAK_IMPORT
#define __MY_AVAILABILITY_INTERNAL__MYVER_2_1 __AVAILABILITY_INTERNAL_REGULAR
And finally, where the buck ends, the macros that expand to the __attribute__ facility.
For the ones I have above, you can just keep using Apple's macros:
#define __AVAILABILITY_INTERNAL_DEPRECATED __attribute__((deprecated,visibility("default")))
#define __AVAILABILITY_INTERNAL_UNAVAILABLE __attribute__((unavailable,visibility("default")))
#define __AVAILABILITY_INTERNAL_WEAK_IMPORT __attribute__((weak_import,visibility("default")))
#define __AVAILABILITY_INTERNAL_REGULAR __attribute__((visibility("default")))
Or, of course, you can define your own craziness.
C Macros are powerful stuff, often overlooked. Good luck!

Is there a way to replace an already defined preprocessor identifier?

I have a library that has several options defined as this:
#define shouldShowToolbar YES
#define shouldAlignToLeft YES
etc..
and I'm looking for a way to actually replace those from outside (without modifying the library, because the future updates will break it). Is it possible, or am I doomed to change the library source code (which I do have) every time an update comes out.
There is #undef
#include "library_header.h" /* Which defines the macro. */
#undef shouldShowToolbar /* You undef it. */
#define shouldShowToolbar NO /* If you want, you can redefine it. */
http://gcc.gnu.org/onlinedocs/cpp/Undefining-and-Redefining-Macros.html
If you don't want a particular macro to take effect for a section of code and you know that macro name too, you can use
#undef shouldShowToolbar
/* Your code */
#define shouldShowToolbar
This wont totally undef the macro, cos you never know which part of your code might actually want it
These are values that are hardcoded at compile time. If you compile the library with your project then you should be able to redefine them in a file that compiles later in the compile list, I think there is a special keyword for it. Otherwise it is like saying I want to replace YES in the library.
As far as i know, preprocessor directives executes before compilation. So after that, there's no chance to change something.