rttraps.c

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

C
347
字号
/****************************************************************************
*
*                            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:  Run-time exception handling.
*
****************************************************************************/


#include "ftnstd.h"
#include "errcod.h"
#include "xfflags.h"
#include "rundat.h"

#include <signal.h>
#if defined( __DOS__ ) || defined( __WINDOWS__ )
  #include <dos.h>
  #include "extender.h"
#elif defined( _M_IX86 )
  #include <i86.h>
#endif
#if defined( __DOS__ )
  #include "nonibm.h"
#endif

#if defined( __OS2__ )
  #if defined( __386__ )
    #define __OS2_386__
  #else
    #define INCL_DOSMISC
    #include <os2.h>
    #define __OS2_286__
  #endif
#endif

#if defined( __NT__ )
  #include "enterdb.h"
#endif

#if defined( __OS2_286__ )
  #define       _handler        interrupt __pascal __far
#elif defined( __DOS__ ) || defined( __WINDOWS__ )
  #define       _handler        interrupt
#else
  #define       _handler
#endif

extern void             RTErr(int,...);
extern void             FPTrapInit(void);
extern void             FPTrapFini(void);

typedef void            (*fsig_func)(intstar4);

#if defined( __WINDOWS_386__ )

#elif defined( __OS2_286__ ) || defined( __DOS__ ) || defined( __WINDOWS__ )
  extern byte           IntOverFlow;
         void           (* __UserIOvFlHandler)(intstar4) = { (fsig_func)SIG_DFL };
  extern byte           IntDivBy0;
         void           (* __UserIDivZHandler)(intstar4) = { (fsig_func)SIG_DFL };
  static void           (_handler *ISave)(void);
  static void           (_handler *ZSave)(void);
#endif

#if defined( __DOS__ )
  extern byte           BreakVector;
         void           (* __UserBreakHandler)(intstar4) = { (fsig_func)SIG_DFL };
  static void           (_handler *CBSave)(void);
 #if defined( __386__ )
  static unsigned long  CBRealSave;
 #endif
#endif

#if defined( __OS2_386__ ) || defined( __NT__ )
  extern byte           __ExceptionHandled;
  static void           IOvFlSignal(int);
#endif

#if (defined( __DOS__ ) || defined( __WINDOWS__ )) && defined( __386__ )
  extern unsigned_32    _STACKLOW;

  void _movestack( unsigned_32 );
  #pragma aux _movestack = \
        "push ds"            \
        "pop  ss"             \
        "mov  esp,eax"        \
        parm [eax] modify [esp];

  extern unsigned long _dos_getrealvect(int);
  extern void          _dos_setrealvect(int,unsigned long);
  extern void          _dos_setvectp(int,void (interrupt far *)(void));
#endif


#if defined( __WINDOWS__ )

#else

static  void    ProcessBreak( void ) {
//==============================

    __XcptFlags &= ~XF_ERR_MASK;
    __XcptFlags |= XF_LIMIT_ERR | XF_KO_INTERRUPT;
    if( __XcptFlags & XF_IO_INTERRUPTABLE ) {
        __XcptFlags |= XF_IO_INTERRUPTED;
 #if defined( __OS2_386__ ) || defined( __NT__ )
    } else {
        __ExceptionHandled = 0;
 #endif
    }
}

static  void    BreakSignal( int sig ) {
//===================================================

    sig = sig;
    signal( SIGINT, BreakSignal );
 #if defined( __OS2__ ) || defined( __NT__ )
    signal( SIGBREAK, BreakSignal );
 #endif
    ProcessBreak();
}

#endif

#if defined( __DOS__ )
static  void    _handler BreakHandler( void ) {
//=============================================

    _enable();
    if( __UserBreakHandler != (fsig_func)SIG_DFL ) {
        if( (__UserBreakHandler != (fsig_func)SIG_IGN) &&
            (__UserBreakHandler != (fsig_func)SIG_ERR) ) {
            __UserBreakHandler( SIGBREAK );
        }
    } else {
        ProcessBreak();
    }
}
#endif


#if defined( __WINDOWS_386__ )

#elif defined( __DOS__ ) || defined( __WINDOWS__ ) || defined( __OS2__ ) || defined( __NT__ )

static  void    ProcessIDivZ( void ) {
//==============================

    RTErr( KO_IDIV_ZERO );
}

static  void    ProcessIOvFl( void ) {
//==============================

    // Set flag so that we report an overflow when we read an integer
    // regardless of whether user wants integer overflows reported
    __XcptFlags |= XF_IOVERFLOW;
}
#endif

#if defined( __WINDOWS_386__ )

#elif defined( __OS2_386__ ) || defined( __NT__ )

static  void    IDivZSignal( int sig ) {
//===================================================

    sig = sig;
    ProcessIDivZ();
}

static  void    IOvFlSignal( int sig ) {
//===================================================

    sig = sig;
    // re-signal exception since we may get many overflows
    // before we actually report the condition
    signal( SIGIOVFL, IOvFlSignal );
    ProcessIOvFl();
}

#elif defined( __DOS__ ) || defined( __WINDOWS__ ) || defined( __OS2_286__ )

