]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Exception-handling scheme
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Mon, 9 Mar 1998 16:37:25 +0000 (16:37 +0000)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Mon, 9 Mar 1998 16:37:25 +0000 (16:37 +0000)
git-svn-id: https://svn.dealii.org/trunk@46 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/base/include/base/exceptions.h [new file with mode: 0644]

diff --git a/deal.II/base/include/base/exceptions.h b/deal.II/base/include/base/exceptions.h
new file mode 100644 (file)
index 0000000..d59a487
--- /dev/null
@@ -0,0 +1,405 @@
+/*----------------------------   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     ---------------------------*/

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.