Home > database >  How can I add variadic args this macro in c and execute more than one action?
How can I add variadic args this macro in c and execute more than one action?

Time:10-19

I am trying write an assert like macro that will check runtime errors. At the very bottom you can find what I have for that macro and some things are not as I expect it to be.

The first thing that does not is function evaluation. Lets say someFuntion() returns an integer and expr = (someFunction() > 0) In this case even if someFunction() is greater zero the expression fails.

Secondly I want to be able to execute more than one action. For example, if I pass 2 actions I want two actions to be executed. I want to be able to pass execute_action_before_exit = (someFunction2(), someFucntion3()) and it should execute all the functions before exit. What should I look into acheive this? Or Is it not possible?

The code I have:

#ifndef RT_ASSERT_H
#define RT_ASSERT_H

#include <stdlib.h>
#include <stdio.h>

#define rt_assert(expr, file, str, execute_action_before_exit)                                \
  ((void) sizeof ((expr) ? 1 : 0), __extension__ ({                                           \
    if (!expr) {                                                                              \
        fprintf(file, "In file %s:%d, Error: %s\n",__FILE__, __LINE__, str);                  \
        execute_action_before_exit;                                                           \
        fclose(file);                                                                         \
        exit(EXIT_FAILURE);                                                                   \
    }                                                                                         \
    }))  

Usage of current the macro

#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "runtime_assert.h"

void someFunction(void) {
   // does some cleaning action or any action
}

void someFunction1(void) {
   // does some cleaning action or any action
}

int main (void) {
    FILE *abort_msg = fopen("exit_msg.txt", "w ");
    if (!abort_msg) {
        printf("Failed to create/open exit_msg.txt\n");
        getchar();
        exit(EXIT_FAILURE);
    }
    FILE *foo = fopen("FOO.txt", "r");
    rt_assert((foo), abort_msg, "Failed of open file -->possibly missing<--", (someFunction()));

    fclose(abort_msg);
    return EXIT_SUCCESS;

How I want to modify the use

rt_assert(                                               \
(foo),                                                   \
abort_msg, "Failed of open file -->possibly missing<--", \
(someFunction(),someFunction1())                         \
);

CodePudding user response:

#define rt_assert(expr, file, str, ...)\
  ((void) sizeof ((expr) ? 1 : 0), __extension__ ({\
    if (!(expr)) {\
        fprintf((file), "In file %s:%d, Error: %s\n",__FILE__, __LINE__, (str));\
        __VA_ARGS__;\
        fclose(file);\
        exit(EXIT_FAILURE);\
    }\
    }))

I've made two changes here:

(1) used !(expr) instead of !expr. This fixes the first problem you were having, that the expressions passed in were being evaluated wrong. Remember, macros are basically just copy-pasting, so when you do rt_assert( x() > 0 , rest of the arguments), this gets "pasted" into the if statement as if (!x() > 0) ..., which will not be evaluated as you expect. What you want is if (!(x() > 0)) ..., which is now correctly handled. I've done the same for the other parameters.

(2) I've changed the macro to be variadic, so you can pass any number of arguments to it. The syntax for this is ... when declaring the macro, and __VA_ARGS__ to use the variadic arguments. (Search "Variadic Macros" to find more info here.)

  • Related