/***************************************************************************** # Copyright (C) 1994-2008 by David Gordon. # All rights reserved. # # This software is part of a beta-test version of the Consed/Autofinish # package. It should not be redistributed or # used for any commercial purpose, including commercially funded # sequencing, without written permission from the author and the # University of Washington. # # This software is provided ``AS IS'' and any express or implied # warranties, including, but not limited to, the implied warranties of # merchantability and fitness for a particular purpose, are disclaimed. # In no event shall the authors or the University of Washington be # liable for any direct, indirect, incidental, special, exemplary, or # consequential damages (including, but not limited to, procurement of # substitute goods or services; loss of use, data, or profits; or # business interruption) however caused and on any theory of liability, # whether in contract, strict liability, or tort (including negligence # or otherwise) arising in any way out of the use of this software, even # if advised of the possibility of such damage. # # Building Consed from source is error prone and not simple which is # why I provide executables. Due to time limitations I cannot # provide any assistance in building Consed. Even if you do not # modify the source, you may introduce errors due to using a # different version of the compiler, a different version of motif, # different versions of other libraries than I used, etc. For this # reason, if you discover Consed bugs, I can only offer help with # those bugs if you first reproduce those bugs with an executable # provided by me--not an executable you have built. # # Modifying Consed is also difficult. Although Consed is modular, # some modules are used by many other modules. Thus making a change # in one place can have unforeseen effects on many other features. # It may takes months for you to notice these other side-effects # which may not seen connected at all. It is not feasable for me to # provide help with modifying Consed sources because of the # potentially huge amount of time involved. # #*****************************************************************************/ // // exceptions.h // // Exception classes provide objects that can differentiate // between a few basic types of exception and provide a // string describing what happened. // // note that the constructor for the base class always calls // member function breakpoint() first, then derivedBreakpoint() // second. for debugging you can set a breakpoint at the // first ("b ExceptionBase::breakpoint()") or at the // the derived class ("b ProgramLogicError::derivedBreakpoint()"). // the idea is to make it easy to intercept the exception // once you know it's coming, then fix the problem if neccessary. // NOTE: to break in inlined procedures may require platform-specific // compilation switches. // // exceptions can be instantiated like any other object before // being thrown, but in many cases the PANIC_EX macro is better. // this variant on the classic PANIC macro instantiates an // ostrstream object and brands it with using the __FILE__ and // __LINE__ directives. Unfortunately, because of a bug // in HP C++ the ostrstream object could not be included in // the exception class. // // some examples: // // // something bad is detected... // // throw(ProgramLogicError("data totally messed up")); // // or... // // PANIC_OST(o) < "data messed up - index " << nIndex << "bad"; // throw ProgramLogicError(o.str()); // // or any variation. note that you can mix and match your own // macros, e.g. // // #define PARSE_PANIC(a,b) \ // { \ // PANIC_OST(o) << " line = " << a << " token# = " << b << endl; \ // InputDataError ple(o.str()); \ // throw ple; \ // } // // ... // // PARSE_PANIC(nLine,nToken); // // etc. // #ifndef EXCEPTIONS_INCLUDED #define EXCEPTIONS_INCLUDED #ifdef SCCS_ID static const char* exceptionsSccsId = "@(#)exception.h 1.7 09/15/95 03:56:08"; #endif #include #include #include #include #include "rwcstring.h" #include "soGetErrno.h" //#include "sysdepend.h" #define PANIC_OST( ost ) ostrstream ost; ost << "File '" << __FILE__ << "', line " << __LINE__ << " " #define THROW_ERROR( szError ) { ostrstream ost; \ ost << szError << endl << ends; \ InputDataError ide( ost.str() ); \ throw ide; } // this macro is better for debugging since it has the file and line, but // isn't as good for user errors since the error messages are longer. #define THROW_ERROR2( szError ) { ostrstream ost; \ ost << szError << endl << "(File '" << __FILE__ << "', line " << __LINE__ << \ ")" << ends; \ InputDataError ide( ost.str() ); \ throw ide; } #define THROW_NOT_ENOUGH_MEMORY {\ RWCString soErrorMessage;\ soErrorMessage = soErrorMessage + "Consed: out of memory on heap (datasize)\nmalloc did not return requested memory.\nThere is not enough datasize (heap).\nThere may not be enough physical memory, or else\nthere may be a software limit imposed on this process.\nWith tcsh, use type: limit to see what you are currently using.\nThen type: limit datasize unlimited.\nThere may be another limit imposed by the kernel which might need to be modified.\nError from file '" + __FILE__ + "', line " + __LINE__;\ SysRequestFailed srf( soErrorMessage );\ throw srf;} #define THROW_FILE_ERROR( szFileName ) { ostrstream ost; \ ost << "could not open file " << szFileName << " due to error " << \ soGetErrno() << endl << "Error from file " << __FILE__ << " line " << \ __LINE__ << endl << ends; \ InputDataError ide( ost.str() ); \ throw ide; } // base class. these can be caught if needed but generally // the derived classes will be more useful (informative) to throw. class ExceptionBase { public: ExceptionBase() : bUserHasBeenNotified_(false) { breakpoint(); } ExceptionBase(const char* szDesc) : soDesc_(szDesc), bUserHasBeenNotified_(false) { breakpoint(); } ~ExceptionBase() {} // returns a string containing the accumulated contents // of the string object const char* szGetDesc() const { return soDesc_; } // instead of using the constructor, you can // append strings to the description with this void addStringToDesc(const char* szDescToAdd) { if (szDescToAdd) soDesc_ += szDescToAdd; } // does nothing, just insures breakpoints available for // debugging. void breakpoint(); // this flag indicates whether the user has been notified // of the exception (presumably by means of an error dialog box) // if an exception gets re-thrown, this can be used to prevent // multiple notices bool bUserNotified() const { return bUserHasBeenNotified_; } void setUserNotified() { bUserHasBeenNotified_ = true; } public: RWCString soDesc_; // client supplied description bool bUserHasBeenNotified_; // should be set when user shown dibox }; // exceptions for program logic error. this should be // used in place of 'assert' - it has all the same // functionality but is potentially recoverable class ProgramLogicError : public ExceptionBase { public: ProgramLogicError() {} ProgramLogicError(const char* szDesc) : ExceptionBase(szDesc) {} }; class RWInternalError : public ExceptionBase { public: RWInternalError(); RWInternalError(const char* szDesc); }; // exceptions for bad user input, either interactive or in a file // (i.e. parse error in .ace file) class InputDataError : public ExceptionBase { public: InputDataError() {} InputDataError(const char* szDesc) : ExceptionBase(szDesc) {} }; // exceptions for system request failing, such as file operation // or memory allocation, system call, etc. // adds an extra call to brand the exception with errno // and its system supplied explanation. class SysRequestFailed : public ExceptionBase { public: SysRequestFailed() {} SysRequestFailed(const char* szDesc) : ExceptionBase(szDesc) {} // this will call the system utility to decode // the error number and add that string to the // message void includeErrnoDescription() { nErrno_ = errno; // preserve this - might want it later char* szErrDesc = strerror(errno); // paranoia: some os (ultrix) will return null on bad number! ostrstream ostr; if (szErrDesc) { ostr << "\nerrno = " << errno << ": " << szErrDesc << endl << ends; } else { ostr << "\nerrno = " << errno << ": bad error number!" << endl << ends; } addStringToDesc( ostr.str() ); } private: int nErrno_; }; #endif // EXCEPTIONS_INCLUDED