Вопрос

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*/
}
Это было полезно?

Решение 2

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.

Другие советы

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top