error.h

Go to the documentation of this file.
00001 /* 
00002  * Scythe Statistical Library Copyright (C) 2000-2002 Andrew D. Martin
00003  * and Kevin M. Quinn; 2002-present Andrew D. Martin, Kevin M. Quinn,
00004  * and Daniel Pemstein.  All Rights Reserved.
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify under the terms of the GNU General Public License as
00008  * published by Free Software Foundation; either version 2 of the
00009  * License, or (at your option) any later version.  See the text files
00010  * COPYING and LICENSE, distributed with this source code, for further
00011  * information.
00012  * --------------------------------------------------------------------
00013  *  scythestat/error.h
00014  */
00015  
00051 #ifndef SCYTHE_ERROR_H
00052 #define SCYTHE_ERROR_H
00053 
00054 #include <exception>
00055 #include <string>
00056 #include <sstream>
00057 #include <iostream>
00058 #include <vector>
00059 
00061 #ifdef SCYTHE_DEBUG_LIB
00062 #define SCYTHE_DEBUG_MSG(MSG)                             \
00063 { std::cout << "SCYTHE_DEBUG_LIB: " << MSG << std::endl; }
00064 #else
00065 #define SCYTHE_DEBUG_MSG(MSG)
00066 #endif
00067 
00069 #define SCYTHE_THROW(EXCEP,MSG)                           \
00070   {                                                       \
00071     std::stringstream _SCYTHE_DEBUG_ss;                   \
00072     _SCYTHE_DEBUG_ss << MSG;                              \
00073     throw EXCEP(__FILE__, __func__, __LINE__,  \
00074         _SCYTHE_DEBUG_ss.str());                          \
00075   }
00076 
00077 #define SCYTHE_CHECK(CHECK,EXCEP,MSG)                     \
00078 {                                                         \
00079   if (CHECK)                                              \
00080     SCYTHE_THROW(EXCEP,MSG)                               \
00081 }
00082 
00084 #ifndef SCYTHE_DEBUG
00085 #define SCYTHE_DEBUG 3
00086 #endif
00087 
00089 #if SCYTHE_DEBUG > 0
00090 #define SCYTHE_CHECK_10(CHECK,EXCEP,MSG) SCYTHE_CHECK(CHECK,EXCEP,MSG)
00091 #else
00092 #define SCYTHE_CHECK_10(CHECK, EXCEP, MSG)
00093 #endif
00094 
00095 #if SCYTHE_DEBUG > 1
00096 #define SCYTHE_CHECK_20(CHECK,EXCEP,MSG) SCYTHE_CHECK(CHECK,EXCEP,MSG)
00097 #else
00098 #define SCYTHE_CHECK_20(CHECK, EXCEP, MSG)
00099 #endif
00100 
00101 #if SCYTHE_DEBUG > 2
00102 #define SCYTHE_CHECK_30(CHECK,EXCEP,MSG) SCYTHE_CHECK(CHECK,EXCEP,MSG)
00103 #else
00104 #define SCYTHE_CHECK_30(CHECK, EXCEP, MSG)
00105 #endif
00106 
00107 #if SCYTHE_DEBUG > 0 
00108 #define SCYTHE_THROW_10(EXCEP,MSG) SCYTHE_THROW(EXCEP,MSG)
00109 #else
00110 #define SCYTHE_THROW_10(EXCEP,MSG)
00111 #endif
00112 
00113 #if SCYTHE_DEBUG > 1 
00114 #define SCYTHE_THROW_20(EXCEP,MSG) SCYTHE_THROW(EXCEP,MSG)
00115 #else
00116 #define SCYTHE_THROW_20(EXCEP,MSG)
00117 #endif
00118 
00119 #if SCYTHE_DEBUG > 2 
00120 #define SCYTHE_THROW_30(EXCEP,MSG) SCYTHE_THROW(EXCEP,MSG)
00121 #else
00122 #define SCYTHE_THROW_30(EXCEP,MSG)
00123 #endif
00124 
00125 #define SCYTHE_WARN(MSG)                                              \
00126   {                                                                   \
00127   std::cerr << "WARNING in " << __FILE__ << ", "                      \
00128     << __func__ << ", " << __LINE__ << ": "                \
00129     << MSG << "\n";                                                   \
00130   }
00131 
00132 #define SCYTHE_CHECK_WARN(CHECK,MSG)                                  \
00133   {                                                                   \
00134   if (CHECK)                                                          \
00135     SCYTHE_WARN(MSG)                                                  \
00136   }
00137 
00138 
00139 namespace scythe
00140 {
00141   /* Forward declaration for serr */
00142   class scythe_exception;
00143 
00144   /**** This file-local variable holds the output of the last
00145    * scythe_exception constructed.
00146    ****/
00147 #ifdef __MINGW32__
00148   static scythe_exception *serr;
00149 #else
00150   namespace
00151   {
00152     scythe_exception *serr;
00153   }
00154 #endif
00155 
00156   /**** A replacement for the default terminate handler.  This outputs
00157    * the string held in serr before calling abort, thereby notifying
00158    * the user of why the program crashed.
00159    ****/
00160   inline void scythe_terminate ();
00161 
00162   /**** The scythe exception abstract base class ****/
00171   class scythe_exception:public std::exception
00172   {
00173   public:
00174     scythe_exception (const std::string & head,
00175                       const std::string & file,
00176                       const std::string & function,
00177                       const unsigned int &line,
00178                       const std::string & message = "",
00179                       const bool & halt = false) throw ()
00180       : exception (),
00181         head_ (head),
00182         file_ (file),
00183         function_ (function),
00184         line_ (line),
00185         message_ (message),
00186         call_files_ (),
00187         call_funcs_ (),
00188         call_lines_ ()
00189     {
00190       std::ostringstream os;
00191       os << head_ << " in " << file_ << ", " << function_ << ", "
00192         << line_ << ": " << message_ << "!\n\n";
00193 
00194       serr = this;
00195       std::set_terminate (scythe_terminate);
00196       if (halt)
00197         std::terminate ();
00198     }
00199 
00200     scythe_exception (const scythe_exception & e) throw ()
00201       : exception (),
00202         head_ (e.head_),
00203         file_ (e.file_),
00204         function_ (e.function_),
00205         line_ (e.line_),
00206         message_ (e.message_),
00207         call_files_ (e.call_files_),
00208         call_funcs_ (e.call_funcs_),
00209         call_lines_ (e.call_lines_)
00210     {
00211     }
00212 
00213     scythe_exception & operator= (const scythe_exception & e) throw ()
00214     {
00215       head_ = e.head_;
00216       file_ = e.file_;
00217       function_ = e.function_;
00218       line_ = e.line_;
00219       message_ = e.message_;
00220 
00221       return *this;
00222     }
00223 
00224     virtual ~ scythe_exception () throw ()
00225     {
00226     }
00227 
00228     virtual const char *what () const throw ()
00229     {
00230       std::ostringstream os;
00231       for (int i = call_files_.size() - 1; i > -1; ++i) {
00232         os << "Called from " << call_files_[i] << ", "
00233           << call_funcs_[i] << ", " << call_lines_[i] << std::endl;
00234       }
00235       os << head_ << " in " << file_ << ", " << function_ << ", "
00236         << line_ << ": " << message_ << "!";
00237       return os.str ().c_str ();
00238     }
00239 
00240     virtual std::string message () const throw ()
00241     {
00242       return message_;
00243     }
00244 
00245     virtual void add_caller (const std::string &file,
00246       const std::string &function, const unsigned int &line) throw ()
00247     {
00248 
00249       /* This if allows one to catch and rethrow an error in the same
00250        * function w/out messing things up.  Nice to keep try-catch
00251        * blocks to a minimum
00252        */
00253 
00254       if (file != file_ && function != function_) {
00255         call_files_.push_back(file);
00256         call_funcs_.push_back(function);
00257         call_lines_.push_back(line);
00258       }
00259     }
00260 
00261   private:
00262     std::string head_;
00263     std::string file_;
00264     std::string function_;
00265     unsigned int line_;
00266     std::string message_;
00267     std::vector<std::string> call_files_;
00268     std::vector<std::string> call_funcs_;
00269     std::vector<unsigned int> call_lines_;
00270   };
00271 
00272 
00273   /**** Exception class types, added as needed ****/
00274 
00282   class scythe_alloc_error:public scythe_exception
00283   {
00284   public:
00285     scythe_alloc_error (const std::string & file,
00286                         const std::string & function,
00287                         const unsigned int &line,
00288                         const std::string & message = "",
00289                         const bool & halt = false) throw ()
00290       : scythe_exception ("SCYTHE_ALLOCATION_ERROR", file, function,
00291           line, message, halt)
00292     {
00293     }
00294   };
00295 
00303   class scythe_invalid_arg:public scythe_exception
00304   {
00305   public:
00306     scythe_invalid_arg (const std::string & file,
00307                         const std::string & function,
00308                         const unsigned int &line,
00309                         const std::string & message = "",
00310                         const bool & halt = false) throw ()
00311       : scythe_exception ("SCYTHE_INVALID ARGUMENT", file, function,
00312           line, message, halt)
00313     {
00314     }
00315   };
00316 
00324   class scythe_file_error:public scythe_exception
00325   {
00326   public:
00327     scythe_file_error(const std::string & file,
00328                        const std::string & function,
00329                        const unsigned int &line,
00330                        const std::string & message = "",
00331                        const bool & halt = false) throw ()
00332       : scythe_exception ("SCYTHE FILE ERROR", file, function, line, 
00333           message, halt)
00334     {
00335     }
00336   };
00337 
00344   class scythe_conformation_error:public scythe_exception
00345   {
00346   public:
00347     scythe_conformation_error(const std::string & file,
00348                                const std::string & function,
00349                                const unsigned int &line,
00350                                const std::string & message = "",
00351                                const bool & halt = false) throw ()
00352       : scythe_exception ("SCYTHE CONFORMATION ERROR", file, function, 
00353           line, message, halt)
00354     {
00355     }
00356   };
00357 
00366   class scythe_dimension_error:public scythe_exception
00367   {
00368   public:
00369     scythe_dimension_error (const std::string & file,
00370                             const std::string & function,
00371                             const unsigned int &line,
00372                             const std::string & message = "",
00373                             const bool & halt = false) throw ()
00374       : scythe_exception ("SCYTHE DIMENSION ERROR", file, function,
00375           line, message, halt)
00376     {
00377     }
00378   };
00379 
00387   class scythe_null_error:public scythe_exception
00388   {
00389   public:
00390     scythe_null_error(const std::string & file,
00391                        const std::string & function,
00392                        const unsigned int &line,
00393                        const std::string & message = "",
00394                        const bool & halt = false) throw ()
00395       : scythe_exception ("SCYTHE NULL ERROR", file, function, line,
00396           message, halt)
00397     {
00398     }
00399   };
00400 
00410   class scythe_type_error:public scythe_exception
00411   {
00412   public:
00413     scythe_type_error(const std::string & file,
00414                        const std::string & function,
00415                        const unsigned int &line,
00416                        const std::string & message = "",
00417                        const bool & halt = false) throw ()
00418       : scythe_exception ("SCYTHE TYPE ERROR", file, function, line,
00419           message, halt)
00420     {
00421     }
00422   };
00423 
00431   class scythe_bounds_error:public scythe_exception
00432   {
00433   public:
00434     scythe_bounds_error(const std::string & file,
00435                                const std::string & function,
00436                                const unsigned int &line,
00437                                const std::string & message = "",
00438                                const bool & halt = false) throw ()
00439       : scythe_exception ("SCYTHE BOUNDS ERROR", file, function,
00440           line, message, halt)
00441     {
00442     }
00443   };
00444 
00452   class scythe_convergence_error:public scythe_exception
00453   {
00454   public:
00455     scythe_convergence_error (const std::string & file,
00456                               const std::string & function,
00457                               const unsigned int &line,
00458                               const std::string & message = "",
00459                               const bool & halt = false) throw ()
00460       : scythe_exception ("SCYTHE CONVERGENCE ERROR", file, function,
00461           line, message, halt)
00462     {
00463     }
00464   };
00465 
00474   class scythe_range_error:public scythe_exception
00475   {
00476   public:
00477     scythe_range_error (const std::string & file,
00478                         const std::string & function,
00479                         const unsigned int &line,
00480                         const std::string & message = "",
00481                         const bool & halt = false) throw ()
00482       : scythe_exception ("SCYTHE RANGE ERROR", file, function, line,
00483           message, halt)
00484     {
00485     }
00486   };
00487 
00497   class scythe_precision_error:public scythe_exception
00498   {
00499   public:
00500     scythe_precision_error (const std::string & file,
00501                             const std::string & function,
00502                             const unsigned int &line,
00503                             const std::string & message = "",
00504                             const bool & halt = false) throw ()
00505       : scythe_exception ("SCYTHE PRECISION ERROR", file, function,
00506           line, message, halt)
00507     {
00508     }
00509   };
00510   
00519   class scythe_randseed_error:public scythe_exception
00520   {
00521   public:
00522     scythe_randseed_error(const std::string & file,
00523                           const std::string & function,
00524                           const unsigned int &line,
00525                           const std::string & message = "",
00526                           const bool & halt = false) throw ()
00527       : scythe_exception ("SCYTHE RANDOM SEED ERROR", file, function,
00528           line, message, halt)
00529     {
00530     }
00531   };
00532 
00542   class scythe_style_error:public scythe_exception
00543   {
00544     public:
00545       scythe_style_error(const std::string& file,
00546           const std::string& function,
00547           const unsigned int& line,
00548           const std::string& message = "",
00549           const bool& halt = false) throw ()
00550         : scythe_exception("SCYTHE STYLE ERROR", file, function,
00551             line, message, halt)
00552       {}
00553   };
00554 
00561   class scythe_lapack_internal_error:public scythe_exception
00562   {
00563     public:
00564       scythe_lapack_internal_error(const std::string& file,
00565           const std::string& function,
00566           const unsigned int& line,
00567           const std::string& message = "",
00568           const bool& halt = false) throw ()
00569         : scythe_exception("SCYTHE LAPACK/BLAS INTERNAL  ERROR", file, 
00570             function, line, message, halt)
00571       {}
00572   };
00573 
00580   class scythe_unexpected_default_error:public scythe_exception
00581   {
00582     public:
00583       scythe_unexpected_default_error(const std::string& file,
00584           const std::string& function,
00585           const unsigned int& line,
00586           const std::string& message = "",
00587           const bool& halt = false) throw ()
00588         : scythe_exception("SCYTHE UNEXPECTED DEFAULT ERROR", file, 
00589             function, line, message, halt)
00590       {}
00591   };
00592 
00593   // The definition of our terminate handler described above
00594   inline void scythe_terminate ()
00595   {
00596     std::cerr << serr->what() << std::endl;
00597     std::cerr << std::endl;
00598     abort ();
00599   }
00600 
00601 }        // end namspace SCYTHE
00602 
00603 #endif /* SCYTHE_ERROR_H */

Generated on Wed Aug 15 14:53:35 2007 for Scythe-1.0.2 by  doxygen 1.4.7