Tag Archives: macro

Logging with a bit more brain

I expect many of you will use the preprocessor macros of __LINE__ and __FILE__ for logging. It’s fairly standard practice, but if you don’t, then I’ll introduce you to it.

#define LOG(x...) log(__FILE__,__LINE__,x)

This will allow you to do, for example

LOG("Something went wrong\n");

and it will include the file and the line number in the log function as the first two parameters.

That’s fairly common. Now, what’s less common is a thing I worked out for more complex logging.
I needed to log a message which may appear very regularly, but I didn’t want to spam logfiles with millions of them, I only needed to see the first one. I thought that I’ll have to tag the log with some kind of hash value for checking when it was last used, or something like that, when I had a brainstorm. It could all be done in the preprocessor.

#define LOGO(x...) { static int loginst__LINE__=0; if (loginst__LINE__==0){ loginst__LINE__=1; log(__FILE__,__LINE__,x);}}

As you can see, the variable loginst_nnn will only be used once per file, so is unique (unless you use LOGO twice on one line, don’t do that. The macro definition has to be all on one line, obviously. I mention this because wordpress is likely to wrap it unless your screen is very wide.

That got me thinking, what else can I do with the preprocessor like this. And I came up with:

#define LOGN(n,x...) { static int loginst__LINE__=0; if (loginst__LINE__++==0){ log(__FILE__,__LINE__,x);} if (loginst__LINE__==w) loginst__LINE__=0;}

This one logs every nth occurence of the log message. I also came up with

#define LOGT(t,x...) { static time_t loginst__LINE__=0; if (loginst__LINE__<=time(NULL)){ log(__FILE__,__LINE__,x);loginst__LINE__=time(NULL)+t;}}

which only logs at most once every t seconds.

All in all, I was quite pleased with that. They’re simple, effective, and a LOT more efficient than some other solutions I’ve seen out there.

 

Variable length C macros

This article was originally published on the LGP Blog on Saturday, May 30th, 2009

Something that came up in porting X2 and X3 is that Visual Studio in Windows handles variable length macros, and as far as we could see, GCC didnt.

This means that in gcc, if you wanted to create a define that would do a job and report where it was called from, you would need to do something like:

void mydebug(const char *file,int line,const char *fmt,...)

#define DEBUGOUT1(x) mydebug(__FILE__,__LINE__,x)
#define DEBUGOUT2(x,y) mydebug(__FILE__,__LINE__,x,y)
#define DEBUGOUT3(x,y,z) mydebug(__FILE__,__LINE__,x,y,z)

and so on…

However, there is a solution which does the job, which we found after a fair amount of investigation. The recommended method would be

#define DEBUGOUT(x,y...) mydebug(__FILE__,__LINE__,x,y)

Which will work, but only if you actually add a second parameter to the DEBUGOUT call. Without, it will expand

DEBUGOUT(x)

to

mydebug(__FILE__,__LINE__,x,)

which will obviously fail to compile. To fix this, simply bear in mind that … in the macro just means everything else, so you can do

#define DEBUGOUT(x...) mydebug(__FILE__,__LINE__,x)

which then works with single and multiple values in macros, x becomes the fmt AND the … for the mydebug .