/* * Copyright (c) 2005, 2006 by KoanLogic s.r.l. - All rights reserved. */ #ifndef _U_CARPAL_H_ #define _U_CARPAL_H_ #include #ifdef TIME_WITH_SYS_TIME #include #endif #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define msg(label, ...) label( __VA_ARGS__) #define msg_noargs(label, literal) label("%s", literal) /** \brief log a message and goto "err" label * * log a message of type \e label if \e expr not zero. * */ #define msg_err(label, ...) do { msg(label, __VA_ARGS__); goto err; } while(0) /** \brief log a message if \e expr not zero. * * log a message of type \e label if \e expr is not zero * * \e expr text statement will be written to the log file. * * For ex.: * warn_if(check(abc) < 0); */ #define msg_if(label, expr) do { if( expr ) msg_noargs(label, #expr); } while(0) /** \brief log a message if \e expr not zero and enter the if-block * * log a message of type \e label if \e expr is not zero and enter the * following if-block. * * \e expr text statement will be written to the log file. * * A C-style dbg_ code block should follow. For ex.: * dbg_ifb(i == 0) * { * do_something(); * do_something(); * } */ #define msg_ifb(label, expr) if( (expr) && (msg_noargs(label, #expr) ? 1 : 1) ) /** \brief log a message if \e expr not zero and return \e err. * * log a message of type \e label if \e expr is not zero and return * \e err to the caller. * * \e expr text statement will be written to the log file. * * Example: * dbg_return_if(param == NULL, FUNC_ERROR); */ #define msg_return_if(label, expr, err) msg_ifb(label, expr) return err /** \brief log a message if \e expr not zero and return \e err. (Log the strerror also) * * log a message of type \e label if \e expr is not zero and return * \e err to the caller. Log also the strerror(errno). * * \e expr text statement will be written to the log file. */ #define msg_return_sif(label, expr, err) \ do { msg_ifb(label, expr) { msg_strerror(label, errno); return err; } } while(0) /** \brief log a message if \e expr not zero and goto \e gt. * * log a message of type \e label if \e expr is not zero and goto * to the label \e gt (that must be in-scope). * * \e expr text statement will be written to the log file. */ #define msg_goto_if(label, expr, gt) msg_ifb(label, expr) goto gt /** \brief log a message if \e expr not zero and goto to the label "err" * * log a message of type \e label if \e expr is not zero and goto * to the label "err" (that must be defined). * * \e expr text statement will be written to the log file. */ #define msg_err_if(label, expr) do { msg_ifb(label, expr) { goto err;} } while(0) /** \brief log a message if \e expr not zero and goto to the label "err". * * log a message of type \e label if \e expr is not zero and goto * to the label "err" (that must be defined). also logs arguments provided * by the caller. */ #define msg_err_ifm(label, expr, ...) \ do { if( (expr) ) { msg(label, __VA_ARGS__); goto err; } } while(0) /** \brief log a message if \e expr not zero and goto to the label "err". * * log a message of type \e label if \e expr is not zero and goto * to the label "err" (that must be defined). also logs strerror(errno). */ #define msg_err_sif(label, expr) \ do { msg_ifb(label, expr) { msg_strerror(label, errno); goto err; } } while(0) /** \brief write a debug message containing the message returned by strerror(errno) */ #ifdef WIN32 #define msg_strerror(label, en) \ do { \ LPVOID lpMsgBuf = NULL; DWORD dw = GetLastError(); \ if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | \ FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, \ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \ (LPTSTR) &lpMsgBuf, 0, NULL ) && lpMsgBuf) \ { \ msg(label, "%s", lpMsgBuf); \ LocalFree(lpMsgBuf); \ } \ } while(0) #else #ifdef HAVE_STRERROR_R #ifdef STRERROR_R_CHAR_P #define msg_strerror(label, en) \ do { \ enum { _DBG_BUFSZ = 256 }; \ char *p, _eb[_DBG_BUFSZ] = { 0 }; \ p = strerror_r(en, _eb, _DBG_BUFSZ); \ if(p) { \ msg(label, "%s", p); \ } else { \ msg(label, "strerror_r(%d, ...) failed", en); \ } \ } while(0) #else #define msg_strerror(label, en) \ do { \ enum { _DBG_BUFSZ = 256 }; \ char _eb[_DBG_BUFSZ] = { 0 }; \ if(strerror_r(en, _eb, _DBG_BUFSZ) == 0) { \ msg(label, "%s", _eb); \ } else { \ msg(label, "strerror_r(%d, ...) failed", en); \ } \ } while(0) #endif #else #define msg_strerror(label, en) \ do { \ char *p; \ if((p = strerror(en)) != NULL) { \ msg(label, "%s", p); \ } else { \ msg(label, "strerror(%d) failed", en); \ } \ } while(0) #endif #endif /* ! def WIN32 */ /* nop_ macros */ #define nop_return_if(expr, err) do { if(expr) return err; } while(0) #define nop_err_if(expr) do { if(expr) goto err; } while(0) #define nop_goto_if(expr, gt) do { if(expr) goto gt; } while(0) /* con_ macros */ #define con(...) msg(console, __VA_ARGS__) #define con_err(...) msg_err(console, __VA_ARGS__) #define con_ifb(expr) msg_ifb(console, expr) #define con_if(expr) msg_if(console, expr) #define con_return_if(expr, err) msg_return_if(console, expr, err) #define con_err_if(expr) msg_err_if(console, expr) #define con_err_ifm(expr, ...) \ msg_err_ifm(console, expr, __VA_ARGS__) #define con_goto_if(expr, gt) msg_goto_if(console, expr, gt) #define con_strerror(errno) msg_strerror(console, errno) /* info_ macros */ /* #define info(...) msg(info, __VA_ARGS__) */ #define info_err(...) msg_err(info, __VA_ARGS__) #define info_ifb(expr) msg_ifb(info, expr) #define info_if(expr) msg_if(info, expr) #define info_return_if(expr, err) msg_return_if(info, expr, err) #define info_err_if(expr) msg_err_if(info, expr) #define info_err_sif(expr) msg_err_sif(info, expr) #define info_err_ifm(expr, ...) \ msg_err_ifm(info, expr, __VA_ARGS__) #define info_goto_if(expr, gt) msg_goto_if(info, expr, gt) #define info_strerror(errno) msg_strerror(info, errno) /* warn_ macros */ #define warn(...) msg(warning, __VA_ARGS__) #define warn_err(...) msg_err(warning, __VA_ARGS__) #define warn_ifb(expr) msg_ifb(warning, expr) #define warn_if(expr) msg_if(warning, expr) #define warn_return_if(expr, err) msg_return_if(warning, expr, err) #define warn_err_if(expr) msg_err_if(warning, expr) #define warn_err_sif(expr) msg_err_sif(warning, expr) #define warn_err_ifm(expr, ...) \ msg_err_ifm(warning, expr, __VA_ARGS__) #define warn_goto_if(expr, gt) msg_goto_if(warning, expr, gt) #define warn_strerror(errno) msg_strerror(warning, errno) /* dbg_ macros */ #ifdef DEBUG #define dbg(...) msg(debug, __VA_ARGS__) #define dbg_err(...) msg_err(debug, __VA_ARGS__) #define dbg_ifb(expr) msg_ifb(debug, expr) #define dbg_if(expr) msg_if(debug, expr) #define dbg_return_if(expr, err) msg_return_if(debug, expr, err) #define dbg_return_sif(expr, err) msg_return_sif(debug, expr, err) #define dbg_err_if(expr) msg_err_if(debug, expr) #define dbg_err_sif(expr) msg_err_sif(debug, expr) #define dbg_err_ifm(expr, ...) \ msg_err_ifm(debug, expr, __VA_ARGS__) #define dbg_goto_if(expr, gt) msg_goto_if(debug, expr, gt) #define dbg_strerror(errno) msg_strerror(debug, errno) /* simple debugging timing macros */ #define TIMER_ON \ time_t _t_beg = time(0), _t_prev = _t_beg, _t_now; int _t_step = 0 #define TIMER_STEP \ do { \ _t_now = time(0); \ dbg(" step %u: %u s (delta: %u s)", \ _t_step++, _t_now - _t_beg, _t_now - _t_prev); \ _t_prev = _t_now; \ } while(0) #define TIMER_OFF dbg("elapsed: %u s", (time(0) - _t_beg)) #else /* disable debugging */ #include /* this will be used just to avoid empty-if (and similar) warnings */ #define dbg_nop() #define dbg(...) dbg_nop() #define dbg_err(...) do { goto err; } while(0) #define dbg_ifb(expr) if( (expr) ) #define dbg_if(expr) expr #define dbg_return_if(expr, err) do { if( (expr) ) return err; } while(0) #define dbg_err_if(expr) do { if( (expr)) goto err; } while(0) #define dbg_err_sif(expr) do { if( (expr)) goto err; } while(0) #define dbg_err_ifm(expr, ...) do { if( (expr)) goto err; } while(0) #define dbg_goto_if(expr, gt) do { if((expr)) goto gt; } while(0) #define dbg_strerror(errno) dbg_nop() #define TIMER_ON #define TIMER_STEP #define TIMER_OFF #endif /* ifdef DEBUG */ #ifdef __cplusplus } #endif #endif /* _U_CARPAL_H_ */