0

I have many functions and while entering each function, I am calling a Macro FUNC_ENTRY, which is in turn calling the default logging macro (LOGGING).

To be specific, this is my FUNC_ENTRY macro:

#define FUNC_ENTRY LOGGING(ONE, "Entry");

My LOGGING macro is defined as below:

#define LOGGING(prio, my_var, ...) \
{\
    char priority[6];\
    bzero(level,4); \
    if (prio == ONE) { sprintf(priority,"ONE");} \
    if (prio == TWO) { sprintf(priority,"TWO");} \
    if (prio == THREE) { sprintf(priority,"THREE");} \
    fprintf(fp,"%s:  %s:  %s:  %d: %s:%s|\n",__DATE__, __TIME__, __FILE__,__LINE__, __func__,level);\
    fflush(fp); \
    fprintf(fp,my_var,##__VA_ARGS__);\
    fflush(fp); \
    fprintf(fp,"\n");\
    fflush(fp); \
}

OK, now my question is, whenever I enter any function, my LOGGING macro should print "Entry to xyz function". As of now, it only prints "Entry". Any clue how to achieve this?

The way I am calling the FUNC_ENTRY macro is as below. Suppose I have a function xyz;

void xyz {
  FUNC_ENTRY;
  /*other statements*/
}
aod
  • 77
  • 1
  • 2
  • 7
  • "THREE" is larger than [4] :-) – Guy Sirton Jan 22 '14 at 05:06
  • Those things I can correct it myself. This actually is the piece of code I am testing things. Could you please help me with the entry function prints? – aod Jan 22 '14 at 05:09
  • 1
    This might be useful: http://stackoverflow.com/a/733074/441099 – Guy Sirton Jan 22 '14 at 05:14
  • When I redefined it as FUNC_ENTRY LOGGING(ONE, "Entry to"__func__); , I get the error: expected ‘)’ before ‘__func__’ everywhere LOGGING is called. LOGGING(ONE,"count %d",myStruct.count); -> This is how LOGGING is called generally – aod Jan 22 '14 at 05:26
  • You need to quote code in the comment. At any rate see my answer below and you may need to apply some macro processor magic if you want to concatenate those at compile time. There's an answer to that here: http://stackoverflow.com/questions/5256313/c-c-macro-string-concatenation – Guy Sirton Jan 22 '14 at 05:28
  • That's two too many `fflush(fp)` calls for most purposes, unless you think you often write buggy code. 'Tis odd that you zero `level`, declare and set `priority`, but print `level` which is still all zeros. That fragment is big enough to warrant a function. You don't want the semi-colon after `#define FUNCENTRY`. – Jonathan Leffler Jan 22 '14 at 05:29
  • It seems like `__func__` is a variable and so can't be concatenated to a string in a macro. So you need to do this in run time. – Guy Sirton Jan 22 '14 at 05:33

2 Answers2

3

There are a number of issues:

  1. That's two too many fflush(fp) calls for most purposes, unless you think you often write buggy code.

  2. 'Tis odd that you zero level, declare and set priority, but print level which is still all zeros.

  3. That fragment is big enough to warrant a function.

  4. You don't want the semi-colon after #define FUNCENTRY.

  5. 'Tis also odd that you think you should get Entry to xyz function when you don't include to or function in the strings in the macro.

  6. It also seems pointless reporting the time and date when the file was compiled in your error messages (which is what __DATE__ and __TIME__ are for).

Fixing some of those issues leads to:

#define FUNC_ENTRY LOGGING(ONE, "Entry to %s function\n", __func__)

#define LOGGING(prio, my_var, ...) \
{\
    char priority[6];\
    memset(priority, '\0', sizeof(priority)); \
    if (prio == ONE) { sprintf(priority, "ERR");} \
    if (prio == TWO) { sprintf(priority, "TWO");} \
    if (prio == THREE) { sprintf(priority, "THREE");} \
    fprintf(fp,"%s:  %s:  %s:  %d: %s:%s|\n", __DATE__, __TIME__, __FILE__, __LINE__, __func__, priority);\
    fprintf(fp, my_var, ##__VA_ARGS__); \
    fprintf(fp,"\n"); \
    fflush(fp); \
}

I note that , ##__VA_ARGS__ is a GCC extension over standard C. The bzero() function was marked obsolescent in POSIX 2004 and is missing from POSIX 2008; it is best not to use it.

It is not clear, but judging from the code, you have a global (or, at least, file scope) variable FILE *fp; which is initialized to the log file you want to write to. Ick; and likewise yuck!

Were it my code (and I wanted the Entry to xyz function message spelled thus), I'd probably use:

extern void err_logger(int level, int line, char const *file, char const *func, ...);

and

#define FUNC_ENTRY LOGGING(ONE, "Entry to %s function\n", __func__)

#define LOGGING(prio, ...) \
    err_logger(level, __LINE__, __FILE__, __func__, __VA_ARGS)

And the implementation of err_logger() might be:

void err_logger(int level, int line, char const *file, char const *func, ...)
{
    char *priority = "";
    if (level == ONE)   priority = "ERR";
    if (level == TWO)   priority = "TWO";
    if (level == THREE) priority = "THREE";
    time_t t = time(0);
    char date_time[32];
    strftime(date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", gmtime(&t));
    fprintf(logfp, "%s: %s: %d: %s: %s|\n", date_time, file, line, func, priority);
    va_list args;
    va_start(args, func);
    char *fmt = va_arg(args, char *);
    vfprintf(logfp, fmt, args);
    va_end(args);
    fflush(logfp);
}

Where logfp would be the log file stream and would be private to the file that holds the source for err_logger().

I've not compiled that code; there could be minor errors in it. It does, however, give you the general idea of what to do and how to do it — I think.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

Something along these lines:

#include <stdio.h>

#define T printf("Entering %s\n", __func__)

int main(void) 
{
  T;
  return 0;
}

Unfortunately it looks like you're not going to be able to concatenate that to your string at compile time (see here: Can I substitute __func__ into an identifier name in a C macro?). There may be some other compiler specific or C++ specific tricks but otherwise you will need to build your string at run time.

Community
  • 1
  • 1
Guy Sirton
  • 8,331
  • 2
  • 26
  • 36
  • Thanks! I used fprintf to print it inside the file and it worked. Replaced my old LOGGING function. – aod Jan 22 '14 at 05:38