/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * debug.cc * * Wed Feb 11 11:22:12 CET 2009 * Copyright 2009 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of Pracro. * * Pracro 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. * * Pracro 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 Pracro; 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 #define NELEM(x) (sizeof(x)/sizeof((x)[0])) struct __pracro_debug_channel { char name[16]; unsigned flags; }; static const char * const debug_class_str[] = { "fixme", "info", "warn", "err", "debug" }; #define __PRACRO_DEBUG_CHANNEL_MAX 256 static struct __pracro_debug_channel debug_channel[__PRACRO_DEBUG_CHANNEL_MAX]; static unsigned n_debug_channel = 0; static unsigned debug_flags = (1 << __pracro_class_err) | (1 << __pracro_class_fixme); static int __pracro_debug_enabled(const enum __pracro_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); } #ifdef WITH_DEBUG int __pracro_debug(const char *func, const int line, const enum __pracro_debug_class cl, const char *ch, const char *fmt, ...) { int ret = 0; if(__pracro_debug_enabled(cl, ch)) { if((unsigned)cl < NELEM(debug_class_str)) ret += fprintf(stderr, "%s:%s:%s:%d ", debug_class_str[(unsigned)cl], ch, func, line); if(fmt) { va_list va; va_start(va, fmt); ret += vfprintf(stderr, fmt, va); va_end(va); } } if(ret) fflush(stderr); return ret; } int __pracro_debug_va(const char *func, const int line, const enum __pracro_debug_class cl, const char *ch, const char *fmt, va_list va) { int ret = 0; if(__pracro_debug_enabled(cl, ch)) { if((unsigned)cl < NELEM(debug_class_str)) ret += fprintf(stderr, "%s:%s:%s:%d ", debug_class_str[(unsigned)cl], ch, func, line); if(fmt) ret += vfprintf(stderr, fmt, va); } if(ret) fflush(stderr); return ret; } void pracro_debug_init(void) { } #else /* FIXME: should do syslog here... */ int __pracro_log(const char *func, const int line, const enum __pracro_debug_class cl, const char *ch, const char *fmt, ...) { int ret = 0; if(__pracro_debug_enabled(cl, ch)) { if((unsigned)cl < NELEM(debug_class_str)) ret += fprintf(stderr, "%s:%s:%s:%d ", debug_class_str[(unsigned)cl], ch, func, line); if(fmt) { va_list va; va_start(va, fmt); ret += vfprintf(stderr, fmt, va); va_end(va); } } return ret; } /* FIXME: should do syslog here... */ int __pracro_log_va(const char *func, const int line, const enum __pracro_debug_class cl, const char *ch, const char *fmt, va_list va) { int ret = 0; if(__pracro_debug_enabled(cl, ch)) { if((unsigned)cl < NELEM(debug_class_str)) ret += fprintf(stderr, "%s:%s:%s:%d ", debug_class_str[(unsigned)cl], ch, func, line); if(fmt) ret += vfprintf(stderr, fmt, va); } return ret; } void pracro_debug_init(void) { } #endif /* * fmt := [set[,set]*]* * set := [+-]channel * | class[+-]channel * | [+-]all */ void pracro_debug_parse(const char *fmt) { 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 < __PRACRO_DEBUG_CHANNEL_MAX) { strcpy(debug_channel[i].name, p); debug_channel[i].flags = (debug_flags & ~clr) | set; n_debug_channel++; } } } free(s); }