/* This file is part of Mailfromd. -*- c -*- Copyright (C) 2007, 2008 Sergey Poznyakoff This program 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 3, or (at your option) any later version. This program 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 this program. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "mailfromd.h" struct modinfo { char *name; unsigned code; }; static char *modname[] = { "all", MAKEDEBUGTAB(SRCLIST) }; #define NMODULES (sizeof modname / sizeof modname[0]) static int modlevel[NMODULES]; /* Per-module levels */ /* Implementation */ int debug_level_p(int modn, int level) { return modn < NMODULES && (modlevel[modn] ? (modlevel[modn] >= level) : modlevel[0] >= level); } static int find_module(const char *name) { size_t len, i; const char *q; const char *p; p = strrchr(name, '/'); if (p) p++; else p = name; q = strrchr(p, '.'); if (q) len = q - name; else len = strlen(p); for (i = 0; i < NMODULES; i++) { if (strlen(modname[i]) == len && memcmp(modname[i], p, len) == 0) return i; } return -1; } void debug_enable_module(const char *file, int level) { int modn = find_module(file); if (modn < 0) { mu_error(_("unknown module: %s"), file); return; } modlevel[modn] = level; } int debug_module_level(const char *modname, int *plev) { int modn; if (modname) { modn = find_module(modname); if (modn < 0) return 1; } else modn = 0; *plev = modlevel[modn]; return 0; } static void parse_spec(char *spec) { char *p, *q; int level; if (isdigit(*spec)) { modlevel[0] = strtoul(spec, &q, 0); if (*q) mu_error(_("%s: wrong debug spec near %s"), spec, q); if (modlevel[0] >= 100) enable_prog_trace("all"); return; } p = strchr(spec, '='); if (p) { *p++ = 0; level = strtol(p, &q, 0); if (*q || level < 0) { mu_error(_("%s: wrong debug spec near %s"), spec, q); return; } } else level = 100; debug_enable_module(spec, level); } void debug_parse_spec(const char *spec) { char *copy = xstrdup(spec); char *s; for (s = strtok(copy, ","); s; s = strtok(NULL, ",")) parse_spec(s); free(copy); } int debug_spec_string(const char *spec, char **pbuf) { char mods[NMODULES]; size_t len = 0, i; char nbuf[NUMERIC_BUFSIZE_BOUND]; char *buf, *ptr; if (!spec) { memset(mods, 0xff, sizeof mods); } else { char *copy = xstrdup(spec); char *s; memset(mods, 0, sizeof mods); for (s = strtok(copy, ","); s; s = strtok(NULL, ",")) { int n = find_module(s); if (n < 0) { free(copy); return EINVAL; } mods[n] = 1; } } if (mods[0]) { snprintf(nbuf, sizeof nbuf, "%d", modlevel[0]); len += strlen(nbuf) + 1; } for (i = 1; i < NMODULES; i++) { if (mods[i]) { snprintf(nbuf, sizeof nbuf, "%d", modlevel[i]); len += strlen(modname[i]) + 1 + strlen(nbuf) + 1; } } buf = malloc(len + 1); if (!buf) return ENOMEM; ptr = buf; if (mods[0]) { sprintf(ptr, "%d", modlevel[0]); ptr += strlen(ptr); } for (i = 1; i < NMODULES; i++) { if (mods[i]) { if (ptr > buf) *ptr++ = ','; sprintf(ptr, "%s=%d", modname[i], modlevel[i]); ptr += strlen(ptr); } } *ptr = 0; *pbuf = buf; return 0; }