1 /*************************************************************************** 2 error.h 3 ------------------- 4 5 Class for error handling 6 7 __________________________________________________________________________ 8 9 begin : Thu Oct 9 2003 10 copyright : (C) 2003 by W. Michael Brown 11 email : wmbrown@sandia.gov 12 ***************************************************************************/ 13 14 #ifndef ERRORCLASS 15 #define ERRORCLASS 16 17 #include <string> 18 #include <vector> 19 #include <map> 20 #include <iostream> 21 #include <sstream> 22 #include <iomanip> 23 #include <math.h> 24 25 #ifdef MUSE_MPI 26 #include <mpi.h> 27 #endif 28 29 using namespace std; 30 // forward declarations 31 namespace a { 32 string itoa(unsigned int); 33 void format_fit(unsigned, const string &, vector<string> &); 34 } 35 36 /// Notice Class for Handling Object Output 37 /** A notice object stores an ostream for output and a notice_level. 38 * All output is sent along with a level. Any output whose level is 39 * greater than notice_level is sent to a null stream. The C++ output 40 * operator '<<' can be used with the Notice operator '[]' which passes 41 * the level: 42 * \verbatim notice_object[29] << "This notice has level 29" << endl; 43 * \endverbatim 44 * 45 * The guidelines for output notice levels are: 46 * - \e 0: Information that must be output 47 * - \e 1 - 9: Normal program output 48 * - \e 10-19: Parameters useful for storing how the program was run 49 * - \e 20-29: Extraneous information useful that may be useful to user 50 * - \e 30- : Debugging information */ 51 class Notice { 52 public: 53 /// Standard output (cout) is the default notice output ostream 54 /** The default maximum notice level is 9 \e (notice_level=10) */ 55 Notice(); 56 ~Notice(); 57 58 /// Set the output stream for notice output 59 void setostream(ostream &out); 60 61 /// Returns a null stream if level is two high, else returns notice stream 62 ostream & operator[] (const unsigned level); 63 64 /// Set the degree of program output 65 void set_notice_level(unsigned l); 66 /// Get the degree of program output 67 unsigned get_notice_level(); 68 /// Generate a notice with a specified calling class 69 void notice(unsigned level, const string calling_class, const string note); 70 /// Generate a notice with a specified calling class 71 void notice(unsigned level, const string calling_class, 72 vector<string> ¬es); 73 /// Generate a notice 74 void notice(unsigned level, const string note); 75 /// Generate a notice 76 void notice(unsigned level, vector<string> ¬e); 77 78 private: 79 unsigned notice_level; 80 81 ostream *nullout; // Null stream for redirecting output to nowhere 82 ostream *noteout; // Output for notices 83 }; 84 85 /// Error and Notice Handling 86 /** This class is intended to handle all output to the user. Output is 87 * divided into notices and warnings/errors. Output of any message is 88 * associated with a level. For notices, if level is greater than or equal to 89 * max_notice_level, no output is generated. For warnings, if level is less 90 * than min_warning_level, it is dismissed with no output. If the level is 91 * greater than max_warning_level, the program is terminated and all warnings 92 * and errors are output. 93 * 94 * \note By default, on destruction of an Error object, all unhandled 95 * warnings and errors are output 96 * 97 * A log file can be specified for each object. In this case, all notices 98 * are output to the log file only and errors are output to both stderr 99 * and the log file 100 * 101 * Errors can be generated with a string or using the internal message buffer: 102 \verbatim 103 Error error; 104 error.buffer() << "Incorrect file format for file: " << filename; 105 error.addbuf(512,19,"FooClass"; 106 // --- OR 107 string message = "Incorrect file format for file: "+filename; 108 error.addwarning(512,19,"FooClass",message); 109 \endverbatim 110 * 111 * Newlines will be inserted into the error message automatically in order 112 * to format it for the string. Forced newlines can be specified with \n 113 * 114 * Programs can check whether or not errors have been generated using the [] 115 * operator and can 'handle' them by outputting the message or dismissing 116 * them without any output 117 * 118 * Notices are generated using the public Notice class (see Notice()) 119 * 120 * \b Error \b Levels: 121 * - \e 0 - 1: Errors expected to happen during normal execution 122 * - \e 2 - 9: Errors that a non-interactive program can handle and continue 123 * - \e 10-19: Errors that interactive program can handle (file not found,etc.) 124 * - \e 20- : Serious errors that should terminate execution 125 **/ 126 class Error { 127 public: 128 /// Default constructor (use cerr for output and no log file) 129 /** Default max notice level is 9, min warning level is 2, and max warning 130 * level is 9 */ 131 Error(); 132 ~Error(); 133 134 /// Set a log file for error AND notice output 135 void set_logfile(ostream &out); 136 137 /// Returns the number of errors (if any) generated with id 138 unsigned operator[](unsigned id); 139 140 /// Add warning, terminate if level is greater than max level 141 /** Newlines will be inserted into the message automatically when the 142 * message is formatted for output. However, forced newlines can also 143 * be inserted. **/ 144 void addwarning(unsigned ID, unsigned level, const string calling_class, 145 const string warning); 146 /// Add serious error (terminates execution) 147 void generate_error(unsigned ID, const string calling_class, 148 const string error); 149 150 /// Add an message to the error buffer. Warning generated with addbuf() 151 /** Newlines will be inserted into the message automatically when the 152 * message is formatted for output. However, forced newlines can also 153 * be inserted. 154 * 155 \verbatim 156 Error error; 157 error.buffer() << "Choice not supported: " << choice; 158 error.addbuf(512,9,"FooClass"); 159 \endverbatim **/ 160 ostringstream & buffer(); 161 /// Generate warning with message in buffer 162 /** \sa buffer() **/ 163 void addbuf(unsigned ID, unsigned level, const string calling_class); 164 /// Generate serious error with message in buffer 165 /** \sa buffer() **/ 166 void addbuf(unsigned ID, const string calling_class); 167 168 /// Number of Unhandled Warnings 169 unsigned warnings(); 170 /// Total number of warnings 171 unsigned total_warnings(); 172 173 /// Handle all warnings with this ID by writing them to out 174 void writewarning(unsigned ID); 175 /// Handle LAST warning with this ID WITHOUT writing it 176 void dismiss_warning(unsigned ID); 177 /// Handle ALL warnings with this ID WITHOUT writing it 178 void dismiss_all_warnings(unsigned ID); 179 /// Handle all warnings by writing them out 180 void writewarnings(); 181 /// Handle all warnings without writing 182 void dismiss_warnings(); 183 184 /// Write out the total warnings (write errorcount errors) 185 void writetotals(unsigned errorcount); 186 187 /// For generating notices 188 /** \sa Notice **/ 189 Notice note; 190 private: 191 struct ErrCom; 192 map<unsigned,vector<ErrCom> > warning_list; 193 typedef multimap<unsigned, vector<ErrCom> >::iterator warning_iter; 194 unsigned handled_warnings; 195 unsigned unhandled_warnings; 196 bool handleatend; // Write any unhandled errors on destruct 197 bool writetotalatend; // Write totals on destruct if not 0 198 199 unsigned min_level; // Don't output warnings less than min_level 200 unsigned max_level; // if a warning has a level>max_level error! 201 ostream *errout, *logout; // Output for errors and warnings! 202 ostream *nullout; // No output 203 204 ostringstream buffer_stream; // For creating messages for warnings 205 206 unsigned column_width; 207 void write_err(unsigned ID, ErrCom &err); 208 void writeline(); 209 }; 210 211 struct Error::ErrCom { 212 unsigned level; 213 string calling_class; 214 string message; 215 }; 216 217 #endif 218 219