1 /***************************************************************************
2 error.cpp
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 #include "error.h"
15 #include <cstring>
16 #include <cstdlib>
17
Notice()18 Notice::Notice() {
19 nullout=new ostream(NULL);
20 noteout=&cout;
21 notice_level=9;
22 }
23
~Notice()24 Notice::~Notice() {
25 if (nullout!=NULL)
26 delete nullout;
27 }
28
29 // Returns a null stream if level is two high, else returns notice stream
operator [](const unsigned level)30 ostream & Notice::operator[] (const unsigned level) {
31 if (level<=notice_level)
32 return *noteout;
33 else
34 return *nullout;
35 }
36
setostream(ostream & out)37 void Notice::setostream(ostream &out) {
38 noteout=&out;
39 }
40
set_notice_level(unsigned l)41 void Notice::set_notice_level(unsigned l) {
42 notice_level=l;
43 }
44
get_notice_level()45 unsigned Notice::get_notice_level() {
46 return notice_level;
47 }
48
notice(unsigned level,const string calling_class,const string note)49 void Notice::notice(unsigned level, const string calling_class,
50 const string note) {
51 if (level<notice_level)
52 *noteout << calling_class << "::" << note;
53 }
54
notice(unsigned level,const string calling_class,vector<string> & notes)55 void Notice::notice(unsigned level,const string calling_class,
56 vector<string> ¬es) {
57 if (level<=notice_level) {
58 *noteout << calling_class << "::";
59 for (unsigned i=0; i<notes.size(); i++)
60 *noteout << notes[i];
61 }
62 }
63
notice(unsigned level,const string note)64 void Notice::notice(unsigned level, const string note) {
65 if (level<=notice_level)
66 *noteout << note;
67 }
68
notice(unsigned level,vector<string> & notes)69 void Notice::notice(unsigned level, vector<string> ¬es) {
70 if (level<=notice_level)
71 for (unsigned i=0; i<notes.size(); i++)
72 *noteout << notes[i];
73 }
74
Error()75 Error::Error() {
76 nullout=new ostream(NULL);
77 unhandled_warnings=0;
78 handled_warnings=0;
79 max_level=9;
80 min_level=2;
81
82 handleatend=true;
83 writetotalatend=true;
84
85 errout=&cerr;
86 logout=nullout;
87 column_width=70;
88 }
89
~Error()90 Error::~Error() {
91 if (handleatend && unhandled_warnings!=0)
92 writewarnings();
93 if (writetotalatend && total_warnings()!=0)
94 writetotals(0);
95 if (nullout!=NULL)
96 delete nullout;
97 }
98
99 // Set a log file for error AND notice output
set_logfile(ostream & out)100 void Error::set_logfile(ostream &out) {
101 logout=&out;
102 note.setostream(out);
103 }
104
105 // Total number of warnings
total_warnings()106 unsigned Error::total_warnings() {
107 return unhandled_warnings+handled_warnings;
108 }
109
110 // Returns the number of errors generated with ID
operator [](unsigned id)111 unsigned Error::operator[](unsigned id) {
112 warning_iter m;
113 m=warning_list.find(id);
114 if (m==warning_list.end())
115 return 0;
116 return m->second.size();
117 }
118
addwarning(unsigned ID,unsigned level,const string calling_class,const string warning)119 void Error::addwarning(unsigned ID, unsigned level, const string calling_class,
120 const string warning) {
121 if (level<min_level)
122 return;
123 if (level>max_level)
124 generate_error(ID,calling_class,warning);
125 vector<ErrCom> *e=&(warning_list[ID]);
126 e->push_back(ErrCom());
127 e->back().level=level;
128 e->back().calling_class=calling_class;
129 e->back().message=warning;
130 unhandled_warnings++;
131 }
132
generate_error(unsigned ID,const string calling_class,const string error)133 void Error::generate_error(unsigned ID, const string calling_class,
134 const string error) {
135 ErrCom err;
136 err.level=max_level+1;
137 err.calling_class=calling_class;
138 err.message=error;
139
140 if (warnings()!=0)
141 writewarnings();
142 write_err(ID,err);
143 writetotals(1);
144 #ifdef MUSE_MPI
145 MPI_Abort ( MPI_COMM_WORLD, 1 );
146 #else
147 exit(1);
148 #endif
149 }
150
151 // Add an error/warning (Program termination if level >= max level
buffer()152 ostringstream & Error::buffer() {
153 return buffer_stream;
154 }
155
156 // Generate warning with message in buffer
addbuf(unsigned ID,unsigned level,const string calling_class)157 void Error::addbuf(unsigned ID, unsigned level, const string calling_class) {
158 addwarning(ID,level,calling_class,buffer_stream.str());
159 buffer_stream.str("");
160 }
161
162 // Generate serious error with message in buffer
addbuf(unsigned ID,const string calling_class)163 void Error::addbuf(unsigned ID, const string calling_class) {
164 generate_error(ID,calling_class,buffer_stream.str());
165 }
166
warnings()167 unsigned Error::warnings() {
168 return unhandled_warnings;
169 }
170
writeline()171 void Error::writeline() {
172 *errout << "+";
173 *logout << "+";
174 for (unsigned i=0; i<column_width-2; i++) {
175 *errout << "-";
176 *logout << "-";
177 }
178 *errout << "+\n";
179 *logout << "+\n";
180 }
181
write_err(unsigned ID,ErrCom & err)182 void Error::write_err(unsigned ID, ErrCom &err) {
183 if (err.level<min_level)
184 return;
185
186 *errout << "\n";
187 *logout << "\n";
188 writeline();
189 (*errout).setf(ios::left);
190 (*errout).unsetf(ios::right);
191
192 // Output the IDs
193 unsigned width12=(unsigned)floor((double)(column_width-10)/3.0);
194 unsigned width3=column_width-10-width12-width12;
195 string et;
196 unsigned width1;
197 if (err.level>max_level) {
198 et="| Error: "; width1=width12-7;
199 } else {
200 et="| Warning: "; width1=width12-9;
201 }
202 *errout << et << setw(width1) << ID << " | Level: "
203 << setw(width12-7) << err.level << " | " << setw(width3)
204 << err.calling_class << " |\n";
205 *logout << et << setw(width1) << ID << " | Level: "
206 << setw(width12-7) << err.level << " | " << setw(width3)
207 << err.calling_class << " |\n";
208 writeline();
209
210 // Output the message
211 vector <string> messages;
212 a::format_fit(column_width-3,err.message,messages);
213 for (unsigned i=0; i<messages.size(); i++) {
214 *errout << "| " << setw(column_width-3) << messages[i] << "|\n";
215 *logout << "| " << setw(column_width-3) << messages[i] << "|\n";
216 }
217 writeline();
218
219 return;
220 }
221
writewarning(unsigned ID)222 void Error::writewarning(unsigned ID) {
223 for (unsigned i=0; i<warning_list[ID].size(); i++)
224 write_err(ID,warning_list[ID][i]);
225 handled_warnings+=warning_list[ID].size();
226 dismiss_all_warnings(ID);
227 return;
228 }
229
dismiss_warning(unsigned ID)230 void Error::dismiss_warning(unsigned ID) {
231 warning_iter m;
232 m=warning_list.find(ID);
233 if (m==warning_list.end())
234 return;
235 unhandled_warnings--;
236 if (m->second.size()==1)
237 warning_list.erase(m);
238 else
239 m->second.erase(m->second.end()--);
240 }
241
dismiss_all_warnings(unsigned ID)242 void Error::dismiss_all_warnings(unsigned ID) {
243 warning_iter m;
244 m=warning_list.find(ID);
245 if (m==warning_list.end())
246 return;
247 unhandled_warnings-=m->second.size();
248 warning_list.erase(m);
249 }
250
writewarnings()251 void Error::writewarnings() {
252 while (warning_list.size()>0)
253 writewarning(warning_list.begin()->first);
254 return;
255 }
256
dismiss_warnings()257 void Error::dismiss_warnings() {
258 while (warning_list.size()>0)
259 dismiss_warning(warning_list.begin()->first);
260 return;
261 }
262
263 // Write out the total warnings and errors
writetotals(unsigned errorcount)264 void Error::writetotals(unsigned errorcount) {
265 *errout << "\n";
266 *logout << "\n";
267 writeline();
268 (*errout).setf(ios::left);
269 (*errout).unsetf(ios::right);
270 unsigned width1=(unsigned)floor((double)(column_width-7)/2.0);
271 unsigned width2=column_width-7-width1;
272 string swarnings="Total Warnings: "+a::itoa(handled_warnings+
273 unhandled_warnings);
274 string serrors="Total Errors: "+a::itoa(errorcount);
275 *errout << "| " << setw(width1) << swarnings << " | " << setw(width2)
276 << serrors << " |\n";
277 *logout << "| " << setw(width1) << swarnings << " | " << setw(width2)
278 << serrors << " |\n";
279 writeline();
280 }
281
282