How to enable custom TRACE macro for specific files only? - c

I wrote the following trace macro in a file named "debug.h".
#define TRACE(x) \
printf( \
"%s(%d): ", \
__FILE__, \
__LINE__ \
); \
\
printf(x);
In debug I'd like to enable the macro only for certain files since resources are limited on the platform that I'm using. I don't want to completely remove the TRACE calls from the files. Just disable them.
Is there a clean way to do this in C using the preprocessor?

In debug.h:
#if TRACE_ENABLE
#define TRACE(x) \
printf( \
"%s(%d): ", \
__FILE__, \
__LINE__ \
); \
\
printf(x);
#else
#define TRACE(x)
#endif
Then, in your source files where you don't want trace:
#define TRACE_ENABLE 0
#include "debug.h"
or just:
#include "debug.h"
In source files to enable trace:
#define TRACE_ENABLE 1
#include "debug.h"

While both answers seems good to me, I think Giuseppe's answer is more useful most of the time since if you use this macro many times in a file, and you want to switch debug on/off for complete files, pmg's method is exhausting.
The important thing is to not forget adding the else statement: #else TRACE(X); if you want to edit it in the specific file and not in header, use:
#ifdef TRACE
#undef TRACE
#endif
#define TRACE(X)

A trick I've used somtimes is the use of a bit mask to enable a subset of the files whete the TRACE is used:
File1.c:
#if TRACE_MASK & 0x01
#define TRACE(x) ...
#endif
File2.c:
#if TRACE_MASK & 0x02
#define TRACE(x) ...
#endif
...
Then you can define your TRACE_MASK macro in the preprocessing options: /DTRACE_MASK=0x03 to enable the trace on both File1.c and File2.c
The only problem is that there is a limited numner of bits... (but you can use more than one macro: TRACE_MASK1, TRACE_MASK2...)
Bye
EDIT: of course you can write tdefinition once in a file "trace.h", and just redefine the mask in each source:
File trace.h:
#if TRACE_MASK & TRACE_CURRENT
#define TRACE(x) ...
#else
#define TRACE(x) do {} while(0)
#endif
File1.c:
#define TRACE_CURRENT 0x01
#include "trace.h"
File2.c:
#define TRACE_CURRENT 0x02
#include "trace.h"

What about
#define TRACE(x, y) do if (y) {/*your prints*/} while (0)
and also
#define TRACE_ENABLE 1
or
#define TRACE_ENABLE 0
at the top of your sources.
Then replace the TRACE invocations with
TRACE(foo, TRACE_ENABLE);

Related

How to define macro bases on macro value?

I have macros:
#if defined DEBUG && DEBUG
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
Which effectively do nothing when DEBUG has TRUE value.
But now I want to provide the TYPE thing. Which will show the type of debugging:
D( 1, "some string" );
D( 2, "another thing" );
Is there a way to define such macros which will do nothing for D(1,..) and print debug messages for D(2,...) when DEBUG is 2 and viceversa when 1?
I wanna something like this::
#if defined DEBUG && DEBUG
# define D(type,...) if DEBUG&type THEN printf(__VA_ARGS__) else do nothing
#else
# define D(...)
#endif
Well, it won't be truely evaluated at preprocessing time, but if the type is a compile-time-constant, still at compile-type.
#define D(type, ...) (void)((type & DEBUG) && fprintf(stderr, __VA_ARGS__))
The above needs at least C99 though.
You can do it like this;
#if defined DEBUG
# define P1(...)
# define P2(...) printf(__VA_ARGS__)
# define D(n, ...) P##n(__VA_ARGS__)
#else
# define D(...)
#endif
main()
{
D(1, "Test");
D(2, "Test2");
}
This did not resolve the problem but take me closer. Maybe it will be useful for someone:
#define _CAT(a, ...) a ## __VA_ARGS__
#define CHECK(...) SECOND(__VA_ARGS__, 0)
#define SECOND(x, n, ...) n
#define _NOT_0 _TRUE()
#define _TRUE() ~, 1
#define BOOL(x) NOT(NOT(x))
#define NOT(x) CHECK(_CAT(_NOT_, x))
#define IF(cond) _IF(BOOL(cond))
#define _IF(cond) _CAT(_IF_, cond)
#define _IF_1(...) __VA_ARGS__
#define _IF_0(...)
IF(1)(printf("YES\n");)
IF(0)(printf("NO\n");)
Links to tricks: first and second. Second link is more interesting because it describes what is coming on step-by-step

