libsigrok  0.3.0
sigrok hardware access and backend library
log.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of the libsigrok project.
00003  *
00004  * Copyright (C) 2011-2012 Uwe Hermann <uwe@hermann-uwe.de>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00019  */
00020 
00021 #include <stdarg.h>
00022 #include <stdio.h>
00023 #include "libsigrok.h"
00024 /** @cond PRIVATE */
00025 #define NO_LOG_WRAPPERS
00026 /** @endcond */
00027 #include "libsigrok-internal.h"
00028 
00029 /**
00030  * @file
00031  *
00032  * Controlling the libsigrok message logging functionality.
00033  */
00034 
00035 /**
00036  * @defgroup grp_logging Logging
00037  *
00038  * Controlling the libsigrok message logging functionality.
00039  *
00040  * @{
00041  */
00042 
00043 /* Currently selected libsigrok loglevel. Default: SR_LOG_WARN. */
00044 static int cur_loglevel = SR_LOG_WARN; /* Show errors+warnings per default. */
00045 
00046 /* Function prototype. */
00047 static int sr_logv(void *cb_data, int loglevel, const char *format,
00048                    va_list args);
00049 
00050 /* Pointer to the currently selected log callback. Default: sr_logv(). */
00051 static sr_log_callback sr_log_cb = sr_logv;
00052 
00053 /*
00054  * Pointer to private data that can be passed to the log callback.
00055  * This can be used (for example) by C++ GUIs to pass a "this" pointer.
00056  */
00057 static void *sr_log_cb_data = NULL;
00058 
00059 /* Log domain (a short string that is used as prefix for all messages). */
00060 /** @cond PRIVATE */
00061 #define LOGDOMAIN_MAXLEN 30
00062 #define LOGDOMAIN_DEFAULT "sr: "
00063 /** @endcond */
00064 static char sr_log_domain[LOGDOMAIN_MAXLEN + 1] = LOGDOMAIN_DEFAULT;
00065 
00066 /**
00067  * Set the libsigrok loglevel.
00068  *
00069  * This influences the amount of log messages (debug messages, error messages,
00070  * and so on) libsigrok will output. Using SR_LOG_NONE disables all messages.
00071  *
00072  * Note that this function itself will also output log messages. After the
00073  * loglevel has changed, it will output a debug message with SR_LOG_DBG for
00074  * example. Whether this message is shown depends on the (new) loglevel.
00075  *
00076  * @param loglevel The loglevel to set (SR_LOG_NONE, SR_LOG_ERR, SR_LOG_WARN,
00077  *                 SR_LOG_INFO, SR_LOG_DBG, or SR_LOG_SPEW).
00078  *
00079  * @return SR_OK upon success, SR_ERR_ARG upon invalid loglevel.
00080  *
00081  * @since 0.1.0
00082  */
00083 SR_API int sr_log_loglevel_set(int loglevel)
00084 {
00085         if (loglevel < SR_LOG_NONE || loglevel > SR_LOG_SPEW) {
00086                 sr_err("Invalid loglevel %d.", loglevel);
00087                 return SR_ERR_ARG;
00088         }
00089 
00090         cur_loglevel = loglevel;
00091 
00092         sr_dbg("libsigrok loglevel set to %d.", loglevel);
00093 
00094         return SR_OK;
00095 }
00096 
00097 /**
00098  * Get the libsigrok loglevel.
00099  *
00100  * @return The currently configured libsigrok loglevel.
00101  *
00102  * @since 0.1.0
00103  */
00104 SR_API int sr_log_loglevel_get(void)
00105 {
00106         return cur_loglevel;
00107 }
00108 
00109 /**
00110  * Set the libsigrok logdomain string.
00111  *
00112  * @param logdomain The string to use as logdomain for libsigrok log
00113  *                  messages from now on. Must not be NULL. The maximum
00114  *                  length of the string is 30 characters (this does not
00115  *                  include the trailing NUL-byte). Longer strings are
00116  *                  silently truncated.
00117  *                  In order to not use a logdomain, pass an empty string.
00118  *                  The function makes its own copy of the input string, i.e.
00119  *                  the caller does not need to keep it around.
00120  *
00121  * @return SR_OK upon success, SR_ERR_ARG upon invalid logdomain.
00122  *
00123  * @since 0.1.0
00124  */
00125 SR_API int sr_log_logdomain_set(const char *logdomain)
00126 {
00127         if (!logdomain) {
00128                 sr_err("log: %s: logdomain was NULL", __func__);
00129                 return SR_ERR_ARG;
00130         }
00131 
00132         /* TODO: Error handling. */
00133         snprintf((char *)&sr_log_domain, LOGDOMAIN_MAXLEN, "%s", logdomain);
00134 
00135         sr_dbg("Log domain set to '%s'.", (const char *)&sr_log_domain);
00136 
00137         return SR_OK;
00138 }
00139 
00140 /**
00141  * Get the currently configured libsigrok logdomain.
00142  *
00143  * @return A copy of the currently configured libsigrok logdomain
00144  *         string. The caller is responsible for g_free()ing the string when
00145  *         it is no longer needed.
00146  *
00147  * @since 0.1.0
00148  */
00149 SR_API char *sr_log_logdomain_get(void)
00150 {
00151         return g_strdup((const char *)&sr_log_domain);
00152 }
00153 
00154 /**
00155  * Set the libsigrok log callback to the specified function.
00156  *
00157  * @param cb Function pointer to the log callback function to use.
00158  *           Must not be NULL.
00159  * @param cb_data Pointer to private data to be passed on. This can be used by
00160  *                the caller to pass arbitrary data to the log functions. This
00161  *                pointer is only stored or passed on by libsigrok, and is
00162  *                never used or interpreted in any way. The pointer is allowed
00163  *                to be NULL if the caller doesn't need/want to pass any data.
00164  *
00165  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments.
00166  *
00167  * @since 0.3.0
00168  */
00169 SR_API int sr_log_callback_set(sr_log_callback cb, void *cb_data)
00170 {
00171         if (!cb) {
00172                 sr_err("log: %s: cb was NULL", __func__);
00173                 return SR_ERR_ARG;
00174         }
00175 
00176         /* Note: 'cb_data' is allowed to be NULL. */
00177 
00178         sr_log_cb = cb;
00179         sr_log_cb_data = cb_data;
00180 
00181         return SR_OK;
00182 }
00183 
00184 /**
00185  * Set the libsigrok log callback to the default built-in one.
00186  *
00187  * Additionally, the internal 'sr_log_cb_data' pointer is set to NULL.
00188  *
00189  * @return SR_OK upon success, a negative error code otherwise.
00190  *
00191  * @since 0.1.0
00192  */
00193 SR_API int sr_log_callback_set_default(void)
00194 {
00195         /*
00196          * Note: No log output in this function, as it should safely work
00197          * even if the currently set log callback is buggy/broken.
00198          */
00199         sr_log_cb = sr_logv;
00200         sr_log_cb_data = NULL;
00201 
00202         return SR_OK;
00203 }
00204 
00205 static int sr_logv(void *cb_data, int loglevel, const char *format, va_list args)
00206 {
00207         int ret;
00208 
00209         /* This specific log callback doesn't need the void pointer data. */
00210         (void)cb_data;
00211 
00212         /* Only output messages of at least the selected loglevel(s). */
00213         if (loglevel > cur_loglevel)
00214                 return SR_OK; /* TODO? */
00215 
00216         if (sr_log_domain[0] != '\0')
00217                 fprintf(stderr, "%s", sr_log_domain);
00218         ret = vfprintf(stderr, format, args);
00219         fprintf(stderr, "\n");
00220 
00221         return ret;
00222 }
00223 
00224 /** @private */
00225 SR_PRIV int sr_log(int loglevel, const char *format, ...)
00226 {
00227         int ret;
00228         va_list args;
00229 
00230         va_start(args, format);
00231         ret = sr_log_cb(sr_log_cb_data, loglevel, format, args);
00232         va_end(args);
00233 
00234         return ret;
00235 }
00236 
00237 /** @private */
00238 SR_PRIV int sr_spew(const char *format, ...)
00239 {
00240         int ret;
00241         va_list args;
00242 
00243         va_start(args, format);
00244         ret = sr_log_cb(sr_log_cb_data, SR_LOG_SPEW, format, args);
00245         va_end(args);
00246 
00247         return ret;
00248 }
00249 
00250 /** @private */
00251 SR_PRIV int sr_dbg(const char *format, ...)
00252 {
00253         int ret;
00254         va_list args;
00255 
00256         va_start(args, format);
00257         ret = sr_log_cb(sr_log_cb_data, SR_LOG_DBG, format, args);
00258         va_end(args);
00259 
00260         return ret;
00261 }
00262 
00263 /** @private */
00264 SR_PRIV int sr_info(const char *format, ...)
00265 {
00266         int ret;
00267         va_list args;
00268 
00269         va_start(args, format);
00270         ret = sr_log_cb(sr_log_cb_data, SR_LOG_INFO, format, args);
00271         va_end(args);
00272 
00273         return ret;
00274 }
00275 
00276 /** @private */
00277 SR_PRIV int sr_warn(const char *format, ...)
00278 {
00279         int ret;
00280         va_list args;
00281 
00282         va_start(args, format);
00283         ret = sr_log_cb(sr_log_cb_data, SR_LOG_WARN, format, args);
00284         va_end(args);
00285 
00286         return ret;
00287 }
00288 
00289 /** @private */
00290 SR_PRIV int sr_err(const char *format, ...)
00291 {
00292         int ret;
00293         va_list args;
00294 
00295         va_start(args, format);
00296         ret = sr_log_cb(sr_log_cb_data, SR_LOG_ERR, format, args);
00297         va_end(args);
00298 
00299         return ret;
00300 }
00301 
00302 /** @} */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines