home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tlx501.zip / SRC / ASSERTS.CPP next >
C/C++ Source or Header  |  1996-07-08  |  14KB  |  412 lines

  1. /****************************************************************************
  2.     $Id: asserts.cpp 501.0 1995/03/07 12:26:06 RON Exp $
  3.  
  4.     Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
  5.  
  6.     Project:    Tarma Library for C++ V5.0
  7.     Author:    Ron van der Wal
  8.  
  9.     Implementation of class TLAssert. The implementation of its functions
  10.     depends on the platform:
  11.  
  12.     - MS-DOS prints to stderr
  13.     - Macintosh pops up a message box
  14.     - OS/2 command line version prints to stderr
  15.     - OS/2 Presentation Manager version pops up message box
  16.     - Windows pops up a message box
  17.  
  18.     $Log: asserts.cpp $
  19.     Revision 501.0  1995/03/07 12:26:06  RON
  20.     Updated for TLX 5.01
  21.     Revision 1.12  1995/01/31 16:30:02  RON
  22.     Update for release 012
  23.     Added partial support for SunPro C++ compiler
  24.     Revision 1.11  1995/01/18  19:00:08  ron
  25.     Added support for _GUI preprocessor name
  26.  
  27.     Revision 1.10  1995/01/10  16:31:14  ron
  28.     Small formatting changes
  29.  
  30.     Revision 1.9  1995/01/06  15:57:21  ron
  31.     Corrected Revision keyword
  32.  
  33.     Revision 1.8  1995/01/05  15:19:36  ron
  34.     Added Ensure() functions
  35.  
  36.     Revision 1.7  1994/11/16  15:35:35  ron
  37.     Made global functions into static members of TLAssert
  38.     Added module info; rearranged #include directives
  39.  
  40.     Revision 1.6  1994/10/05  18:33:17  ron
  41.     Renamed TLx...() functions to tl...()
  42.  
  43.     Revision 1.5  1994/09/28  14:12:06  ron
  44.     Removed Macintosh-style #include references
  45.  
  46.     Revision 1.4  1994/09/27  20:21:54  ron
  47.     Changed path separator from / to \
  48.  
  49.     Revision 1.3  1994/09/26  15:38:24  ron
  50.     Moved code around
  51.  
  52.     Revision 1.2  1994/09/06  14:09:32  ron
  53.     Replaced exit() in ABORT action by throw TLXAssert
  54.  
  55.     Revision 1.1  1994/08/16  18:12:51  ron
  56.     Initial revision
  57.  
  58. ****************************************************************************/
  59.  
  60. #include <tlx\501\_build.h>
  61.  
  62. TLX_MODULE_INFO("$Revision: 501.0 $");
  63.  
  64. #include <stdarg.h>
  65. #include <stdlib.h>
  66. #include <tlx\501\except.h>
  67.  
  68. #ifndef _GUI
  69.     #include <ctype.h>
  70.     #include <stdio.h>
  71. #elif OS_MAC
  72.     #include <stdio.h>
  73.     #include <string.h>
  74.     #include <pascal.h>
  75.     #define ALRT_ASSERT 30000    // ALRT resource ID
  76. #elif OS_WINXXX
  77.     #include <string.h>
  78.     #include <windows.h>
  79. #endif
  80.  
  81. /*-------------------------------------------------------------------------*/
  82.     void TLAssert::AssertFailed(const char *aFile, int aLine)
  83.  
  84. /*  Called when a general assertion has failed. It displays an appropriate
  85.     diagnostic message and lets the user choose how to continue.
  86. ---------------------------------------------------------------------------*/
  87. {
  88.     Diagnostic(dfError, aFile, aLine, "Assertion failed");
  89. }
  90.  
  91. /*-------------------------------------------------------------------------*/
  92.     void TLAssert::CheckFailed(const char *aFile, int aLine)
  93.  
  94. /*  Called when a general check has failed. It displays an appropriate
  95.     diagnostic message and lets the user choose how to continue.
  96. ---------------------------------------------------------------------------*/
  97. {
  98.     Diagnostic(dfWarning, aFile, aLine, "Check failed");
  99. }
  100.  
  101. /*-------------------------------------------------------------------------*/
  102.     void TLAssert::Diagnostic(
  103.         int         aSeverity,     // Severity of the diagnostic
  104.     const char *    aFile,         // File name of the diagnostic
  105.     int         aLine,         // Line number
  106.     const char *    aFmt,         // printf-style format string
  107.     ...                // Format arguments
  108.     )
  109.  
  110. /*  Performs the actual diagnostic output. It accepts various parameters from
  111.     which to paste together the entire diagnostic message. After the message
  112.     is displayed, the function gives the user the choice whether to abort or
  113.     to continue the program.
  114. ----------------------------------------------------------------------------*/
  115. {
  116.     //lint -e606    (Do not complain about '\p')
  117.  
  118.     // Continuation choices after a diagnostic message
  119.     #define DO_ABORT    1
  120.     #define DO_BREAK    2
  121.     #define DO_CONTINUE    3
  122.  
  123.     const char *title = "Tarma Library for C++ diagnostic";
  124.     int result = DO_ABORT;
  125.     va_list args;
  126.     va_start(args, aFmt);
  127.  
  128.   #ifndef _GUI
  129.  
  130.     const BUFSIZE = 256;
  131.     char buf[BUFSIZE];
  132.     const char *sev;
  133.  
  134.     switch (aSeverity)
  135.     {
  136.     case dfInfo:
  137.         sev = "[Info] ";
  138.         result = DO_CONTINUE;
  139.         break;
  140.     case dfWarning:
  141.         sev = "[Warn] ";
  142.         result = DO_CONTINUE;
  143.         break;
  144.     case dfError:
  145.         sev = "[Error] ";
  146.         result = DO_ABORT;
  147.         break;
  148.     case dfFatal:
  149.         sev = "[Fatal] ";
  150.         result = DO_ABORT;
  151.         break;
  152.     default:
  153.         sev = "[-----] ";
  154.         result = DO_CONTINUE;
  155.         break;
  156.     }
  157.  
  158.     fprintf(stderr, "\n***** %s *****\n\n%s", title, sev);
  159.     vfprintf(stderr, aFmt, args);
  160.     fprintf(stderr, "\n\nFile: %s\nLine: %d\n", aFile, aLine);
  161.     fprintf(stderr, "\nAbort, Break, or Continue (A/B/C)? ");
  162.     fflush(stderr);
  163.     gets(buf);
  164.  
  165.     // Default case has been set up above
  166.     switch (toupper(buf[0]))
  167.     {
  168.     default:
  169.     case 'A':
  170.         result = DO_ABORT;
  171.         break;
  172.     case 'B':
  173.         result = DO_BREAK;
  174.         break;
  175.     case 'C':
  176.         result = DO_CONTINUE;
  177.         break;
  178.     }
  179.  
  180.   #elif OS_MAC
  181.  
  182.     const BUFSIZE = 256;
  183.     char msgBuf[BUFSIZE];
  184.     char fileBuf[BUFSIZE];
  185.     unsigned char lineBuf[12];
  186.  
  187.     // ALRT resource layout:
  188.     //
  189.     //    ^0 = Assertion text
  190.     //    ^1 = Source file name
  191.     //    ^2 = Source line number
  192.     //
  193.     // Note: the following vsprintf() might have difficulty interpreting
  194.     // integers (%d and %u) in the format string under THINK C, because
  195.     // the THINK C implementation of the printf() family assumes 2-byte
  196.     // integer arguments for these formats. However, TLX is compiled with
  197.     // 4-byte integers under THINK C for compatibility with Symantec C++,
  198.     // and all 'int' and 'unsigned int' are therefore 4 bytes. The safest
  199.     // way is NOT to use %d and %u specifiers for integers, but %ld and %lu.
  200.     // For short integers, there should not be a problem.. (Or are they
  201.     // converted implicitly to integer, and therefore to 4 bytes as well??)
  202.  
  203.     vsprintf(msgBuf, aFmt, args);
  204.     strncpy(fileBuf, aFile, 128);
  205.     NumToString(aLine, lineBuf);
  206.  
  207.     ParamText(CtoPstr(msgBuf), CtoPstr(fileBuf), lineBuf, "\p");
  208.     StopAlert(ALRT_ASSERT, NULL);
  209.  
  210.   #elif OS_WINXXX
  211.  
  212.     const BUFSIZE = 512;
  213.     char vBuffer[BUFSIZE];
  214.     int mbFlags;
  215.  
  216.     wvsprintf(vBuffer, aFmt, args);
  217.     wsprintf(&vBuffer[strlen(vBuffer)], "\n\nFile: %s\nLine: %d", aFile, aLine);
  218.  
  219.     switch (aSeverity)
  220.     {
  221.     case dfInfo:
  222.         mbFlags = MB_OK | MB_ICONINFORMATION;
  223.         break;
  224.     case dfWarning:
  225.         mbFlags = MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_DEFBUTTON3;
  226.         break;
  227.     case dfError:
  228.     case dfFatal:
  229.     default:
  230.         mbFlags = MB_ABORTRETRYIGNORE | MB_ICONSTOP | MB_DEFBUTTON3;
  231.         break;
  232.     }
  233.  
  234.     switch (MessageBox(0, vBuffer, title, MB_TASKMODAL | mbFlags))
  235.     {
  236.     case IDABORT:        // Abort - stays abort
  237.         result = DO_ABORT;
  238.         break;
  239.     case IDRETRY:        // Retry - converted to Break
  240.         result = DO_BREAK;
  241.         break;
  242.     case IDIGNORE:        // Ignore - converted to Continue
  243.     case IDOK:        // OK - converted to continue
  244.         result = DO_CONTINUE;
  245.         break;
  246.     default:
  247.         TLX_ASSERT_UNREACHABLE;
  248.         result = DO_ABORT;
  249.         break;
  250.     }
  251.  
  252.   #else
  253.     #error Unsupported platform; contact Tarma Software Research
  254.   #endif
  255.  
  256.     va_end(args);
  257.  
  258.     // Deal with user's response.
  259.     switch (result)
  260.     {
  261.     case DO_BREAK:
  262.         TLX_DEBUG_BREAK;    // Invokes debugger
  263.         break;
  264.     case DO_CONTINUE:    // Just pretend nothing happened
  265.         break;
  266.     case DO_ABORT:
  267.         THROW(TLXAssert(TLXLocus(aFile, aLine)));
  268.         // FALL THROUGH - if 'throw' isn't supported
  269.     default:
  270.         TLX_ASSERT_UNREACHABLE;
  271.         break;
  272.     }
  273. }
  274.  
  275. /*-------------------------------------------------------------------------*/
  276.     void TLAssert::EnsureFailed(const char *aFile, int aLine)
  277.  
  278. /*  Called when a postcondition has failed. It displays an appropriate
  279.     diagnostic message and lets the user choose how to continue.
  280. ---------------------------------------------------------------------------*/
  281. {
  282.     Diagnostic(dfError, aFile, aLine, "Postcondition failed");
  283. }
  284.  
  285. /*-------------------------------------------------------------------------*/
  286.     void TLAssert::EnsureNullPtrFailed(const char *aFile, int aLine)
  287.  
  288. /*  Called when a non-NULL pointer has been detected during an assertion. It
  289.     displays an error diagnostic to that effect.
  290. ---------------------------------------------------------------------------*/
  291. {
  292.     Diagnostic(dfError, aFile, aLine,
  293.                "Postcondition failed: NULL pointer expected");
  294. }
  295.  
  296. /*-------------------------------------------------------------------------*/
  297.     void TLAssert::EnsurePtrFailed(const char *aFile, int aLine)
  298.  
  299. /*  Called when a NULL pointer has been detected during an assertion. It
  300.     displays an error diagnostic to that effect.
  301. ---------------------------------------------------------------------------*/
  302. {
  303.     Diagnostic(dfError, aFile, aLine,
  304.                "Precondition failed: valid pointer expected");
  305. }
  306.  
  307. /*-------------------------------------------------------------------------*/
  308.     void TLAssert::NotImplemented(
  309.         const char *    aMsg,        // Describes not implemented feature
  310.     const char *    aFile,         // Filename
  311.     int         aLine        // Line number
  312.     )
  313.  
  314. /*  Called when a piece of code is executed that is not fully implemented.
  315.     It displays an informational diagnostic describing the missing feature.
  316. ---------------------------------------------------------------------------*/
  317. {
  318.     Diagnostic(dfInfo, aFile, aLine, "\"%s\" not implemented", aMsg);
  319. }
  320.  
  321. /*-------------------------------------------------------------------------*/
  322.     void TLAssert::NullPtrCheck(const char *aFile, int aLine)
  323.  
  324. /*  Called when a non-NULL pointer has been detected during a check. It
  325.     displays a warning diagnostic to that effect.
  326. ---------------------------------------------------------------------------*/
  327. {
  328.     Diagnostic(dfWarning, aFile, aLine, "Pointer should be NULL");
  329. }
  330.  
  331. /*-------------------------------------------------------------------------*/
  332.     void TLAssert::NullPtrFailed(const char *aFile, int aLine)
  333.  
  334. /*  Called when a non-NULL pointer has been detected during an assertion. It
  335.     displays an error diagnostic to that effect.
  336. ---------------------------------------------------------------------------*/
  337. {
  338.     Diagnostic(dfError, aFile, aLine, "Pointer should be NULL");
  339. }
  340.  
  341. /*-------------------------------------------------------------------------*/
  342.     void TLAssert::PtrCheck(const char *aFile, int aLine)
  343.  
  344. /*  Called when a NULL pointer has been detected during a check. It displays
  345.     a warning diagnostic to that effect.
  346. ---------------------------------------------------------------------------*/
  347. {
  348.     Diagnostic(dfWarning, aFile, aLine, "Unexpected NULL pointer");
  349. }
  350.  
  351. /*-------------------------------------------------------------------------*/
  352.     void TLAssert::PtrFailed(const char *aFile, int aLine)
  353.  
  354. /*  Called when a NULL pointer has been detected during an assertion. It
  355.     displays an error diagnostic to that effect.
  356. ---------------------------------------------------------------------------*/
  357. {
  358.     Diagnostic(dfError, aFile, aLine, "Unexpected NULL pointer");
  359. }
  360.  
  361. /*-------------------------------------------------------------------------*/
  362.     void TLAssert::Reached(const char *aFile, int aLine)
  363.  
  364. /*  Called when an unreachable statement has been executed.  It displays an
  365.     error diagnostic to that effect.
  366. ---------------------------------------------------------------------------*/
  367. {
  368.     Diagnostic(dfError, aFile, aLine, "Unreachable code reached");
  369. }
  370.  
  371. /*-------------------------------------------------------------------------*/
  372.     void TLAssert::RequireFailed(const char *aFile, int aLine)
  373.  
  374. /*  Called when a precondition has failed. It displays an appropriate
  375.     diagnostic message and lets the user choose how to continue.
  376. ---------------------------------------------------------------------------*/
  377. {
  378.     Diagnostic(dfError, aFile, aLine, "Precondition failed");
  379. }
  380.  
  381. /*-------------------------------------------------------------------------*/
  382.     void TLAssert::RequireNullPtrFailed(const char *aFile, int aLine)
  383.  
  384. /*  Called when a non-NULL pointer has been detected during an assertion. It
  385.     displays an error diagnostic to that effect.
  386. ---------------------------------------------------------------------------*/
  387. {
  388.     Diagnostic(dfError, aFile, aLine,
  389.                "Precondition failed: NULL pointer expected");
  390. }
  391.  
  392. /*-------------------------------------------------------------------------*/
  393.     void TLAssert::RequirePtrFailed(const char *aFile, int aLine)
  394.  
  395. /*  Called when a NULL pointer has been detected during an assertion. It
  396.     displays an error diagnostic to that effect.
  397. ---------------------------------------------------------------------------*/
  398. {
  399.     Diagnostic(dfError, aFile, aLine,
  400.                "Precondition failed: valid pointer expected");
  401. }
  402.  
  403. /*-------------------------------------------------------------------------*/
  404.     void TLAssert::ToDo(const char *aMsg, const char *aFile, int aLine)
  405.  
  406. /*  Called when a piece of code is executed that is incomplete. It displays
  407.     an informational message describing the missing piece.
  408. ---------------------------------------------------------------------------*/
  409. {
  410.     Diagnostic(dfInfo, aFile, aLine, "To do: %s", aMsg);
  411. }
  412.