static  void    _handler IDivZHandler( void ) {
//=============================================

 #if defined( __DOS__ ) || defined( __WINDOWS__ )
    _enable();
  #ifdef __386__
    // Under pharlap, ss != ds when this interrupt is taken.
    // But in order for our error reporting code to work we have to
    // set ss = ds.
    _movestack( _STACKLOW+512 );
  #endif
 #endif
    if( __UserIDivZHandler != (fsig_func)SIG_DFL ) {
        if( (__UserIDivZHandler != (fsig_func)SIG_IGN) &&
            (__UserIDivZHandler != (fsig_func)SIG_ERR) ) {
            __UserIDivZHandler(SIGIDIVZ);
        }
    } else {
        ProcessIDivZ();
    }
}

static  void    _handler IOvFlHandler( void ) {
//=============================================

 #if defined( __DOS__ ) || defined( __WINDOWS__ )
    _enable();
 #endif
    if( __UserIOvFlHandler != (fsig_func)SIG_DFL ) {
        if( (__UserIOvFlHandler != (fsig_func)SIG_IGN) &&
            (__UserIOvFlHandler != (fsig_func)SIG_ERR) ) {
            __UserIOvFlHandler(SIGIOVFL);
        }
    } else {
        ProcessIOvFl();
    }
}
#endif

static  void    AbnormalTerm( int dummy ) {
//==============================

    RTErr( CP_TERMINATE );
}

int     __EnableF77RTExceptionHandling( void ) {
//==============================================

#if defined( __NT__ )
    return( !DebuggerPresent() );
#else
    return( 1 );
#endif
}

void    R_TrapInit( void ) {
//====================

    int enable_excpt;

    enable_excpt = __EnableF77RTExceptionHandling();

    if( enable_excpt ) {
        signal( SIGSEGV, AbnormalTerm );
        signal( SIGILL, AbnormalTerm );
    }
#if !defined( __WINDOWS__ )
    signal( SIGINT, BreakSignal );
#endif
#if defined( __DOS__ )
    if( __NonIBM ) {
        // Assume NEC
        BreakVector = 0x06;
    }
    CBSave = _dos_getvect( BreakVector );
    _dos_setvect( BreakVector, (void (interrupt far *)(void))(void (near *)(void))BreakHandler );
  #if defined( __386__ )
    if( _IsPharLap() ) {
        CBRealSave = _dos_getrealvect( BreakVector );
        _dos_setvectp( BreakVector, (void (interrupt far *)(void))(void (near *)(void))BreakHandler );
    }
  #endif
    ISave = _dos_getvect( IntOverFlow );
    _dos_setvect( IntOverFlow, (void (interrupt far *)(void))(void (near *)(void))IOvFlHandler );
    ZSave = _dos_getvect( IntDivBy0 );
    _dos_setvect( IntDivBy0, (void (interrupt far *)(void))(void (near *)(void))IDivZHandler );
#elif defined( __WINDOWS__ )
 #if !defined( __386__ )
    ISave = _dos_getvect( IntOverFlow );
    _dos_setvect( IntOverFlow, (void (interrupt far *)(void))(void (near *)(void))IOvFlHandler );
    ZSave = _dos_getvect( IntDivBy0 );
    _dos_setvect( IntDivBy0, (void (interrupt far *)(void))(void (near *)(void))IDivZHandler );
 #endif
#elif defined( __OS2_386__ ) || defined( __NT__ )
    signal( SIGBREAK, BreakSignal );
    if( enable_excpt ) {
        signal( SIGIDIVZ, IDivZSignal );
        signal( SIGIOVFL, IOvFlSignal );
    }
#elif defined( __OS2_286__ )
    signal( SIGBREAK, BreakSignal );
    DosSetVec( IntOverFlow, (PFN)IOvFlHandler, (PFN FAR *)&ISave );
    DosSetVec( IntDivBy0, (PFN)IDivZHandler, (PFN FAR *)&ZSave );
#endif
    FPTrapInit();
}

void    R_TrapFini( void ) {
//====================

#if defined( __DOS__ )
    _dos_setvect( BreakVector, CBSave );
 #if defined( __386__ )
    if( _IsPharLap() ) {
        _dos_setrealvect( BreakVector, CBRealSave );
    }
 #endif
    _dos_setvect( IntOverFlow, ISave );
    _dos_setvect( IntDivBy0, ZSave );
#elif defined( __WINDOWS__ )
 #if !defined( __386__ )
    _dos_setvect( IntOverFlow, ISave );
    _dos_setvect( IntDivBy0, ZSave );
 #endif
#elif defined( __OS2_286__ )
    DosSetVec( IntOverFlow, (PFN)ISave, (PFN FAR *)&ISave );
    DosSetVec( IntDivBy0, (PFN)ZSave, (PFN FAR *)&ZSave );
#endif
    FPTrapFini();
}

extern void             (*_ExceptionInit)( void );
extern void             (*_ExceptionFini)( void );

void    __InitExceptionVectors( void ) {
//================================

    _ExceptionInit = &R_TrapInit;
    _ExceptionFini = &R_TrapFini;
}

⌨️ 快捷键说明

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