diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-src/liblcdf/error.cc')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-src/liblcdf/error.cc | 1185 |
1 files changed, 0 insertions, 1185 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/liblcdf/error.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-src/liblcdf/error.cc deleted file mode 100644 index 2c41f3f2e79..00000000000 --- a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/liblcdf/error.cc +++ /dev/null @@ -1,1185 +0,0 @@ -// -*- related-file-name: "../include/lcdf/error.hh" -*- -/* - * error.{cc,hh} -- flexible classes for error reporting - * Eddie Kohler - * - * Copyright (c) 1999-2000 Massachusetts Institute of Technology - * Copyright (c) 2001-2019 Eddie Kohler - * Copyright (c) 2008 Meraki, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, subject to the conditions - * listed in the Click LICENSE file. These conditions include: you must - * preserve this copyright notice, and you cannot mention the copyright - * holders in advertising related to the Software without their permission. - * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This - * notice is a summary of the Click LICENSE file; the license in that file is - * legally binding. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <lcdf/error.hh> -#include <lcdf/straccum.hh> -#include <lcdf/hashmap.hh> -#include <errno.h> -#include <ctype.h> -#include <algorithm> -#ifndef __KERNEL__ -# include <stdlib.h> -# if HAVE_UNISTD_H -# include <unistd.h> -# endif -#endif - -/** @file error.hh - * @brief Flexible error handling classes. - */ - -struct ErrorHandler::Conversion { - String name; - ConversionFunction hook; - Conversion *next; -}; -static ErrorHandler::Conversion *error_items; - -const char ErrorHandler::e_abort[] = "<-999>"; -const char ErrorHandler::e_fatal[] = "<-1>"; -const char ErrorHandler::e_emergency[] = "<0>"; -const char ErrorHandler::e_alert[] = "<1>"; -const char ErrorHandler::e_critical[] = "<2>"; -const char ErrorHandler::e_error[] = "<3>"; -const char ErrorHandler::e_warning[] = "<4>"; -const char ErrorHandler::e_warning_annotated[] = "<4>warning: "; -const char ErrorHandler::e_notice[] = "<5>"; -const char ErrorHandler::e_info[] = "<6>"; -const char ErrorHandler::e_debug[] = "<7>"; - -const int ErrorHandler::ok_result = 0; -const int ErrorHandler::error_result = -EINVAL; - -ErrorHandler *ErrorHandler::the_default_handler = 0; -ErrorHandler *ErrorHandler::the_silent_handler = 0; - - -// ANNOTATION MANAGEMENT - -static const char * -parse_level(const char *begin, const char *end, int *result) -{ - int x = 0; - const char *s = begin; - - bool negative = false; - if (s != end && *s == '-') { - negative = true; - ++s; - } else if (s != end && *s == '+') - ++s; - - const char *digits = s; - for (; s != end && *s >= '0' && *s <= '9'; ++s) - x = x * 10 + *s - '0'; - - if (s != end && *s == '.') - for (++s; s != end && *s >= '0' && *s <= '9'; ++s) - /* nada */; - - if (s == digits || (s == digits + 1 && s[-1] == '.')) - return begin; - if (result) - *result = (negative ? -x : x); - return s; -} - -String -ErrorHandler::make_anno(const char *name, const String &value) -{ - StringAccum sa; - sa.reserve(value.length() + 10); - - // level annotation requires special handling - if (name[0] == '<' && name[1] == '>' && name[2] == 0) { - if (parse_level(value.begin(), value.end(), 0) == value.end()) { - sa << '<' << value << '>'; - return sa.take_string(); - } else - return String(); - } - - sa << '{' << name << ':'; - const char *last = value.begin(), *end = value.end(); - for (const char *s = value.begin(); s != end; ++s) - if (*s == '\\' || *s == '}') { - sa.append(last, s); - sa << '\\' << *s; - last = s + 1; - } else if (*s == '\n') { - sa.append(last, s); - sa << '\\' << 'n'; - last = s + 1; - } - sa.append(last, end); - sa << '}'; - return sa.take_string(); -} - -const char * -ErrorHandler::skip_anno(const String &str, const char *begin, const char *end, - String *name_result, String *value_result, bool raw) -{ - String name, value; - const char *s = begin; - - if (s + 3 <= end && *s == '<') { - const char *x = parse_level(s + 1, end, 0); - if (x != s + 1 && x != end && *x == '>') { - name = String::make_stable("<>", 2); - if (str) - value = str.substring(begin + 1, x); - begin = x + 1; - } - - } else if (s + 2 <= end && *s == '{' && s[1] == '}') - begin = s + 2; - - else if (s + 3 <= end && *s == '{' && str) { - for (++s; s != end && isalnum((unsigned char) *s); ++s) - /* nada */; - if (s == end || s == begin + 1 || (*s != '}' && *s != ':')) - /* not an annotation */; - else if (*s == '}' && str) { - name = str.substring(begin + 1, s); - begin = s + 1; - } else if (*s == '}') { - name = String::make_stable("{}", 2); - begin = s + 1; - } else if (str) { - const char *x, *last = s + 1; - StringAccum sa; - for (x = s + 1; x != end && *x != '\n' && *x != '}'; ++x) - if (*x == '\\' && x + 1 != end && x[1] != '\n') { - if (!raw) { - sa.append(last, x); - sa << (x[1] == 'n' ? '\n' : x[1]); - last = x + 2; - } - ++x; - } - if (x != end && *x == '}') { - name = str.substring(begin + 1, s); - if (sa) { - sa.append(last, x); - value = sa.take_string(); - } else - value = str.substring(s + 1, x); - begin = x + 1; - } - } else { - const char *x; - for (x = s + 1; x != end && *x != '\n' && *x != '}'; ++x) - if (*x == '\\' && x + 1 != end && x[1] != '\n') - ++x; - if (x != end && *x == '}') { - name = String::make_stable("{}", 2); - begin = x + 1; - } - } - } - - if (name_result) - *name_result = name; - if (value_result) - *value_result = value; - return begin; -} - -const char * -ErrorHandler::parse_anno(const String &str, const char *begin, const char *end, - ...) -{ - const char *names[8]; - void *values[8]; - int nanno = 0; - - va_list val; - va_start(val, end); - while (const char *n = va_arg(val, const char *)) { - assert(nanno < 8); - names[nanno] = n; - if (n[0] == '#') - values[nanno] = va_arg(val, int *); - else - values[nanno] = va_arg(val, String *); - ++nanno; - } - - String name, value; - while (1) { - begin = skip_anno(str, begin, end, &name, &value, false); - if (!name) - break; - for (int i = 0; i < nanno; ++i) - if (names[i][0] == '#') { - if (name == (names[i] + 1)) - parse_level(value.begin(), value.end(), (int *) values[i]); - } else { - if (name == names[i]) - *(String *) values[i] = value; - } - } - - return begin; -} - -String -ErrorHandler::combine_anno(const String &text, const String &anno) -{ - if (!anno) - return text; - - String names[8], values[8]; - int nanno = 0; - const char *abegin = anno.begin(); - while (abegin != anno.end()) { - assert(nanno < 8); - abegin = skip_anno(anno, abegin, anno.end(), &names[nanno], &values[nanno], true); - if (names[nanno]) - ++nanno; - else - break; - } - - const char *last = text.begin(), *s = last; - String name; - StringAccum sa; - while (s != text.end()) { - const char *line = s; - uint32_t mask = (1U << nanno) - 1; - while (1) { - s = skip_anno(text, s, text.end(), &name, 0, false); - if (!name) - break; - for (int i = 0; i < nanno; ++i) - if (name == names[i]) - mask &= ~(1U << i); - } - - if (mask) { - sa.append(last, line); - for (int i = 0; i < nanno; ++i) - if (mask & (1U << i)) { - if (names[i].equals("<>", 2)) - sa << '<' << values[i] << '>'; - else - sa << '{' << names[i] << ':' << values[i] << '}'; - } - last = line; - } - if (abegin != anno.end()) { - sa.append(last, s); - sa.append(abegin, anno.end()); - last = s; - } - - while (s != text.end() && *s != '\n') - ++s; - if (s != text.end()) - ++s; - } - - if (sa) { - sa.append(last, text.end()); - return sa.take_string(); - } else - return text; -} - -String -ErrorHandler::clean_landmark(const String &landmark, bool with_colon) -{ - const char *end = landmark.end(); - while (end != landmark.begin() && isspace((unsigned char) end[-1])) - --end; - if (end != landmark.begin() && end[-1] == ':') - --end; - if (end == landmark.begin()) - return String(); - else if (with_colon) - return landmark.substring(landmark.begin(), end) + ": "; - else - return landmark.substring(landmark.begin(), end); -} - - -// FORMATTING - -#define NUMBUF_SIZE 128 -#define ErrH ErrorHandler - -#if SIZEOF_UNSIGNED_LONG >= SIZEOF_VOID_P -typedef unsigned long do_number_t; -#else -typedef uintptr_t do_number_t; -#endif - -static char* -do_number(do_number_t num, char *after_last, int base, int flags) -{ - const char *digits = - ((flags & ErrH::cf_uppercase) ? "0123456789ABCDEF" : "0123456789abcdef"); - char *pos = after_last; - while (num) { - *--pos = digits[num % base]; - num /= base; - } - if (pos == after_last) - *--pos = '0'; - return pos; -} - -static char * -do_number_flags(char *pos, char *after_last, int base, int flags, - int precision, int field_width) -{ - // remove cf_alternate_form for zero results in base 16 - if ((flags & ErrH::cf_alternate_form) && base == 16 && *pos == '0') - flags &= ~ErrH::cf_alternate_form; - - // account for zero padding - if (precision >= 0) - while (after_last - pos < precision) - *--pos = '0'; - else if (flags & ErrH::cf_zero_pad) { - if ((flags & ErrH::cf_alternate_form) && base == 16) - field_width -= 2; - if ((flags & ErrH::cf_negative) - || (flags & (ErrH::cf_plus_positive | ErrH::cf_space_positive))) - field_width--; - while (after_last - pos < field_width) - *--pos = '0'; - } - - // alternate forms - if ((flags & ErrH::cf_alternate_form) && base == 8 && pos[1] != '0') - *--pos = '0'; - else if ((flags & ErrH::cf_alternate_form) && base == 16) { - *--pos = ((flags & ErrH::cf_uppercase) ? 'X' : 'x'); - *--pos = '0'; - } - - // sign - if (flags & ErrH::cf_negative) - *--pos = '-'; - else if (flags & ErrH::cf_plus_positive) - *--pos = '+'; - else if (flags & ErrH::cf_space_positive) - *--pos = ' '; - - return pos; -} - -String -ErrorHandler::vxformat(int default_flags, const char *s, va_list val) -{ - StringAccum msg; - - char numbuf[NUMBUF_SIZE]; // for numerics - numbuf[NUMBUF_SIZE-1] = 0; - - String strstore; // to ensure temporaries aren't destroyed - - // declare and initialize these here to make gcc shut up about possible - // use before initialization - int flags = 0; - int field_width = -1; - int precision = -1; - int width_flag = 0; - int base = 10; - while (1) { - - const char *pct = strchr(s, '%'); - if (!pct) { - if (*s) - msg << s; - break; - } - if (pct != s) { - msg.append(s, pct - s); - s = pct; - } - - // parse flags - flags = default_flags; - flags: - switch (*++s) { - case '#': flags |= cf_alternate_form; goto flags; - case '0': flags |= cf_zero_pad; goto flags; - case '-': flags |= cf_left_just; goto flags; - case ' ': flags |= cf_space_positive; goto flags; - case '+': flags |= cf_plus_positive; goto flags; - case '\'': flags |= cf_singlequote; goto flags; - case '_': flags &= ~cf_utf8; goto flags; - } - - // parse field width - field_width = -1; - if (*s == '*') { - field_width = va_arg(val, int); - if (field_width < 0) { - field_width = -field_width; - flags |= cf_left_just; - } - s++; - } else if (*s >= '0' && *s <= '9') - for (field_width = 0; *s >= '0' && *s <= '9'; s++) - field_width = 10*field_width + *s - '0'; - - // parse precision - precision = -1; - if (*s == '.') { - s++; - precision = 0; - if (*s == '*') { - precision = va_arg(val, int); - s++; - } else if (*s >= '0' && *s <= '9') - for (; *s >= '0' && *s <= '9'; s++) - precision = 10*precision + *s - '0'; - } - - // parse width flags - width_flag = 0; - width_flags: - switch (*s) { - case 'h': case 'l': - if (width_flag == *s) - width_flag = *s + 'A' - 'a'; - else if (width_flag) - break; - else - width_flag = *s; - s++; - goto width_flags; - case 'z': - case 't': - if (width_flag) - break; - width_flag = *s++; - break; - case '^': - if (!isdigit((unsigned char) s[1]) || width_flag) - break; - for (s++; isdigit((unsigned char) *s); s++) - width_flag = width_flag * 10 + *s - '0'; - width_flag = -width_flag; - break; - } - - // conversion character - // after switch, data lies between `s1' and `s2' - const char *s1 = 0, *s2 = 0; - base = 10; - switch (*s++) { - - case 's': { - s1 = va_arg(val, const char *); - if (!s1) - s1 = "(null)"; - - // fetch length - int len; - if (precision < 0) - len = strlen(s1); - else - len = strnlen(s1, precision); - - // transform string if alternate form - if (flags & cf_alternate_form) { - strstore = String(s1, len).printable(); - if (precision < 0 || strstore.length() < precision) - len = strstore.length(); - } - - // quote characters that look like annotations, readjusting length - if (flags & (cf_singlequote | cf_alternate_form)) { - if (!(flags & cf_alternate_form)) - strstore = String(s1, len); - - // check first line, considering trailing part of 'msg' - const char *mbegin = msg.end(); - while (mbegin != msg.begin() && mbegin[-1] != '\n') - --mbegin; - if (skip_anno(strstore.begin(), strstore.end()) != strstore.begin() - && skip_anno(mbegin, msg.end()) == msg.end()) { - strstore = String::make_stable("{}", 2) + strstore; - len += 2; - } - - // check subsequent lines - const char *s = std::find(strstore.begin(), strstore.end(), '\n'); - while (s != strstore.end() && s + 1 != strstore.end()) { - size_t nextpos = (s + 1) - strstore.begin(); - if (skip_anno(s + 1, strstore.end()) != s + 1) { - strstore = strstore.substring(strstore.begin(), s + 1) - + String::make_stable("{}", 2) - + strstore.substring(s + 1, strstore.end()); - len += 2; - } - s = std::find(strstore.begin() + nextpos, strstore.end(), '\n'); - } - } - - // obtain begin and end pointers - if (flags & (cf_singlequote | cf_alternate_form)) - s1 = strstore.begin(); - s2 = s1 + len; - break; - } - - case 'c': { - int c = va_arg(val, int); - // check for extension of 'signed char' to 'int' - if (c < 0) - c += 256; - // assume ASCII - if (c == '\n') - strcpy(numbuf, "\\n"); - else if (c == '\t') - strcpy(numbuf, "\\t"); - else if (c == '\r') - strcpy(numbuf, "\\r"); - else if (c == '\0') - strcpy(numbuf, "\\0"); - else if (c < 0 || c >= 256) - strcpy(numbuf, "(bad char)"); - else if (c < 32 || c >= 0177) - sprintf(numbuf, "\\%03o", c); - else - sprintf(numbuf, "%c", c); - s1 = numbuf; - s2 = strchr(numbuf, 0); - break; - } - - case '%': { - numbuf[0] = '%'; - s1 = numbuf; - s2 = s1 + 1; - break; - } - - case '<': - s1 = (flags & cf_utf8 ? "\342\200\230" : "\'"); - s2 = s1 + strlen(s1); - break; - - case '>': - case ',': - s1 = (flags & cf_utf8 ? "\342\200\231" : "\'"); - s2 = s1 + strlen(s1); - break; - - case 'd': - case 'i': - flags |= cf_signed; - /* fallthru */ - case 'u': - number: { - // protect numbuf from overflow - if (field_width > NUMBUF_SIZE) - field_width = NUMBUF_SIZE; - if (precision > NUMBUF_SIZE - 4) - precision = NUMBUF_SIZE - 4; - - s2 = numbuf + NUMBUF_SIZE; - - do_number_t num; - switch (width_flag) { - case 'H': - case -8: - num = (unsigned char) va_arg(val, int); - if ((flags & cf_signed) && (signed char) num < 0) - num = -(signed char) num, flags |= cf_negative; - break; - case 'h': - case -16: - num = (unsigned short) va_arg(val, int); - if ((flags & cf_signed) && (short) num < 0) - num = -(short) num, flags |= cf_negative; - break; - case 0: - case -32: -#if SIZEOF_LONG == 4 - case 'l': -#endif -#if SIZEOF_SIZE_T == 4 - case 'z': -#endif -#if SIZEOF_PTRDIFF_T == 4 - case 't': -#endif - num = va_arg(val, unsigned); - if ((flags & cf_signed) && (int) num < 0) - num = -(int) num, flags |= cf_negative; - break; -#if HAVE_INT64_TYPES -# if SIZEOF_LONG == 8 - case 'l': -# endif -# if SIZEOF_LONG_LONG == 8 - case 'L': -# endif -# if SIZEOF_SIZE_T == 8 - case 'z': -# endif -# if SIZEOF_PTRDIFF_T == 8 - case 't': -# endif - case -64: { - uint64_t qnum = va_arg(val, uint64_t); - if ((flags & cf_signed) && (int64_t)qnum < 0) - qnum = -(int64_t) qnum, flags |= cf_negative; - StringAccum sa; - sa.append_numeric(static_cast<String::uintmax_t>(qnum), base, (flags & cf_uppercase)); - s1 = s2 - sa.length(); - memcpy(const_cast<char*>(s1), sa.data(), s2 - s1); - goto got_number; - } -#endif - default: - goto error; - } - s1 = do_number(num, (char*) s2, base, flags); - -#if HAVE_INT64_TYPES - got_number: -#endif - s1 = do_number_flags((char*)s1, (char*) s2, base, flags, precision, field_width); - break; - } - - case 'o': - base = 8; - goto number; - - case 'X': - flags |= cf_uppercase; - /* fallthru */ - case 'x': - base = 16; - goto number; - - case 'p': { - if (*s == '{') { - s1 = s2 = s + 1; - while (*s2 && *s2 != '}' && !isspace((unsigned char) *s2)) - ++s2; - if (*s2 == '}') - goto braces; - } - void* v = va_arg(val, void*); - s2 = numbuf + NUMBUF_SIZE; - s1 = do_number((do_number_t) v, (char*) s2, 16, flags); - s1 = do_number_flags((char*) s1, (char*) s2, 16, flags | cf_alternate_form, precision, field_width); - break; - } - -#ifndef __KERNEL__ - case 'e': case 'f': case 'g': - case 'E': case 'F': case 'G': { - char format[80], *f = format, new_numbuf[NUMBUF_SIZE]; - *f++ = '%'; - if (flags & cf_alternate_form) - *f++ = '#'; - if (precision >= 0) - f += sprintf(f, ".%d", precision); - *f++ = s[-1]; - *f++ = 0; - - int len = sprintf(new_numbuf, format, va_arg(val, double)); - - s2 = numbuf + NUMBUF_SIZE; - s1 = s2 - len; - memcpy((char *)s1, new_numbuf, len); // note: no terminating \0 - s1 = do_number_flags((char *)s1, (char *)s2, 10, flags & ~cf_alternate_form, -1, field_width); - break; - } -#endif - - case '{': - s1 = s2 = s; - while (*s2 && *s2 != '}' && !isspace((unsigned char) *s2)) - ++s2; - if (*s2 != '}') - goto error; - goto braces; - - braces: - s = s2 + 1; - for (Conversion *item = error_items; item; item = item->next) - if (item->name.equals(s1, s2 - s1)) { - strstore = item->hook(flags, VA_LIST_REF(val)); - s1 = strstore.begin(); - s2 = strstore.end(); - goto got_result; - } - goto error; - - error: - default: - assert(0 /* Bad % in error */); - break; - - } - - // add result of conversion - got_result: - int slen = s2 - s1; - if (slen > field_width) - field_width = slen; - char *dest = msg.extend(field_width); - if (flags & cf_left_just) { - memcpy(dest, s1, slen); - memset(dest + slen, ' ', field_width - slen); - } else { - memcpy(dest + field_width - slen, s1, slen); - memset(dest, (flags & cf_zero_pad ? '0' : ' '), field_width - slen); - } - } - - return msg.take_string(); -} - -String -ErrorHandler::xformat(int default_flags, const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String s = vxformat(default_flags, fmt, val); - va_end(val); - return s; -} - -String -ErrorHandler::xformat(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String s = vxformat(0, fmt, val); - va_end(val); - return s; -} - -String -ErrorHandler::format(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String s = vformat(fmt, val); - va_end(val); - return s; -} - - -// ERROR MESSAGE SHORTHAND - -void -ErrorHandler::debug(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - xmessage(String::make_stable(e_debug, 3), fmt, val); - va_end(val); -} - -void -ErrorHandler::message(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - xmessage(String::make_stable(e_info, 3), fmt, val); - va_end(val); -} - -int -ErrorHandler::warning(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - int r = xmessage(String::make_stable(e_warning_annotated, 12), fmt, val); - va_end(val); - return r; -} - -int -ErrorHandler::error(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - int r = xmessage(String::make_stable(e_error, 3), fmt, val); - va_end(val); - return r; -} - -void -ErrorHandler::fatal(const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - (void) xmessage(String::make_stable(e_fatal, 4), fmt, val); - va_end(val); - abort(); -} - -void -ErrorHandler::ldebug(const String &landmark, const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String l = make_landmark_anno(landmark); - xmessage(String::make_stable(e_debug, 3) + l, fmt, val); - va_end(val); -} - -void -ErrorHandler::lmessage(const String &landmark, const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String l = make_landmark_anno(landmark); - xmessage(String::make_stable(e_info, 3) + l, fmt, val); - va_end(val); -} - -int -ErrorHandler::lwarning(const String &landmark, const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String l = make_landmark_anno(landmark); - int r = xmessage(l + String::make_stable(e_warning_annotated, 12), fmt, val); - va_end(val); - return r; -} - -int -ErrorHandler::lerror(const String &landmark, const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String l = make_landmark_anno(landmark); - int r = xmessage(String::make_stable(e_error, 3) + l, fmt, val); - va_end(val); - return r; -} - -void -ErrorHandler::lfatal(const String &landmark, const char *fmt, ...) -{ - va_list val; - va_start(val, fmt); - String l = make_landmark_anno(landmark); - (void) xmessage(String::make_stable(e_fatal, 4) + l, fmt, val); - va_end(val); - abort(); -} - -int -ErrorHandler::xmessage(const String &str) -{ - String xstr = decorate(str); - - int min_level = 1000, xlevel = 1000; - const char *s = xstr.begin(), *end = xstr.end(); - void *user_data = 0; - while (s != end) { - const char *l = parse_anno(xstr, s, end, "#<>", &xlevel, - (const char *) 0); - const char *nl = std::find(l, end, '\n'); - String line = xstr.substring(s, nl); - s = nl + (nl != end); - user_data = emit(line, user_data, s != end); - min_level = (xlevel < min_level ? xlevel : min_level); - } - - account(min_level); - - return (min_level <= el_warning ? error_result : ok_result); -} - -String -ErrorHandler::vformat(const char *fmt, va_list val) -{ - return vxformat(0, fmt, val); -} - -String -ErrorHandler::decorate(const String &str) -{ - return str; -} - -void * -ErrorHandler::emit(const String &, void *user_data, bool) -{ - return user_data; -} - -void -ErrorHandler::account(int level) -{ - if (level <= el_error) - ++_nerrors; -#ifndef __KERNEL__ - if (level <= el_abort) - abort(); - else if (level <= el_fatal) - exit(-level); -#endif -} - - -#ifndef __KERNEL__ -// -// FILE ERROR HANDLER -// - -FileErrorHandler::FileErrorHandler(FILE *f, const String &context) - : _f(f), _context(context), _default_flags(0) -{ -# if HAVE_UNISTD_H - if (isatty(fileno(_f))) { -# endif - char *s = getenv("LANG"); - if (s && (strstr(s, "UTF-8") != 0 || strstr(s, "UTF8") != 0 - || strstr(s, "utf8") != 0)) - _default_flags |= cf_utf8; -# if HAVE_UNISTD_H - } -# endif -} - -String -FileErrorHandler::vformat(const char *fmt, va_list val) -{ - return vxformat(_default_flags, fmt, val); -} - -void * -FileErrorHandler::emit(const String &str, void *, bool) -{ - String landmark; - const char *s = parse_anno(str, str.begin(), str.end(), - "l", &landmark, (const char *) 0); - StringAccum sa; - sa << _context << clean_landmark(landmark, true) - << str.substring(s, str.end()) << '\n'; - ssize_t result = fwrite(sa.begin(), 1, sa.length(), _f); - (void) result; - return 0; -} - -#endif - - -// -// STATIC ERROR HANDLERS -// - -ErrorHandler::Conversion * -ErrorHandler::add_conversion(const String &name, ConversionFunction function) -{ - if (Conversion *c = new Conversion) { - c->name = name; - c->hook = function; - c->next = error_items; - error_items = c; - return c; - } else - return 0; -} - -int -ErrorHandler::remove_conversion(ErrorHandler::Conversion *conv) -{ - Conversion **pprev = &error_items; - for (Conversion *c = error_items; c; pprev = &c->next, c = *pprev) - if (c == conv) { - *pprev = c->next; - delete c; - return 0; - } - return -1; -} - -ErrorHandler * -ErrorHandler::static_initialize(ErrorHandler *default_handler) -{ - if (!the_silent_handler) { - the_default_handler = default_handler; - the_silent_handler = new SilentErrorHandler; - } - return default_handler; -} - -void -ErrorHandler::static_cleanup() -{ - delete the_default_handler; - delete the_silent_handler; - the_default_handler = the_silent_handler = 0; - while (error_items) { - Conversion *next = error_items->next; - delete error_items; - error_items = next; - } -} - -void -ErrorHandler::set_default_handler(ErrorHandler *errh) -{ - the_default_handler = errh; -} - - -// -// ERROR VENEER -// - -String -ErrorVeneer::vformat(const char *fmt, va_list val) -{ - if (_errh) - return _errh->vformat(fmt, val); - else - return ErrorHandler::vformat(fmt, val); -} - -String -ErrorVeneer::decorate(const String &str) -{ - if (_errh) - return _errh->decorate(str); - else - return ErrorHandler::decorate(str); -} - -void * -ErrorVeneer::emit(const String &str, void *user_data, bool more) -{ - if (_errh) - return _errh->emit(str, user_data, more); - else - return ErrorHandler::emit(str, user_data, more); -} - -void -ErrorVeneer::account(int level) -{ - ErrorHandler::account(level); - if (_errh) - _errh->account(level); -} - - -// -// CONTEXT ERROR HANDLER -// - -ContextErrorHandler::ContextErrorHandler(ErrorHandler *errh, const char *fmt, - ...) - : ErrorVeneer(errh), _indent(String::make_stable(" ", 2)), - _context_landmark("{l:}"), _context_printed(false) -{ - va_list val; - va_start(val, fmt); - _context = ErrorVeneer::vformat(fmt, val); - va_end(val); - if (_context) - _context = combine_anno(_context, String::make_stable("{context:context}", 17)); -} - -String -ContextErrorHandler::decorate(const String &str) -{ - String context_anno; - const char *str_endanno = parse_anno(str, str.begin(), str.end(), - "context", &context_anno, - (const char *) 0); - if (context_anno.equals("no", 2)) - return ErrorVeneer::decorate(str); - - String istr; - if (context_anno.equals("noindent", 8)) - istr = combine_anno(str, _context_landmark); - else - istr = combine_anno(str, _context_landmark + _indent); - - if (!_context_printed && !context_anno.equals("nocontext", 9)) { - String astr = combine_anno(combine_anno(_context, _context_landmark), - str.substring(str.begin(), str_endanno)); - if (astr && astr.back() != '\n') - astr += '\n'; - _context_printed = true; - return ErrorVeneer::decorate(astr + istr); - } else - return ErrorVeneer::decorate(istr); -} - - -// -// PREFIX ERROR HANDLER -// - -PrefixErrorHandler::PrefixErrorHandler(ErrorHandler *errh, - const String &prefix) - : ErrorVeneer(errh), _prefix(prefix) -{ -} - -String -PrefixErrorHandler::decorate(const String &str) -{ - return ErrorVeneer::decorate(combine_anno(str, _prefix)); -} - - -// -// LANDMARK ERROR HANDLER -// - -LandmarkErrorHandler::LandmarkErrorHandler(ErrorHandler *errh, const String &landmark) - : ErrorVeneer(errh), _landmark(make_landmark_anno(landmark)) -{ -} - -String -LandmarkErrorHandler::decorate(const String &str) -{ - return ErrorVeneer::decorate(combine_anno(str, _landmark)); -} - - -// -// BAIL ERROR HANDLER -// - -#ifndef __KERNEL__ - -BailErrorHandler::BailErrorHandler(ErrorHandler *errh, int l) - : ErrorVeneer(errh), _level(l) -{ -} - -void -BailErrorHandler::account(int level) -{ - ErrorVeneer::account(level); - if (level <= _level) - exit(1); -} - -#endif |