00001 #ifndef _EC_H_ 00002 #define _EC_H_ 00003 00004 /* 00005 It might be nice to code functions or macros to replace the system calls or libraryfunctions (e.g., close_e()), but there's no way to execute a goto from an expression. So, ec_neg1(), etc., must be statements. Two alternatives: 00006 1. Exit instead of goto, which is allowed in a function called within an expression. 00007 2. In C++, use throw inside a function. 00008 #1 doesn't allow error recovery, and #2 doesn't work in C. 00009 */ 00010 /*[basic]*/ 00011 extern const bool ec_in_cleanup; 00012 00013 typedef enum {EC_ERRNO = 0, EC_EAI = 1, EC_GETDATE = 2, EC_NONE = 3} EC_ERRTYPE; 00014 00015 #define EC_CLEANUP_BGN\ 00016 ec_warn();\ 00017 ec_cleanup_bgn:\ 00018 {\ 00019 bool ec_in_cleanup;\ 00020 ec_in_cleanup = true; 00021 00022 #define EC_CLEANUP_END\ 00023 } 00024 00025 #define ec_cmp(var, errrtn)\ 00026 {\ 00027 assert(!ec_in_cleanup);\ 00028 if ((intptr_t)(var) == (intptr_t)(errrtn)) {\ 00029 ec_push(__func__, __FILE__, __LINE__, #var, errno, EC_ERRNO);\ 00030 goto ec_cleanup_bgn;\ 00031 }\ 00032 } 00033 00034 #define ec_rv(var)\ 00035 {\ 00036 int errrtn;\ 00037 assert(!ec_in_cleanup);\ 00038 if ((errrtn = (var)) != 0) {\ 00039 ec_push(__func__, __FILE__, __LINE__, #var, errrtn, EC_ERRNO);\ 00040 goto ec_cleanup_bgn;\ 00041 }\ 00042 } 00043 00044 #define ec_ai(var)\ 00045 {\ 00046 int errrtn;\ 00047 assert(!ec_in_cleanup);\ 00048 if ((errrtn = (var)) != 0) {\ 00049 ec_push(__func__, __FILE__, __LINE__, #var, errrtn, EC_EAI);\ 00050 goto ec_cleanup_bgn;\ 00051 }\ 00052 } 00053 00054 #define ec_neg1(x) ec_cmp(x, -1) 00055 /* 00056 Not in book: 0 used instead of NULL to avoid warning from C++ compilers. 00057 */ 00058 #define ec_null(x) ec_cmp(x, 0) 00059 #define ec_zero(x) ec_null(x) /* not in book */ 00060 #define ec_false(x) ec_cmp(x, false) 00061 #define ec_eof(x) ec_cmp(x, EOF) 00062 #define ec_nzero(x)\ 00063 {\ 00064 if ((x) != 0)\ 00065 EC_FAIL\ 00066 } 00067 00068 #define EC_FAIL ec_cmp(0, 0) 00069 00070 #define EC_CLEANUP goto ec_cleanup_bgn; 00071 00072 #define EC_FLUSH(str)\ 00073 {\ 00074 ec_print();\ 00075 ec_reinit();\ 00076 } 00077 /*[]*/ 00078 #define EC_EINTERNAL INT_MAX 00079 00080 void ec_push(const char *fcn, const char *file, int line, 00081 const char *str, int errno_arg, EC_ERRTYPE type); 00082 void ec_print(void); 00083 void ec_reinit(void); 00084 void ec_warn(void); 00085 00086 #endif /* _EC_H_ */