/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * debug.cc * * Thu Nov 1 13:38:47 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 #include #include //#include #include #include //#include "mutex.h" //static Mutex mutex; static unsigned int gettid() { return 0;//(unsigned int)pthread_self(); } static FILE *logfp = stderr; #define NELEM(x) (sizeof(x)/sizeof((x)[0])) struct __debug_channel { char name[32]; unsigned flags; }; static const char * const debug_class_str[] = { "fixme", "err", "warn", "info", "debug" }; #define __DEBUG_CHANNEL_MAX 256 static struct __debug_channel debug_channel[__DEBUG_CHANNEL_MAX]; static unsigned n_debug_channel = 0; static unsigned debug_flags = (1 << __class_err) | (1 << __class_fixme); static int __debug_enabled(const enum __debug_class cl, const char *ch) { unsigned i; for(i = 0; i < n_debug_channel; i++) { if(!strcmp(ch, debug_channel[i].name)) { return (debug_channel[i].flags & (1 << cl)) != 0; } } return debug_flags & (1 << cl); } int __debug(const char *func, const int line, const enum __debug_class cl, const char *ch, const char *fmt, ...) { time_t rawtime = time(NULL); struct tm *t = localtime(&rawtime); // MutexAutolock m(mutex); int ret = 0; if(__debug_enabled(cl, ch)) { if((unsigned)cl < NELEM(debug_class_str)) ret += fprintf(logfp, "%d-%02d-%02d %02d:%02d:%02d %u %s:%s:%s:%d ", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, gettid(), debug_class_str[(unsigned)cl], ch, func, line); if(fmt) { va_list va; va_start(va, fmt); ret += vfprintf(logfp, fmt, va); va_end(va); } } if(ret){ fflush(logfp); } return ret; } void debug_init(FILE *fp) { // mutex.name = "debug"; // MutexAutolock m(mutex); logfp = fp; } /* * fmt := [set[,set]*]* * set := [+-]channel * | class[+-]channel * | [+-]all */ void debug_parse(const char *fmt) { // MutexAutolock m(mutex); char *s; char *next; char *opt; if(!(s = strdup(fmt))) return; for(opt = s; opt; opt = next) { int set = 0; int clr = 0; unsigned i; if((next = strchr(opt, ','))) *next++ = '\0'; char *p = opt + strcspn(opt, "+-"); if(!*p) p = opt; // All chars -> a channel name if(p > opt) { // we have a class for(i = 0; i < NELEM(debug_class_str); i++) { int n = strlen(debug_class_str[i]); if(n != (p - opt)) continue; if(!memcmp(opt, debug_class_str[i], n)) { // Found the class if(*p == '+') set = 1 << i; else clr = 1 << i; break; } } if(i == NELEM(debug_class_str)) continue; } else { if(*p == '-') clr = ~0; else set = ~0; } if(*p == '+' || *p == '-') p++; if(!*p) continue; if(!strcmp("all", p)) { debug_flags = (debug_flags & ~clr) | set; } else { if(strlen(p) >= sizeof(debug_channel[0].name)) continue; for(i = 0; i < n_debug_channel; i++) { if(!strcmp(p, debug_channel[i].name)) { debug_channel[i].flags = (debug_channel[i].flags & ~clr) | set; break; } } if(i == n_debug_channel && n_debug_channel < __DEBUG_CHANNEL_MAX) { strcpy(debug_channel[i].name, p); debug_channel[i].flags = (debug_flags & ~clr) | set; n_debug_channel++; } } } free(s); }