Logical implementation of #ifdef inside #define

Is there a way in this code
#include <stdio.h>
// #define t1
#define msg_a 1
#define msg_b 2
#define msg_c 3
#ifdef t1
#define msg_d 4
#define msg_e 5
#endif
#define call(msg) case msg_ ## msg: printf("msg_" #msg); break;
#define avail \
call(a) \
call(b) \
call(c) \
call(d) \
call(e) \
int main(void)
{
int test;
test = 2;
printf("test = %d\n", test);
switch (test)
{
avail
}
printf("\nend\n");
return 0;
}
to get (logically) the same result as if the bellow code works?
#define avail \
call(a) \
call(b) \
call(c)
#ifdef t1
call(d) \
call(e) \
#endif
So, I don't want to generate code like case msg_b: printf("msg_" "b"); break; inside my switch if t1 is not defined.
Also, more defines like this maybe included, and then there will be
...
#ifdef t2
#define msg_f 6
#define msg_g 7
#endif
...
and again, this should works like this
#define avail \
call(a) \
call(b) \
call(c)
#ifdef t1
call(d) \
call(e) \
#endif
#ifdef t2
call(f) \
call(g) \
#endif
Is there a way to get something similar to this?
I'm not sure what you're trying to accomplish with this, so I can't really know that this is a good idea, but...
#ifdef t1
#define t1_calls call(d) \
call(e)
#else
#define t1_calls
#endif
#ifdef t2
#define t2_calls call(f) \
call(g)
#else
#define t2_calls
#endif
#define avail t1_calls t2_calls
Incidentally, I assume that this is just to show what you mean and you know about normal C conventions regarding macros (functions, capitalization, scoping, etc.)
One straightforward way:
#ifdef t1
#define avail call(a); call(b); call(c); call(d); call(e);
#else
#define avail call(a); call(b); call(c);
#endif
So you can extend this to get:
#ifdef t1
#define T1 call(d); call(e);
#else
#define T1
#endif
#ifdef t2
#define T2 call(f); call(g);
#else
#define T2
#endif
#define avail call(a); call(b); call(c); T1 T2
Not elegantly.
Firstly, a macro cannot expand to preprocessor directives. Every directive must be visible at the toplevel without any expansion (among other things, it's syntactically impossible since there's no such thing as a multi-line macro - the \ escapes the newline, rather than including it - and directives rely on newlines as part of the syntax).
You can have conditional expansion within a macro (see here, here, etc.). But those are based on macros that expand to boolean values (or at least to some substitute for booleans). Unfortunately defined is an operator rather than a macro, which means it can only appear in preprocessor expressions, i.e. the argument to an #if directive. It cannot expand into anything that would be inserted into the program body, and thus cannot form part of a macro definition that relies on expansion to choose an action.
If you really want a static if macro, make t1, t2 etc. defined at all times (the choice being between two possible values rather than between defined and undefined), and use one of the other static-if techniques in the linked questions. Or better, reconsider your need for a static if at all: in most cases, it's better to use a C-level if statement and let the compiler optimise out the dead branch.

Preprocessor Directive: #elif not defined?

Is there a preprocessor directive that checks whether a constant is not defined. I am aware of the #ifndef directive but I am also looking for a #elif not defined directive. Does #elif not defined exist?
This is how I would use it:
#define REGISTER_CUSTOM_CALLBACK_FUNCTION(callbackFunctName) \
#ifndef CUSTOM_CALLBACK_1 \
#define CUSTOM_CALLBACK_1 \
FORWARD_DECLARE_CALLBACK_FUNCTION(callbackFunctName) \
#elif not defined CUSTOM_CALLBACK_2 \
#define CUSTOM_CALLBACK_2 \
FORWARD_DECLARE_CALLBACK_FUNCTION(callbackFunctName) \
#elif not not defined CUSTOM_CALLBACK_3 \
#define CUSTOM_CALLBACK_3 \
FORWARD_DECLARE_CALLBACK_FUNCTION(callbackFunctName) \
#endif
How about the
#elif !defined(...)
But you've got bigger problems - the trailing \ exclude the other directives - or rather make them illegal. So, even with the valid syntax, your definitions won't do what you want.
You'll need to move the initial define inside the conditions.
#ifndef CUSTOM_CALLBACK_1
#define CUSTOM_CALLBACK_1
#define REGISTER_CUSTOM_CALLBACK_FUNCTION(callbackFunctName) \
FORWARD_DECLARE_CALLBACK_FUNCTION(callbackFunctName)
#elif !defined(CUSTOM_CALLBACK_2)
//.....

