888 lines
32 KiB
C++
888 lines
32 KiB
C++
// -*- related-file-name: "../../lib/error.cc" -*-
|
|
#ifndef CLICK_ERROR_HH
|
|
#define CLICK_ERROR_HH
|
|
#include <click/string.hh>
|
|
#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL) || defined(CLICK_MINIOS)
|
|
# include <stdio.h>
|
|
#endif
|
|
#if CLICK_BSDMODULE
|
|
# include <machine/stdarg.h>
|
|
#else
|
|
# include <stdarg.h>
|
|
#endif
|
|
|
|
#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
|
|
CLICK_DECLS
|
|
|
|
/** @class ErrorHandler
|
|
* @brief Error reporting class.
|
|
*
|
|
* Click elements 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>
|
|
*
|
|
* Click's 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 Click process's 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 Click 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 xmessage(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 xmessage(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;
|
|
|
|
};
|
|
|
|
|
|
#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL) || defined(CLICK_MINIOS)
|
|
/** @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;
|
|
|
|
};
|
|
|
|
|
|
#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL) || defined(CLICK_MINIOS)
|
|
/** @class BailErrorHandler
|
|
* @brief A stackable ErrorHandler that exits when errors occur.
|
|
*
|
|
* The stackable BailErrorHandler, available only at user level, causes the
|
|
* Click 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
|
|
CLICK_ENDDECLS
|
|
#endif
|