1 // -*- related-file-name: "../../liblcdf/error.cc" -*-
2 #ifndef LCDF_ERROR_HH
3 #define LCDF_ERROR_HH
4 #include <lcdf/string.hh>
5 #ifndef __KERNEL__
6 # include <stdio.h>
7 #endif
8 #include <stdarg.h>
9 #if HAVE_ADDRESSABLE_VA_LIST
10 # define VA_LIST_REF_T		va_list *
11 # define VA_LIST_DEREF(val)	(*(val))
12 # define VA_LIST_REF(val)	(&(val))
13 #else
14 # define VA_LIST_REF_T		va_list
15 # define VA_LIST_DEREF(val)	(val)
16 # define VA_LIST_REF(val)	(val)
17 #endif
18 #if __GNUC__ <= 3
19 # define ERRH_SENTINEL
20 #else
21 # define ERRH_SENTINEL __attribute__((sentinel))
22 #endif
23 
24 /** @class ErrorHandler
25  * @brief Error reporting class.
26  *
27  * Report errors through ErrorHandler objects, which represent
28  * error collectors and printers.  ErrorHandlers are passed to configure() and
29  * initialize() methods explicitly, as well as to write handlers; the
30  * click_chatter() function calls ErrorHandler implicitly.
31  *
32  * <h3>Cooked error messages</h3>
33  *
34  * Most ErrorHandler interactions consist of a simple call like this:
35  * @code
36  * errh->error("not enough arguments (%d needed)", 5);
37  *     // prints something like "not enough arguments (5 needed)\n"
38  * @endcode
39  *
40  * This function constructs an error message string from the format arguments,
41  * annotates the string with a default error level (here, el_error), and
42  * prints it.  Alternate versions take a landmark specifying where the error
43  * took place:
44  * @code
45  * errh->lwarning("file.click:2", "syntax error at '%s'", word.c_str());
46  *     // prints something like "file.click:2: syntax error at 'foo'\n"
47  * @endcode
48  *
49  * <h3>Raw error messages</h3>
50  *
51  * For finer control over error levels and annotations, construct an error
52  * message string directly.  An error message is a string consisting of one or
53  * more lines.  Each line begins with a set of optional textual @em
54  * annotations.  The following error message has a @em level annotation
55  * determining how serious the error is (this one is critical, since
56  * el_critical == 2), and a @em landmark annotation, which specifies where the
57  * error took place (here, "x.click:1"):
58  *
59  * <tt>"<2>{l:x.click:1}syntax error"</tt>
60  *
61  * The default ErrorHandlers understand the level and landmark
62  * annotations.  Users can add other arbitrary annotations, which can be
63  * useful to pass error metadata.  A pair of braces ends the annotation area.
64  * This example has one user annotation <tt>eoc</tt>, and a message area that
65  * would be mistaken for an annotation were it not for the <tt>{}</tt>:
66  *
67  * <tt>"<2>{l:x.click:1}{eoc:520}{}{not:an annotation}"</tt>
68  *
69  * <h3>Stacking handlers</h3>
70  *
71  * Some ErrorHandlers stack on top of others, adding useful functionality like
72  * automatic context description and prefixing.  For example,
73  * ContextErrorHandler can be used to print messages like "In function
74  * 'xxx':".
75  * @code
76  * FileErrorHandler errh1(stderr);
77  * ContextErrorHandler errh2(&errh1, "While counting to 2:");
78  * errh2.error("An error occurred.");
79  * errh2.error("Another error occurred.");
80  *     // prints "While counting to 2:\n"
81  *     //        "  An error occurred.\n"
82  *     //        "  Another error occurred.\n"
83  * @endcode */
84 class ErrorHandler { public:
85 
86     /** @brief Error level constants.
87      *
88      * Lower values represent more serious errors.  Levels 0-7 correspond to
89      * Linux's error levels.  Negative levels request immediate exit; at user
90      * level, the exit status is the absolute value of the
91      * error level. */
92     enum Level {
93 	el_abort = -999,	///< Error level that triggers abort().
94 	el_fatal = -1,		///< Fatal exit error level.
95 				///  Exit status equals -(level).
96 	el_emergency = 0,	///< Emergency error level: system is unusable.
97 	el_alert = 1,		///< Alert error level: action must be taken.
98 	el_critical = 2,	///< Error level for critical conditions.
99 	el_error = 3,		///< Error level for normal error conditions.
100 	el_warning = 4,		///< Error level for warning conditions.
101 	el_notice = 5,		///< Error level for normal, but significant
102 				///  conditions.
103 	el_info = 6,		///< Error level for informational messages.
104 	el_debug = 7		///< Error level for debug messages.
105     };
106 
107     /** @brief Error level indicators. */
108     static const char e_abort[],
109 	e_fatal[],
110 	e_emergency[],
111 	e_alert[],
112 	e_critical[],
113 	e_error[],
114 	e_warning[],
115 	e_warning_annotated[],
116 	e_notice[],
117 	e_info[],
118 	e_debug[];
119 
120     /** @brief Construct an ErrorHandler. */
ErrorHandler()121     ErrorHandler()
122 	: _nerrors(0) {
123     }
124 
~ErrorHandler()125     virtual ~ErrorHandler() {
126     }
127 
128 
129     /** @brief Initialize the ErrorHandler implementation.
130      * @param errh default error handler
131      * @return @a errh
132      *
133      * Call this function to initialize the ErrorHandler implementation.  The
134      * function installs the default conversions, creates the
135      * silent_handler(), and installs @a errh as the default error handler
136      * (see default_handler()).
137      *
138      * @note The @a errh object becomes the property of the ErrorHandler
139      * implementation and must not be deleted.
140      * (ErrorHandler::static_cleanup() will delete it.)  Only the first call
141      * to static_initialize() has any effect. */
142     static ErrorHandler *static_initialize(ErrorHandler *errh);
143 
144     /** @brief Tear down the ErrorHandler implementation.
145      *
146      * Deletes the internal ErrorHandlers and uninstalls default
147      * conversions. */
148     static void static_cleanup();
149 
150 
151     /** @brief Return the default ErrorHandler.
152      * @sa static_initialize() */
default_handler()153     static ErrorHandler *default_handler() {
154 	return the_default_handler;
155     }
156 
157     /** @brief Set the default ErrorHandler to @a errh.
158      * @note @a errh becomes property of the ErrorHandler implementation,
159      * and will be freed by static_cleanup().  However, any prior default
160      * handler is @em not destroyed.  Callers should delete the prior handler
161      * when necessary. */
162     static void set_default_handler(ErrorHandler *errh);
163 
164     /** @brief Return the global silent ErrorHandler. */
silent_handler()165     static ErrorHandler *silent_handler() {
166 	return the_silent_handler;
167     }
168 
169 
170     static const int ok_result;		///< Equals 0, used for error levels
171 					///  <5> and above
172     static const int error_result;	///< Equals -EINVAL, used for error
173 					///  levels <4> and below
174 
175 
176     /** @brief Print a debug message (level el_debug).
177      *
178      * @a fmt and any following arguments are parsed as by format(), and the
179      * resulting string is passed to xmessage(). */
180     void debug(const char *fmt, ...);
181     /** @brief Print an informational message (level el_info). */
182     void message(const char *fmt, ...);
183     /** @brief Print a warning message (level el_warning).
184      * @return error_result
185      *
186      * The string "warning: " is prepended to every line of the message. */
187     int warning(const char *fmt, ...);
188     /** @brief Print an error message (level el_error).
189      * @return error_result */
190     int error(const char *fmt, ...);
191     /** @brief Print a fatal error message (level el_fatal).
192      * @return error_result
193      *
194      * In many ErrorHandlers, calling fatal() will cause the process to
195      * abort. */
196     int fatal(const char *fmt, ...);
197 
198     /** @brief Print a debug message with a landmark annotation. */
199     void ldebug(const String &landmark, const char *fmt, ...);
200     /** @brief Print an informational message with a landmark annotation. */
201     void lmessage(const String &landmark, const char *fmt, ...);
202     /** @brief Print a warning message with a landmark annotation. */
203     int lwarning(const String &landmark, const char *fmt, ...);
204     /** @brief Print an error message with a landmark annotation. */
205     int lerror(const String &landmark, const char *fmt, ...);
206     /** @brief Print a fatal error message with a landmark annotation. */
207     int lfatal(const String &landmark, const char *fmt, ...);
208 
209 
210     /** @brief Print an annotated error message.
211      * @return ok_result if the minimum error level was el_notice or higher,
212      * otherwise error_result
213      *
214      * This function drives the virtual functions actually responsible for
215      * error message decoration and printing.  It passes @a str to decorate(),
216      * separates the result into lines, calls emit() for each line, and calls
217      * account() with the minimum error level of any line.
218      *
219      * Most users will call shorthand functions like error(), warning(), or
220      * lmessage(), which add relevant annotations to the message. */
221     int xmessage(const String &str);
222     /** @brief Print an error message, adding annotations.
223      * @param anno annotations
224      * @param str error message
225      *
226      * Shorthand for xmessage(combine_anno(@a str, @a anno)). */
xmessage(const String & anno,const String & str)227     int xmessage(const String &anno, const String &str) {
228 	return xmessage(combine_anno(str, anno));
229     }
230     /** @brief Format and print an error message, adding annotations.
231      * @param anno annotations
232      * @param fmt error message format
233      * @param val format arguments
234      *
235      * Shorthand for xmessage(@a anno, vformat(@a fmt, @a val)). */
vxmessage(const String & anno,const char * fmt,va_list val)236     int vxmessage(const String &anno, const char *fmt, va_list val) {
237 	return xmessage(anno, vformat(fmt, val));
238     }
239     /** @brief Print an error message, adding landmark and other annotations.
240      * @param landmark landmark annotation
241      * @param anno additional annotations
242      * @param str error message
243      *
244      * Shorthand for xmessage(combine_anno(@a anno, make_landmark_anno(@a
245      * landmark)), @a str). */
xmessage(const String & landmark,const String & anno,const String & str)246     int xmessage(const String &landmark, const String &anno,
247 		 const String &str) {
248 	return xmessage(combine_anno(anno, make_landmark_anno(landmark)), str);
249     }
250     /** @brief Format and print an error message, adding landmark and other
251      * annotations.
252      * @param landmark landmark annotation
253      * @param anno additional annotations
254      * @param fmt error message format
255      * @param val format arguments
256      *
257      * Shorthand for xmessage(@a landmark, @a anno, vformat(@a fmt, @a
258      * val)). */
vxmessage(const String & landmark,const String & anno,const char * fmt,va_list val)259     int vxmessage(const String &landmark, const String &anno,
260 		  const char *fmt, va_list val) {
261 	return xmessage(landmark, anno, vformat(fmt, val));
262     }
263 
264 
265     /** @brief Return the number of errors reported via this handler.
266      *
267      * An error is any message that contains at least one line with error
268      * level 3 (#el_error) or below.
269      *
270      * @note The error count will also contain errors reported via stacked
271      * handlers.  For instance:
272      * @code
273      * SilentErrorHandler errh1;
274      * PrefixErrorHandler errh2(&errh1, "");
275      * assert(errh1.nerrors() == 0);
276      * errh2.error("blah");
277      * assert(errh1.nerrors() == 1);
278      * @endcode
279      *
280      * @sa account, clear */
nerrors() const281     int nerrors() const {
282 	return _nerrors;
283     }
284 
285 
286     /** @brief Format an error string.
287      * @param default_flags default ConversionFlags
288      * @param fmt printf-like format string
289      * @return formatted error string
290      *
291      * Formats an error string using printf-like % conversions.  Conversions
292      * include:
293      *
294      * <table>
295      *
296      * <tr><td><tt>\%d</tt>, <tt>\%i</tt></td><td>Format an <tt>int</tt> as a
297      * decimal string.  Understands flags in <tt>#0- +</tt>, field widths
298      * (including <tt>*</tt>), and precisions.</td></tr>
299      *
300      * <tr><td><tt>\%hd</tt>, <tt>\%ld</tt>, <tt>\%lld</tt>,
301      * <tt>\%zd</tt></td><td>Format a <tt>short</tt>, <tt>long</tt>, <tt>long
302      * long</tt>, or <tt>size_t</tt>.</td></tr>
303      *
304      * <tr><td><tt>\%^16d</tt>, <tt>\%^32d</tt>, <tt>\%^64d</tt></td>
305      * <td>Format a 16-, 32-, or 64-bit integer.</td></tr>
306      *
307      * <tr><td><tt>\%o</tt>, <tt>\%u</tt>, <tt>\%x</tt>,
308      * <tt>\%X</tt></td><td>Format an unsigned integer in octal, decimal, or
309      * hexadecimal (with lower-case or upper-case letters).</td></tr>
310      *
311      * <tr><td><tt>\%s</tt></td><td>Format a C string (<tt>const char *</tt>).
312      * The alternate form <tt>\%\#s</tt> calls String::printable() on the
313      * input string.  Both <tt>\%\#s</tt> and the alternate form <tt>\%'s</tt>
314      * ensure that no part of the string is mistaken for an error
315      * annotation.</td></tr>
316      *
317      * <tr><td><tt>\%c</tt></td><td>Format a character.  Prints a C-like
318      * escape if the input character isn't printable ASCII.</td></tr>
319      *
320      * <tr><td><tt>\%p</tt></td><td>Format a pointer as a hexadecimal
321      * value.</td></tr>
322      *
323      * <tr><td><tt>\%e</tt>, <tt>\%E</tt>, <tt>\%f</tt>, <tt>\%F</tt>,
324      * <tt>\%g</tt>, <tt>\%G</tt></td><td>Format a <tt>double</tt> (user-level
325      * only).</td></tr>
326      *
327      * <tr><td><tt>\%p{...}</tt><td>Call a user-provided conversion function.
328      * For example, <tt>\%p{ip_ptr}</tt> reads an <tt>IPAddress *</tt> argument
329      * from the argument list, and formats the pointed-to address using
330      * IPAddress::unparse().</td></tr>
331      *
332      * <tr><td><tt>\%\%</tt></td><td>Format a literal \% character.</td></tr>
333      *
334      * <tr><td><tt>\%\<</tt></td><td>Format a left quote string.  Usually
335      * prints a single quote.</td></tr>
336      *
337      * <tr><td><tt>\%\></tt></td><td>Format a right quote string.  Usually
338      * prints a single quote.</td></tr>
339      *
340      * <tr><td><tt>\%,</tt></td><td>Format an apostrophe string.  Usually
341      * prints a single quote.</td></tr>
342      *
343      * </table> */
344     static String xformat(int default_flags, const char *fmt, ...);
345     /** @overload */
346     static String vxformat(int default_flags, const char *fmt, va_list val);
347     /** @overload */
348     static String xformat(const char *fmt, ...);
349     /** @overload */
vxformat(const char * fmt,va_list val)350     static String vxformat(const char *fmt, va_list val) {
351 	return vxformat(0, fmt, val);
352     }
353 
354 
355     /** @brief Format an error string.
356      * @param fmt format string
357      * @param val argument list
358      *
359      * @warning ErrorHandler users don't need to call this function directly;
360      * it is called implicitly by the error()/xmessage() functions.
361      *
362      * This virtual function is called to format an error message.  The
363      * default implementation returns the result of vxformat(@a fmt, @a val). */
364     virtual String vformat(const char *fmt, va_list val);
365 
366     /** @brief Format an error string.
367      * @param fmt format string
368      *
369      * @warning ErrorHandler users don't usually need to call this function
370      * directly.
371      *
372      * This is a convenience function that calls vformat(const char *fmt,
373      * va_list val) for a va_list taken from the ellipsis arguments. */
374     String format(const char *fmt, ...);
375 
376     /** @brief Decorate an error message.
377      * @param str error message, possibly with annotations
378      * @return decorated error message
379      *
380      * @warning ErrorHandler users don't need to call this function directly;
381      * it is called implicitly by the error()/xmessage() functions.
382      *
383      * This virtual function is called to decorate an error message before it
384      * is emitted.  The input @a str is an error message string, possibly
385      * annotated.  The default implementation returns @a str unchanged.  Other
386      * ErrorHandlers might add context lines (ContextErrorHandler), prefixes
387      * (PrefixErrorHandler), or a default landmark (LandmarkErrorHandler). */
388     virtual String decorate(const String &str);
389 
390     /** @brief Output an error message line.
391      * @param str error message line, possibly with annotations
392      * @param user_data callback data, 0 for first line in a message
393      * @param more true iff this is the last line in the current message
394      * @return @a user_data to be passed to emit() for the next line
395      *
396      * @warning ErrorHandler users don't need to call this function directly;
397      * it is called implicitly by the error()/xmessage() functions.
398      *
399      * After calling decorate(), ErrorHandler splits the message into
400      * individual lines and calls emit() once per line.  ErrorHandler
401      * subclasses should output the error lines as appropriate; for example,
402      * FileErrorHandler outputs the error message to a file.
403      *
404      * @a str does not contain a newline, but may contain annotations,
405      * including a landmark annotation.  Most ErrorHandlers use parse_anno()
406      * to extract the landmark annotation, clean it with clean_landmark(), and
407      * print it ahead of the error message proper.
408      *
409      * ErrorHandler can handle multi-line error messages.  However, the emit()
410      * function takes a line at a time; this is more useful in practice for
411      * most error message printers.  The @a user_data and @a more arguments
412      * can help an ErrorHandler combine the lines of a multi-line error
413      * message.  @a user_data is null for the first line; for second and
414      * subsequent lines, ErrorHandler passes the result of the last line's
415      * emit() call.  @a more is true iff this is the last line in the current
416      * message.
417      *
418      * The default emit() implementation does nothing. */
419     virtual void *emit(const String &str, void *user_data, bool more);
420 
421     /** @brief Account for an error message at level @a level.
422      * @param level minimum error level in the message
423      *
424      * @warning ErrorHandler users don't need to call this function directly;
425      * it is called implicitly by the error()/xmessage() functions.
426      *
427      * After calling emit() for the lines of an error message, ErrorHandler
428      * calls account(), passing the minimum (worst) error level of any message
429      * line (or 1000 if no line had a level).  The default implementation
430      * updates the nerrors() counter.  Some other ErrorHandlers
431      * add account() behavior that, for example, exits after printing messages
432      * at el_fatal level or below. */
account(int level)433     virtual void account(int level) {
434 	if (level <= el_error)
435 	    ++_nerrors;
436     }
437 
438     /** @brief Clear accumulated error state.
439      *
440      * The default implementation sets the nerrors() counter to zero. */
clear()441     virtual void clear() {
442 	_nerrors = 0;
443     }
444 
445 
446     /** @brief Create an error annotation.
447      * @param name annotation name
448      * @param value annotation value
449      * @return annotation string
450      *
451      * Returns an error annotation that associates annotation @a name with @a
452      * value.
453      *
454      * If @a name equals "<>", then returns a level annotation of the form
455      * "<@a value>".  @a value must be valid number; if it isn't, the function
456      * returns the empty string.
457      *
458      * Otherwise, @a name must be a nonempty series of letters and digits.
459      * make_anno() returns a string of the form "{@a name:@a value}", where
460      * special characters in @a value are quoted with backslashes. */
461     static String make_anno(const char *name, const String &value);
462 
463     /** @brief Apply annotations from @a anno to every line in @a str.
464      * @param str string
465      * @param anno annotation string
466      *
467      * The annotations from @a anno are applied to every line in @a str.  New
468      * annotations do not override existing annotations with the same names.
469      * If the @a anno string ends with non-annotation characters, this
470      * substring is prefixed to every line in @a str.
471      *
472      * For example:
473      * @code
474      * combine_anno("Line 1\n{l:old}{x:x}Line 2\n", "<0>{l:new}  ")
475      *    // returns "<0>{l:new}  Line 1\n<0>{l:old}{x:x}  Line 2\n"
476      * @endcode */
477     static String combine_anno(const String &str, const String &anno);
478 
479     /** @brief Parse error annotations from a string.
480      * @param str the string
481      * @param begin pointer within @a str to start of annotation area
482      * @param end pointer to end of error region, usually @a str.end()
483      * @return pointer to first character after annotation area
484      * @pre @a str.begin() <= {@a begin, @a end} <= @a str.end()
485      * @post @a begin <= returned value <= @a end
486      *
487      * Use this function to skip an error line's annotation area, possibly
488      * extracting named annotations.
489      *
490      * The variable arguments portion consists of a series of pairs of C
491      * strings and value pointers, terminated by a null character pointer.
492      * Each C string is an annotation name.  The corresponding annotation
493      * value, if found, is stored as a String object in the value pointer.
494      * You can also store the <tt>int</tt> value of an annotation by prefixing
495      * an annotation name with the '#' character.
496      *
497      * For example:
498      * @code
499      * String line = "{l:file:30}<4.5>error message\n";
500      * String landmark_str, level_str;
501      * const char *s = ErrorHandler::parse_anno(line, line.begin(), line.end(),
502      *            "l", &landmark_str, "<>", &level_str, (const char *) 0);
503      *     // Results: s points to "error message\n",
504      *     // landmark_str == "file:30", level_str == "4.5"
505      *
506      * int level;
507      * s = ErrorHandler::parse_anno(line, line.begin(), line.end(),
508      *            "#<>", &level, (const char *) 0);
509      *     // Results: s points to "error message\n", level_str == 4
510      * @endcode */
511     static const char *parse_anno(const String &str,
512 		const char *begin, const char *end, ...) ERRH_SENTINEL;
513 
514     /** @brief Skip a string's error annotations.
515      * @param begin pointer to start of string
516      * @param end pointer one past end of string
517      * @return pointer to first character after annotation area
518      * @post @a begin <= returned value <= @a end
519      *
520      * Use this function to skip an error line's annotation area.  The error
521      * line is defined as a pair of iterators. */
skip_anno(const char * begin,const char * end)522     static const char *skip_anno(const char *begin, const char *end) {
523 	String name, value;
524 	const char *x = begin;
525 	do {
526 	    x = skip_anno(String(), x, end, &name, &value, false);
527 	} while (name);
528 	return x;
529     }
530 
531 
532     /** @brief Return a landmark annotation equal to @a x.
533      * @param x landmark
534      *
535      * If @a x is empty, returns the empty string.  Otherwise, if @a x looks
536      * like a formatted annotation (it starts with an open brace), returns @a
537      * x unchanged.  Otherwise, returns make_anno("l", @a x). */
make_landmark_anno(const String & x)538     static String make_landmark_anno(const String &x) {
539 	if (x && x[0] == '{')
540 	    return x;
541 	else if (x)
542 	    return make_anno("l", x);
543 	else
544 	    return String();
545     }
546 
547     /** @brief Clean the @a landmark.
548      * @param landmark landmark text
549      * @param colon if true, append <tt>": "</tt> to a nonempty landmark
550      *
551      * Removes trailing space and an optional trailing colon from @a landmark
552      * and returns the result.  If @a colon is true, and the cleaned landmark
553      * isn't the empty string, then appends <tt>": "</tt> to the result. */
554     static String clean_landmark(const String &landmark, bool colon = false);
555 
556 
557     // error conversions
558     struct Conversion;
559     typedef String (*ConversionFunction)(int flags, VA_LIST_REF_T);
560     enum ConversionFlags {
561 	cf_zero_pad = 1,	///< Set for conversions using the '0' flag.
562 	cf_plus_positive = 2,	///< Set for conversions using the '+' flag.
563 	cf_space_positive = 4,	///< Set for conversions using the ' ' flag.
564 	cf_left_just = 8,	///< Set for conversions using the '-' flag.
565 	cf_alternate_form = 16,	///< Set for conversions using the '#' flag.
566 	cf_singlequote = 32,	///< Set for conversions using the '\'' flag.
567 	cf_uppercase = 64,	///< Set for 'X' conversions (not 'x').
568 	cf_signed = 128,	///< Set for conversions of signed numbers.
569 	cf_negative = 256,	///< Set for conversions of negative numbers.
570 	cf_utf8 = 1024		///< Set to use UTF-8 characters on output.
571     };
572     static Conversion *add_conversion(const String &name, ConversionFunction func);
573     static int remove_conversion(Conversion *conversion);
574 
575   private:
576 
577     int _nerrors;
578 
579     static ErrorHandler *the_default_handler;
580     static ErrorHandler *the_silent_handler;
581 
582     static const char *skip_anno(const String &str,
583 				 const char *begin, const char *end,
584 				 String *name_result, String *value_result,
585 				 bool raw);
586 
587 };
588 
589 
590 /** @class SilentErrorHandler
591  * @brief An ErrorHandler that does not report messages.
592  *
593  * Use SilentErrorHandler when an ErrorHandler object is required, but error
594  * messages should not be printed. */
595 class SilentErrorHandler : public ErrorHandler { public:
596 
SilentErrorHandler()597     SilentErrorHandler() {
598     }
599 
600 };
601 
602 
603 /** @class ErrorVeneer
604  * @brief Base class for ErrorHandlers that forward messages.
605  *
606  * ErrorHandlers can stack.  Stacking ErrorHandlers simplify modify a message
607  * and then pass the result to a base ErrorHandler, which does the actual
608  * printing.  The ErrorVeneer base class simplifies the implementation of
609  * stacking ErrorHandlers.  It provides versions of ErrorHandler's format(),
610  * decorate(), emit(), and account() methods that forward to the underlying
611  * handler.  Note that the clear() method is <em>not</em> automatically
612  * forwarded. */
613 class ErrorVeneer : public ErrorHandler { public:
614 
615     /** @brief Construct an ErrorVeneer.
616      * @param errh base ErrorHandler
617      *
618      * If @a errh is 0, then the ErrorVeneer acts like a
619      * SilentErrorHandler. */
ErrorVeneer(ErrorHandler * errh)620     ErrorVeneer(ErrorHandler *errh)
621 	: _errh(errh) {
622     }
623 
624     String vformat(const char *fmt, va_list val);
625     String decorate(const String &str);
626     void *emit(const String &str, void *user_data, bool more);
627     void account(int level);
628 
629   private:
630 
631     ErrorHandler *_errh;
632 
633 };
634 
635 
636 #ifndef __KERNEL__
637 /** @class FileErrorHandler
638  * @brief An ErrorHandler that prints error messages to a given file.
639  *
640  * FileErrorHandler is the typical base ErrorHandler used at user level.  It
641  * prints messages to a file passed in to the constructor, and calls exit() or
642  * abort() based on the error level. */
643 class FileErrorHandler : public ErrorHandler { public:
644 
645     /** @brief Construct a FileErrorHandler.
646      * @param f file to print errors
647      * @param prefix string to prefix every error line */
648     FileErrorHandler(FILE *f, const String &prefix = String());
649 
set_default_flags(int default_flags)650     void set_default_flags(int default_flags) {
651 	_default_flags = default_flags;
652     }
653 
654     String vformat(const char *fmt, va_list val);
655     void *emit(const String &str, void *user_data, bool more);
656     void account(int level);
657 
658   private:
659 
660     FILE *_f;
661     String _context;
662     int _default_flags;
663 
664 };
665 #endif
666 
667 
668 /** @class LocalErrorHandler
669  * @brief A convenience stackable ErrorHandler.
670  *
671  * It's often convenient to pass a null ErrorHandler pointer when errors
672  * should not be printed.  The LocalErrorHandler class simplifies dealing with
673  * ErrorHandler pointers that may or may not be null.  LocalErrorHandler is a
674  * transparent layer on the base handler; but if the base handler is null, it
675  * acts like a SilentErrorHandler.  For example:
676  * @code
677  * void f(ErrorHandler *errh) {   // errh might or might not be null
678  *     LocalErrorHandler lerrh(errh);
679  *     ... lerrh.message("message") ...
680  * }
681  * @endcode */
682 class LocalErrorHandler : public ErrorVeneer { public:
683 
684     /** @brief Construct a LocalErrorHandler. */
LocalErrorHandler(ErrorHandler * errh)685     LocalErrorHandler(ErrorHandler *errh)
686 	: ErrorVeneer(errh) {
687     }
688 
689 };
690 
691 
692 /** @class ContextErrorHandler
693  * @brief A stackable ErrorHandler that prints context lines.
694  *
695  * The stackable ContextErrorHandler adds context to the first error
696  * message printed, and optionally indent error messages so that they appear
697  * grouped underneath the context.
698  * @code
699  * FileErrorHandler errh1(stderr);
700  * ContextErrorHandler errh2(&errh1, "While counting to 2:");
701  * errh2.error("An error occurred.");
702  * errh2.error("Another error occurred.");
703  *     // prints "While counting to 2:\n"
704  *     //        "  An error occurred.\n"
705  *     //        "  Another error occurred.\n"
706  * @endcode
707  *
708  * To prevent ContextErrorHandler from indenting or printing context for a
709  * message, add a "{context:no}" annotation to the message's first line.  To
710  * turn off the indent but keep the context, add a "{context:noindent}"
711  * annotation.
712  * @code
713  * FileErrorHandler errh1(stderr);
714  * ContextErrorHandler errh2(&errh1, "While counting to 2:");
715  * errh2.error("{context:no}An error occurred.");
716  * errh2.error("Another error occurred.");
717  *     // prints "An error occurred.\n"
718  *     //        "While counting to 2:\n"
719  *     //        "  Another error occurred.\n"
720  *
721  * FileErrorHandler errh1(stderr);
722  * PrefixErrorHandler noctx_errh(stderr, "{context:no}");
723  * ContextErrorHandler errh2(&errh1, "While counting to 2:");
724  * errh2.error("An error occurred.");
725  * errh2.error("Another error occurred.");
726  *     // prints "An error occurred.\n"
727  *     //        "Another error occurred.\n"
728  * @endcode
729  *
730  * ContextErrorHandler adds the "{context:context}" annotation to context
731  * lines. */
732 class ContextErrorHandler : public ErrorVeneer { public:
733 
734     /** @brief Construct a ContextErrorHandler.
735      * @param errh base ErrorHandler
736      * @param fmt format for context lines
737      *
738      * The context message is formed by @a errh->format() using @a fmt and
739      * any additional arguments. */
740     ContextErrorHandler(ErrorHandler *errh, const char *fmt, ...);
741 
742     /** @brief Return true iff the context has already been printed. */
context_printed() const743     bool context_printed() const {
744 	return _context_printed;
745     }
746 
747     /** @brief Set whether the context has been printed. */
set_context_printed(bool x)748     void set_context_printed(bool x) {
749 	_context_printed = x;
750     }
751 
752     /** @brief Set the context string to @a str. */
set_context(const String & str)753     void set_context(const String &str) {
754 	_context = str;
755     }
756 
757     /** @brief Set the indent string to @a str.
758      *
759      * The indent string is prepended to all non-context messages.  It can
760      * contain landmarks as well as non-landmark text.  The default indent
761      * string is "  " (two spaces). */
set_indent(const String & str)762     void set_indent(const String &str) {
763 	_indent = str;
764     }
765 
766     /** @brief Set the context landmark to @a str.
767      *
768      * The context landmark is used to decorate the context, and also applied
769      * to any error messages that lack landmarks of their own.  The default
770      * context landmark is empty.
771      *
772      * @note The input @a str is passed to
773      * ErrorHandler::make_landmark_anno(). */
set_context_landmark(const String & str)774     void set_context_landmark(const String &str) {
775 	_context_landmark = make_landmark_anno(str);
776     }
777 
778     String decorate(const String &str);
779 
780   private:
781 
782     String _context;
783     String _indent;
784     String _context_landmark;
785     bool _context_printed;
786 
787 };
788 
789 
790 /** @class PrefixErrorHandler
791  * @brief A stackable ErrorHandler that adds a prefix to error messages.
792  *
793  * The stackable ContextErrorHandler adds a prefix to every error line
794  * printed.  For example:
795  * @code
796  * FileErrorHandler errh1(stderr);
797  * PrefixErrorHandler errh2(&errh1, "Blah--");
798  * errh2.error("An error occurred.");
799  * errh2.error("Another error occurred.");
800  *     // prints "Blah--An error occurred.\n"
801  *     //        "Blah--Another error occurred.\n"
802  * @endcode */
803 class PrefixErrorHandler : public ErrorVeneer { public:
804 
805     /** @brief Construct a PrefixErrorHandler.
806      * @param errh base ErrorHandler
807      * @param prefix string to prefix to error lines */
808     PrefixErrorHandler(ErrorHandler *errh, const String &prefix);
809 
810     String decorate(const String &str);
811 
812   private:
813 
814     String _prefix;
815 
816 };
817 
818 
819 /** @class LandmarkErrorHandler
820  * @brief A stackable ErrorHandler that adds a default landmark to error
821  * messages.
822  *
823  * The stackable ContextErrorHandler adds a default landmark to every error
824  * line printed.  Error lines' own landmarks are preserved when they exist.
825  * For example:
826  * @code
827  * FileErrorHandler errh1(stderr);
828  * LandmarkErrorHandler errh2(&errh1, "file:1");
829  * errh2.error("An error occurred.");
830  * errh2.lerror("file:2", "Another error occurred.");
831  *     // prints "file:1: An error occurred.\n"
832  *     //        "file:2: Another error occurred.\n"
833  * @endcode */
834 class LandmarkErrorHandler : public ErrorVeneer { public:
835 
836     /** @brief Construct a LandmarkErrorHandler.
837      * @param errh base ErrorHandler
838      * @param landmark default landmark */
839     LandmarkErrorHandler(ErrorHandler *errh, const String &landmark);
840 
841     /** @brief Set the default landmark applied to error messages. */
set_landmark(const String & landmark)842     void set_landmark(const String &landmark) {
843 	_landmark = make_landmark_anno(landmark);
844     }
845 
846     String decorate(const String &str);
847 
848   private:
849 
850     String _landmark;
851 
852 };
853 
854 
855 #ifndef __KERNEL__
856 /** @class BailErrorHandler
857  * @brief A stackable ErrorHandler that exits when errors occur.
858  *
859  * The stackable BailErrorHandler, available only at user level, causes the
860  * process to exit if an error worse than a configurable level occurs. */
861 class BailErrorHandler : public ErrorVeneer { public:
862 
863     /** @brief Construct a BailErrorHandler.
864      * @param errh base ErrorHandler
865      * @param level error level that causes premature exit
866      *
867      * An error message with level less than or equal to @a el_error will
868      * cause the process to exit with status 1. */
869     BailErrorHandler(ErrorHandler *errh, int level = el_error);
870 
871     void account(int level);
872 
873   private:
874 
875     int _level;
876 
877 };
878 #endif
879 
880 #undef ERRH_SENTINEL
881 #endif
882