/* This file is part of Eclat.
Copyright (C) 2012 Sergey Poznyakoff.
Eclat 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.
Eclat 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 Eclat. If not, see . */
#include "libeclat.h"
#include
#include
const char *program_name;
struct debug_category debug_category[LIBECLAT_DBG_MAX];
int debug_avail;
void
set_program_name(const char *arg)
{
program_name = strrchr(arg, '/');
if (!program_name)
program_name = arg;
else
program_name++;
}
void
vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
va_list ap)
{
if (program_name)
fprintf(stderr, "%s: ", program_name);
if (locus) {
size_t size = 0;
if (locus->beg.col == 0)
fprintf(stderr, "%s:%u",
locus->beg.file,
locus->beg.line);
else if (strcmp(locus->beg.file, locus->end.file))
fprintf(stderr, "%s:%u.%u-%s:%u.%u",
locus->beg.file,
locus->beg.line, locus->beg.col,
locus->end.file,
locus->end.line, locus->end.col);
else if (locus->beg.line != locus->end.line)
fprintf(stderr, "%s:%u.%u-%u.%u",
locus->beg.file,
locus->beg.line, locus->beg.col,
locus->end.line, locus->end.col);
else
fprintf(stderr, "%s:%u.%u-%u",
locus->beg.file,
locus->beg.line, locus->beg.col,
locus->end.col);
fprintf(stderr, ": ");
}
if (qual)
fprintf(stderr, "%s: ", qual);
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
}
void
diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vdiag(locus, qual, fmt, ap);
va_end(ap);
}
void
die(int status, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vdiag(NULL, NULL, fmt, ap);
va_end(ap);
exit(status);
}
void
err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vdiag(NULL, NULL, fmt, ap);
va_end(ap);
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vdiag(NULL, "warning", fmt, ap);
va_end(ap);
}
void
debug_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vdiag(NULL, "debug", fmt, ap);
va_end(ap);
}
static struct debug_category *
find_category(const char *arg, size_t len)
{
struct debug_category *dp;
for (dp = debug_category; dp < debug_category + debug_avail; dp++)
if (dp->length == len && memcmp(dp->name, arg, len) == 0)
return dp;
return NULL;
}
int
parse_debug_level(const char *arg)
{
unsigned long lev;
char *p;
size_t len = strcspn(arg, ".");
struct debug_category *dp;
if (arg[len] == 0) {
lev = strtoul(arg, &p, 10);
if (*p)
return -1;
for (dp = debug_category; dp < debug_category + debug_avail;
dp++)
dp->level = lev;
return 0;
}
dp = find_category(arg, len);
if (!dp)
return -1;
p = (char*) arg + len;
if (*p == 0)
lev = 100;
else if (*p != '.')
return -1;
else {
lev = strtoul(p + 1, &p, 10);
if (*p)
return -1;
}
dp->level = lev;
return 0;
}
int
debug_register(char *name)
{
if (debug_avail >= LIBECLAT_DBG_MAX)
die(EX_SOFTWARE, "no more debug slots available");
debug_category[debug_avail].name = grecs_strdup(name);
debug_category[debug_avail].length = strlen(name);
debug_category[debug_avail].level = 0;
return debug_avail++;
}