summaryrefslogtreecommitdiffabout
path: root/lib/diag.c
Side-by-side diff
Diffstat (limited to 'lib/diag.c') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/diag.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/lib/diag.c b/lib/diag.c
new file mode 100644
index 0000000..d061e9e
--- a/dev/null
+++ b/lib/diag.c
@@ -0,0 +1,181 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include "libeclat.h"
+#include <string.h>
+#include <sysexits.h>
+
+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++;
+}

Return to:

Send suggestions and report system problems to the System administrator.