Reputation: 7466
I am writing a log writer, and for that I am writing a wrapper function over vfprintf so I am able to include some extra information around it.
The log writing macro is defined as this:
#define LOG_WRITE(type, fmt, args...) write_log(type, __FILE__, __FUNCTION__, __LINE__, fmt, ## args)
And I have my function defined like this:
int write_log(enum LogType_e type, const char* file, const char* function, int line, const char* format, ...) {
va_list arg;
int rv;
va_start(arg, format);
rv = vfprintf(log_fd, format, arg);
va_end(arg);
return rv;
}
That function gets some extra information, like the log level, the file where the log call was ran, function, line of code, and finally the text.
Of course, I want to check that information and format it nicely and add it to 'format'. How can I do that?
Upvotes: 2
Views: 2067
Reputation: 17288
Amend the fprintf
statement to suit the output you require. Note the example below uses __VA_ARGS__
which is the C pre-processor way to process variadic arguments AFAIK.
#define LOG_WRITE(type, fp, fmt, ...) write_log(type, fp, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__)
int write_log(enum LogType_e type, FILE *fp, const char *file, const char* function, int line, const char* format, ...)
{
va_list arg;
int rv;
va_start(arg, format);
fprintf(fp, "file %s:function %s:line %d:", file, function, __LINE__);
rv = vfprintf(fp, format, arg);
va_end(arg);
return rv;
}
int main()
{
FILE* fp = fopen("test.log", "w");
int b = 13, c = 5;
write_log(LOG_ERROR, fp, "vfprintf.c", "main", 27, "%s %d\n", "value of b=", b);
LOG_WRITE(LOG_ERROR, fp, "value of c=%d\n", c);
LOG_WRITE(LOG_ERROR, fp, "help!!\n");
}
Upvotes: 0
Reputation: 29136
The easiest solution is probably not to fiddle with the format string, but to add further calls to fprintf(log_fd, ...)
:
void write_log(enum LogType_e type, const char* file, const char* function, int line, const char* format, ...) {
va_list arg;
int rv;
switch (type) {
case TYPE_ERROR:
fprintf(log_fd, "Error: ");
break;
case TYPE_WARN:
fprintf(log_fd, "Warning: ");
break;
}
if (file) {
if (function) {
fprintf(log_fd, "[%s in %s, %d] ", function, file, line);
} else {
fprintf(log_fd, "[%s, %d] ", file, line);
}
}
va_start(arg, format);
rv = vfprintf(log_fd, format, arg);
va_end(arg);
}
This makes it harder to keep track of the number of characters printed, but you're not going to use that information anyway, so there's no point in calculating and returning it.
(You could also log to a temporary string and then pretty-print that if you need word-wrapping. But that would mean you'd have to keep track of the overall string length again.)
Upvotes: 2