warning: too many arguments for format - c

#include<stdio.h>
#include<errno.h>
#include<error.h>
#include<stdlib.h>
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define DEBUG_ERROR(M,...) fprintf(stderr, "[ERROR] (%s:%d: (error: %s)) M \n", __FILE__, __LINE__, clean_errno(),##__VA_ARGS__)
int main()
{
int test =10;
DEBUG_ERROR("Test variable %s = %d.\n","test",test);
return 0;
}
Any ideas on how to fix the following warning with the debug macro...
warn.c:12:4: warning: too many arguments for format [-Wformat-extra-args]

Your macro should be:
#define DEBUG_ERROR(M,...) fprintf(stderr, "[ERROR] (%s:%d: (error: %s)) " M " \n", __FILE__, __LINE__, clean_errno(),##__VA_ARGS__)
Note that M is not in quotes now.

Related

Multiple definition of function error wont go away

I have a project with many files and they all include one header called logging.h, I dont know what happened but for some reason when i try to compile this happens. I can not revert the changes and I dont know what to do.
These lines repeat themselves multiple times
/usr/bin/ld: fs/operations.o: in function `send_request':
/root/so/mbroker/utils/logging.h:59: multiple definition of `send_request'; mbroker/mbroker.o:/root/so/mbroker/utils/logging.h:59: first defined here
/usr/bin/ld: fs/operations.o: in function `serialize':
/root/so/mbroker/utils/logging.h:68: multiple definition of `serialize'; mbroker/mbroker.o:/root/so/mbroker/utils/logging.h:68: first defined here
/usr/bin/ld: fs/state.o: in function `clear_session':
/root/so/mbroker/utils/logging.h:53: multiple definition of `clear_session'; mbroker/mbroker.o:/root/so/mbroker/utils/logging.h:53: first defined here
As you can see it's all happening in logging.h
Here's my logging.h
#ifndef __UTILS_LOGGING_H__
#define __UTILS_LOGGING_H__
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h> //open
#include <fcntl.h> //flags for open
#include <unistd.h>
#define PIPENAME 256
#define BOXNAME 32
#define MSIZE 256
#define COMMAND 8
static const __uint8_t REGISTER_PUBLISHER = 1;
static const __uint8_t REGISTER_SUBSCRIBER = 2;
static const __uint8_t CREATE_BOX = 3;
static const __uint8_t REMOVE_BOX = 5;
static const __uint8_t LIST_BOX = 7;
static const char INVALID_SESSIONS[] = "Invalid number of sessions";
static const char PIPENAME_TOO_BIG[] = "The pipe's name has too many characters";
static const char INVALID_BOXNAME[] = "The box's name is invalid";
static const char INVALID_NUMBER_OF_ARGUMENTS[] = "Insufficient or too many arguments";
static const char INVALID_ARGUMENTS[] = "One of the arguments is invalid";
static const char UNEXISTENT_PIPE[] = "Pipe doesn't exist";
static const char EXISTENT_PIPE[] = "Pipe already exists";
static const char ERROR_WRITING_PIPE[] = "Error writing to pipe";
static const char SIGNAL_FAIL[] ="Failed to initialize signals";
typedef struct box{
char boxname[BOXNAME];
int hasWriter;
int n_readers;
struct box *next;
} box;
typedef struct req{
int _code;
char _client_pipe[PIPENAME];
char _box_name[BOXNAME];
} request;
typedef enum {
LOG_QUIET = 0,
LOG_NORMAL = 1,
LOG_VERBOSE = 2,
} log_level_t;
//deletes fifo
void clear_session(int fd, char* fn){
close(fd);
unlink(fn);
}
/*writes to pipe tx a pointer with information*/
void send_request(int tx, request *r1) {
ssize_t ret = write(tx, &r1, sizeof(r1));
if (ret < 0) {
fprintf(stdout, "ERROR: %s\n", ERROR_WRITING_PIPE);
exit(EXIT_FAILURE);
}
}
/*Returns a pointer to a struct containing the request*/
request *serialize(int code, char* client_pipe, char* box_name){
request *r1 = (request*) malloc(sizeof(request));
r1->_code = code;
strcpy(r1->_client_pipe, client_pipe);
strcpy(r1->_box_name, box_name);
return r1;
}
void sig_handler(int sig);
void set_log_level(log_level_t level);
extern log_level_t g_level;
#define INFO(...) \
do { \
char buf[2048]; \
snprintf(buf, 2048, __VA_ARGS__); \
fprintf(stderr, "[INFO]: %s:%d :: %s :: %s\n", __FILE__, __LINE__, \
__func__, buf); \
} while (0);
#define PANIC(...) \
do { \
char buf[2048]; \
snprintf(buf, 2048, __VA_ARGS__); \
fprintf(stderr, "[PANIC]: %s:%d :: %s :: %s\n", __FILE__, __LINE__, \
__func__, buf); \
exit(EXIT_FAILURE); \
} while (0);
#define WARN(...) \
do { \
if (g_level == LOG_NORMAL || g_level == LOG_VERBOSE) { \
char buf[2048]; \
snprintf(buf, 2048, __VA_ARGS__); \
fprintf(stderr, "[WARN]: %s:%d :: %s :: %s\n", __FILE__, \
__LINE__, __func__, buf); \
} \
} while (0);
#define LOG(...) \
do { \
if (g_level == LOG_NORMAL || g_level == LOG_VERBOSE) { \
char buf[2048]; \
snprintf(buf, 2048, __VA_ARGS__); \
fprintf(stderr, "[LOG]: %s:%d :: %s :: %s\n", __FILE__, \
__LINE__, __func__, buf); \
} \
} while (0);
#define DEBUG(...) \
do { \
if (g_level == LOG_VERBOSE) { \
char buf[2048]; \
snprintf(buf, 2048, __VA_ARGS__); \
fprintf(stderr, "[DEBUG]: %s:%d :: %s :: %s\n", __FILE__, \
__LINE__, __func__, buf); \
} \
} while (0);
#endif // __UTILS_LOGGING_H__
I tried deleting files, going back as far as i could but this error wont stop haunting me.
I also tried make clean multiple times, but did nothing either.
I went back to an old backup of the project which was ok and now it's showing me this same error message again. I tried compiling both through vsc and through wsl.
Now that i think it through, the error might have started when i included .c in another file. I have long deleted that include line but am still getting the errors.
The solution involved only writing prototypes on the header and implementing the functions in a logging.c. It's weird the compiler only warned me after like many and many trials, but it's solved and that's all i could ask for.

C Overwrite data strftime macro

I am trying to write a small log system.
void write_log_msg(char * type, char * file_name, int line_number, char * fmt, ...);
To call this function in a nice way, I used macro
#define log_msg(fmt, ...) (write_log_msg(LOG, __FILE__, __LINE__, fmt, ##__VA_ARGS__))
I want to format the date of now and I use the function strftime to do that. But when I do, it seems it overwrites the data stored in __FILE__ and __LINE__ and I can't tell why.
time_t now = time(NULL);
char date_str[DATE_SIZE];
char time_str[TIME_SIZE];
struct tm * local_now = localtime(&now);
printf("file %s\n", file_name);
printf("line %d\n", line_number);
status = strftime(date_str, DATE_SIZE, "%b %d %Y", local_now);
if(status == 0){
printf("Error 1");
exit(EXIT_FAILURE);
}
status = strftime(time_str, TIME_SIZE, "%X", local_now);
if(status == 0){
printf("Error 2");
exit(EXIT_FAILURE);
}
When I check for the content of the value of __FILE__ and __LINE__ before strftime, it works just fine then the __FILE__ takes the value of date_str and line_str I can't even tell. Any idea why it would do that ? Thanks !
Any idea why it would do that ?

How to evaluate part of an expression using macros in C?

I am currently developing a unit test library in C and I wanted to add a functionality Catch (in C++) had.
When you do, using Catch :
int x = 5;
REQUIRE(x == 4);
The output will be something like this :
Failed statement : x == 4
evaluated as 5 == 4
Is it possible to do something like that in C ?
This needs to be done at runtime.
You could do something like this. It's not very convenient, but it works:
#include <stdio.h>
#include <stdlib.h>
#define ASSERT_INT 1
#define ASSERT_EQ(x,y,type) do { if((x)!=(y)) { \
switch(type) { \
case ASSERT_INT: \
printf("Failed statement : %s == %d\n\tevaluated as %d == %d\n", \
#x, (y),(x), (y)); break; \
} exit(EXIT_FAILURE); }} while(0)
It requires some work though. If you want many operations you can do like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ASSERT_INT 1
#define ASSERT_EQ 1
#define ASSERT(x,y,op,type) do { \
int success; \
char op_str[3]; \
switch(op) { \
case ASSERT_EQ: \
strcpy(op_str, "==");success = ((x) == (y)); break; \
} \
if(!success) { \
switch(type) { \
case ASSERT_INT: \
printf("Failed statement : %s %s %d\n\tevaluated as %d %s %d\n", \
#x, op_str, (y),(x), op_str, (y)); break; \
} exit(EXIT_FAILURE); }} while(0)
And the output:
$ ./a.out
Failed statement : x == 4
evaluated as 5 == 4
You will need to add a modified version of strcpy(op_str, "==");success = ((x) == (y)); break; for each different logical operation and a modified version of printf("Failed statement : %s %s %d\n\tevaluated as %d %s %d\n", #x, op_str, (y),(x), op_str, (y)); break; for each different type.

Macro to jump to label on error fails: use of undeclared label

I'm going through Zed Shaw's tutorial on C debug macros, and am running an undeclared label problem, call the following file debug_macro.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
int test_check(char *file_name)
{
FILE *input = NULL;
char *block = NULL;
block = malloc(100);
input = fopen(file_name, "r");
check(input, "Failed to open %s.", file_name);
free(block);
fclose(input);
return 0;
error:
if(input) free(input);
if(block) free(block);
return -1;
}
int main(int argc, char *argv[])
{
// open up a bogus file and then trigger error
check(test_check("bogus.txt") == 0, "failed with bogus.txt");
return 0;
}
When I compile it with either cc or gcc, I get the following error:
gcc -Wall -g -O0 -I/opt/X11/include goto.c -o goto
goto.c:36:5: error: use of undeclared label 'error'
check(test_check("bogus.txt") == 0, "failed with bogus.txt");
^
goto.c:10:78: note: expanded from macro 'check'
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
^
1 error generated.
make: *** [goto] Error 1
shell returned 2
Press ENTER or type command to continue
When the macro is expanded, it inserts a goto error inside the test_check function, which has an error: label defined, so I don't know why I'm getting this compiler error.
You are trying to jump from main to another function test_check, but goto can only jump to a label inside the same function.
C11 ยง6.8.6.1 The goto statement
A goto statement causes an unconditional jump to the statement prefixed by the named
label in the enclosing function.

C macro with syslog logging

How can I replace this
syslog("some text");
with this, using C macro
if (debug)
syslog (LOG_DEBUG, "Function %s Line %d File %s Text %s", __func__, __LINE__, __FILE__,"some text");
The do..while(0) trick handles the compound 'if' statement, but syslog() is printf-like, and can take a variable number of arguments. We need a couple of tricks from the gcc preprocessor to handle this.
First, macros with variable numbers of arguments are supported, using the '...' notation.
We can use this to put our own text between the format string and the variable list. However, there is a catch: what if there is no variable list? In that case we use a special meaning of the ## operator for just this situation to eat the extra ','.
#define syslog(fmt, args...) \
do { \
if (debug) \
syslog(LOG_DEBUG, "Func %s Line %d file %s text " fmt, __func__, __LINE__, __FILE__, ##args); \
} while (0)
This expands these:
syslog("string");
syslog("format %d", value);
if (value)
syslog("something %d more %s", little, "complicated");
into this:
do { if (debug) syslog(LOG_DEBUG, "Func %s Line %d file %s text " "string", __func__, 8, "tp.c"); } while (0);
do { if (debug) syslog(LOG_DEBUG, "Func %s Line %d file %s text " "format %d", __func__, 10, "tp.c", value); } while (0);
if (value)
do { if (debug) syslog(LOG_DEBUG, "Func %s Line %d file %s text " "something %d more %s", __func__, 13, "tp.c", little, "complicated"); } while (0);
#define syslog(text) \
do { \
if(debug) \
syslog (LOG_DEBUG, "Function %s Line %d File %s Text %s", __func__, __LINE__, __FILE__, text); \
} while(0)
If debug is defined somewhere you can eliminate the if branch:
#ifdef debug
#define syslog(text) syslog (LOG_DEBUG, "Function %s Line %d File %s Text %s", __func__, __LINE__, __FILE__, text);
#else
#define syslog(text)
#endif

Resources