ncbiexpt.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:15k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbiexpt.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:09:07  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.38
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbiexpt.cpp,v 1000.2 2004/06/01 19:09:07 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Denis Vakatov, Andrei Gourianov,
  35.  *           Eugene Vasilchenko, Anton Lavrentiev
  36.  *
  37.  * File Description:
  38.  *   CException
  39.  *   CExceptionReporter
  40.  *   CExceptionReporterStream
  41.  *   CErrnoException
  42.  *   CParseException
  43.  *   + initialization for the "unexpected"
  44.  *
  45.  */
  46. #include <ncbi_pch.hpp>
  47. #include <corelib/ncbiexpt.hpp>
  48. #include <errno.h>
  49. #include <string.h>
  50. #include <stdio.h>
  51. #include <stack>
  52. #ifdef NCBI_OS_MSWIN
  53. #  include <corelib/ncbi_os_mswin.hpp>
  54. #endif
  55. BEGIN_NCBI_SCOPE
  56. /////////////////////////////////
  57. // SetThrowTraceAbort
  58. // DoThrowTraceAbort
  59. static bool s_DoThrowTraceAbort = false; //if to abort() in DoThrowTraceAbort()
  60. static bool s_DTTA_Initialized  = false; //if s_DoThrowTraceAbort is init'd
  61. extern void SetThrowTraceAbort(bool abort_on_throw_trace)
  62. {
  63.     s_DTTA_Initialized = true;
  64.     s_DoThrowTraceAbort = abort_on_throw_trace;
  65. }
  66. extern void DoThrowTraceAbort(void)
  67. {
  68.     if ( !s_DTTA_Initialized ) {
  69.         const char* str = getenv(ABORT_ON_THROW);
  70.         if (str  &&  *str)
  71.             s_DoThrowTraceAbort = true;
  72.         s_DTTA_Initialized  = true;
  73.     }
  74.     if ( s_DoThrowTraceAbort )
  75.         abort();
  76. }
  77. extern void DoDbgPrint(const char* file, int line, const char* message)
  78. {
  79.     CNcbiDiag(file, line, eDiag_Trace) << message;
  80.     DoThrowTraceAbort();
  81. }
  82. extern void DoDbgPrint(const char* file, int line, const string& message)
  83. {
  84.     CNcbiDiag(file, line, eDiag_Trace) << message;
  85.     DoThrowTraceAbort();
  86. }
  87. extern void DoDbgPrint(const char* file, int line,
  88.                        const char* msg1, const char* msg2)
  89. {
  90.     CNcbiDiag(file, line, eDiag_Trace) << msg1 << ": " << msg2;
  91.     DoThrowTraceAbort();
  92. }
  93. /////////////////////////////////////////////////////////////////////////////
  94. // CException implementation
  95. bool CException::sm_BkgrEnabled=true;
  96. CException::CException(const char* file, int line,
  97.     const CException* prev_exception,
  98.     EErrCode err_code, const string& message) throw()
  99.     :   m_ErrCode(err_code),
  100.         m_InReporter(false)
  101. {
  102.     m_Predecessor = 0;
  103.     x_Init(file,line,message,prev_exception);
  104. }
  105. CException::CException(const CException& other) throw()
  106. {
  107.     m_Predecessor = 0;
  108.     x_Assign(other);
  109. }
  110. CException::CException(void) throw()
  111. {
  112. // this only is called in case of multiple inheritance
  113.     m_ErrCode = CException::eInvalid;
  114.     m_Predecessor = 0;
  115.     m_InReporter = false;
  116.     m_Line = -1;
  117. }
  118. CException::~CException(void) throw()
  119. {
  120.     if (m_Predecessor) {
  121.         delete m_Predecessor;
  122.         m_Predecessor = 0;
  123.     }
  124. }
  125. const char* CException::GetType(void) const
  126. {
  127.     return "CException";
  128. }
  129. void CException::AddBacklog(const char* file,int line,
  130.                             const string& message)
  131. {
  132.     const CException* prev = m_Predecessor;
  133.     m_Predecessor = x_Clone();
  134.     if (prev) {
  135.         delete prev;
  136.     }
  137.     x_Init(file,line,message,0);
  138. }
  139. // ---- report --------------
  140. const char* CException::what(void) const throw()
  141. {
  142.     m_What = ReportAll();
  143.     return m_What.c_str();    
  144. }
  145. void CException::Report(const char* file, int line,
  146.                         const string& title,CExceptionReporter* reporter,
  147.                         TDiagPostFlags flags) const
  148. {
  149.     if (reporter ) {
  150.         reporter->Report(file, line, title, *this, flags);
  151.     }
  152.     // unconditionally ... 
  153.     // that is, there will be two reports
  154.     CExceptionReporter::ReportDefault(file, line, title, *this, flags);
  155. }
  156. string CException::ReportAll(TDiagPostFlags flags) const
  157. {
  158.     // invert the order
  159.     stack<const CException*> pile;
  160.     const CException* pex;
  161.     for (pex = this; pex; pex = pex->GetPredecessor()) {
  162.         pile.push(pex);
  163.     }
  164.     ostrstream os;
  165.     os << "NCBI C++ Exception:" << 'n';
  166.     for (; !pile.empty(); pile.pop()) {
  167.         //indentation
  168.         os << "    ";
  169.         os << pile.top()->ReportThis(flags) << 'n';
  170.     }
  171.     if (sm_BkgrEnabled && !m_InReporter) {
  172.         m_InReporter = true;
  173.         CExceptionReporter::ReportDefault(0, 0, "(background reporting)",
  174.                                           *this, eDPF_Trace);
  175.         m_InReporter = false;
  176.     }
  177.     return CNcbiOstrstreamToString(os);
  178. }
  179. string CException::ReportThis(TDiagPostFlags flags) const
  180. {
  181.     ostrstream os, osex;
  182.     ReportStd(os, flags);
  183.     ReportExtra(osex);
  184.     if (osex.pcount() != 0) {
  185.         os << " (" << (string)CNcbiOstrstreamToString(osex) << ')';
  186.     }
  187.     return CNcbiOstrstreamToString(os);
  188. }
  189. void CException::ReportStd(ostream& out, TDiagPostFlags flags) const
  190. {
  191.     string text(GetMsg());
  192.     string err_type(GetType());
  193.     err_type += "::";
  194.     err_type += GetErrCodeString();
  195.     SDiagMessage diagmsg(
  196.         eDiag_Error, text.c_str(), text.size(),
  197.         GetFile().c_str(), GetLine(),
  198.         flags, 0,0,0,err_type.c_str());
  199.     diagmsg.Write(out, SDiagMessage::fNoEndl);
  200. }
  201. void CException::ReportExtra(ostream& /*out*/) const
  202. {
  203.     return;
  204. }
  205. const char* CException::GetErrCodeString(void) const
  206. {
  207.     switch (GetErrCode()) {
  208.     case eUnknown: return "eUnknown";
  209.     default:       return "eInvalid";
  210.     }
  211. }
  212. CException::TErrCode CException::GetErrCode (void) const
  213. {
  214.     return typeid(*this) == typeid(CException) ?
  215.         (TErrCode) x_GetErrCode() :
  216.         (TErrCode) CException::eInvalid;
  217. }
  218. void CException::x_ReportToDebugger(void) const
  219. {
  220. #ifdef NCBI_OS_MSWIN
  221.     ostrstream os;
  222.     os << "NCBI C++ Exception:" << 'n';
  223.     os <<
  224.         GetFile() << "(" << GetLine() << ") : " <<
  225.         GetType() << "::" << GetErrCodeString() << " : "" <<
  226.         GetMsg() << "" ";
  227.     ReportExtra(os);
  228.     os << 'n';
  229.     OutputDebugString(((string)CNcbiOstrstreamToString(os)).c_str());
  230. #endif
  231.     DoThrowTraceAbort();
  232. }
  233. bool CException::EnableBackgroundReporting(bool enable)
  234. {
  235.     bool prev = sm_BkgrEnabled;
  236.     sm_BkgrEnabled = enable;
  237.     return prev;
  238. }
  239. const CException* CException::x_Clone(void) const
  240. {
  241.     return new CException(*this);
  242. }
  243. void CException::x_Init(const string& file,int line,const string& message,
  244.                         const CException* prev_exception)
  245. {
  246.     m_File = file;
  247.     m_Line = line;
  248.     m_Msg  = message;
  249.     if (!m_Predecessor && prev_exception) {
  250.         m_Predecessor = prev_exception->x_Clone();
  251.     }
  252. }
  253. void CException::x_Assign(const CException& src)
  254. {
  255.     m_InReporter = false;
  256.     x_Init(src.m_File, src.m_Line, src.m_Msg, src.m_Predecessor);
  257.     x_AssignErrCode(src);
  258. }
  259. void CException::x_AssignErrCode(const CException& src)
  260. {
  261.     m_ErrCode = typeid(*this) == typeid(src) ?
  262.         src.m_ErrCode : CException::eInvalid;
  263. }
  264. void CException::x_InitErrCode(EErrCode err_code)
  265. {
  266.     m_ErrCode = err_code;
  267.     if (m_ErrCode != eInvalid && !m_Predecessor) {
  268.         x_ReportToDebugger();
  269.     }
  270. }
  271. /////////////////////////////////////////////////////////////////////////////
  272. // CExceptionReporter
  273. const CExceptionReporter* CExceptionReporter::sm_DefHandler = 0;
  274. bool CExceptionReporter::sm_DefEnabled = true;
  275. CExceptionReporter::CExceptionReporter(void)
  276. {
  277.     return;
  278. }
  279. CExceptionReporter::~CExceptionReporter(void)
  280. {
  281.     return;
  282. }
  283. void CExceptionReporter::SetDefault(const CExceptionReporter* handler)
  284. {
  285.     sm_DefHandler = handler;
  286. }
  287. const CExceptionReporter* CExceptionReporter::GetDefault(void)
  288. {
  289.     return sm_DefHandler;
  290. }
  291. bool CExceptionReporter::EnableDefault(bool enable)
  292. {
  293.     bool prev = sm_DefEnabled;
  294.     sm_DefEnabled = enable;
  295.     return prev;
  296. }
  297. void CExceptionReporter::ReportDefault(const char* file, int line,
  298.     const string& title,const CException& ex, TDiagPostFlags flags)
  299. {
  300.     if ( !sm_DefEnabled )
  301.         return;
  302.     if ( sm_DefHandler ) {
  303.         sm_DefHandler->Report(file, line, title, ex, flags);
  304.     } else {
  305.         CNcbiDiag(file, line, eDiag_Error, flags) << title << ex;
  306.     }
  307. }
  308. /////////////////////////////////////////////////////////////////////////////
  309. // CExceptionReporterStream
  310. CExceptionReporterStream::CExceptionReporterStream(ostream& out)
  311.     : m_Out(out)
  312. {
  313.     return;
  314. }
  315. CExceptionReporterStream::~CExceptionReporterStream(void)
  316. {
  317.     return;
  318. }
  319. void CExceptionReporterStream::Report(const char* file, int line,
  320.     const string& title, const CException& ex, TDiagPostFlags flags) const
  321. {
  322.     SDiagMessage diagmsg(
  323.         eDiag_Error, title.c_str(), title.size(),
  324.         file, line, flags);
  325.     diagmsg.Write(m_Out);
  326.     m_Out << "NCBI C++ Exception:" << endl;
  327.     // invert the order
  328.     stack<const CException*> pile;
  329.     const CException* pex;
  330.     for (pex = &ex; pex; pex = pex->GetPredecessor()) {
  331.         pile.push(pex);
  332.     }
  333.     for (; !pile.empty(); pile.pop()) {
  334.         pex = pile.top();
  335.         m_Out << "    ";
  336.         m_Out << pex->ReportThis(flags) << endl;
  337.     }
  338. }
  339. /////////////////////////////////////////////////////////////////////////////
  340. // Core exceptions
  341. /////////////////////////////////////////////////////////////////////////////
  342. const char* CCoreException::GetErrCodeString(void) const
  343. {
  344.     switch (GetErrCode()) {
  345.     case eCore:       return "eCore";
  346.     case eNullPtr:    return "eNullPtr";
  347.     case eDll:        return "eDll";
  348.     case eInvalidArg: return "eInvalidArg";
  349.     default:          return CException::GetErrCodeString();
  350.     }
  351. }
  352. END_NCBI_SCOPE
  353. /*
  354.  * ===========================================================================
  355.  * $Log: ncbiexpt.cpp,v $
  356.  * Revision 1000.2  2004/06/01 19:09:07  gouriano
  357.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.38
  358.  *
  359.  * Revision 1.38  2004/05/14 13:59:27  gorelenk
  360.  * Added include of ncbi_pch.hpp
  361.  *
  362.  * Revision 1.37  2004/05/11 15:55:31  gouriano
  363.  * Change GetErrCode method prototype to return TErrCode - to be able to
  364.  * safely cast EErrCode to an eInvalid
  365.  *
  366.  * Revision 1.36  2004/04/26 14:41:23  ucko
  367.  * Drop the obsolete INLINE_CSTRERRADAPT hack.
  368.  *
  369.  * Revision 1.35  2003/10/31 19:39:46  lavr
  370.  * Elaborate R1.34 change log to include ends removal
  371.  *
  372.  * Revision 1.34  2003/10/24 13:24:55  vasilche
  373.  * Moved body of virtual method to *.cpp file; ends removed everywhere...
  374.  *
  375.  * Revision 1.33  2003/06/02 15:25:14  lavr
  376.  * Replace some endl's with 'n's; and all ''s with ends's
  377.  *
  378.  * Revision 1.32  2003/04/29 19:47:10  ucko
  379.  * KLUDGE: avoid inlining CStrErrAdapt::strerror with GCC 2.95 on OSF/1,
  380.  * due to a weird, apparently platform-specific, bug.
  381.  *
  382.  * Revision 1.31  2003/02/24 19:56:05  gouriano
  383.  * use template-based exceptions instead of errno and parse exceptions
  384.  *
  385.  * Revision 1.30  2003/02/20 17:55:19  gouriano
  386.  * added the possibility to abort a program on an attempt to throw CException
  387.  *
  388.  * Revision 1.29  2003/01/13 20:42:50  gouriano
  389.  * corrected the problem with ostrstream::str(): replaced such calls with
  390.  * CNcbiOstrstreamToString(os)
  391.  *
  392.  * Revision 1.28  2002/09/19 20:05:42  vasilche
  393.  * Safe initialization of static mutexes
  394.  *
  395.  * Revision 1.27  2002/08/20 19:11:30  gouriano
  396.  * added DiagPostFlags into CException reporting functions
  397.  *
  398.  * Revision 1.26  2002/07/29 19:29:42  gouriano
  399.  * changes to allow multiple inheritance in CException classes
  400.  *
  401.  * Revision 1.24  2002/07/15 18:17:24  gouriano
  402.  * renamed CNcbiException and its descendents
  403.  *
  404.  * Revision 1.23  2002/07/11 14:18:26  gouriano
  405.  * exceptions replaced by CNcbiException-type ones
  406.  *
  407.  * Revision 1.22  2002/06/27 18:56:16  gouriano
  408.  * added "title" parameter to report functions
  409.  *
  410.  * Revision 1.21  2002/06/26 18:38:04  gouriano
  411.  * added CNcbiException class
  412.  *
  413.  * Revision 1.20  2002/04/11 21:08:02  ivanov
  414.  * CVS log moved to end of the file
  415.  *
  416.  * Revision 1.19  2001/07/30 14:42:10  lavr
  417.  * eDiag_Trace and eDiag_Fatal always print as much as possible
  418.  *
  419.  * Revision 1.18  2001/05/21 21:44:00  vakatov
  420.  * SIZE_TYPE --> string::size_type
  421.  *
  422.  * Revision 1.17  2001/05/17 15:04:59  lavr
  423.  * Typos corrected
  424.  *
  425.  * Revision 1.16  2000/11/16 23:52:41  vakatov
  426.  * Porting to Mac...
  427.  *
  428.  * Revision 1.15  2000/04/04 22:30:26  vakatov
  429.  * SetThrowTraceAbort() -- auto-set basing on the application
  430.  * environment and/or registry
  431.  *
  432.  * Revision 1.14  1999/12/29 13:58:39  vasilche
  433.  * Added THROWS_NONE.
  434.  *
  435.  * Revision 1.13  1999/12/28 21:04:18  vasilche
  436.  * Removed three more implicit virtual destructors.
  437.  *
  438.  * Revision 1.12  1999/11/18 20:12:43  vakatov
  439.  * DoDbgPrint() -- prototyped in both _DEBUG and NDEBUG
  440.  *
  441.  * Revision 1.11  1999/10/04 16:21:04  vasilche
  442.  * Added full set of macros THROW*_TRACE
  443.  *
  444.  * Revision 1.10  1999/09/27 16:23:24  vasilche
  445.  * Changed implementation of debugging macros (_TRACE, _THROW*, _ASSERT etc),
  446.  * so that they will be much easier for compilers to eat.
  447.  *
  448.  * Revision 1.9  1999/05/04 00:03:13  vakatov
  449.  * Removed the redundant severity arg from macro ERR_POST()
  450.  *
  451.  * Revision 1.8  1999/04/14 19:53:29  vakatov
  452.  * + <stdio.h>
  453.  *
  454.  * Revision 1.7  1999/01/04 22:41:43  vakatov
  455.  * Do not use so-called "hardware-exceptions" as these are not supported
  456.  * (on the signal level) by UNIX
  457.  * Do not "set_unexpected()" as it works differently on UNIX and MSVC++
  458.  *
  459.  * Revision 1.6  1998/12/28 17:56:37  vakatov
  460.  * New CVS and development tree structure for the NCBI C++ projects
  461.  *
  462.  * Revision 1.3  1998/11/13 00:17:13  vakatov
  463.  * [UNIX] Added handler for the unexpected exceptions
  464.  *
  465.  * Revision 1.2  1998/11/10 17:58:42  vakatov
  466.  * [UNIX] Removed extra #define's (POSIX... and EXTENTIONS...)
  467.  * Allow adding strings in CNcbiErrnoException(must have used "CC -xar"
  468.  * instead of just "ar" when building a library;  otherwise -- link error)
  469.  *
  470.  * Revision 1.1  1998/11/10 01:20:01  vakatov
  471.  * Initial revision(derived from former "ncbiexcp.cpp")
  472.  *
  473.  * ===========================================================================
  474.  */