summaryrefslogtreecommitdiff
path: root/pjlib
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2009-11-09 04:09:13 +0000
committerBenny Prijono <bennylp@teluu.com>2009-11-09 04:09:13 +0000
commit92515c8944079f941a9bb1a2820ade33999c3c74 (patch)
treee3cea76092d5e326392a350dc01c780f7114483e /pjlib
parent8bb8512eb7e6e0883964c1f58750d80dd90c6e2d (diff)
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 git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2992 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib')
-rw-r--r--pjlib/include/pj/errno.h229
-rw-r--r--pjlib/src/pj/errno.c103
-rw-r--r--pjlib/src/pjlib-test/errno.c4
3 files changed, 295 insertions, 41 deletions
diff --git a/pjlib/include/pj/errno.h b/pjlib/include/pj/errno.h
index 8b536c40..10ad8aaa 100644
--- a/pjlib/include/pj/errno.h
+++ b/pjlib/include/pj/errno.h
@@ -22,21 +22,24 @@
/**
* @file errno.h
- * @brief PJLIB Error Codes
+ * @brief PJLIB Error Subsystem
*/
#include <pj/types.h>
#include <pj/compat/errno.h>
+#include <stdarg.h>
PJ_BEGIN_DECL
/**
- * @defgroup pj_errno Error Codes
+ * @defgroup pj_errno Error Subsystem
* @{
*
- * In PJLIB, error/status codes from operating system are translated
- * into PJLIB error namespace, and stored in @a pj_status_t. All functions
- * that work with @a pj_status_t expect to get PJLIB error code instead
- * of native codes.
+ * The PJLIB Error Subsystem is a framework to unify all error codes
+ * produced by all components into a single error space, and provide
+ * uniform set of APIs to access them. With this framework, any error
+ * codes are encoded as pj_status_t value. The framework is extensible,
+ * application may register new error spaces to be recognized by
+ * the framework.
*
* @section pj_errno_retval Return Values
*
@@ -47,20 +50,33 @@ PJ_BEGIN_DECL
* #PJ_STATUS_FROM_OS() macro. The function will do this automatically
* before returning the error to caller.
*
- * @section pj_errno_errmsg Error Message
+ * @section err_services Retrieving and Displaying Error Messages
*
- * To get the error message corresponding to a particular code, use function
- * #pj_strerror(). This function expects error code in PJLIB error namespace,
- * not the native error code. Application can pass the value from the
- * following sources to this function:
- * - #pj_get_os_error()
- * - #pj_get_netos_error()
- * - any return value from function returning @a pj_status_t.
+ * The framework provides the following APIs to retrieve and/or display
+ * error messages:
*
- * Application MUST NOT pass native error code (such as error code from
+ * - #pj_strerror(): this is the base API to retrieve error string
+ * description for the specified pj_status_t error code.
+ *
+ * - #PJ_PERROR() macro: use this macro similar to PJ_LOG to format
+ * an error message and display them to the log
+ *
+ * - #pj_perror(): this function is similar to PJ_PERROR() but unlike
+ * #PJ_PERROR(), this function will always be included in the
+ * link process. Due to this reason, prefer to use #PJ_PERROR()
+ * if the application is concerned about the executable size.
+ *
+ * Application MUST NOT pass native error codes (such as error code from
* functions like GetLastError() or errno) to PJLIB functions expecting
* @a pj_status_t.
*
+ * @section err_extending Extending the Error Space
+ *
+ * Application may register new error space to be recognized by the
+ * framework by using #pj_register_strerror(). Use the range started
+ * from PJ_ERRNO_START_USER to avoid conflict with existing error
+ * spaces.
+ *
*/
/**
@@ -69,6 +85,14 @@ PJ_BEGIN_DECL
#define PJ_ERR_MSG_SIZE 80
/**
+ * Buffer for title string of #PJ_PERROR().
+ */
+#ifndef PJ_PERROR_TITLE_BUF_SIZE
+# define PJ_PERROR_TITLE_BUF_SIZE 120
+#endif
+
+
+/**
* Get the last platform error/status, folded into pj_status_t.
* @return OS dependent error code, folded into pj_status_t.
* @remark This function gets errno, or calls GetLastError() function and
@@ -112,24 +136,71 @@ PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode,
char *buf, pj_size_t bufsize);
/**
- * Print the error message pertaining to the specified error code to
- * the log.
+ * A utility macro to print error message pertaining to the specified error
+ * code to the log. This macro will construct the error message title
+ * according to the 'title_fmt' argument, and add the error string pertaining
+ * to the error code after the title string. A colon (':') will be added
+ * automatically between the title and the error string.
+ *
+ * This function is similar to pj_perror() function, but has the advantage
+ * that the function call can be omitted from the link process if the
+ * log level argument is below PJ_LOG_MAX_LEVEL threshold.
+ *
+ * Note that the title string constructed from the title_fmt will be built on
+ * a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is
+ * allocated from the stack. By default this buffer size is small (around
+ * 120 characters). Application MUST ensure that the constructed title string
+ * will not exceed this limit, since not all platforms support truncating
+ * the string.
+ *
+ * @see pj_perror()
+ *
+ * @param level The logging verbosity level, valid values are 0-6. Lower
+ * number indicates higher importance, with level zero
+ * indicates fatal error. Only numeral argument is
+ * permitted (e.g. not variable).
+ * @param arg Enclosed 'printf' like arguments, with the following
+ * arguments:
+ * - the sender (NULL terminated string),
+ * - the error code (pj_status_t)
+ * - the format string (title_fmt), and
+ * - optional variable number of arguments suitable for the
+ * format string.
+ *
+ * Sample:
+ * \verbatim
+ PJ_PERROR(2, (__FILE__, PJ_EBUSY, "Error making %s", "coffee"));
+ \endverbatim
+ * @hideinitializer
+ */
+#define PJ_PERROR(level,arg) do { \
+ pj_perror_wrapper_##level(arg); \
+ } while (0)
+
+/**
+ * A utility function to print error message pertaining to the specified error
+ * code to the log. This function will construct the error message title
+ * according to the 'title_fmt' argument, and add the error string pertaining
+ * to the error code after the title string. A colon (':') will be added
+ * automatically between the title and the error string.
*
- * @param log_level The log will be printed at this log level.
- * @param sender The log sender string.
- * @param status The error code which error message will be printed.
- * @param title String to be printed before the error message. Note
- * that a colon will be added automatically between
- * this string and the error message.
- * @param options Options, currently must be zero.
+ * Unlike the PJ_PERROR() macro, this function takes the \a log_level argument
+ * as a normal argument, unlike in PJ_PERROR() where a numeral value must be
+ * given. However this function will always be linked to the executable,
+ * unlike PJ_PERROR() which can be omitted when the level is below the
+ * PJ_LOG_MAX_LEVEL.
+ *
+ * Note that the title string constructed from the title_fmt will be built on
+ * a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is
+ * allocated from the stack. By default this buffer size is small (around
+ * 120 characters). Application MUST ensure that the constructed title string
+ * will not exceed this limit, since not all platforms support truncating
+ * the string.
+ *
+ * @see PJ_PERROR()
*/
-#if PJ_LOG_MAX_LEVEL >= 1
-PJ_DECL(void) pj_perror(int log_level, const char *sender,
- pj_status_t status, const char *title,
- int options);
-#else
-# define pj_perror(level, sender, status, title, options)
-#endif /* #if PJ_LOG_MAX_LEVEL >= 1 */
+PJ_DECL(void) pj_perror(int log_level, const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
/**
@@ -402,6 +473,102 @@ PJ_DECL(pj_status_t) pj_register_strerror(pj_status_t start_code,
/* Internal */
void pj_errno_clear_handlers(void);
+
+/****** Internal for PJ_PERROR *******/
+
+/**
+ * @def pj_perror_wrapper_1(arg)
+ * Internal function to write log with verbosity 1. Will evaluate to
+ * empty expression if PJ_LOG_MAX_LEVEL is below 1.
+ * @param arg Log expression.
+ */
+#if PJ_LOG_MAX_LEVEL >= 1
+ #define pj_perror_wrapper_1(arg) pj_perror_1 arg
+ /** Internal function. */
+ PJ_DECL(void) pj_perror_1(const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
+#else
+ #define pj_perror_wrapper_1(arg)
+#endif
+
+/**
+ * @def pj_perror_wrapper_2(arg)
+ * Internal function to write log with verbosity 2. Will evaluate to
+ * empty expression if PJ_LOG_MAX_LEVEL is below 2.
+ * @param arg Log expression.
+ */
+#if PJ_LOG_MAX_LEVEL >= 2
+ #define pj_perror_wrapper_2(arg) pj_perror_2 arg
+ /** Internal function. */
+ PJ_DECL(void) pj_perror_2(const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
+#else
+ #define pj_perror_wrapper_2(arg)
+#endif
+
+/**
+ * @def pj_perror_wrapper_3(arg)
+ * Internal function to write log with verbosity 3. Will evaluate to
+ * empty expression if PJ_LOG_MAX_LEVEL is below 3.
+ * @param arg Log expression.
+ */
+#if PJ_LOG_MAX_LEVEL >= 3
+ #define pj_perror_wrapper_3(arg) pj_perror_3 arg
+ /** Internal function. */
+ PJ_DECL(void) pj_perror_3(const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
+#else
+ #define pj_perror_wrapper_3(arg)
+#endif
+
+/**
+ * @def pj_perror_wrapper_4(arg)
+ * Internal function to write log with verbosity 4. Will evaluate to
+ * empty expression if PJ_LOG_MAX_LEVEL is below 4.
+ * @param arg Log expression.
+ */
+#if PJ_LOG_MAX_LEVEL >= 4
+ #define pj_perror_wrapper_4(arg) pj_perror_4 arg
+ /** Internal function. */
+ PJ_DECL(void) pj_perror_4(const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
+#else
+ #define pj_perror_wrapper_4(arg)
+#endif
+
+/**
+ * @def pj_perror_wrapper_5(arg)
+ * Internal function to write log with verbosity 5. Will evaluate to
+ * empty expression if PJ_LOG_MAX_LEVEL is below 5.
+ * @param arg Log expression.
+ */
+#if PJ_LOG_MAX_LEVEL >= 5
+ #define pj_perror_wrapper_5(arg) pj_perror_5 arg
+ /** Internal function. */
+ PJ_DECL(void) pj_perror_5(const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
+#else
+ #define pj_perror_wrapper_5(arg)
+#endif
+
+/**
+ * @def pj_perror_wrapper_6(arg)
+ * Internal function to write log with verbosity 6. Will evaluate to
+ * empty expression if PJ_LOG_MAX_LEVEL is below 6.
+ * @param arg Log expression.
+ */
+#if PJ_LOG_MAX_LEVEL >= 6
+ #define pj_perror_wrapper_6(arg) pj_perror_6 arg
+ /** Internal function. */
+ PJ_DECL(void) pj_perror_6(const char *sender, pj_status_t status,
+ const char *title_fmt, ...);
+#else
+ #define pj_perror_wrapper_6(arg)
+#endif
+
+
+
+
PJ_END_DECL
#endif /* __PJ_ERRNO_H__ */
diff --git a/pjlib/src/pj/errno.c b/pjlib/src/pj/errno.c
index 652b8099..667c7d91 100644
--- a/pjlib/src/pj/errno.c
+++ b/pjlib/src/pj/errno.c
@@ -199,7 +199,7 @@ PJ_DEF(pj_str_t) pj_strerror( pj_status_t statcode,
}
#if PJ_LOG_MAX_LEVEL >= 1
-static void call_logger(const char *sender, int level, const char *format, ...)
+static void invoke_log(const char *sender, int level, const char *format, ...)
{
va_list arg;
va_start(arg, format);
@@ -207,21 +207,104 @@ static void call_logger(const char *sender, int level, const char *format, ...)
va_end(arg);
}
-/*
- * perror()
- */
-PJ_DEF(void) pj_perror(int log_level, const char *sender,
- pj_status_t status, const char *title,
- int options)
+static void pj_perror_imp(int log_level, const char *sender,
+ pj_status_t status,
+ const char *title_fmt, va_list marker)
{
+ char titlebuf[PJ_PERROR_TITLE_BUF_SIZE];
char errmsg[PJ_ERR_MSG_SIZE];
+ int len;
- PJ_ASSERT_ON_FAIL(options==0, return);
- PJ_UNUSED_ARG(options);
+ /* Build the title */
+ len = pj_ansi_vsnprintf(titlebuf, sizeof(titlebuf), title_fmt, marker);
+ if (len < 0 || len >= sizeof(titlebuf))
+ pj_ansi_strcpy(titlebuf, "Error");
+ /* Get the error */
pj_strerror(status, errmsg, sizeof(errmsg));
- call_logger(sender, log_level, "%s: %s", title, errmsg);
+
+ /* Send to log */
+ invoke_log(sender, log_level, "%s: %s", titlebuf, errmsg);
+}
+
+PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(log_level, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+
+PJ_DEF(void) pj_perror_1(const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(1, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+
+#else /* #if PJ_LOG_MAX_LEVEL >= 1 */
+PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
}
#endif /* #if PJ_LOG_MAX_LEVEL >= 1 */
+#if PJ_LOG_MAX_LEVEL >= 2
+PJ_DEF(void) pj_perror_2(const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(2, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+#endif
+
+#if PJ_LOG_MAX_LEVEL >= 3
+PJ_DEF(void) pj_perror_3(const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(3, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+#endif
+
+#if PJ_LOG_MAX_LEVEL >= 4
+PJ_DEF(void) pj_perror_4(const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(4, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+#endif
+
+#if PJ_LOG_MAX_LEVEL >= 5
+PJ_DEF(void) pj_perror_5(const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(5, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+#endif
+
+#if PJ_LOG_MAX_LEVEL >= 6
+PJ_DEF(void) pj_perror_6(const char *sender, pj_status_t status,
+ const char *title_fmt, ...)
+{
+ va_list marker;
+ va_start(marker, title_fmt);
+ pj_perror_imp(6, sender, status, title_fmt, marker);
+ va_end(marker);
+}
+#endif
+
diff --git a/pjlib/src/pjlib-test/errno.c b/pjlib/src/pjlib-test/errno.c
index 61137d2d..d1e980e2 100644
--- a/pjlib/src/pjlib-test/errno.c
+++ b/pjlib/src/pjlib-test/errno.c
@@ -158,6 +158,10 @@ int errno_test(void)
PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG, cut at %d chars: '%s'",
CUT, errbuf));
+ /* Perror */
+ pj_perror(3, THIS_FILE, PJ_SUCCESS, "...testing %s", "pj_perror");
+ PJ_PERROR(3,(THIS_FILE, PJ_SUCCESS, "...testing %s", "PJ_PERROR"));
+
return 0;
}