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