How to port pgm_read_byte macro (AVR-GCC) to Mircrochip C18 Compiler?

I'm porting the T6963-based LCD driver from AVR-GCC to the microchip C18 compiler. I have seen the macro "pgm_read_byte": does anyone know how to port this macro?
UPDATE
From here I can see the implementation of the macro
#define pgm_read_byte(address_short)
pgm_read_byte_near(address_short)
...
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
...
#define __LPM(addr) __LPM_enhanced__(addr)
...
#define __LPM_enhanced__(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ \
( \
"lpm %0, Z" "\n\t" \
: "=r" (__result) \
: "z" (__addr16) \
); \
__result; \
}))
According to the link you posted, the macro is defined as:
#define pgm_read_byte(address_short) pgm_read_byte_near(address_short)
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
Those macros should be portable without any problems, they're simply aliasing the names of other functions/macros. What specifically are you having trouble with? What have you tried so far, and what went wrong?
AVR is Harvard architecture and pgm_read_ macros serves to access AVR's flash memory which resides in an other address space than RAM.
On a target with a linear address space you can just use the pointers to access the data:
#if defined (__GNUC__) && defined (__AVR__)
#include <avr/pgmspace.h>
#else
#include <stdint.h>
#define PROGMEM /* empty */
#define pgm_read_byte(x) (*(x))
#define pgm_read_word(x) (*(x))
#define pgm_read_float(x) (*(x))
...
#endif

turning off DEBUG macros for a specific function (NDEBUG)

I am using the following macro for printing debug information that I found on the web. It works great.
However, I would like to turn-off debug printing for function A when debugging function B, which calls function A. I tried #define NDEBUG function A #undef NDEBUG but haven't managed to suppress printing in function A.
Any help will be greatly appreciated.
Any suggestions for alternative ways of accomplishing the task is also welcome.
Thanks ~RT
#ifdef NDEBUG
/*
If not debugging, DEBUGPRINT NOTHING.
*/
#define DEBUGPRINT2(...)
#define DEBUGPRINT(_fmt,G ...)
#else
/*
Debugging enabled:
*/
#define WHERESTR "[file %s, line %d]: "
#define WHEREARG __FILE__, __LINE__
#define DEBUGPRINT2(...) fprintf(stderr, __VA_ARGS__)
#define DEBUGPRINT(_fmt, ...) DEBUGPRINT2(WHERESTR _fmt, WHEREARG, __VA_ARGS__)
#endif /* NDEBUG */
maybe you should wrap the trace into a module so that you can turn on/off the tracing dynamically in run-time and in that way you can specifically turn it off for a function call. In release mode you could replace all tracing with empty statements although in my experience I find it good to keep tracing in release mode as well - just in case.
NDEBUG is useful at the time assert.h is included, so #define NDEBUG/#undef NDEBUG later will not do anything.
You can do something like this though:
#if defined(NDEBUG) || !defined(MY_DEBUG)
/*
If not debugging, DEBUGPRINT NOTHING.
*/
#define DEBUGPRINT2(...)
#define DEBUGPRINT(_fmt,G ...)
#else
/*
Debugging enabled:
*/
#define WHERESTR "[file %s, line %d]: "
#define WHEREARG __FILE__, __LINE__
#define DEBUGPRINT2(...) fprintf(stderr, __VA_ARGS__)
#define DEBUGPRINT(_fmt, ...) DEBUGPRINT2(WHERESTR _fmt, WHEREARG, __VA_ARGS__)
#endif /* NDEBUG */
Then, in function A():
...
#undef MY_DEBUG
result = B();
#define MY_DEBUG
...
This will debug B() when it's called from anywhere except from A(). To get debugging, you will need MY_DEBUG to be defined and NDEBUG to be undefined.
Edit: You will need to define MY_DEBUG when you want to compile with debugging, but hopefully you're using make or some other build tool, so this should be easy.

Resources