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
Related
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.
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 ?
Is there a quick and easy way to comment out multi lined print statements? Something like this? I have a ton of printf statements that I use for debugging that are spread out across my program. I would like to comment out every printf() except the ones that contain "ACCEPT" or "Reject". I have several hundred of them but they are scattered between important code so I can't use block comments.
lower_bound_of_big_boy_counter++;
printf("3387 strings_line_tokens[lower_bound_of_big_boy_counter] %s \n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("3389 lower_bound_of_big_boy_counter %d \n", lower_bound_of_big_boy_counter);
}
strcpy(array_id1, strings_line_tokens[lower_bound_of_big_boy_counter]);
integer_match_flag = 0;
float_match_flag = 0;
}
}
if(keywords_match_flag1 != 1)
{
lower_bound_of_big_boy_counter++;
}
cmp_str9 = strcmp("return", strings_line_tokens[lower_bound_of_big_boy_counter ]);
printf("4006 lower_bound_of_big_boy_counter %d \n", lower_bound_of_big_boy_counter);
printf("4007 strings_line_tokens[lower_bound_of_big_boy_counter] %s \n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
//int
if(cmp_str9 == 0)
{
printf("3402 checking return stuff \n");
return_match_flag = 1;
lower_bound_of_big_boy_counter++;
get_function_type_for_proper_return(symbol_table_functions, type,id,
scope_char, symbol_table_functions_counter, function_type_for_proper_return);
printf("3407 lower_bound_of_big_boy_counter %d \n", lower_bound_of_big_boy_counter);
printf("3408 strings_line_tokens[lower_bound_of_big_boy_counter] %s \n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("3410 function_type_for_proper_return %s \n", function_type_for_proper_return);
Since your base code is C and the printf statements are [obviously] for debug, please allow me to suggest an alternative approach.
Change the printf used for debug into (e.g.) DEBUGPRINTF. This is a CPP macro that can be compiled to something with a compiler command line option like -DDEBUG. See my recent answer here: Why doesn't my simple C macro work? for a more formal description.
Side note: I wrote this current answer before noticing Jonathan's comment about doing it in a similar way.
Thus, you only need to do the change once and can turn debug printing on and off at the flip of a compile option. I've been using this technique for decades and it's served me quite well.
Note: You'll still need to do the global edit once to get this.
Here's a perl script that will do that (invoke via ./script < input > output):
#!/usr/bin/perl
# convert debug printf's
master(#ARGV);
exit(0);
# master -- master control
sub master
{
while ($bf = <STDIN>) {
chomp($bf);
if ($bf =~ /^\s*printf[(]/) {
doprintf($bf);
next
}
print($bf,"\n");
}
}
# doprintf -- process printf
sub doprintf
{
my($bf) = #_;
my($allowflg);
$allowflg = ($bf =~ /ACCEPT|Reject/);
unless ($allowflg) {
$bf =~ s/printf/DEBUGPRINTF/;
}
print($bf,"\n");
while (1) {
last if ($bf =~ /;\s*$/);
$bf = <STDIN>;
last unless (defined($bf));
chomp($bf);
print($bf,"\n");
}
}
A multiline solution with GNU sed :
sed '/ACCEPT\|Reject/!{/^[\t ]*printf(/{:a;s/^/\/\/ &/;/;/!{n;Ta}}}' file.c
Exluding all lines containing ACCEPT or Reject, it comments out all lines starting with printf and ending with ;.
If no ending ; is found on the printf line, it loops over and comments out subsequent lines until a ; is found.
Quick, simple, effective, over-enthusiastic
It is fairly simple to comment out all the printf() lines in a file with sed, even multi-line ones, if you use:
sed -e '/printf(.*);/ { s%^%//%; n; }' -e '/printf(/,/);/ s%^%//%'
On the sample lines, this yields:
lower_bound_of_big_boy_counter++;
// printf("3387 strings_line_tokens[lower_bound_of_big_boy_counter] %s \n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
// printf("3389 lower_bound_of_big_boy_counter %d \n", lower_bound_of_big_boy_counter);
}
strcpy(array_id1, strings_line_tokens[lower_bound_of_big_boy_counter]);
integer_match_flag = 0;
float_match_flag = 0;
}
}
if(keywords_match_flag1 != 1)
{
lower_bound_of_big_boy_counter++;
}
cmp_str9 = strcmp("return", strings_line_tokens[lower_bound_of_big_boy_counter ]);
// printf("4006 lower_bound_of_big_boy_counter %d \n", lower_bound_of_big_boy_counter);
// printf("4007 strings_line_tokens[lower_bound_of_big_boy_counter] %s \n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
//int
if(cmp_str9 == 0)
{
// printf("3402 checking return stuff \n");
return_match_flag = 1;
lower_bound_of_big_boy_counter++;
get_function_type_for_proper_return(symbol_table_functions, type,id,
scope_char, symbol_table_functions_counter, function_type_for_proper_return);
// printf("3407 lower_bound_of_big_boy_counter %d \n", lower_bound_of_big_boy_counter);
// printf("3408 strings_line_tokens[lower_bound_of_big_boy_counter] %s \n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
// printf("3410 function_type_for_proper_return %s \n", function_type_for_proper_return);
However, if any of the printf() statements contained ACCEPT or Reject, those lines would be commented out too. Given that you have hundreds of lines that should be commented out and a few (order of ten) that should not be commented, it is probably easiest to undo the incorrectly commented out lines.
Refined, complex, effective
I got an alternative working, and it handles printf statements with ACCEPT and Reject in the first line correctly. It won't spot those words in the second or subsequent lines of a printf statement.
${SED:-sed} \
-e '/printf(.*ACCEPT.*);/ b' \
-e '/printf(.*Reject.*);/ b' \
-e '/printf(.*);/ { s%^%//%; b
}' \
-e '/printf(.*ACCEPT/, /);/ b' \
-e '/printf(.*Reject/, /);/ b' \
-e '/printf(/, /);/ s%^%//%' \
frag.c
The odd newline is need to placate BSD (Mac OS X) sed.
Input:
lower_bound_of_big_boy_counter++;
printf("3387 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("3389 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
}
strcpy(array_id1, strings_line_tokens[lower_bound_of_big_boy_counter]);
integer_match_flag = 0;
float_match_flag = 0;
}
}
if(keywords_match_flag1 != 1)
{
lower_bound_of_big_boy_counter++;
}
cmp_str9 = strcmp("return", strings_line_tokens[lower_bound_of_big_boy_counter ]);
printf("4006 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("ACCEPT: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("Testing ACCEPT %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("Reject: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("4007 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
wimbol();
printf("Reject: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
wimbol();
printf("ACCEPT: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
wimbol();
printf("4006 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
printf("ACCEPT: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
printf("Testing ACCEPT %d\n", lower_bound_of_big_boy_counter);
printf("Reject: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
printf("4007 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("Reject: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("ACCEPT: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
//int
if(cmp_str9 == 0)
{
printf("3402 checking return stuff\n");
return_match_flag = 1;
lower_bound_of_big_boy_counter++;
get_function_type_for_proper_return(symbol_table_functions, type,id,
scope_char, symbol_table_functions_counter, function_type_for_proper_return);
printf("3407 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
printf("3408 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("3410 function_type_for_proper_return %s\n", function_type_for_proper_return);
Output:
lower_bound_of_big_boy_counter++;
// printf("3387 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
// printf("3389 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
}
strcpy(array_id1, strings_line_tokens[lower_bound_of_big_boy_counter]);
integer_match_flag = 0;
float_match_flag = 0;
}
}
if(keywords_match_flag1 != 1)
{
lower_bound_of_big_boy_counter++;
}
cmp_str9 = strcmp("return", strings_line_tokens[lower_bound_of_big_boy_counter ]);
// printf("4006 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("ACCEPT: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("Testing ACCEPT %d\n", lower_bound_of_big_boy_counter);
wimbol();
printf("Reject: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
wimbol();
// printf("4007 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
wimbol();
printf("Reject: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
wimbol();
printf("ACCEPT: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
wimbol();
// printf("4006 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
printf("ACCEPT: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
printf("Testing ACCEPT %d\n", lower_bound_of_big_boy_counter);
printf("Reject: lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
// printf("4007 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("Reject: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
printf("ACCEPT: strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
strings_line_tokens[lower_bound_of_big_boy_counter]);
//int
if(cmp_str9 == 0)
{
// printf("3402 checking return stuff\n");
return_match_flag = 1;
lower_bound_of_big_boy_counter++;
get_function_type_for_proper_return(symbol_table_functions, type,id,
scope_char, symbol_table_functions_counter, function_type_for_proper_return);
// printf("3407 lower_bound_of_big_boy_counter %d\n", lower_bound_of_big_boy_counter);
// printf("3408 strings_line_tokens[lower_bound_of_big_boy_counter] %s\n",
// strings_line_tokens[lower_bound_of_big_boy_counter]);
// printf("3410 function_type_for_proper_return %s\n", function_type_for_proper_return);
I was previously having some issues; I am kicking myself for some of them (sequencing — it is crucial to deal with all the single-line printf() statements before starting on the multi-line ones). There's a more subtle difference between b (jump to end of script) and n (read next line), which is also crucial.
I'm testing with BSD sed on Mac OS X 10.11.4, JFTR. GNU sed doesn't require the extra newline in the script.
using sed is a oneway conversion and requires a separate step before compiling.
A much better method is:
when debugging use the compiler parameter:
-DDEBUG=1
when not debugging use the compiler parameter:
-DDEBUG=0
Then, in the code use:
if( DEBUG )
{
// your debugging printf()
printf( ,,,, );
}
Then when the code must be certified, for instance to RTCA DO-178B there is no difference in the source code between the tested code and the released code.
#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.
Is there a CUDA function for printing both a caller-supplied error message, and an error message describing the current cudaStatus (or a caller-supplied cudaStatus), a-la-perror()?
I don't think there is a built-in cuda API function to do this.
This macro will do what you're describing:
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
The usage of the above macro is simply to insert it after any cuda API call or any cuda kernel call. It's recommended to insert it after every cuda API call and kernel call, for example:
cudaMemcpy(d_A, A, sizeof(A), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy fail");
my_kernel<<<blocks, threads>>>(d_A);
cudaCheckErrors("kernel launch fail");
cudaDeviceSynchronize();
cudaCheckErrors("cudaDeviceSynchronize fail");
It prints the user-defined message (msg) and also decodes the cuda API error and prints the appropriate error string message:
Fatal error: kernel launch fail (invalid configuration argument at t128.cu:44)
*** FAILED - ABORTING
You may also be interested in a discussion of error-handling here.
In response to a question below, you can easily make a function-call version:
void cudaCheckErrors(char *msg){
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", msg, cudaGetErrorString(__err), __FILE__, __LINE__);
fprintf(stderr, "*** FAILED - ABORTING\n");
exit(1);
}
}