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

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.

Related

Using C macros in Swift

Have my own macro defined in myProject.pch file,
For example:
#define Enable_Analytics
And i want to enclose few statements of code at multiple places inside
#ifdef Enable_Analytics
// Code statements which has to executed only if Enable_Analytics is defined
#endif
This is useful to include/remove code based on the macro.
In Objective-C this works but in swift i get error. How to use #ifdef in swift?
You can call the C preprocessor on just about and kind of file even if it is not C or a C like language.
It is usually available as cpp on most Unix like systems. Just run cpp your-file.swift and the C preprocessor should preprocess the file just as it would C.
However I do not know of a way to make the preprocessor use defines within a project file. So you probably will have to manually specify them on the command line like -DMACRO_NAME=somevalue.
Alternatively you could #include a file containing the defines within each of your swift files and the preprocessor will insert them.

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!