// This may look like C code, but it is really -*- C++ -*-
#ifndef PEXCEPTIONS_SEEN
#define PEXCEPTIONS_SEEN

#include "machdefs.h"
#include <string>

using namespace std;

namespace SOPHYA {

  // Ancestor for PError and PException
  // It has a message, and an id to give more
  // information on the exception.
  class PThrowable {
  public:
    explicit PThrowable(const string& m, int ident=0) 
      : msg(m), id(ident) {}
    virtual ~PThrowable() { }
    virtual string const& Msg() const  {return msg;}
  private:
    string msg;
    int    id;
  };
  
  // A PError is a serious logic error. Usually not caught...
  class PError : public PThrowable {
  public:
    explicit PError(const string& m, int id=0) : PThrowable(m,id) {}
  };
  
  // A PException is not as serious... Can be caught.
  class PException : public PThrowable {
  public:
    explicit PException(const string& m, int id=0) : PThrowable(m,id) {}
  };
  
  // Errors
  // Memory allocation failure
  class AllocationError : public PError {
  public:
    explicit AllocationError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // Null pointer error
  class NullPtrError : public PError {
  public:
    explicit NullPtrError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // Size mismatch between objects
  class SzMismatchError : public PError {
  public:
    explicit SzMismatchError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // Out of bounds for array, matrix, etc.
  class RangeCheckError : public PError {
  public:
    explicit RangeCheckError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // Invalid parameter to method/constructor...
  class ParmError : public PError {
  public:
    explicit ParmError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // Calling a forbidden method, trying a forbidden operation
  class ForbiddenError : public PError {
  public:
    explicit ForbiddenError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // ASSERT macro failure. The message is the assertion...
  class AssertionFailedError : public PError {
  public:
    explicit AssertionFailedError(const string& m, int id=0) : PError(m,id) {}
  };
  
  // Standard exceptions
  //
  // PException
  //   IOExc
  //     FileFormatExc
  //   TypeMismatchExc
  //   DuplicateIdExc
  //   NotFoundExc
  //   MathExc
  //     SingMatxExc
  
  // generic IO Exception
  class IOExc : public PException {
  public:
    explicit IOExc(const string& m, int id=0) : PException(m,id) {}
  };

  // Bad type -> keep ?
  class TypeMismatchExc : public PException {
  public:
    explicit TypeMismatchExc(const string& m, int id=0) : PException(m,id) {}
  };
  
  class MathExc : public PException {
  public:
    explicit MathExc(const string& m, int id=0) : PException(m,id) {}
  };
  
  class DuplicateIdExc : public PException {
  public:
    explicit DuplicateIdExc(const string& m, int id=0) : PException(m,id) {}
  };
  
  class NotFoundExc : public PException {
  public:
    explicit NotFoundExc(const string& m, int id=0) : PException(m,id) {}
  };
  
  class CaughtSignalExc : public PException {
  public:
    explicit CaughtSignalExc(const string& m, int id=0) : PException(m,id) {}
  };

  // Bad file format
  class FileFormatExc : public IOExc {
  public:
    explicit FileFormatExc(const string& m, int id=0) : IOExc(m,id) {}
  };
  
  class SingMatrixExc : public MathExc {
  public:
    explicit SingMatrixExc(const string& m, int id=0) : MathExc(m,id) {}
  };
  
  
}


#define ASSERT(_a_) if (!(_a_)) { \
     cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \
          << endl; \
		     throw(AssertionFailedError(#_a_)); }
   
#define FAILNIL(_x_) \
       {if (!(_x_)) throw(NullPtrError(#_x_))}

void InitFailNewHandler();
  
     
// Compatibility with EROS-PEIDA exceptions

#define EXC_ABORT_NEG(_x)
#define EXC_ABORT_ALL(_x)

#define EXC_AWARE

#define END_CONSTRUCTOR

#define TRY try
#define CATCH(_var) catch(long _var)
#define CATCHALL catch(...)
#define ENDTRY

#define THROW(_i) throw( _i);

#define THROW_ THROW(0)

#define THROW_SAME throw;

#define RETURN(x) return(x)
#define RETURN_ return

#define rangeCheckErr    RangeCheckError("")
#define typeMismatchErr  TypeMismatchExc("")
#define allocationErr    AllocationError("")
#define parmErr          ParmError("")
#define inconsistentErr  ParmError("")
#define sizeMismatchErr  SzMismatchError("")
#define fileErr          IOExc("")
#define nullPtrErr       NullPtrError("")
#define singMatxErr      SingMatrixExc("")

#define DBASSERT(_x_) ASSERT(_x_)

#endif
