C preprocessor: include based on define - macros

How can I include a file or another, based on the value of a defined string?
This doesn't work:
#define VAR VALUE_A
#if VAR == "VALUE_A"
#include "a.h"
#elif VAR == "VALUE_B"
#include "b.h"
#endif
If it's important, I'm not actually defining VAR, I'm passing it down from the command-line via gcc -D NAME=VALUE.

The == operator does not compare strings. But you have a couple of other options to configure your includes. In addition to the solutions already mentioned in other answers, I like this one because I think it is quite self-explanatory.
/* Constant identifying the "alpha" library. */
#define LIBRARY_ALPHA 1
/* Constant identifying the "beta" library. */
#define LIBRARY_BETA 2
/* Provide a default library if the user does not select one. */
#ifndef LIBRARY_TO_USE
#define LIBRARY_TO_USE LIBRARY_ALPHA
#endif
/* Include the selected library while handling errors properly. */
#if LIBRARY_TO_USE == LIBRARY_ALPHA
#include <alpha.h>
#elif LIBRARY_TO_USE == LIBRARY_BETA
#define BETA_USE_OPEN_MP 0 /* You can do more stuff than simply include a header if needed. */
#include <beta.h>
#else
#error "Invalid choice for LIBRARY_TO_USE (select LIBRARY_ALPHA or LIBRARY_BETA)"
#endif
Your users can now compile with:
$ cc -DLIBRARY_TO_USE=LIBRARY_BETA whatever.c

You can use #ifdef or #ifndef for conditional includes.
#ifdef VALUE_A
#include "a.h"
#endif
#ifdef VALUE_B
#include "b.h"
#endif

The closest possilibility I can think of is to utilize third form of #include directive (C11 ยง6.10.2/4), namely define VAR with value, that holds actual header filename:
#define VAR "a.h"
then just use the following:
#include VAR

Related

In Doxygen for a C++ project how do I get documentation for member functions that are #included in this nonstandard way?

I have a class that has a #include inside it containing the member function declarations, like this:
class PContextActions_t {
public:
#define PARG blah...
#include "pActionDecls.h"
#undef PARG
#define PARG
#include "pActionDecls.h"
#undef PARG
void OtherFuncs(); /// Another function
};
because they need to be declared twice with different arguments. When I run doxygen on this project I get documentation for OtherFuncs(), but not for any of the functions declared in pActionDecls.
What can I do about this? I've tried:
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
CLANG_ASSISTED_PARSING = YES

FreeRTOS Project Setup with error: expected ')' before string constant

I am starting a new project on a STM32L476 Nucleo board and planned to use FreeRTOS.
My initial project structure:
main.c
#include "project.h"
int main(void)
{
/* Configure the system clock */
Clock_Config();
/* Configure IOs */
GPIO_Config();
/* FreeRTOS Stuff */
NVIC_SetPriorityGrouping(3);
vTaskStartScheduler();
/* Should never get here! */
while (1){}
}
project.h
#ifndef PROJECT_H_
#define PROJECT_H_
/* MPU Files */
#include "stm32l4xx.h"
/* Project Files */
#include "gpio.h"
#include "clock.h"
/* FreeRTOS */
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
#define TASKPRIO_STD ( tskIDLE_PRIORITY + 1 )
#define TICK_TASK_PERIOD_MS pdMS_TO_TICKS( 500 )
#endif /* PROJECT_H_ */
project.c
#include "project.h"
static void vSerialTask( void * pvParameters );
xTaskCreate( vSerialTask, "I2C", configMINIMAL_STACK_SIZE, NULL, TASKPRIO_STD, NULL);
static void vSerialTask( void *pvParameters ){
for( ;; )
{
}
}
I get a syntax error with this structure in xTaskCreate line: expected ')' before string constant
If I move xTaskCreate to my main.c and leave the task itself in my project.c (also have to delete static in this case) my project compiles successfully.
What is the problem here? I already saw working projects where xTaskCreate is not done within main.c so can't imagine this is the real problem?
You can't call the function outside another function and it is exactly what you try to do.
You can only call functions from another functions. The first function executed is main

How to add an header file in a C project on Eclipse?

