dbgrpt.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 315 行

C
315
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Runtime debug support - error reporting.
*
****************************************************************************/


#include "variety.h"
#define _DEBUG                  /* so prototypes are included */
#include <crtdbg.h>
#include <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#if defined(__NT__) || defined(__WINDOWS__)
    #include <windows.h>
#endif
#ifdef __OS2__
    #define INCL_WIN
    #include <os2.h>
#endif
#ifndef __NT__
    #ifdef __UNIX__
        #include <unistd.h>
    #else
        #include <io.h>
    #endif
#endif
#include "dbgdata.h"
#include "enterdb.h"
#include "liballoc.h"

#define MAX_MSG_LEN             512
#define TOO_LONG_MSG            "_CrtDbgReport: Message too long"
#define ASSERT_PREFIX1          "Assertion failed!"
#define ASSERT_PREFIX2          "Assertion failed: "
#define WINTITLE                "Open Watcom C/C++ Debug Library"



#if defined(__NT__) || defined(__WINDOWS__) || defined(__OS2__)

/*
 * Handle _CRTDBG_MODE_WNDW reporting.
 */
static int window_report( int reporttype, const char *filename,
                          int linenumber, const char *modulename,
                          const char *usermsg )
/***************************************************************/
{
    #if defined(__NT__) || defined(__WINDOWS__)
        int             osrc;
        UINT            flags;
    #endif
    #ifdef __OS2__
        int             usepm = 0;
        HMQ             hMessageQueue = 0;
        HAB             AnchorBlock = 0;
        USHORT          osrc;
    #endif
    char                outmsg[MAX_MSG_LEN];
    char                linestr[32];
    char                progname[_MAX_PATH];
    int                 rc;
    int                 retval = 0;
    static const char * reportnames[3] = {
        "Warning",                      /* _CRT_WARN */
        "Error",                        /* _CRT_ERROR */
        "Assertion Failure"             /* _CRT_ASSERT */
    };

    /*** Initialize some stuff ***/
    #ifdef __NT__
        if( GetModuleFileNameA( NULL, progname, _MAX_PATH )  ==  0 ) {
            strcpy( progname, "<unknown program>" );
        }
    #else
    {
        extern char **  _argv;
        if( (_argv[0])[0] != '\0' ) {
            strcpy( progname, _argv[0] );
        } else {
            strcpy( progname, "<unknown program>" );
        }
    }
    #endif
    if( linenumber != 0 ) {
        _bprintf( linestr, 32, "%d", linenumber );
    } else {
        strcpy( linestr, "" );
    }

    /*** Form the contents of the window ***/
    rc = _bprintf( outmsg, MAX_MSG_LEN,
                   "Debug %s!\n\nProgram: %s%s%s%s%s%s%s%s%s%s",
                   reportnames[reporttype],
                   progname,
                   modulename!=NULL ? "\nModule: " : "",
                   modulename!=NULL ? modulename : "",
                   filename!=NULL ? "\nFile: " : "",
                   filename!=NULL ? filename : "",
                   linestr[0]!='\0' ? "\nLine: " : "",
                   linestr[0]!='\0' ? linestr : "",
                   usermsg[0]!='\0' ? "\n\n" : "",
                   usermsg[0]!='\0' && reporttype==_CRT_ASSERT  ?  "Expression: "  :  "",
                   usermsg[0]!='\0' ? usermsg : "" );
    if( rc < 0 ) {
        strcpy( outmsg, TOO_LONG_MSG );
    }

    /*** Create the window ***/
    #if defined(__NT__) || defined(__WINDOWS__)
        flags = MB_ICONHAND | MB_TASKMODAL | MB_ABORTRETRYIGNORE;
        #ifdef __NT__
            flags |= MB_SETFOREGROUND;
        #endif
        osrc = MessageBox( NULL, outmsg, WINTITLE, flags );
        switch( osrc ) {
            case 0:
                retval = -1;
                break;
            case IDABORT:
                raise( SIGABRT );
                _exit( 3 );
                break;
            case IDRETRY:
                retval = 1;
                break;
            default:
                retval = 0;
        }
    #elif defined(__OS2__)
        AnchorBlock = WinInitialize( 0 );
        if( AnchorBlock != 0 ) {
            hMessageQueue = WinCreateMsgQueue( AnchorBlock, 0 );
            if( hMessageQueue != 0 ) {
                usepm = 1;
            } else {
                int     rc;
                rc = WinGetLastError( AnchorBlock );
                if( (rc & 0xFFFF) == PMERR_MSG_QUEUE_ALREADY_EXISTS ) {
                    usepm = 1;
                }
            }
        }
        if( usepm ) {
            osrc = WinMessageBox( HWND_DESKTOP, 0, outmsg, WINTITLE, 0,
                                  MB_ICONHAND | MB_ABORTRETRYIGNORE );
            switch( osrc ) {
                case MBID_ERROR:
                    retval = -1;
                    break;
                case MBID_ABORT:
                    raise( SIGABRT );
                    _exit( 3 );
                    break;
                case MBID_RETRY:
                    retval = 1;
                    break;
                default:
                    retval = 0;
            }
        } else {
            retval = -1;
        }
        if( hMessageQueue != 0 ) {
            WinDestroyMsgQueue( hMessageQueue );
        }
        if( AnchorBlock != 0 ) {
            WinTerminate( AnchorBlock );
        }
    #endif

    return( retval );
}

