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> &notes);
73 	/// Generate a notice
74 	void notice(unsigned level, const string note);
75 	/// Generate a notice
76 	void notice(unsigned level, vector<string> &note);
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