I real need help over here, I have to do this ASCIITwitter project for an university's exam and I'm stucked with this problem:
I have to add a header file and a source file on my project of course, so first I tried some easy code to see if I'm capable to do this.
Just a program to do some square operations:
There's my code:
Twitter.h
#ifndef TWITTER_H_
#define TWITTER_H_
int square(int);
#endif /* TWITTER_H_ */
Twitter.c
#include "Twitter.h"
int square(int x)
{
return x*x;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Twitter.h"
int main(void)
{
int y;
y=square(5);
printf("%d\n",y);
system("PAUSE");
}
But it give to me "undefined reference to 'square' and I really don't know how to fix this. I've tried searching on internet, but I'm working on windows, I don't have any makefile, I just want to make this work. Please help me.

Why does Perl access to cross-platform packed structs not work with SWIG?

Working from:
Is ignoring __attribute__((packed)) always safe in SWIG interfaces?
Visual C++ equivalent of GCC's __attribute__ ((__packed__))
My .i does:
#define __attribute__(x)
then uses %include to include my cross-platform definition of PACK():
#if defined(SWIG)
#define PACK(...) VA_ARGS
#elif defined(_MSC_VER)
#define PACK(__Decl__) __pragma(pack(push, 1)) __Decl__ __pragma(pack(pop))
#else // GCC
#define PACK(__Decl__) __Decl__ __attribute__ ((packed))
#endif
Then I have code like:
PACK(
typedef struct {
uint8_t something;
uint32_t more;
} ) aName;
With earlier versions of the PACK() macro, I got syntax error from SWIG on the typedef line. Now I get past that but when compiling the SWIG-generated .c file, I have get and set functions that complain aName doesn't exist. The messages are like (edited):
libudr_perl_swig.c: In function '_wrap_aName_set':
libudr_perl_swig.c:2367:20: error: expected identifier or '(' before
'=' token libudr_perl_swig.c: In function '_wrap_aName_get':
libudr_perl_swig.c:2377:3: error: expected expression before 'aName'
SWIG sort of seems to know about my struct -- it creates access functions -- but the doesn't expose them enough that the access functions can find it.
Before I started to make this cross-platform -- when it was still Linux-only with __attribute__ ((packed)) -- it worked in SWIG. And it still works in Linux. So there appears to be something about SWIG's interpretation of PACK() that is flawed.
The old way generated a lot of per-field code like:
XS(_wrap_aName_something_set) {
{
aName *arg1 = (aName *) 0 ;
...
the new way generates a little per-struct code like:
SWIGCLASS_STATIC int _wrap_aName_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) {
MAGIC_PPERL
{
Why should my PACK() (which should be a no-op in SWIG) do that?
Googling "cpp standard variadic macros" leads to http://en.wikipedia.org/wiki/Variadic_macro which notes the expansion of ... is __VA_ARGS__, not VA_ARGS (as I had found somewhere). When I change my macro definition to be:
#if defined(SWIG)
#define PACK(...) __VA_ARGS__
#elif defined(_MSC_VER)
#define PACK(__Decl__) __pragma(pack(push, 1)) __Decl__ __pragma(pack(pop))
#else // GCC
#define PACK(__Decl__) __Decl__ __attribute__ ((packed))
#endif
it works.

Obj-C, using ifndef and target parameters to only printf debug lines?

I've been happily using a replacement for NSLog called DLog so that I don't have to worry about debugging being left in a release build.
#ifndef NDEBUG
# define DLog(FORMAT, ...) printf("%s\n",
[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
# define DLog(...)
#endif
However, I'd like to do some a bit more complicated, I have numerous targets with debug parameters and I'd like to include two parameters to enable me to get debugging information.
I had hoped I could use, something like this...
#ifndef NDEBUG
# define DLog(FORMAT, ...) printf("%s\n", ...
#else
#ifdef TESTFLIGHT && FREEMIUM
# define DLog(FORMAT, ...) printf("%s\n", ...
#else
# define DLog(...)
#endif
But it's not as simple as that.. I'm probably missing something obvious?
I've googled the problem but can't find the AND operator for this purpose and nested IF statements seems a problem too ?
When you're using the existence of the definition like this, to combine use this syntax:
#if defined TESTFLIGHT && defined FREEMIUM
(#ifdef is shorthand for #if defined).
Use #elif for "else if" to cascade without nesting.
You can use the boolean operator straight-up like you want if you're defining the constant to be equal to something (e.g. 1) rather than just being "defined". e.g.
#define TESTFLIGHT 1
#define FREEMIUM 1
...
#if TESTFLIGHT && FREEMIUM
You should use "#elif" to make an else if, instead of nested ifs.
And you can can use the #if defined(TESTFLIGHT) && defined(FREEMIUM), as said on the other answers. So :
#ifndef NDEBUG
# define DLog(FORMAT, ...) printf("%s\n", ...
#elif TESTFLIGHT && FREEMIUM
# define DLog(FORMAT, ...) printf("%s\n", ...
#else
# define DLog(...)
#endif
You need to use "normal" #if:
#if defined(TESTFLIGHT) && defined(FREEMIUM
#ifdef FOO is simply short for #if defined(FOO)
You're also missing an #endif. So complete, it's:
#ifndef NDEBUG
# define DLog(FORMAT, ...) printf("%s\n", ...
#else
# if defined(TESTFLIGHT) && defined(FREEMIUM)
# define DLog(FORMAT, ...) printf("%s\n", ...
# else
# define DLog(...)
# endif
#endif