stabdisp.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 280 行
CPP
280 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "cpplib.h"
#include "rtexcept.h"
static size_t typesigIndex( // FIND BASE-1 INDEX OF MATCHING TYPE SIGNATURE
DISPATCH_EXC* dispatch, // - dispatch control
size_t count, // - number of elements
RT_TYPE_SIG* tsigs ) // - type signatures
{
size_t index; // - base-1 index
THROW_RO* throw_ro; // - throw R/O block
rboolean zero_thrown; // - TRUE ==> zero was thrown
unsigned thr_ctr; // - throw ctr.
unsigned ctr; // - testing ctr.
RT_TYPE_SIG tsig; // - current type signature, in tsigs
RT_TYPE_SIG thr_sig; // - current type signature, from throw
throw_ro = dispatch->ro;
zero_thrown = dispatch->zero;
for( ctr = 0; ctr < count; ++ctr ) {
tsig = tsigs[ ctr ];
if( tsig == NULL ) {
index = ctr + 1;
goto done;
}
for( thr_ctr = 0; thr_ctr < throw_ro->count; ++thr_ctr ) {
dispatch->cnv_try = &throw_ro->cnvs[ thr_ctr ];
thr_sig = dispatch->cnv_try->signature;
if( CPPLIB( ts_equiv )( tsig, thr_sig, zero_thrown ) ) {
index = ctr + 1;
goto done;
}
}
}
index = 0;
done:
return index;
}
static rboolean dispatchableFnExc(// CHECK IF FUNCTION EXCEPTION SPEC. DISPATCH
DISPATCH_EXC *dispatch, // - dispatch control
DTOR_CMD* cmd ) // - DTOR_CMD_FN_EXC command
{
size_t index = typesigIndex( dispatch
, cmd->fn_exc.count
, cmd->fn_exc.sigs );
rboolean retn = ( index == 0 )
|| ( cmd->fn_exc.sigs[ index - 1 ] == NULL );
if( retn ) {
dispatch->try_cmd = cmd;
}
return retn;
}
static rboolean dispatchableCatch(// CHECK IF DISPATCHABLE CATCH
DISPATCH_EXC *dispatch, // - dispatch control
DTOR_CMD* cmd ) // - DTOR_CMD_TRY command
{
rboolean retn; // - return: TRUE ==> dispatachable
size_t index; // - index of match catch (base-1)
index = typesigIndex( dispatch
, cmd->try_cmd.count
, cmd->try_cmd.sigs );
if( index == 0 ) {
retn = FALSE;
} else {
-- index;
dispatch->try_cmd = cmd;
dispatch->catch_no = index;
retn = TRUE;
}
return retn;
}
static DISPATCHABLE dispatchable( // DETERMINE WHERE CATCHABLE WITHIN FUNCTION
DISPATCH_EXC *dispatch, // - dispatch information
RW_DTREG *rw ) // - current read/write
{
_RTCTL rt_ctl // - R/T control
( dispatch->rtc->thr );
STAB_TRAVERSE traverse; // - traversal control
RO_STATE* state; // - current state entry
DISPATCHABLE retn; // - return: dispatchability
DTOR_CMD* cmd; // - command pointer
ACTIVE_EXC *exc; // - active exception
rboolean rethrow; // - TRUE ==> re-throw from top block
if( dispatch->rethrow ) {
exc = dispatch->exc;
if( exc == NULL ) {
GOOF_EXC( "dispatchable: missing caught exception" );
}
dispatch->ro = exc->throw_ro;
dispatch->zero = exc->zero_thrown;
rethrow = TRUE;
} else {
rethrow = FALSE;
}
rt_ctl.setRwRo( rw );
CPPLIB( stab_trav_init )( &traverse, &rt_ctl );
for( ; ; CPPLIB( stab_trav_next )( &traverse ) ) {
state = CPPLIB( stab_trav_move )( &traverse );
if( state == NULL ) {
retn = DISPATCHABLE_NONE;
break;
}
if( state->dtor != NULL ) continue;
cmd = state->u.cmd_addr;
switch( cmd->base.code ) {
case DTC_CATCH :
if( rethrow ) {
if( exc->cat_try == TryFromCatch( cmd ) ) {
dispatch->popped = TRUE;
}
rethrow = FALSE;
}
continue;
case DTC_FN_EXC :
if( dispatchableFnExc( dispatch, cmd ) ) {
// exception violates fn-exc spec.
retn = DISPATCHABLE_FNEXC;
break;
}
continue;
case DTC_TRY :
if( dispatchableCatch( dispatch, cmd ) ) {
retn = DISPATCHABLE_CATCH;
break;
}
continue;
default :
continue;
}
dispatch->state_var = traverse.state_var;
break;
}
return retn;
}
extern "C"
DISPATCHABLE CPPLIB( dispatchable )(// TEST IF R/W BLOCK IS DISPATCHABLE
DISPATCH_EXC *dispatch, // - dispatch control
RW_DTREG* rw ) // - R/W block: search block
{
DISPATCHABLE dispatch_type; // - type of dispatch
// check if r/w on stack
if( rw == 0 ) {
CPPLIB( corrupted_stack )();
}
dispatch->rw = rw;
dispatch->rtc->setRwRo( rw );
RO_DTREG* ro = dispatch->rtc->ro;
switch( ro->base.reg_type ) {
default :
CPPLIB( corrupted_stack )();
case DTRG_FUN :
dispatch_type = dispatchable( dispatch, rw );
break;
case DTRG_STATIC_INITLS :
case DTRG_ARRAY :
case DTRG_OBJECT :
dispatch_type = DISPATCHABLE_NONE;
break;
}
return dispatch_type;
}
#if 0
// future support for catch(...) to catch anything
static DISPATCHABLE catch_any( // DETERMINE WHERE CATCH(...) WITHIN FUNCTION
DISPATCH_EXC *dispatch, // - dispatch information
RW_DTREG *rw ) // - current read/write
{
_RTCTL rt_ctl // - R/T control
( dispatch->rtc->thr );
STAB_TRAVERSE traverse; // - traversal control
RO_STATE* state; // - current state entry
DISPATCHABLE retn; // - return: dispatchability
DTOR_CMD* cmd; // - command pointer
rt_ctl.setRwRo( rw );
CPPLIB( stab_trav_init )( &traverse, &rt_ctl );
for( ; ; CPPLIB( stab_trav_next )( &traverse ) ) {
state = CPPLIB( stab_trav_move )( &traverse );
if( state == NULL ) {
retn = DISPATCHABLE_NONE;
break;
}
if( state->dtor != NULL ) continue;
cmd = state->u.cmd_addr;
if( cmd->base.code == DTC_TRY ) {
if( 0 == cmd->try_cmd.sigs[ cmd->try_cmd.count - 1 ] ) {
dispatch->non_watcom = true;
retn = DISPATCHABLE_CATCH;
break;
}
}
dispatch->state_var = traverse.state_var;
break;
}
return retn;
}
extern "C"
DISPATCHABLE CPPLIB( catch_any )// TEST IF R/W BLOCK IS DISPATCHABLE FOR ...
( FsExcRec* // - exception record
, RW_DTREG* rw ) // - R/W block: search block
{
_RTCTL rt_ctl; // - R/T control
DISPATCHABLE dispatch_type; // - type of dispatch
DISPATCH_EXC dispatch; // - dispatch control
// check if r/w on stack
if( rw == 0 ) {
CPPLIB( corrupted_stack )();
}
CPPLIB( dispatch_dummy )( &dispatch, &rt_ctl );
dispatch.rw = rw;
dispatch.rtc->setRwRo( rw );
RO_DTREG* ro = dispatch.rtc->ro;
switch( ro->base.reg_type ) {
default :
CPPLIB( corrupted_stack )();
case DTRG_FUN :
dispatch_type = catch_any( &dispatch, rw );
break;
case DTRG_STATIC_INITLS :
case DTRG_ARRAY :
case DTRG_OBJECT :
dispatch_type = DISPATCHABLE_NONE;
break;
}
return dispatch_type;
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?