diff options
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | Makefile.files | 10 | ||||
| -rw-r--r-- | debug.c (renamed from debug.cc) | 198 | ||||
| -rw-r--r-- | debug.h | 99 | ||||
| -rw-r--r-- | main.c | 68 | 
5 files changed, 376 insertions, 4 deletions
| diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fc5b439 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +include Makefile.files + +all: +	gcc ${DEBUG_SOURCES} main.c -o debug +# -DWITH_DBG_MUTEX
\ No newline at end of file diff --git a/Makefile.files b/Makefile.files new file mode 100644 index 0000000..e707d13 --- /dev/null +++ b/Makefile.files @@ -0,0 +1,10 @@ +# +# Include this file from your project Makefile and add the +# variable DEBUG_SOURCES to the files that need compilation. +# + +DEBUG_SOURCES = \ +	debug.c + +DEBUG_EXTRA_DIST = \ +	debug.h
\ No newline at end of file @@ -1,7 +1,7 @@  /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */  /* vim: set et sw=2 ts=2: */  /*************************************************************************** - *            debug.cc + *            debug.c   *   *  Thu Nov  1 13:38:47 CET 2012   *  Copyright 2012 Bent Bisballe Nyeng @@ -27,6 +27,199 @@   */  #include "debug.h" +#include <stdio.h> +#include <stdarg.h> +#include <time.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#ifdef WITH_DBG_MUTEX +#include <pthread.h> +#endif + +struct { +  unsigned int flags; +#ifdef WITH_DBG_MUTEX +  pthread_mutex_t mutex; +#endif +  int fd; +  int file_fd; +} dbg_config = { .flags = DBG_FLAG_DEFAULT, .fd = -1, .file_fd = -1 };  + +static void dbg_mutex_init() +{ +#ifdef WITH_DBG_MUTEX +  if(dbg_config.flags & DBG_FLAG_USE_MUTEX) { +    pthread_mutex_init(&dbg_config.mutex, NULL); +  } +#endif +} + +static void dbg_mutex_lock() +{ +#ifdef WITH_DBG_MUTEX +  if(dbg_config.flags & DBG_FLAG_USE_MUTEX) { +    pthread_mutex_lock(&dbg_config.mutex); +  } +#endif +} + +static void dbg_mutex_unlock() +{ +#ifdef WITH_DBG_MUTEX +  if(dbg_config.flags & DBG_FLAG_USE_MUTEX) { +    pthread_mutex_unlock(&dbg_config.mutex); +  } +#endif +} + +static void dbg_mutex_close() +{ +#ifdef WITH_DBG_MUTEX +  if(dbg_config.flags & DBG_FLAG_USE_MUTEX) { +    // Make sure we don't destroy the mutex while another thread is using it. +    dbg_mutex_lock(); +    dbg_mutex_unlock(); +    pthread_mutex_destroy(&dbg_config.mutex); +  } +#endif +} + +dbg_status_t dbg_init(unsigned int flags, ...) +{ +  dbg_status_t status = DBG_STATUS_OK; + +  dbg_config.flags = flags; + +  int end = 0; + +  va_list vl; +  va_start(vl, flags); +  while(!end) { +    int option = va_arg(vl, int); +    switch(option) { +    case DBG_OPTION_END: +      end = 1; +      break; +    case DBG_OPTION_FD: +      dbg_config.fd = va_arg(vl, int); +      break; +    case DBG_OPTION_FILENAME: +      if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FILE) { +        const char *filename = (const char*)va_arg(vl, char*); +        dbg_config.file_fd = open(filename, O_CREAT | O_RDWR, 0777); +      } +      break; +    default: +      status = DBG_STATUS_UNKNOWN_OPTION; +      printf("option: %x\n", option); +      goto err; +    } +  } + +  dbg_mutex_init(); + + err: +  va_end(vl); + +  return status; +} + +void dbg_close() +{ +  if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FILE) { +    if(dbg_config.file_fd != -1) close(dbg_config.file_fd); +  } + +  dbg_mutex_close(); +} + +static const char * const debug_class_str[] = +  { "fixme", "err", "warn", "info", "debug" }; + +static int dbg_create_header(char *hdr, size_t size) +{ +  time_t rawtime = time(NULL); +  struct tm t; +  localtime_r(&rawtime, &t); + +  return snprintf(hdr, size, +                  "%d-%02d-%02d %02d:%02d:%02d", +                  t.tm_year + 1900, +                  t.tm_mon + 1, +                  t.tm_mday, +                  t.tm_hour, +                  t.tm_min, +                  t.tm_sec); +} + +static int dbg_output_fd(int fd, const char *msg) +{ +  if(fd == -1) return 1; + +  char hdr[32]; +  dbg_create_header(hdr, sizeof(hdr)); +  write(fd, hdr, strlen(hdr)); +  write(fd, " ", 1); +  write(fd, msg, strlen(msg)); +  if(msg[strlen(msg) - 1] != '\n') write(fd, "\n", 1); +  return 0; +} + +int __debug(const char *func, const int line, +            const enum __debug_class cl, +            const char *ch, const char *fmt, ...) +{ +  int result = 0; + +  dbg_mutex_lock(); + +  // +  // Generate message +  // + +  char buf[1024]; + +  int sz = snprintf(buf, sizeof(buf), +                    "%s:%s:%s:%d ", +                    debug_class_str[(unsigned)cl], ch, func, line); +  va_list va; +  va_start(va, fmt); +  sz += vsnprintf(buf + sz, sizeof(buf) - sz, fmt, va); +  va_end(va); + +  // +  // Send message to output +  // + +  if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_STDOUT) { +    dbg_output_fd(STDOUT_FILENO, buf); +  } + +  if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_STDERR) { +    dbg_output_fd(STDERR_FILENO, buf); +  } + +  if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FD) { +    dbg_output_fd(dbg_config.fd, buf); +  } + +  if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FILE) { +    dbg_output_fd(dbg_config.file_fd, buf); +  } + + done: +  dbg_mutex_unlock(); + +  return result; +} + +#if 0 +  #include <stdlib.h>  #include <stdarg.h>  #include <string.h> @@ -176,3 +369,6 @@ void debug_parse(const char *fmt)  	}  	free(s);  } + + +#endif @@ -28,10 +28,103 @@  #ifndef __DEBUG_MODULE_DEBUG_H__  #define __DEBUG_MODULE_DEBUG_H__ -#include <stdio.h> +enum DBG_FLAG { +  // Features +#ifdef WITH_DBG_THREAD +  DBG_FLAG_USE_THREAD       = 0x00000001, +#endif +#ifdef WITH_DBG_MUTEX +  DBG_FLAG_USE_MUTEX        = 0x00000002, +#endif +#ifdef WITH_DBG_FILTER +  DBG_FLAG_USE_FILTER       = 0x00000004, +#endif -void debug_init(FILE *fp); -void debug_parse(const char *fmt); +  // Outputs +  DBG_FLAG_OUTPUT_TO_STDOUT = 0x00010000, +  DBG_FLAG_OUTPUT_TO_STDERR = 0x00020000, +  DBG_FLAG_OUTPUT_TO_FD     = 0x00040000, +  DBG_FLAG_OUTPUT_TO_FILE   = 0x00080000, +#ifdef WITH_DBG_SYSLOG +  DBG_FLAG_OUTPUT_TO_SYSLOG = 0x000f0000, +#endif + +  // Default value of flags +  DBG_FLAG_DEFAULT          = DBG_FLAG_OUTPUT_TO_STDOUT, // Output to stdout +}; + +enum DBG_OPTION { +  /** +   * No more options / last option.  This is used +   * to terminate the VARARGs list. +   */ +  DBG_OPTION_END, + +  /** +   * const char* argument containing a filename which will be used for log +   * output. To be used with the DBG_FLAG_OUTPUT_TO_FILE flag. +   */ +  DBG_OPTION_FILENAME, + +  /** +   * Integer argument describing a file descriptor which will be used for log +   * output. To be used with the DBG_FLAG_OUTPUT_TO_FD flag. +   */ +  DBG_OPTION_FD, + +  /** +   * Host and port to use when logging on an external server. +   * Host is a const char* argument, port is an integer. +   * To be used with the DBG_FLAG_USE_SYSLOG flag. +   * Linux: If DBG_OPTION_SYSLOG_HOST is not supplied, the local syslog will be +   * used. +   * Windows: If DBG_OPTION_SYSLOG_HOST is not supplied an error will be +   * returned by debug_init. +   * If DBG_OPTION_SYSLOG_PORT is not supplied, the default syslogd port will +   * be used (port 514). +   */ +#ifdef WITH_DBG_SYSLOG +  DBG_OPTION_SYSLOG_HOST, +  DBG_OPTION_SYSLOG_PORT, +#endif + +  /** +   *  +   */ +}; + +typedef enum { +  DBG_STATUS_OK = 0, +  DBG_STATUS_UNKNOWN_OPTION, +  DBG_STATUS_ERROR, +} dbg_status_t; + +/** + * @param flags combination of DBG_FLAG values + * @param ... list of options (type-value pairs, + *        terminated with DBG_OPTION_END). + * @return 0 on success, 1 on error. + */ +dbg_status_t dbg_init(unsigned int flags, ...); +void dbg_close(); + +/** + * Example of usage (use mutex protected calls, send output to file): + * + * dbg_status_t status; + * status = debug_init(DBG_FLAG_OUTPUT_TO_FILE | DBG_FLAG_USE_MUTEX, + *                     DBG_OPTION_FILENAME, "/tmp/my.log", +                       DBG_OPTION_END); + * if(status != DBG_STATUS_OK) exit(1); + * INFO(example, "We are up and running\n"); + * dbg_close(); + */ + +/** + * Example of usage (simply outputs to stdout): + * + * INFO(example, "We are up and running\n"); + */  enum __debug_class  { @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + *            main.cc + * + *  Fri Dec  7 09:35:45 CET 2012 + *  Copyright 2012 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of Debug Module. + * + *  Debug Module is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  Debug Module is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Debug Module; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "debug.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ +  /* +  int fd = open("/tmp/my.log", O_CREAT | O_RDWR, 0777); +  if(fd == -1) { +    return 1; +  } +  */ +  dbg_status_t status = dbg_init(//DBG_FLAG_USE_MUTEX | +                                 DBG_FLAG_OUTPUT_TO_FILE | +                                 //DBG_FLAG_OUTPUT_TO_FD | +                                 //DBG_FLAG_OUTPUT_TO_STDOUT | +                                 //DBG_FLAG_OUTPUT_TO_STDERR | +                                 0, +                                 //DBG_OPTION_FD, fd, +                                 DBG_OPTION_FILENAME, "/tmp/my2.log", +                                 DBG_OPTION_END); + +  if(status != DBG_STATUS_OK) { +    printf("Error: %d\n", status); +    return 1; +  } + +  INFO(example, "We are up and running"); + +  DEBUG(example, "Or are we %d?", 42); +   +  dbg_close(); + +  //close(fd); + +  return 0; +} | 
