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> &notes) {
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> &notes) {
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