diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-22 16:15:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-22 16:30:07 +0300 |
commit | 0666fc3caae8e2db660d781e43bee2258bf06a00 (patch) | |
tree | 97380903872520efa3b2bf659465e63f2cf51a2a /lib/diag.c | |
parent | 7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee (diff) | |
download | eclat-0666fc3caae8e2db660d781e43bee2258bf06a00.tar.gz eclat-0666fc3caae8e2db660d781e43bee2258bf06a00.tar.bz2 |
Introduce output formatting language
* configure.ac: Check for lex and yacc.
* lib/diag.c: New file (moved from ../src with edits)
* lib/forlan.c: New file.
* lib/forlan.h: New file.
* lib/forlangrm.y: New file.
* lib/forlanlex.l: New file.
* lib/.gitignore: Add new files.
* lib/Makefile.am: Add new file.
* lib/libeclat.h: Add diagnostics-related stuff.
* src/Makefile.am (eclat_SOURCES): Remove diag.c
* src/cmdline.opt (set_program_name): Move to ../lib/diag.c
* src/diag.c: Remove (see above).
* src/config.c: Reflect changes to the diagnostics subsystem.
* src/eclat.c: Likewise.
* src/eclat.h: Remove diagnostics-related stuff.
It lives in libeclat.h from now on.
* src/error.c: Remove.
* tests/forlan01.at: New testcase.
* tests/testsuite.at: Include forlan01.at
* tests/tforlan.c: New file.
* tests/.gitignore: Add new files.
* tests/Makefile.am: Add new files.
Diffstat (limited to 'lib/diag.c')
-rw-r--r-- | lib/diag.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/lib/diag.c b/lib/diag.c new file mode 100644 index 0000000..d061e9e --- /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++; +} |