From fac10ea799fe9b6158d74f66d6ad46536d38a545 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 18 Mar 2009 04:55:00 +0100 Subject: Initial commit --- src/erec.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/erec.c (limited to 'src/erec.c') diff --git a/src/erec.c b/src/erec.c new file mode 100644 index 00000000..501bf4b6 --- /dev/null +++ b/src/erec.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2008 Patrick McHardy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + */ + +#include +#include +#include + +#include +#include +#include + +static const struct input_descriptor internal_indesc = { + .type = INDESC_INTERNAL, + .name = "internal", +}; + +const struct location internal_location = { + .indesc = &internal_indesc, +}; + +static const char *error_record_names[] = { + [EREC_INFORMATIONAL] = NULL, + [EREC_WARNING] = "Warning", + [EREC_ERROR] = "Error" +}; + +void erec_add_location(struct error_record *erec, const struct location *loc) +{ + assert(erec->num_locations < EREC_LOCATIONS_MAX); + erec->locations[erec->num_locations++] = *loc; +} + +static void erec_destroy(struct error_record *erec) +{ + xfree(erec->msg); + xfree(erec); +} + +struct error_record *erec_vcreate(enum error_record_types type, + const struct location *loc, + const char *fmt, va_list ap) +{ + struct error_record *erec; + + erec = xmalloc(sizeof(*erec)); + erec->type = type; + erec->num_locations = 0; + erec_add_location(erec, loc); + + gmp_vasprintf(&erec->msg, fmt, ap); + return erec; +} + +struct error_record *erec_create(enum error_record_types type, + const struct location *loc, + const char *fmt, ...) +{ + struct error_record *erec; + va_list ap; + + va_start(ap, fmt); + erec = erec_vcreate(type, loc, fmt, ap); + va_end(ap); + return erec; +} + +void erec_print(FILE *f, const struct error_record *erec) +{ + const struct location *loc = erec->locations, *iloc; + const struct input_descriptor *indesc = loc->indesc, *tmp; + const char *line = NULL; /* silence gcc */ + char buf[1024]; + unsigned int i, end; + int l; + + switch (indesc->type) { + case INDESC_BUFFER: + case INDESC_CLI: + line = indesc->data; + break; + case INDESC_FILE: + memset(buf, 0, sizeof(buf)); + lseek(indesc->fd, loc->line_offset, SEEK_SET); + read(indesc->fd, buf, sizeof(buf) - 1); + *strchrnul(buf, '\n') = '\0'; + line = buf; + break; + case INDESC_INTERNAL: + case INDESC_NETLINK: + break; + default: + BUG(); + } + + if (indesc->type == INDESC_NETLINK) { + fprintf(f, "%s: ", indesc->name); + if (error_record_names[erec->type]) + fprintf(f, "%s: ", error_record_names[erec->type]); + fprintf(f, "%s\n", erec->msg); + for (l = 0; l < (int)erec->num_locations; l++) { + loc = &erec->locations[l]; + netlink_dump_object(loc->nl_obj); + } + fprintf(f, "\n"); + } else { + if (indesc->location.indesc != NULL) { + const char *prefix = "In file included from"; + iloc = &indesc->location; + for (tmp = iloc->indesc; tmp != NULL; tmp = iloc->indesc) { + fprintf(f, "%s %s:%u:%u-%u:\n", prefix, + tmp->name, + iloc->first_line, iloc->first_column, + iloc->last_column); + prefix = " from"; + iloc = &tmp->location; + } + } + if (indesc->name != NULL) + fprintf(f, "%s:%u:%u-%u: ", indesc->name, + loc->first_line, loc->first_column, + loc->last_column); + if (error_record_names[erec->type]) + fprintf(f, "%s: ", error_record_names[erec->type]); + fprintf(f, "%s\n", erec->msg); + + if (indesc->type != INDESC_INTERNAL) + fprintf(f, "%s\n", line); + + memset(buf, ' ', sizeof(buf)); + end = 0; + for (l = erec->num_locations - 1; l >= 0; l--) { + loc = &erec->locations[l]; + for (i = loc->first_column - 1; i < loc->last_column; i++) + buf[i] = l ? '~' : '^'; + end = max(end, loc->last_column); + } + buf[end] = '\0'; + fprintf(f, "%s", buf); + } + fprintf(f, "\n"); +} + +void erec_print_list(FILE *f, struct list_head *list) +{ + struct error_record *erec, *next; + + list_for_each_entry_safe(erec, next, list, list) { + list_del(&erec->list); + erec_print(f, erec); + erec_destroy(erec); + } +} -- cgit v1.2.3