diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-2.99/include/lcdf/error.hh')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-2.99/include/lcdf/error.hh | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.99/include/lcdf/error.hh b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.99/include/lcdf/error.hh new file mode 100644 index 00000000000..2af4a77763d --- /dev/null +++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.99/include/lcdf/error.hh @@ -0,0 +1,881 @@ +// -*- related-file-name: "../../liblcdf/error.cc" -*- +#ifndef LCDF_ERROR_HH +#define LCDF_ERROR_HH +#include <lcdf/string.hh> +#ifndef __KERNEL__ +# include <stdio.h> +#endif +#include <stdarg.h> +#if HAVE_ADDRESSABLE_VA_LIST +# define VA_LIST_REF_T va_list * +# define VA_LIST_DEREF(val) (*(val)) +# define VA_LIST_REF(val) (&(val)) +#else +# define VA_LIST_REF_T va_list +# define VA_LIST_DEREF(val) (val) +# define VA_LIST_REF(val) (val) +#endif +#if __GNUC__ <= 3 +# define ERRH_SENTINEL +#else +# define ERRH_SENTINEL __attribute__((sentinel)) +#endif + +/** @class ErrorHandler + * @brief Error reporting class. + * + * Report errors through ErrorHandler objects, which represent + * error collectors and printers. ErrorHandlers are passed to configure() and + * initialize() methods explicitly, as well as to write handlers; the + * click_chatter() function calls ErrorHandler implicitly. + * + * <h3>Cooked error messages</h3> + * + * Most ErrorHandler interactions consist of a simple call like this: + * @code + * errh->error("not enough arguments (%d needed)", 5); + * // prints something like "not enough arguments (5 needed)\n" + * @endcode + * + * This function constructs an error message string from the format arguments, + * annotates the string with a default error level (here, el_error), and + * prints it. Alternate versions take a landmark specifying where the error + * took place: + * @code + * errh->lwarning("file.click:2", "syntax error at '%s'", word.c_str()); + * // prints something like "file.click:2: syntax error at 'foo'\n" + * @endcode + * + * <h3>Raw error messages</h3> + * + * For finer control over error levels and annotations, construct an error + * message string directly. An error message is a string consisting of one or + * more lines. Each line begins with a set of optional textual @em + * annotations. The following error message has a @em level annotation + * determining how serious the error is (this one is critical, since + * el_critical == 2), and a @em landmark annotation, which specifies where the + * error took place (here, "x.click:1"): + * + * <tt>"<2>{l:x.click:1}syntax error"</tt> + * + * The default ErrorHandlers understand the level and landmark + * annotations. Users can add other arbitrary annotations, which can be + * useful to pass error metadata. A pair of braces ends the annotation area. + * This example has one user annotation <tt>eoc</tt>, and a message area that + * would be mistaken for an annotation were it not for the <tt>{}</tt>: + * + * <tt>"<2>{l:x.click:1}{eoc:520}{}{not:an annotation}"</tt> + * + * <h3>Stacking handlers</h3> + * + * Some ErrorHandlers stack on top of others, adding useful functionality like + * automatic context description and prefixing. For example, + * ContextErrorHandler can be used to print messages like "In function + * 'xxx':". + * @code + * FileErrorHandler errh1(stderr); + * ContextErrorHandler errh2(&errh1, "While counting to 2:"); + * errh2.error("An error occurred."); + * errh2.error("Another error occurred."); + * // prints "While counting to 2:\n" + * // " An error occurred.\n" + * // " Another error occurred.\n" + * @endcode */ +class ErrorHandler { public: + + /** @brief Error level constants. + * + * Lower values represent more serious errors. Levels 0-7 correspond to + * Linux's error levels. Negative levels request immediate exit; at user + * level, the exit status is the absolute value of the + * error level. */ + enum Level { + el_abort = -999, ///< Error level that triggers abort(). + el_fatal = -1, ///< Fatal exit error level. + /// Exit status equals -(level). + el_emergency = 0, ///< Emergency error level: system is unusable. + el_alert = 1, ///< Alert error level: action must be taken. + el_critical = 2, ///< Error level for critical conditions. + el_error = 3, ///< Error level for normal error conditions. + el_warning = 4, ///< Error level for warning conditions. + el_notice = 5, ///< Error level for normal, but significant + /// conditions. + el_info = 6, ///< Error level for informational messages. + el_debug = 7 ///< Error level for debug messages. + }; + + /** @brief Error level indicators. */ + static const char e_abort[], + e_fatal[], + e_emergency[], + e_alert[], + e_critical[], + e_error[], + e_warning[], + e_warning_annotated[], + e_notice[], + e_info[], + e_debug[]; + + /** @brief Construct an ErrorHandler. */ + ErrorHandler() + : _nerrors(0) { + } + + virtual ~ErrorHandler() { + } + + + /** @brief Initialize the ErrorHandler implementation. + * @param errh default error handler + * @return @a errh + * + * Call this function to initialize the ErrorHandler implementation. The + * function installs the default conversions, creates the + * silent_handler(), and installs @a errh as the default error handler + * (see default_handler()). + * + * @note The @a errh object becomes the property of the ErrorHandler + * implementation and must not be deleted. + * (ErrorHandler::static_cleanup() will delete it.) Only the first call + * to static_initialize() has any effect. */ + static ErrorHandler *static_initialize(ErrorHandler *errh); + + /** @brief Tear down the ErrorHandler implementation. + * + * Deletes the internal ErrorHandlers and uninstalls default + * conversions. */ + static void static_cleanup(); + + + /** @brief Return the default ErrorHandler. + * @sa static_initialize() */ + static ErrorHandler *default_handler() { + return the_default_handler; + } + + /** @brief Set the default ErrorHandler to @a errh. + * @note @a errh becomes property of the ErrorHandler implementation, + * and will be freed by static_cleanup(). However, any prior default + * handler is @em not destroyed. Callers should delete the prior handler + * when necessary. */ + static void set_default_handler(ErrorHandler *errh); + + /** @brief Return the global silent ErrorHandler. */ + static ErrorHandler *silent_handler() { + return the_silent_handler; + } + + + static const int ok_result; ///< Equals 0, used for error levels + /// <5> and above + static const int error_result; ///< Equals -EINVAL, used for error + /// levels <4> and below + + + /** @brief Print a debug message (level el_debug). + * + * @a fmt and any following arguments are parsed as by format(), and the + * resulting string is passed to xmessage(). */ + void debug(const char *fmt, ...); + /** @brief Print an informational message (level el_info). */ + void message(const char *fmt, ...); + /** @brief Print a warning message (level el_warning). + * @return error_result + * + * The string "warning: " is prepended to every line of the message. */ + int warning(const char *fmt, ...); + /** @brief Print an error message (level el_error). + * @return error_result */ + int error(const char *fmt, ...); + /** @brief Print a fatal error message (level el_fatal). + * @return error_result + * + * In many ErrorHandlers, calling fatal() will cause the process to + * abort. */ + int fatal(const char *fmt, ...); + + /** @brief Print a debug message with a landmark annotation. */ + void ldebug(const String &landmark, const char *fmt, ...); + /** @brief Print an informational message with a landmark annotation. */ + void lmessage(const String &landmark, const char *fmt, ...); + /** @brief Print a warning message with a landmark annotation. */ + int lwarning(const String &landmark, const char *fmt, ...); + /** @brief Print an error message with a landmark annotation. */ + int lerror(const String &landmark, const char *fmt, ...); + /** @brief Print a fatal error message with a landmark annotation. */ + int lfatal(const String &landmark, const char *fmt, ...); + + + /** @brief Print an annotated error message. + * @return ok_result if the minimum error level was el_notice or higher, + * otherwise error_result + * + * This function drives the virtual functions actually responsible for + * error message decoration and printing. It passes @a str to decorate(), + * separates the result into lines, calls emit() for each line, and calls + * account() with the minimum error level of any line. + * + * Most users will call shorthand functions like error(), warning(), or + * lmessage(), which add relevant annotations to the message. */ + int xmessage(const String &str); + /** @brief Print an error message, adding annotations. + * @param anno annotations + * @param str error message + * + * Shorthand for xmessage(combine_anno(@a str, @a anno)). */ + int xmessage(const String &anno, const String &str) { + return xmessage(combine_anno(str, anno)); + } + /** @brief Format and print an error message, adding annotations. + * @param anno annotations + * @param fmt error message format + * @param val format arguments + * + * Shorthand for xmessage(@a anno, vformat(@a fmt, @a val)). */ + int vxmessage(const String &anno, const char *fmt, va_list val) { + return xmessage(anno, vformat(fmt, val)); + } + /** @brief Print an error message, adding landmark and other annotations. + * @param landmark landmark annotation + * @param anno additional annotations + * @param str error message + * + * Shorthand for xmessage(combine_anno(@a anno, make_landmark_anno(@a + * landmark)), @a str). */ + int xmessage(const String &landmark, const String &anno, + const String &str) { + return xmessage(combine_anno(anno, make_landmark_anno(landmark)), str); + } + /** @brief Format and print an error message, adding landmark and other + * annotations. + * @param landmark landmark annotation + * @param anno additional annotations + * @param fmt error message format + * @param val format arguments + * + * Shorthand for xmessage(@a landmark, @a anno, vformat(@a fmt, @a + * val)). */ + int vxmessage(const String &landmark, const String &anno, + const char *fmt, va_list val) { + return xmessage(landmark, anno, vformat(fmt, val)); + } + + + /** @brief Return the number of errors reported via this handler. + * + * An error is any message that contains at least one line with error + * level 3 (#el_error) or below. + * + * @note The error count will also contain errors reported via stacked + * handlers. For instance: + * @code + * SilentErrorHandler errh1; + * PrefixErrorHandler errh2(&errh1, ""); + * assert(errh1.nerrors() == 0); + * errh2.error("blah"); + * assert(errh1.nerrors() == 1); + * @endcode + * + * @sa account, clear */ + int nerrors() const { + return _nerrors; + } + + + /** @brief Format an error string. + * @param default_flags default ConversionFlags + * @param fmt printf-like format string + * @return formatted error string + * + * Formats an error string using printf-like % conversions. Conversions + * include: + * + * <table> + * + * <tr><td><tt>\%d</tt>, <tt>\%i</tt></td><td>Format an <tt>int</tt> as a + * decimal string. Understands flags in <tt>#0- +</tt>, field widths + * (including <tt>*</tt>), and precisions.</td></tr> + * + * <tr><td><tt>\%hd</tt>, <tt>\%ld</tt>, <tt>\%lld</tt>, + * <tt>\%zd</tt></td><td>Format a <tt>short</tt>, <tt>long</tt>, <tt>long + * long</tt>, or <tt>size_t</tt>.</td></tr> + * + * <tr><td><tt>\%^16d</tt>, <tt>\%^32d</tt>, <tt>\%^64d</tt></td> + * <td>Format a 16-, 32-, or 64-bit integer.</td></tr> + * + * <tr><td><tt>\%o</tt>, <tt>\%u</tt>, <tt>\%x</tt>, + * <tt>\%X</tt></td><td>Format an unsigned integer in octal, decimal, or + * hexadecimal (with lower-case or upper-case letters).</td></tr> + * + * <tr><td><tt>\%s</tt></td><td>Format a C string (<tt>const char *</tt>). + * The alternate form <tt>\%\#s</tt> calls String::printable() on the + * input string. Both <tt>\%\#s</tt> and the alternate form <tt>\%'s</tt> + * ensure that no part of the string is mistaken for an error + * annotation.</td></tr> + * + * <tr><td><tt>\%c</tt></td><td>Format a character. Prints a C-like + * escape if the input character isn't printable ASCII.</td></tr> + * + * <tr><td><tt>\%p</tt></td><td>Format a pointer as a hexadecimal + * value.</td></tr> + * + * <tr><td><tt>\%e</tt>, <tt>\%E</tt>, <tt>\%f</tt>, <tt>\%F</tt>, + * <tt>\%g</tt>, <tt>\%G</tt></td><td>Format a <tt>double</tt> (user-level + * only).</td></tr> + * + * <tr><td><tt>\%p{...}</tt><td>Call a user-provided conversion function. + * For example, <tt>\%p{ip_ptr}</tt> reads an <tt>IPAddress *</tt> argument + * from the argument list, and formats the pointed-to address using + * IPAddress::unparse().</td></tr> + * + * <tr><td><tt>\%\%</tt></td><td>Format a literal \% character.</td></tr> + * + * <tr><td><tt>\%\<</tt></td><td>Format a left quote string. Usually + * prints a single quote.</td></tr> + * + * <tr><td><tt>\%\></tt></td><td>Format a right quote string. Usually + * prints a single quote.</td></tr> + * + * <tr><td><tt>\%,</tt></td><td>Format an apostrophe string. Usually + * prints a single quote.</td></tr> + * + * </table> */ + static String xformat(int default_flags, const char *fmt, ...); + /** @overload */ + static String vxformat(int default_flags, const char *fmt, va_list val); + /** @overload */ + static String xformat(const char *fmt, ...); + /** @overload */ + static String vxformat(const char *fmt, va_list val) { + return vxformat(0, fmt, val); + } + + + /** @brief Format an error string. + * @param fmt format string + * @param val argument list + * + * @warning ErrorHandler users don't need to call this function directly; + * it is called implicitly by the error()/xmessage() functions. + * + * This virtual function is called to format an error message. The + * default implementation returns the result of vxformat(@a fmt, @a val). */ + virtual String vformat(const char *fmt, va_list val); + + /** @brief Format an error string. + * @param fmt format string + * + * @warning ErrorHandler users don't usually need to call this function + * directly. + * + * This is a convenience function that calls vformat(const char *fmt, + * va_list val) for a va_list taken from the ellipsis arguments. */ + String format(const char *fmt, ...); + + /** @brief Decorate an error message. + * @param str error message, possibly with annotations + * @return decorated error message + * + * @warning ErrorHandler users don't need to call this function directly; + * it is called implicitly by the error()/xmessage() functions. + * + * This virtual function is called to decorate an error message before it + * is emitted. The input @a str is an error message string, possibly + * annotated. The default implementation returns @a str unchanged. Other + * ErrorHandlers might add context lines (ContextErrorHandler), prefixes + * (PrefixErrorHandler), or a default landmark (LandmarkErrorHandler). */ + virtual String decorate(const String &str); + + /** @brief Output an error message line. + * @param str error message line, possibly with annotations + * @param user_data callback data, 0 for first line in a message + * @param more true iff this is the last line in the current message + * @return @a user_data to be passed to emit() for the next line + * + * @warning ErrorHandler users don't need to call this function directly; + * it is called implicitly by the error()/xmessage() functions. + * + * After calling decorate(), ErrorHandler splits the message into + * individual lines and calls emit() once per line. ErrorHandler + * subclasses should output the error lines as appropriate; for example, + * FileErrorHandler outputs the error message to a file. + * + * @a str does not contain a newline, but may contain annotations, + * including a landmark annotation. Most ErrorHandlers use parse_anno() + * to extract the landmark annotation, clean it with clean_landmark(), and + * print it ahead of the error message proper. + * + * ErrorHandler can handle multi-line error messages. However, the emit() + * function takes a line at a time; this is more useful in practice for + * most error message printers. The @a user_data and @a more arguments + * can help an ErrorHandler combine the lines of a multi-line error + * message. @a user_data is null for the first line; for second and + * subsequent lines, ErrorHandler passes the result of the last line's + * emit() call. @a more is true iff this is the last line in the current + * message. + * + * The default emit() implementation does nothing. */ + virtual void *emit(const String &str, void *user_data, bool more); + + /** @brief Account for an error message at level @a level. + * @param level minimum error level in the message + * + * @warning ErrorHandler users don't need to call this function directly; + * it is called implicitly by the error()/xmessage() functions. + * + * After calling emit() for the lines of an error message, ErrorHandler + * calls account(), passing the minimum (worst) error level of any message + * line (or 1000 if no line had a level). The default implementation + * updates the nerrors() counter. Some other ErrorHandlers + * add account() behavior that, for example, exits after printing messages + * at el_fatal level or below. */ + virtual void account(int level) { + if (level <= el_error) + ++_nerrors; + } + + /** @brief Clear accumulated error state. + * + * The default implementation sets the nerrors() counter to zero. */ + virtual void clear() { + _nerrors = 0; + } + + + /** @brief Create an error annotation. + * @param name annotation name + * @param value annotation value + * @return annotation string + * + * Returns an error annotation that associates annotation @a name with @a + * value. + * + * If @a name equals "<>", then returns a level annotation of the form + * "<@a value>". @a value must be valid number; if it isn't, the function + * returns the empty string. + * + * Otherwise, @a name must be a nonempty series of letters and digits. + * make_anno() returns a string of the form "{@a name:@a value}", where + * special characters in @a value are quoted with backslashes. */ + static String make_anno(const char *name, const String &value); + + /** @brief Apply annotations from @a anno to every line in @a str. + * @param str string + * @param anno annotation string + * + * The annotations from @a anno are applied to every line in @a str. New + * annotations do not override existing annotations with the same names. + * If the @a anno string ends with non-annotation characters, this + * substring is prefixed to every line in @a str. + * + * For example: + * @code + * combine_anno("Line 1\n{l:old}{x:x}Line 2\n", "<0>{l:new} ") + * // returns "<0>{l:new} Line 1\n<0>{l:old}{x:x} Line 2\n" + * @endcode */ + static String combine_anno(const String &str, const String &anno); + + /** @brief Parse error annotations from a string. + * @param str the string + * @param begin pointer within @a str to start of annotation area + * @param end pointer to end of error region, usually @a str.end() + * @return pointer to first character after annotation area + * @pre @a str.begin() <= {@a begin, @a end} <= @a str.end() + * @post @a begin <= returned value <= @a end + * + * Use this function to skip an error line's annotation area, possibly + * extracting named annotations. + * + * The variable arguments portion consists of a series of pairs of C + * strings and value pointers, terminated by a null character pointer. + * Each C string is an annotation name. The corresponding annotation + * value, if found, is stored as a String object in the value pointer. + * You can also store the <tt>int</tt> value of an annotation by prefixing + * an annotation name with the '#' character. + * + * For example: + * @code + * String line = "{l:file:30}<4.5>error message\n"; + * String landmark_str, level_str; + * const char *s = ErrorHandler::parse_anno(line, line.begin(), line.end(), + * "l", &landmark_str, "<>", &level_str, (const char *) 0); + * // Results: s points to "error message\n", + * // landmark_str == "file:30", level_str == "4.5" + * + * int level; + * s = ErrorHandler::parse_anno(line, line.begin(), line.end(), + * "#<>", &level, (const char *) 0); + * // Results: s points to "error message\n", level_str == 4 + * @endcode */ + static const char *parse_anno(const String &str, + const char *begin, const char *end, ...) ERRH_SENTINEL; + + /** @brief Skip a string's error annotations. + * @param begin pointer to start of string + * @param end pointer one past end of string + * @return pointer to first character after annotation area + * @post @a begin <= returned value <= @a end + * + * Use this function to skip an error line's annotation area. The error + * line is defined as a pair of iterators. */ + static const char *skip_anno(const char *begin, const char *end) { + String name, value; + const char *x = begin; + do { + x = skip_anno(String(), x, end, &name, &value, false); + } while (name); + return x; + } + + + /** @brief Return a landmark annotation equal to @a x. + * @param x landmark + * + * If @a x is empty, returns the empty string. Otherwise, if @a x looks + * like a formatted annotation (it starts with an open brace), returns @a + * x unchanged. Otherwise, returns make_anno("l", @a x). */ + static String make_landmark_anno(const String &x) { + if (x && x[0] == '{') + return x; + else if (x) + return make_anno("l", x); + else + return String(); + } + + /** @brief Clean the @a landmark. + * @param landmark landmark text + * @param colon if true, append <tt>": "</tt> to a nonempty landmark + * + * Removes trailing space and an optional trailing colon from @a landmark + * and returns the result. If @a colon is true, and the cleaned landmark + * isn't the empty string, then appends <tt>": "</tt> to the result. */ + static String clean_landmark(const String &landmark, bool colon = false); + + + // error conversions + struct Conversion; + typedef String (*ConversionFunction)(int flags, VA_LIST_REF_T); + enum ConversionFlags { + cf_zero_pad = 1, ///< Set for conversions using the '0' flag. + cf_plus_positive = 2, ///< Set for conversions using the '+' flag. + cf_space_positive = 4, ///< Set for conversions using the ' ' flag. + cf_left_just = 8, ///< Set for conversions using the '-' flag. + cf_alternate_form = 16, ///< Set for conversions using the '#' flag. + cf_singlequote = 32, ///< Set for conversions using the '\'' flag. + cf_uppercase = 64, ///< Set for 'X' conversions (not 'x'). + cf_signed = 128, ///< Set for conversions of signed numbers. + cf_negative = 256, ///< Set for conversions of negative numbers. + cf_utf8 = 1024 ///< Set to use UTF-8 characters on output. + }; + static Conversion *add_conversion(const String &name, ConversionFunction func); + static int remove_conversion(Conversion *conversion); + + private: + + int _nerrors; + + static ErrorHandler *the_default_handler; + static ErrorHandler *the_silent_handler; + + static const char *skip_anno(const String &str, + const char *begin, const char *end, + String *name_result, String *value_result, + bool raw); + +}; + + +/** @class SilentErrorHandler + * @brief An ErrorHandler that does not report messages. + * + * Use SilentErrorHandler when an ErrorHandler object is required, but error + * messages should not be printed. */ +class SilentErrorHandler : public ErrorHandler { public: + + SilentErrorHandler() { + } + +}; + + +/** @class ErrorVeneer + * @brief Base class for ErrorHandlers that forward messages. + * + * ErrorHandlers can stack. Stacking ErrorHandlers simplify modify a message + * and then pass the result to a base ErrorHandler, which does the actual + * printing. The ErrorVeneer base class simplifies the implementation of + * stacking ErrorHandlers. It provides versions of ErrorHandler's format(), + * decorate(), emit(), and account() methods that forward to the underlying + * handler. Note that the clear() method is <em>not</em> automatically + * forwarded. */ +class ErrorVeneer : public ErrorHandler { public: + + /** @brief Construct an ErrorVeneer. + * @param errh base ErrorHandler + * + * If @a errh is 0, then the ErrorVeneer acts like a + * SilentErrorHandler. */ + ErrorVeneer(ErrorHandler *errh) + : _errh(errh) { + } + + String vformat(const char *fmt, va_list val); + String decorate(const String &str); + void *emit(const String &str, void *user_data, bool more); + void account(int level); + + private: + + ErrorHandler *_errh; + +}; + + +#ifndef __KERNEL__ +/** @class FileErrorHandler + * @brief An ErrorHandler that prints error messages to a given file. + * + * FileErrorHandler is the typical base ErrorHandler used at user level. It + * prints messages to a file passed in to the constructor, and calls exit() or + * abort() based on the error level. */ +class FileErrorHandler : public ErrorHandler { public: + + /** @brief Construct a FileErrorHandler. + * @param f file to print errors + * @param prefix string to prefix every error line */ + FileErrorHandler(FILE *f, const String &prefix = String()); + + void set_default_flags(int default_flags) { + _default_flags = default_flags; + } + + String vformat(const char *fmt, va_list val); + void *emit(const String &str, void *user_data, bool more); + void account(int level); + + private: + + FILE *_f; + String _context; + int _default_flags; + +}; +#endif + + +/** @class LocalErrorHandler + * @brief A convenience stackable ErrorHandler. + * + * It's often convenient to pass a null ErrorHandler pointer when errors + * should not be printed. The LocalErrorHandler class simplifies dealing with + * ErrorHandler pointers that may or may not be null. LocalErrorHandler is a + * transparent layer on the base handler; but if the base handler is null, it + * acts like a SilentErrorHandler. For example: + * @code + * void f(ErrorHandler *errh) { // errh might or might not be null + * LocalErrorHandler lerrh(errh); + * ... lerrh.message("message") ... + * } + * @endcode */ +class LocalErrorHandler : public ErrorVeneer { public: + + /** @brief Construct a LocalErrorHandler. */ + LocalErrorHandler(ErrorHandler *errh) + : ErrorVeneer(errh) { + } + +}; + + +/** @class ContextErrorHandler + * @brief A stackable ErrorHandler that prints context lines. + * + * The stackable ContextErrorHandler adds context to the first error + * message printed, and optionally indent error messages so that they appear + * grouped underneath the context. + * @code + * FileErrorHandler errh1(stderr); + * ContextErrorHandler errh2(&errh1, "While counting to 2:"); + * errh2.error("An error occurred."); + * errh2.error("Another error occurred."); + * // prints "While counting to 2:\n" + * // " An error occurred.\n" + * // " Another error occurred.\n" + * @endcode + * + * To prevent ContextErrorHandler from indenting or printing context for a + * message, add a "{context:no}" annotation to the message's first line. To + * turn off the indent but keep the context, add a "{context:noindent}" + * annotation. + * @code + * FileErrorHandler errh1(stderr); + * ContextErrorHandler errh2(&errh1, "While counting to 2:"); + * errh2.error("{context:no}An error occurred."); + * errh2.error("Another error occurred."); + * // prints "An error occurred.\n" + * // "While counting to 2:\n" + * // " Another error occurred.\n" + * + * FileErrorHandler errh1(stderr); + * PrefixErrorHandler noctx_errh(stderr, "{context:no}"); + * ContextErrorHandler errh2(&errh1, "While counting to 2:"); + * errh2.error("An error occurred."); + * errh2.error("Another error occurred."); + * // prints "An error occurred.\n" + * // "Another error occurred.\n" + * @endcode + * + * ContextErrorHandler adds the "{context:context}" annotation to context + * lines. */ +class ContextErrorHandler : public ErrorVeneer { public: + + /** @brief Construct a ContextErrorHandler. + * @param errh base ErrorHandler + * @param fmt format for context lines + * + * The context message is formed by @a errh->format() using @a fmt and + * any additional arguments. */ + ContextErrorHandler(ErrorHandler *errh, const char *fmt, ...); + + /** @brief Return true iff the context has already been printed. */ + bool context_printed() const { + return _context_printed; + } + + /** @brief Set whether the context has been printed. */ + void set_context_printed(bool x) { + _context_printed = x; + } + + /** @brief Set the context string to @a str. */ + void set_context(const String &str) { + _context = str; + } + + /** @brief Set the indent string to @a str. + * + * The indent string is prepended to all non-context messages. It can + * contain landmarks as well as non-landmark text. The default indent + * string is " " (two spaces). */ + void set_indent(const String &str) { + _indent = str; + } + + /** @brief Set the context landmark to @a str. + * + * The context landmark is used to decorate the context, and also applied + * to any error messages that lack landmarks of their own. The default + * context landmark is empty. + * + * @note The input @a str is passed to + * ErrorHandler::make_landmark_anno(). */ + void set_context_landmark(const String &str) { + _context_landmark = make_landmark_anno(str); + } + + String decorate(const String &str); + + private: + + String _context; + String _indent; + String _context_landmark; + bool _context_printed; + +}; + + +/** @class PrefixErrorHandler + * @brief A stackable ErrorHandler that adds a prefix to error messages. + * + * The stackable ContextErrorHandler adds a prefix to every error line + * printed. For example: + * @code + * FileErrorHandler errh1(stderr); + * PrefixErrorHandler errh2(&errh1, "Blah--"); + * errh2.error("An error occurred."); + * errh2.error("Another error occurred."); + * // prints "Blah--An error occurred.\n" + * // "Blah--Another error occurred.\n" + * @endcode */ +class PrefixErrorHandler : public ErrorVeneer { public: + + /** @brief Construct a PrefixErrorHandler. + * @param errh base ErrorHandler + * @param prefix string to prefix to error lines */ + PrefixErrorHandler(ErrorHandler *errh, const String &prefix); + + String decorate(const String &str); + + private: + + String _prefix; + +}; + + +/** @class LandmarkErrorHandler + * @brief A stackable ErrorHandler that adds a default landmark to error + * messages. + * + * The stackable ContextErrorHandler adds a default landmark to every error + * line printed. Error lines' own landmarks are preserved when they exist. + * For example: + * @code + * FileErrorHandler errh1(stderr); + * LandmarkErrorHandler errh2(&errh1, "file:1"); + * errh2.error("An error occurred."); + * errh2.lerror("file:2", "Another error occurred."); + * // prints "file:1: An error occurred.\n" + * // "file:2: Another error occurred.\n" + * @endcode */ +class LandmarkErrorHandler : public ErrorVeneer { public: + + /** @brief Construct a LandmarkErrorHandler. + * @param errh base ErrorHandler + * @param landmark default landmark */ + LandmarkErrorHandler(ErrorHandler *errh, const String &landmark); + + /** @brief Set the default landmark applied to error messages. */ + void set_landmark(const String &landmark) { + _landmark = make_landmark_anno(landmark); + } + + String decorate(const String &str); + + private: + + String _landmark; + +}; + + +#ifndef __KERNEL__ +/** @class BailErrorHandler + * @brief A stackable ErrorHandler that exits when errors occur. + * + * The stackable BailErrorHandler, available only at user level, causes the + * process to exit if an error worse than a configurable level occurs. */ +class BailErrorHandler : public ErrorVeneer { public: + + /** @brief Construct a BailErrorHandler. + * @param errh base ErrorHandler + * @param level error level that causes premature exit + * + * An error message with level less than or equal to @a el_error will + * cause the process to exit with status 1. */ + BailErrorHandler(ErrorHandler *errh, int level = el_error); + + void account(int level); + + private: + + int _level; + +}; +#endif + +#undef ERRH_SENTINEL +#endif |