#include #include #include #include enum handling { PERROR, FPRINTF, IGNORE, HANDLING_INVALID }; struct func_handling { const char *name; enum handling handling; }; struct func_handling null_functions [] = { { "fopen", PERROR }, { "malloc", PERROR }, { } }; struct func_handling nonzero_functions [] = { { "fclose", FPRINTF }, { } }; static void handle_error(struct func_handling *functions, const char *action) { assert(functions != NULL); assert(action != NULL); while (functions->name) { size_t len = strlen(functions->name); if (!strncmp(functions->name, action, len)) { switch (functions->handling) { case PERROR: perror(action); break; case FPRINTF: fprintf(stderr, "%s failed\n", action); break; case IGNORE: return; default: break; } exit(1); } functions++; } } #define check_null(action) \ do { \ void *ptr = (action); \ if (ptr == NULL) \ handle_error(null_functions, #action); \ } while (0) #define check_nonzero(action) \ do { \ int ret = (action); \ if (ret != 0) \ handle_nonzero(nonzero_functions, #action); \ } while (0) int main(void) { check_null(fopen("subor", "r")); return 0; }