--- /dev/null
+/*---------------------------- exceptions.h ---------------------------*/
+/* $Id$ */
+#ifndef __exceptions_H
+#define __exceptions_H
+/*---------------------------- exceptions.h ---------------------------*/
+
+
+#include <iostream.h>
+
+
+
+#ifndef __GNUC__
+# define __PRETTY_FUNCTION__ "(unknown)"
+#endif
+
+ /**
+ * This class should be used as a base class for
+ * all exception classes. Do not use its methods
+ * and variables directly since the interface
+ * and mechanism may be subject to change. Rather
+ * create new exception classes using the
+ * #DeclException# macro family.
+ *
+ * @see Assert
+ * @see DeclException0
+ * @author Wolfgang Bangerth, November 1997
+ */
+class ExceptionBase {
+ public:
+ ExceptionBase () {};
+ /**
+ * The constructor takes the file in which the
+ * error happened, the line and the violated
+ * condition as well as the name of the
+ * exception class as a #char*# as arguments.
+ */
+ ExceptionBase (const char* f, const int l, const char *func,
+ const char* c, const char *e) :
+ file(f), line(l), function(func), cond(c), exc(e) {};
+
+ /**
+ * Set the file name and line of where the
+ * exception appeared as well as the violated
+ * condition and the name of the exception as
+ * a char pointer.
+ */
+ void SetFields (const char* f,
+ const int l,
+ const char *func,
+ const char *c,
+ const char *e) {
+ file = f;
+ line = l;
+ function = func;
+ cond = c;
+ exc = e;
+ };
+ /**
+ * Print out the general part of the error
+ * information.
+ */
+ void PrintExcData (ostream &out) const {
+ out << "An error occurred in line <" << line
+ << "> of file <" << file
+ << "> in function" << endl
+ << " " << function << endl
+ << "The violated condition was: "<< endl
+ << " " << cond << endl
+ << "The name and call sequence of the exception was:" << endl
+ << " " << exc << endl
+ << "Additional Information: " << endl;
+ };
+
+ /**
+ * Print more specific information about the
+ * exception which occured. Overload this
+ * function in your own exception classes.
+ * Since we use templates rather than derivation
+ * information, we need not declare this
+ * function as #virtual# and thus avoid problems
+ * with virtual functions in classes in which
+ * all functions are declared inline.
+ */
+ void PrintInfo (ostream &out) const {
+ out << "(none)" << endl;
+ };
+
+
+ const char *file;
+ int line;
+ const char *function;
+ const char *cond;
+ const char *exc;
+};
+
+
+ /**
+ * This routine does the main work for the
+ * exception generation mechanism.
+ *
+ * @see Assert
+ */
+template <class exc>
+void __IssueError (const char *file,
+ int line,
+ const char *function,
+ const char *cond,
+ const char *exc,
+ exc e) {
+ // Fill the fields of the exception object
+ e.SetFields (file, line, function, cond, exc);
+ cerr << "--------------------------------------------------------"
+ << endl;
+ // print out general data
+ e.PrintExcData (cerr);
+ // print out exception specific data
+ e.PrintInfo (cerr);
+ cerr << "--------------------------------------------------------"
+ << endl;
+
+ abort ();
+ };
+
+
+
+#ifdef DEBUG ////////////////////////////////////////
+
+/**
+ This is the main routine in the exception mechanism.
+ Use it in the following way: declare an exception
+ class using the #DeclException# macros (see there),
+ for example
+ \begin{verbatim}
+ DeclException2 (ExcDomain, int, int,
+ << "Index= " << arg1 << "Upper Bound= " << arg2);
+ \end{verbatim}
+ to declare an exception class named #ExcDomain#, which
+ has two variables as additional information (named
+ #arg1# and #arg2# by default) and which outputs the
+ given sequence (which is appended to an #ostream#
+ variable's name, thus the weird syntax). There are
+ other #DeclExceptionN# macros for exception classes
+ with more or no parameters. It is proposed to let start
+ the name of all exceptions by #Exc...#.
+
+ In your source code write lines like
+ \begin{verbatim}
+ Assert (n<dim, ExcDomain(n,dim));
+ \end{verbatim}
+ which does the following:
+ \begin{verbatim}
+ #ifdef DEBUG
+ if (!cond)
+ issue error of class ExcDomain(n,dim)
+ #else
+ do nothing
+ #endif
+ \end{verbatim}
+ i.e. it issues an error only if the preprocessor variable
+ #DEBUG# is set and if the given condition (in this case
+ #n<dim# is violated.
+
+ If the exception was declared using the #DeclException0 (...)#
+ macro, i.e. without any additional parameters, its name has
+ nonetheless to be given with parentheses:
+ #Assert (i>m, ExcSomewhat());#
+
+ {\bf How it works internally:}
+ The call #Assert (cond, exc);#
+ is converted by the preprocessor into the sequence
+ \begin{verbatim}
+ if (!(cond))
+ __IssueError (__FILE__,
+ __LINE__,
+ __PRETTY_FUNCTION__,
+ #cond,
+ #exc,
+ &exc);
+ \end{verbatim}
+ i.e. if the given condition is violated, then the file and
+ line in which the exception occured as well as
+ the condition itself and the call sequence of the
+ exception object is transferred. Additionally an object
+ of the form given by #exc# is created (this is normally an
+ unnamed object like in #ExcDomain (n, dim)# of class
+ #ExcDomain#) and transferred to the #__IssueError#
+ function.
+
+ #__PRETTY__FUNCTION__# is a macro defined only by the GNU CC
+ compiler and gives the name of the function. If another compiler
+ is used, we set #__PRETTY_FUNCTION__ = "(unknown)"#.
+
+ In #__IssueError# the given data
+ is transferred into the #exc# object by calling the
+ #SetFields# function; after that, the general error info
+ is printed onto #cerr# using the #PrintError# function of
+ #exc# and finally the exception specific data is printed
+ using the user defined function #PrintError# (which is
+ normally created using the #DeclException (...)# macro
+ family.
+
+ After printing all this information, #abort()# is called.
+ This may in future versions be replaced by calling
+ #throw exc;#.
+
+ If the preprocessor variable #DEBUG# is not set, then nothing
+ happens, i.e. the macro is expanded to #(void) 0;#.
+
+ @memo Assert that a certain condition is fulfilled, otherwise
+ issue an error and abort the program.
+
+ @see DeclException0
+ @author Wolfgang Bangerth, November 1997
+ */
+#define Assert(cond, exc) \
+ if (!(cond)) \
+ __IssueError (__FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, #cond, #exc, exc)
+
+
+#else ////////////////////////////////////////
+
+#define Assert(cond, exc) \
+ (void) 0
+#endif ////////////////////////////////////////
+
+
+
+/**
+ Declare an exception class without any additional parameters.
+ There is a whole family of #DeclException?# macros
+ where #?# is to be replaced by the number of additional
+ parameters (0 to 5 presently).
+
+ The syntax is as follows:
+ \begin{verbatim}
+ DeclException2 (ExcDomain,
+ int,
+ int,
+ << " i=" << arg1 << ", m=" << arg2);
+ \end{verbatim}
+ The first is the name of the exception class to be created.
+ The next arguments are the types of the parameters (in this
+ case there are two type names needed) and finally the output
+ sequence with which you can print additional information.
+
+ The syntax of the output sequence is a bit weird but gets
+ clear once you see how this macro is defined:
+ \begin{verbatim}
+ class name : public ExceptionBase {
+ public:
+ name (const type1 a1, const type2 a2) :
+ arg1 (a1), arg2(a2) {};
+ void PrintInfo (ostream &out) const {
+ out outsequence << endl;
+ };
+ private:
+ type1 arg1;
+ type2 arg2;
+ };
+ \end{verbatim}
+ The #PrintInfo# function is not declared #virtual# since we would
+ then create a class with virtual functions and only inlined code.
+ For this kind of class at least GNU C++ does not know where to put
+ the virtual method table and the program will not be compiled.
+
+ If declared as specified, you can later use this exception class
+ in the following manner:
+ \begin{verbatim}
+ int i=5;
+ int m=3;
+ Assert (i<m, MyExc2(i,m));
+ \end{verbatim}
+ and the output if the condition fails will be
+ \begin{verbatim}
+ --------------------------------------------------------
+ An error occurred in line <301> of file <exc-test.cc>.
+ The violated condition was:
+ i<m
+ The name and call sequence of the exception was:
+ MyExc2(i,m)
+ Additional Information:
+ i=5, m=3
+ --------------------------------------------------------
+ \end{verbatim}
+
+ Obviously for the #DeclException0(name)# macro, no types and
+ also no output sequence is allowed.
+
+ @author Wolfgang Bangerth, November 1997
+ */
+#define DeclException0(Exception0) \
+class Exception0 : public ExceptionBase {};
+
+ /**
+ * Declare an exception class with
+ * one additional parameter.
+ *
+ * @see DeclException0
+ */
+#define DeclException1(Exception1, type1, outsequence) \
+class Exception1 : public ExceptionBase { \
+ public: \
+ Exception1 (const type1 a1) : arg1 (a1) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+}
+
+ /**
+ * Declare an exception class with
+ * two additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException2(Exception2, type1, type2, outsequence) \
+class Exception2 : public ExceptionBase { \
+ public: \
+ Exception2 (const type1 a1, const type2 a2) : \
+ arg1 (a1), arg2(a2) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+}
+
+ /**
+ * Declare an exception class with
+ * three additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException3(Exception3, type1, type2, type3, outsequence) \
+class Exception3 : public ExceptionBase { \
+ public: \
+ Exception3 (const type1 a1, const type2 a2, const type3 a3) : \
+ arg1 (a1), arg2(a2), arg3(a3) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+ const type3 arg3; \
+}
+
+ /**
+ * Declare an exception class with
+ * four additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException4(Exception4, type1, type2, type3, type4, outsequence) \
+class Exception4 : public ExceptionBase { \
+ public: \
+ Exception4 (const type1 a1, const type2 a2, \
+ const type3 a3, const type4 a4) : \
+ arg1 (a1), arg2(a2), arg3(a3), arg4(a4) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+ const type3 arg3; \
+ const type4 arg4; \
+}
+
+ /**
+ * Declare an exception class with
+ * five additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException5(Exception5, type1, type2, type3, type4, type5, outsequence) \
+class Exception5 : public ExceptionBase { \
+ public: \
+ Exception5 (const type1 a1, const type2 a2, const type3 a3, \
+ const type4 a4, const type5 a5) : \
+ arg1 (a1), arg2(a2), arg3(a3), arg4(a4), arg5(a5) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+ const type3 arg3; \
+ const type4 arg4; \
+ const type5 arg5; \
+}
+
+
+
+
+
+
+/*---------------------------- exceptions.h ---------------------------*/
+/* end of #ifndef __exceptions_H */
+#endif
+/*---------------------------- exceptions.h ---------------------------*/