Changeset 2992


Ignore:
Timestamp:
Nov 9, 2009 4:09:13 AM (10 years ago)
Author:
bennylp
Message:

Updated ticket #981: pj_perror() and PJ_PERROR() API:

  • added PJ_PERROR() macro to allow compile time omitting
  • changed pj_perror() API to allow formatting of the title using printf like format
  • added a simple test in pjlib-test
  • updated Doxygen documentation
Location:
pjproject/trunk/pjlib
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/errno.h

    r2965 r2992  
    2323/** 
    2424 * @file errno.h 
    25  * @brief PJLIB Error Codes 
     25 * @brief PJLIB Error Subsystem 
    2626 */ 
    2727#include <pj/types.h> 
    2828#include <pj/compat/errno.h> 
     29#include <stdarg.h> 
    2930 
    3031PJ_BEGIN_DECL 
    3132 
    3233/** 
    33  * @defgroup pj_errno Error Codes 
     34 * @defgroup pj_errno Error Subsystem 
    3435 * @{ 
    3536 * 
    36  * In PJLIB, error/status codes from operating system are translated 
    37  * into PJLIB error namespace, and stored in @a pj_status_t. All functions 
    38  * that work with @a pj_status_t expect to get PJLIB error code instead 
    39  * of native codes. 
     37 * The PJLIB Error Subsystem is a framework to unify all error codes 
     38 * produced by all components into a single error space, and provide 
     39 * uniform set of APIs to access them. With this framework, any error 
     40 * codes are encoded as pj_status_t value. The framework is extensible, 
     41 * application may register new error spaces to be recognized by 
     42 * the framework. 
    4043 * 
    4144 * @section pj_errno_retval Return Values 
     
    4851 * before returning the error to caller. 
    4952 * 
    50  * @section pj_errno_errmsg Error Message 
    51  * 
    52  * To get the error message corresponding to a particular code, use function 
    53  * #pj_strerror(). This function expects error code in PJLIB error namespace, 
    54  * not the native error code. Application can pass the value from the  
    55  * following sources to this function: 
    56  *  - #pj_get_os_error() 
    57  *  - #pj_get_netos_error() 
    58  *  - any return value from function returning @a pj_status_t. 
    59  * 
    60  * Application MUST NOT pass native error code (such as error code from 
     53 * @section err_services Retrieving and Displaying Error Messages 
     54 * 
     55 * The framework provides the following APIs to retrieve and/or display 
     56 * error messages: 
     57 * 
     58 *   - #pj_strerror(): this is the base API to retrieve error string 
     59 *      description for the specified pj_status_t error code. 
     60 * 
     61 *   - #PJ_PERROR() macro: use this macro similar to PJ_LOG to format 
     62 *      an error message and display them to the log 
     63 * 
     64 *   - #pj_perror(): this function is similar to PJ_PERROR() but unlike 
     65 *      #PJ_PERROR(), this function will always be included in the 
     66 *      link process. Due to this reason, prefer to use #PJ_PERROR() 
     67 *      if the application is concerned about the executable size. 
     68 * 
     69 * Application MUST NOT pass native error codes (such as error code from 
    6170 * functions like GetLastError() or errno) to PJLIB functions expecting 
    6271 * @a pj_status_t. 
    6372 * 
     73 * @section err_extending Extending the Error Space 
     74 * 
     75 * Application may register new error space to be recognized by the 
     76 * framework by using #pj_register_strerror(). Use the range started 
     77 * from PJ_ERRNO_START_USER to avoid conflict with existing error 
     78 * spaces. 
     79 * 
    6480 */ 
    6581 
     
    6884 */ 
    6985#define PJ_ERR_MSG_SIZE  80 
     86 
     87/** 
     88 * Buffer for title string of #PJ_PERROR(). 
     89 */ 
     90#ifndef PJ_PERROR_TITLE_BUF_SIZE 
     91#   define PJ_PERROR_TITLE_BUF_SIZE     120 
     92#endif 
     93 
    7094 
    7195/** 
     
    113137 
    114138/** 
    115  * Print the error message pertaining to the specified error code to 
    116  * the log. 
    117  * 
    118  * @param log_level The log will be printed at this log level. 
    119  * @param sender    The log sender string. 
    120  * @param status    The error code which error message will be printed. 
    121  * @param title     String to be printed before the error message. Note 
    122  *                  that a colon will be added automatically between 
    123  *                  this string and the error message. 
    124  * @param options   Options, currently must be zero. 
    125  */ 
    126 #if PJ_LOG_MAX_LEVEL >= 1 
    127 PJ_DECL(void) pj_perror(int log_level, const char *sender,  
    128                         pj_status_t status, const char *title, 
    129                         int options); 
    130 #else 
    131 #   define pj_perror(level, sender, status, title, options) 
    132 #endif  /* #if PJ_LOG_MAX_LEVEL >= 1 */ 
     139 * A utility macro to print error message pertaining to the specified error  
     140 * code to the log. This macro will construct the error message title  
     141 * according to the 'title_fmt' argument, and add the error string pertaining 
     142 * to the error code after the title string. A colon (':') will be added  
     143 * automatically between the title and the error string. 
     144 * 
     145 * This function is similar to pj_perror() function, but has the advantage 
     146 * that the function call can be omitted from the link process if the 
     147 * log level argument is below PJ_LOG_MAX_LEVEL threshold. 
     148 * 
     149 * Note that the title string constructed from the title_fmt will be built on 
     150 * a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is 
     151 * allocated from the stack. By default this buffer size is small (around 
     152 * 120 characters). Application MUST ensure that the constructed title string 
     153 * will not exceed this limit, since not all platforms support truncating 
     154 * the string. 
     155 * 
     156 * @see pj_perror() 
     157 * 
     158 * @param level     The logging verbosity level, valid values are 0-6. Lower 
     159 *                  number indicates higher importance, with level zero  
     160 *                  indicates fatal error. Only numeral argument is  
     161 *                  permitted (e.g. not variable). 
     162 * @param arg       Enclosed 'printf' like arguments, with the following 
     163 *                  arguments: 
     164 *                   - the sender (NULL terminated string), 
     165 *                   - the error code (pj_status_t) 
     166 *                   - the format string (title_fmt), and  
     167 *                   - optional variable number of arguments suitable for the  
     168 *                     format string. 
     169 * 
     170 * Sample: 
     171 * \verbatim 
     172   PJ_PERROR(2, (__FILE__, PJ_EBUSY, "Error making %s", "coffee")); 
     173   \endverbatim 
     174 * @hideinitializer 
     175 */ 
     176#define PJ_PERROR(level,arg)    do { \ 
     177                                    pj_perror_wrapper_##level(arg); \ 
     178                                } while (0) 
     179 
     180/** 
     181 * A utility function to print error message pertaining to the specified error  
     182 * code to the log. This function will construct the error message title  
     183 * according to the 'title_fmt' argument, and add the error string pertaining 
     184 * to the error code after the title string. A colon (':') will be added  
     185 * automatically between the title and the error string. 
     186 * 
     187 * Unlike the PJ_PERROR() macro, this function takes the \a log_level argument 
     188 * as a normal argument, unlike in PJ_PERROR() where a numeral value must be 
     189 * given. However this function will always be linked to the executable, 
     190 * unlike PJ_PERROR() which can be omitted when the level is below the  
     191 * PJ_LOG_MAX_LEVEL. 
     192 * 
     193 * Note that the title string constructed from the title_fmt will be built on 
     194 * a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is 
     195 * allocated from the stack. By default this buffer size is small (around 
     196 * 120 characters). Application MUST ensure that the constructed title string 
     197 * will not exceed this limit, since not all platforms support truncating 
     198 * the string. 
     199 * 
     200 * @see PJ_PERROR() 
     201 */ 
     202PJ_DECL(void) pj_perror(int log_level, const char *sender, pj_status_t status, 
     203                        const char *title_fmt, ...); 
    133204 
    134205 
     
    403474void pj_errno_clear_handlers(void); 
    404475 
     476 
     477/****** Internal for PJ_PERROR *******/ 
     478 
     479/** 
     480 * @def pj_perror_wrapper_1(arg) 
     481 * Internal function to write log with verbosity 1. Will evaluate to 
     482 * empty expression if PJ_LOG_MAX_LEVEL is below 1. 
     483 * @param arg       Log expression. 
     484 */ 
     485#if PJ_LOG_MAX_LEVEL >= 1 
     486    #define pj_perror_wrapper_1(arg)    pj_perror_1 arg 
     487    /** Internal function. */ 
     488    PJ_DECL(void) pj_perror_1(const char *sender, pj_status_t status,  
     489                              const char *title_fmt, ...); 
     490#else 
     491    #define pj_perror_wrapper_1(arg) 
     492#endif 
     493 
     494/** 
     495 * @def pj_perror_wrapper_2(arg) 
     496 * Internal function to write log with verbosity 2. Will evaluate to 
     497 * empty expression if PJ_LOG_MAX_LEVEL is below 2. 
     498 * @param arg       Log expression. 
     499 */ 
     500#if PJ_LOG_MAX_LEVEL >= 2 
     501    #define pj_perror_wrapper_2(arg)    pj_perror_2 arg 
     502    /** Internal function. */ 
     503    PJ_DECL(void) pj_perror_2(const char *sender, pj_status_t status,  
     504                              const char *title_fmt, ...); 
     505#else 
     506    #define pj_perror_wrapper_2(arg) 
     507#endif 
     508 
     509/** 
     510 * @def pj_perror_wrapper_3(arg) 
     511 * Internal function to write log with verbosity 3. Will evaluate to 
     512 * empty expression if PJ_LOG_MAX_LEVEL is below 3. 
     513 * @param arg       Log expression. 
     514 */ 
     515#if PJ_LOG_MAX_LEVEL >= 3 
     516    #define pj_perror_wrapper_3(arg)    pj_perror_3 arg 
     517    /** Internal function. */ 
     518    PJ_DECL(void) pj_perror_3(const char *sender, pj_status_t status,  
     519                              const char *title_fmt, ...); 
     520#else 
     521    #define pj_perror_wrapper_3(arg) 
     522#endif 
     523 
     524/** 
     525 * @def pj_perror_wrapper_4(arg) 
     526 * Internal function to write log with verbosity 4. Will evaluate to 
     527 * empty expression if PJ_LOG_MAX_LEVEL is below 4. 
     528 * @param arg       Log expression. 
     529 */ 
     530#if PJ_LOG_MAX_LEVEL >= 4 
     531    #define pj_perror_wrapper_4(arg)    pj_perror_4 arg 
     532    /** Internal function. */ 
     533    PJ_DECL(void) pj_perror_4(const char *sender, pj_status_t status,  
     534                              const char *title_fmt, ...); 
     535#else 
     536    #define pj_perror_wrapper_4(arg) 
     537#endif 
     538 
     539/** 
     540 * @def pj_perror_wrapper_5(arg) 
     541 * Internal function to write log with verbosity 5. Will evaluate to 
     542 * empty expression if PJ_LOG_MAX_LEVEL is below 5. 
     543 * @param arg       Log expression. 
     544 */ 
     545#if PJ_LOG_MAX_LEVEL >= 5 
     546    #define pj_perror_wrapper_5(arg)    pj_perror_5 arg 
     547    /** Internal function. */ 
     548    PJ_DECL(void) pj_perror_5(const char *sender, pj_status_t status,  
     549                              const char *title_fmt, ...); 
     550#else 
     551    #define pj_perror_wrapper_5(arg) 
     552#endif 
     553 
     554/** 
     555 * @def pj_perror_wrapper_6(arg) 
     556 * Internal function to write log with verbosity 6. Will evaluate to 
     557 * empty expression if PJ_LOG_MAX_LEVEL is below 6. 
     558 * @param arg       Log expression. 
     559 */ 
     560#if PJ_LOG_MAX_LEVEL >= 6 
     561    #define pj_perror_wrapper_6(arg)    pj_perror_6 arg 
     562    /** Internal function. */ 
     563    PJ_DECL(void) pj_perror_6(const char *sender, pj_status_t status,  
     564                              const char *title_fmt, ...); 
     565#else 
     566    #define pj_perror_wrapper_6(arg) 
     567#endif 
     568 
     569 
     570 
     571 
    405572PJ_END_DECL 
    406573 
  • pjproject/trunk/pjlib/src/pj/errno.c

    r2965 r2992  
    200200 
    201201#if PJ_LOG_MAX_LEVEL >= 1 
    202 static void call_logger(const char *sender, int level, const char *format, ...) 
     202static void invoke_log(const char *sender, int level, const char *format, ...) 
    203203{ 
    204204    va_list arg; 
     
    208208} 
    209209 
    210 /* 
    211  * perror() 
    212  */ 
    213 PJ_DEF(void) pj_perror(int log_level, const char *sender,  
    214                        pj_status_t status, const char *title, 
    215                        int options) 
    216 { 
     210static void pj_perror_imp(int log_level, const char *sender,  
     211                          pj_status_t status, 
     212                          const char *title_fmt, va_list marker) 
     213{ 
     214    char titlebuf[PJ_PERROR_TITLE_BUF_SIZE]; 
    217215    char errmsg[PJ_ERR_MSG_SIZE]; 
    218  
    219     PJ_ASSERT_ON_FAIL(options==0, return); 
    220     PJ_UNUSED_ARG(options); 
    221  
     216    int len; 
     217 
     218    /* Build the title */ 
     219    len = pj_ansi_vsnprintf(titlebuf, sizeof(titlebuf), title_fmt, marker); 
     220    if (len < 0 || len >= sizeof(titlebuf)) 
     221        pj_ansi_strcpy(titlebuf, "Error"); 
     222 
     223    /* Get the error */ 
    222224    pj_strerror(status, errmsg, sizeof(errmsg)); 
    223     call_logger(sender, log_level, "%s: %s", title, errmsg); 
     225 
     226    /* Send to log */ 
     227    invoke_log(sender, log_level, "%s: %s", titlebuf, errmsg); 
     228} 
     229 
     230PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status, 
     231                       const char *title_fmt, ...) 
     232{ 
     233    va_list marker; 
     234    va_start(marker, title_fmt); 
     235    pj_perror_imp(log_level, sender, status, title_fmt, marker); 
     236    va_end(marker); 
     237} 
     238 
     239PJ_DEF(void) pj_perror_1(const char *sender, pj_status_t status, 
     240                         const char *title_fmt, ...) 
     241{ 
     242    va_list marker; 
     243    va_start(marker, title_fmt); 
     244    pj_perror_imp(1, sender, status, title_fmt, marker); 
     245    va_end(marker); 
     246} 
     247 
     248#else /* #if PJ_LOG_MAX_LEVEL >= 1 */ 
     249PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status, 
     250                       const char *title_fmt, ...) 
     251{ 
    224252} 
    225253#endif  /* #if PJ_LOG_MAX_LEVEL >= 1 */ 
    226254 
    227255 
     256#if PJ_LOG_MAX_LEVEL >= 2 
     257PJ_DEF(void) pj_perror_2(const char *sender, pj_status_t status, 
     258                         const char *title_fmt, ...) 
     259{ 
     260    va_list marker; 
     261    va_start(marker, title_fmt); 
     262    pj_perror_imp(2, sender, status, title_fmt, marker); 
     263    va_end(marker); 
     264} 
     265#endif 
     266 
     267#if PJ_LOG_MAX_LEVEL >= 3 
     268PJ_DEF(void) pj_perror_3(const char *sender, pj_status_t status, 
     269                         const char *title_fmt, ...) 
     270{ 
     271    va_list marker; 
     272    va_start(marker, title_fmt); 
     273    pj_perror_imp(3, sender, status, title_fmt, marker); 
     274    va_end(marker); 
     275} 
     276#endif 
     277 
     278#if PJ_LOG_MAX_LEVEL >= 4 
     279PJ_DEF(void) pj_perror_4(const char *sender, pj_status_t status, 
     280                         const char *title_fmt, ...) 
     281{ 
     282    va_list marker; 
     283    va_start(marker, title_fmt); 
     284    pj_perror_imp(4, sender, status, title_fmt, marker); 
     285    va_end(marker); 
     286} 
     287#endif 
     288 
     289#if PJ_LOG_MAX_LEVEL >= 5 
     290PJ_DEF(void) pj_perror_5(const char *sender, pj_status_t status, 
     291                         const char *title_fmt, ...) 
     292{ 
     293    va_list marker; 
     294    va_start(marker, title_fmt); 
     295    pj_perror_imp(5, sender, status, title_fmt, marker); 
     296    va_end(marker); 
     297} 
     298#endif 
     299 
     300#if PJ_LOG_MAX_LEVEL >= 6 
     301PJ_DEF(void) pj_perror_6(const char *sender, pj_status_t status, 
     302                         const char *title_fmt, ...) 
     303{ 
     304    va_list marker; 
     305    va_start(marker, title_fmt); 
     306    pj_perror_imp(6, sender, status, title_fmt, marker); 
     307    va_end(marker); 
     308} 
     309#endif 
     310 
  • pjproject/trunk/pjlib/src/pjlib-test/errno.c

    r2394 r2992  
    159159              CUT, errbuf)); 
    160160 
     161    /* Perror */ 
     162    pj_perror(3, THIS_FILE, PJ_SUCCESS, "...testing %s", "pj_perror"); 
     163    PJ_PERROR(3,(THIS_FILE, PJ_SUCCESS, "...testing %s", "PJ_PERROR")); 
     164 
    161165    return 0; 
    162166} 
Note: See TracChangeset for help on using the changeset viewer.