#endif  /* defined(__NT__) || defined(__WINDOWS__) || defined(__OS2__) */



/*
 * Main reporting routine.
 */
_WCRTLINK int _CrtDbgReport( int reporttype, const char *filename,
                             int linenumber, const char *modulename,
                             const char *format, ... )
/******************************************************************/
{
    #ifdef __NT__
        DWORD           byteswritten;
        BOOL            osrc;
    #endif
    char                usermsg[MAX_MSG_LEN] = { 0 };
    char                linemsg[MAX_MSG_LEN] = { 0 };
    char                outmsg[MAX_MSG_LEN] = { 0 };
    va_list             args;
    size_t              len;
    int                 retval = 0;
    int                 rc;

    /*** Ensure reporttype is valid ***/
    if( reporttype < _CRT_WARN  ||  reporttype > _CRT_ASSERT ) {
        return( -1 );
    }

    /*** Create the user message if necessary ***/
    va_start( args, format );
    if( format != NULL ) {
        len = max( strlen( ASSERT_PREFIX1 ), strlen( ASSERT_PREFIX2 ) );
        if( _vbprintf( usermsg, MAX_MSG_LEN-len, format, args )  <  0 ) {
            strcpy( usermsg, TOO_LONG_MSG );
        }
    }

    /*** Create an assertion failure message if appropriate ***/
    if( reporttype == _CRT_ASSERT ) {
        if( format == NULL ) {
            strcpy( linemsg, ASSERT_PREFIX1 );
        } else {
            strcpy( linemsg, ASSERT_PREFIX2 );
        }
        strcat( linemsg, usermsg );
        strcat( linemsg, "\n" );
    } else {
        strcpy( linemsg, usermsg );
    }

    /*** Add file information if it's available ***/
    if( filename != NULL ) {
        if( _bprintf( outmsg, MAX_MSG_LEN, "%s(%d): %s", filename,
                      linenumber, linemsg )  <  0 ) {
            strcpy( outmsg, TOO_LONG_MSG );
        }
    } else {
        strcpy( outmsg, linemsg );
    }

    /*** If there's a user-installed report hook function, call it ***/
    if( __DbgReportHook != NULL ) {
        /* MS documents this as ...==0 but really ...!=0 is what they do */
        if( (*__DbgReportHook)( reporttype, usermsg, &retval )  !=  0 ) {
            return( retval );
        }
    }

    /*** Handle _CRTDBG_MODE_FILE ***/
    if( __DbgReportModes[reporttype] & _CRTDBG_MODE_FILE ) {
        if( __DbgReportFiles[reporttype] != _CRTDBG_INVALID_HFILE ) {
            #ifdef __NT__
                osrc = WriteFile( __DbgReportFiles[reporttype], outmsg,
                                  strlen( outmsg ), &byteswritten, NULL );
                if( osrc == FALSE )  retval = -1;
            #else
                rc = write( __DbgReportFiles[reporttype], outmsg,
                            strlen( outmsg ) );
                if( rc == -1 )  retval = -1;
            #endif
        }
    }

    /*** Handle _CRTDBG_MODE_DEBUG ***/
    if( __DbgReportModes[reporttype] & _CRTDBG_MODE_DEBUG ) {
        char *          buff;
        size_t          len;

        len = sizeof( DEBUGGER_MESSAGE_COMMAND ) + strlen( outmsg ) + 1;
        buff = (char*) lib_malloc( len );
        if( buff != NULL ) {
            sprintf( buff, DEBUGGER_MESSAGE_FORMAT, outmsg );
            PassDebuggerAMessage( buff );
            lib_free( buff );
        } else {
            retval = -1;
        }
    }

    /*** Handle _CRTDBG_MODE_WNDW ***/
    if( __DbgReportModes[reporttype] & _CRTDBG_MODE_WNDW ) {
        #if defined(__NT__) || defined(__WINDOWS__) || defined(__OS2__)
            rc = window_report( reporttype, filename, linenumber, modulename,
                                usermsg );
            if( rc != 0 )  retval = rc;
        #else
            retval = -1;
        #endif
    }

    return( retval );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?