1 /* *****************************************************************
2 MESQUITE -- The Mesh Quality Improvement Toolkit
3
4 Copyright 2004 Sandia Corporation and Argonne National
5 Laboratory. Under the terms of Contract DE-AC04-94AL85000
6 with Sandia Corporation, the U.S. Government retains certain
7 rights in this software.
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 (lgpl.txt) along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 ***************************************************************** */
24 /*!
25 \file MsqError.cpp
26 \brief Used to hold the error state and return it to the application.
27 \author Jason Kraftcheck
28 \date 2004-09-17
29 */
30
31 #include "MsqError.hpp"
32 #include "Mesquite.hpp"
33
34 #include <ostream>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <assert.h>
38
39 #include <cstring>
40 using std::strncpy;
41
42 namespace MBMesquite {
43
error_message() const44 const char* MsqError::error_message() const
45 {
46 static const char* const error_messages[] = {
47 "No Error",
48 "<unknown>",
49 "Out of memory",
50 "Invalid argument",
51 "Data not initialized",
52 "Invalid state",
53 "File access error",
54 "File format error",
55 "Syntax error",
56 "I/O error",
57 "Invalid mesh",
58 "No storage mode for PatchData",
59 "Not implemented",
60 "Internal error",
61 "Interrupted",
62 "Duplicate tag name",
63 "Tag not found",
64 "Unsupported element type",
65 "Parallel Error - error occurred on at least one processor",
66 "barruer violated when processing barrier Target Metric",
67 "Invalid Error Code"
68 };
69
70 /* If this is ever false, it should be caught by a unit test.
71 Do an assert here so the unit test fails.
72 This asserts that all error codes have a string in the above list. */
73 assert( sizeof(error_messages) == sizeof(char*) * (LAST_ERROR_CODE+1) );
74
75 if (!errorMessage.empty())
76 return errorMessage.c_str();
77
78 if (errorCode >= 0 && errorCode < LAST_ERROR_CODE)
79 return error_messages[errorCode];
80
81 return error_messages[LAST_ERROR_CODE];
82 }
83
~MsqError()84 MsqError::~MsqError() {}
85
set(const std::string & msg,ErrorCode num)86 bool MsqError::Setter::set( const std::string& msg, ErrorCode num )
87 {
88 return mErr.set_error( num, msg.c_str() )
89 && mErr.push( functionName, fileName, lineNumber );
90 }
91
set(const char * msg,ErrorCode num)92 bool MsqError::Setter::set( const char* msg, ErrorCode num )
93 {
94 return mErr.set_error( num, msg )
95 && mErr.push( functionName, fileName, lineNumber );
96 }
97
set(ErrorCode num)98 bool MsqError::Setter::set( ErrorCode num )
99 {
100 return mErr.set_error( num )
101 && mErr.push( functionName, fileName, lineNumber );
102 }
103
set(ErrorCode num,const char * format,...)104 bool MsqError::Setter::set( ErrorCode num, const char* format, ... )
105 {
106 char buffer[1024];
107
108 #if defined(HAVE_VSNPRINTF)
109 va_list args;
110 va_start( args, format );
111 vsnprintf( buffer, sizeof(buffer), format, args );
112 va_end( args );
113 #elif defined(HAVE__VSNPRINTF)
114 va_list args;
115 va_start( args, format );
116 _vsnprintf( buffer, sizeof(buffer), format, args );
117 va_end( args );
118 #elif defined(HAVE_VSPRINTF)
119 va_list args;
120 va_start( args, format );
121 vsprintf( buffer, format, args );
122 va_end( args );
123 #else
124 strncpy( buffer, format, sizeof(buffer) );
125 buffer[sizeof(buffer)-1] = '\0';
126 #endif
127
128 return mErr.set_error( num, buffer )
129 && mErr.push( functionName, fileName, lineNumber );
130 }
131
push(const char * function,const char * file,int line)132 bool MsqError::push( const char* function, const char* file, int line )
133 {
134 stackTrace.push_back( Trace(function, file, line) );
135 return true;
136 }
137
set_error(ErrorCode num,const char * msg)138 bool MsqError::set_error( ErrorCode num, const char* msg )
139 {
140 errorCode = num;
141 stackTrace.clear();
142
143 if (msg)
144 errorMessage = msg;
145 else
146 // MS VC6 doesn't have string::clear()!
147 errorMessage.resize(0);
148
149 return num != NO_ERROR;
150 }
151
clear()152 void MsqError::clear()
153 {
154 errorCode = NO_ERROR;
155 // MS VC6 doesn't have string::clear()!
156 errorMessage.resize(0);
157 stackTrace.clear();
158 }
159
operator <<(std::ostream & str,const MsqError::Trace & tr)160 std::ostream& operator<<( std::ostream& str, const MsqError::Trace& tr )
161 {
162 return (str << tr.function << " at " << tr.file << ":" << tr.line);
163 }
164
operator <<(std::ostream & str,const MsqError & err)165 std::ostream& operator<<( std::ostream& str, const MsqError& err )
166 {
167 str << "MESQUITE ERROR " << (int)err.error_code() << " : "
168 << err.error_message() << std::endl;
169
170 MsqError::StackTrace::const_iterator iter = err.stack().begin();
171 const MsqError::StackTrace::const_iterator end = err.stack().end();
172 if (iter != end)
173 {
174 str << " at " << *iter << std::endl;
175 ++iter;
176 }
177 for ( ; iter != end; ++iter)
178 str << " in " << *iter << std::endl;
179
180 return str;
181 }
182
~MsqPrintError()183 MsqPrintError::~MsqPrintError()
184 { if (error()) outputStream << *this << std::endl; }
185
186 }
187