#include "p99_if.h"
#define CHECK(condition, label, ...) \
if (!(condition)) { \
fprintf (stderr, "%s, %s, %i\n", __FILE__, __func__, __LINE__); \
P99_IF_EMPTY(__VA_ARGS__) () (fprintf(stderr, __VA_ARGS__);) \
goto label; \
}
CHECK(1, error);
CHECK(1, error, "Data is %d\n", 2);
if (!(1)) { fprintf (stderr, "%s, %s, %i\n", "test.c", __func__, 12); goto error; };
if (!(1)) { fprintf (stderr, "%s, %s, %i\n", "test.c", __func__, 14); fprintf(stderr, "Data is %d\n", 2); goto error; };
squalyl (./61) :
Non le truc de RHJPP est sale, le fonctionnement de printf c'est FORMAT(obligatoire)+ARGS(eventuellement vide), pas ARGS(eventuellement vide)+""
Pas besoin de "truc" quand la methode officielle existe
squalyl (./64) :
pour moi le fait de devoir ajouter un -Wkekchoz n'est pas satisfaisant
Apres chacun fait comme il veut
#define CHECK(condition, label, ...) \
if (!(condition)) { \
fprintf(stderr, "%s, %s, %i\n", __FILE__, __func__, __LINE__); \
if (*#__VA_ARGS__) \
fprintf(stderr, ##__VA_ARGS__, "pas vide"); \
goto label; \
}
#define IF_TRUE(condition, label, ...) \
if (condition) { \
fprintf (stderr, ##__VA_ARGS__, ""); \
fprintf (stderr, "%s, %s, %i\n", __FILE__, __func__, __LINE__); \
goto label; \
}
#define IF_FALSE(condition, label, ...) IF_TRUE (!(condition), label, ##__VA_ARGS__)
Folco (./70) :Non, il y a if (*#__VA_ARGS__) pour gérer ce cas
Non, ça ne va pas, "pas vide" sera affiché à chaque fois que j'appelle la macro sans chaine de caractère, non ? du coup ça ferait super crade ^^
flanker (./67) :
Mais ça ne suffit pas
Comme l'indique bien son nom, -Wall n'active pas tous les warnings. -Wextra non plus, d'ailleurs
#define IF_TRUE(condition, label, ...) \
if (condition) { \
if (*#__VA_ARGS__) { \
fprintf (stderr, ##__VA_ARGS__, ""); \
fprintf (stderr, "\n"); \
} \
fprintf (stderr, "%s, %s, %i\n", __FILE__, __func__, __LINE__); \
goto label; \
}
#define IF_FALSE(condition, label, ...) IF_TRUE (!(condition), label, ##__VA_ARGS__)
int main (void)
{
// Initialization
int ret = EXIT_FAILURE;
IF_FALSE (InitSdl (), SdlFail)
IF_FALSE (InitFont (), FontFail)
IF_FALSE (InitRessources(), RessourcesFail)
IF_FALSE (InitGameState(), GameStateFail)
// Game engine
IF_FALSE (GameStateEngine(), EngineFail)
ret = EXIT_SUCCESS;
// Cleanup
EngineFail:
DeinitGameState ();
GameStateFail:
DeinitRessources ();
RessourcesFail:
DeinitFont ();
FontFail:
DeinitSdl ();
SdlFail:
return ret;
}
Bon, vala maintenant : #define IF_TRUE(condition, label, ...) \
if (condition) { \
if (*#__VA_ARGS__) { \
fprintf (stderr, "ERROR: "); \
fprintf (stderr, ##__VA_ARGS__, ""); \
fprintf (stderr, "\n"); \
} \
fprintf (stderr, "TRACE: %s:%i, in %s()\n", __FILE__, __LINE__, __func__); \
goto label; \
}
#define IF_FALSE(condition, label, ...) IF_TRUE (!(condition)
folco@Foch:~/fpgc/Debug$ ./fpgc ERROR: Couldn't open ../spr/ButtonExit_out.png TRACE: /home/folco/fpgc/src/Ressources.c:18, in LoadSpriteFile() TRACE: /home/folco/fpgc/src/Ressources.c:32, in InitRessources() TRACE: /home/folco/fpgc/src/main.c:15, in main() folco@Foch:~/fpgc/Debug$
$ ./fpgc TRACE: /home/folco/fpgc/src/GameStates.c:130, in GameStateEngine() TRACE: /home/folco/fpgc/src/main.c:19, in main()
Folco (./75) :
J'ai pas trouvé comment éviter ça (sans utiliser une lib telle celle proposée par PpHd).
Folco (./75) :
Par contre, je dois passer -Wno-format-extra-args pour éviter un warning, dans le cas où je fournis une chaine avec des donénes à formatter, genre IF_TRUE (m_count == GS_COUNT_MAX, Exit, "ERROR: max game state reached, %i", GS_COUNT_MAX), parce qu'il n'y a que %i à formater, et gcc voit GS_COUNT_MAX et le "" de la macro. J'ai pas trouvé comment éviter ça (sans utiliser une lib telle celle proposée par PpHd).
#define SP_FPRINTF(file, format, ...) \
if (*#__VA_ARGS__) { \
const char *f = format; \
size_t l = strlen(f); \
char f2[l + 3]; \
strcpy (f2, f); \
strcpy (f2 + l, "%s"); \
fprintf (file, f2, ##__VA_ARGS__); \
} else { \
fprintf (file, format); \
}
#define IF_TRUE(condition, label, ...) \
if (condition) { \
if (*#__VA_ARGS__) { \
fprintf (stderr, "ERROR: "); \
SP_FPRINTF (stderr, ##__VA_ARGS__, "\n"); \
} \
fprintf (stderr, "TRACE: %s:%i, in %s()\n", __FILE__, __LINE__, __func__); \
goto label; \
}
#define IF_FALSE(condition, label, ...) IF_TRUE (!(condition), label, ##__VA_ARGS__)
PpHd (./84) :
C'est juste des .h, rien d'autres. Tu peux récupérer juste ce que tu veux.
Folco (./86) :
J'ai meme essayé de les comprendre, c'est certainement très puissant, mais les sources sont quand même vachement capillo-tractées, et j'ai pas compris comment ça marchait, donc j'utilise pas. On a ses principes, non mais.
#define P99_HAS_COMMA(...) P00_ARG(__VA_ARGS__, \
1, 1, 1, 1, 1, 1, 1, \
...
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 0, 0)
#define P99_IS_EMPTY(...) \
P00_ISEMPTY( \
/* test if there is just one argument, that might be empty */ \
P99_HAS_COMMA(__VA_ARGS__), \
/* test if P99_IS__EQ__ together with the argument \
adds a comma */ \
P99_HAS_COMMA(P00_IS__EQ__ __VA_ARGS__), \
/* test if the argument together with a parenthesis \
adds a comma */ \
P99_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
/* test if placing it between P99_IS__EQ__ and the \
parenthesis adds a comma */ \
P99_HAS_COMMA(P00_IS__EQ__ __VA_ARGS__ (/*empty*/)) \
)
#define P00_IS_EMPTY_CASE_0000 P00_IS_EMPTY_CASE_0000
#define P00_IS_EMPTY_CASE_0001 ,
#define P00_IS_EMPTY_CASE_0010 P00_IS_EMPTY_CASE_0010
#define P00_IS_EMPTY_CASE_0011 P00_IS_EMPTY_CASE_0011
....
#define MACHIN_TO_KEEP_IF_1(...)
#define MACHIN_TO_KEEP_IF_0(...) __VA_ARGS__
#define KEEP_IF_NOT_EMPTY(...) MACHIN_TO_KEEP_ ## IS_EMPTY(__VA_ARGS__) (func(__VA_ARGS__))
PpHd (./87) :
avec le bon niveau de substitution