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