Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
static void fneDispatch(        // DISPATCH "unexpected"
    DISPATCH_EXC *dispatch )    // - dispatch control
{
    THREAD_CTL *ctl;            // - thread-specific data
    ACTIVE_EXC *exc;            // - active exception
    ACTIVE_EXC *srch;           // - previous exception for this FNEXC

    ctl = dispatch->rtc->thr;
    ctl->abort_msg = RTMSG_FNEXC;
    exc = ctl->excepts;
    exc->dispatch = dispatch;
    for( srch = exc; ; ) {
        if( srch == NULL ) {
            // first time through fn_exc
            exc->dispatch = dispatch;
            exc->fnexc_state = exc->state;
            exc->state = EXCSTATE_UNEXPECTED;
            _EXC_PR_FNEXC marker( dispatch->rtc
                                , 0
                                , dispatch->rw
                                , dispatch->rethrow ? 0 : exc );
            unexpected();
            marker._state = EXCSTATE_TERMINATE;
            CPPLIB( call_terminate )( RTMSG_RET_UNEXPECT, ctl );
            // never return
        }
        DISPATCH_EXC *cand = srch->dispatch;
        if( NULL != cand
          && dispatch->rw        == cand->rw
          && dispatch->state_var == cand->state_var ) {
            if( srch->state == EXCSTATE_UNEXPECTED ) {
                // throw/rethrow did not get through fn-exc
                exc->state = EXCSTATE_BAD_EXC;
                _EXC_PR_FNEXC marker( dispatch->rtc
                                    , 0
                                    , dispatch->rw
                                    , dispatch->rethrow ? 0 : exc );
                throw bad_exception();
            }
            if( srch->state == EXCSTATE_BAD_EXC ) {
                // throw of bad_exception did not get through fn-exc
                _EXC_PR_DTOR marker( dispatch->rtc
                                   , 0
                                   , EXCSTATE_TERMINATE
                                   , dispatch->rethrow ? 0 :exc );
                CPPLIB( call_terminate )( RTMSG_FNEXC, ctl );
                // never return
            }
            if( srch != exc ) {
                CPPLIB( corrupted_stack )();
                // never return
            }
        }
        srch = srch->prev;
        if( exc == srch ) {
            CPPLIB( corrupted_stack )();
            // never return
        }
    }
}
Пример #5
0
void CPPLIB( module_dtor )      // DTOR STATICS FOR PROGRAM
    ( void )
{
    THREAD_CTL *thr;            // - thread control ptr.
    RW_DTREG* rw;               // - read/write entry
    union {
        RW_DTREG inlined;       // - inlined copy for destruction
        RW_DTREG_INITLS ls;     // - inlined copy for destruction
    };


#ifdef RW_REGISTRATION
    inlined.base.handler = & CPPLIB( fs_handler_rtn );
    thr = 0;
#else
    thr = &_RWD_ThreadData;
#endif
    for( ; ; ) {
#ifdef __MT__
        _RWD_StaticInitSema.p();
#endif
        rw = _RWD_ModuleInit;
        if( rw != 0 ) {
            _RWD_ModuleInit = rw->base_st.prev;
        }
#ifdef __MT__
        _RWD_StaticInitSema.v();
#endif
        if( rw == 0) break;
        RO_STATE* state = &rw->base_st.ro->init_ls.state_table[0];
        (*state->dtor)( state->u.data_addr, DTOR_NULL );
    }
}
Пример #6
0
_EXC_PR_DTOR::~_EXC_PR_DTOR     // _EXC_PR_DTOR DESTRUCTOR
    ( void )
{
    ACTIVE_EXC* exc = _exc;
    CPPLIB( dtor_free_exc )( _exc, _rtc );
    _exc = 0;
}
Пример #7
0
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;
}
Пример #8
0
_WPRTLINK
void CPPLIB( fun_register )(    // REGISTRATION FOR FUNCTION
    RW_DTREG* rw,               // - R/W block
    RO_DTREG* ro )              // - R/O block
{
    CPPLIB( base_register )( rw, ro, 0 );
}
Пример #9
0
THREAD_CTL* CPPLIB( fs_lookup ) // LOOK THRU FS ENTRIES FOR LAST, THREAD_CTL
    ( RW_DTREG** a_last )       // - addr[ ptr to last WATCOM entry ]
{
    _RTCTL rt_ctl( 0 );         // - fake R/T control
    FsExcRec excrec;            // - system exception record
    DISPATCH_EXC dispatch;      // - dispatch control
    RW_DTREG* last;             // - last WATCOM R/W block
    RW_DTREG *ctl;              // R/W block (based fs:0)
    THREAD_CTL* retn;           // PGM THREAD (first WATCOM .EXE, .DLL active)
    THREAD_CTL* base;           // PGM THREAD (call base)

#ifdef SYSIND_REGISTRATION
    #define LIST_END 0          // - link-list ending
#else
    #define LIST_END (void*)(-1L)// - link-list ending
#endif

    CPPLIB( dispatch_dummy )( &dispatch, &rt_ctl );
    excrec.code = EXCREC_CODE;
    excrec.flags = EXCREC_FLAGS;
    excrec.rec = 0;
    excrec.addr = 0;
    excrec.parm_count = EXCREC_PARM_COUNT;
    excrec.object = 0;
    excrec.dispatch = &dispatch;
    last = 0;
    retn = 0;
    for( ctl = FsTop(); ctl != LIST_END; ctl = ctl->base.prev ) {
#ifdef FS_REGISTRATION
        uint_8* handler = findHandler( (uint_8*)ctl->base.handler );
        if( handler[5]  == 'W'
         && handler[6]  == 'A'
         && handler[7]  == 'T'
         && handler[8]  == 'C'
         && handler[9]  == 'O'
         && handler[10] == 'M' ) {
#endif
            if( EXC_HAND_CATCH
                    == (*ctl->base.handler)( &excrec, 0, 0, 0 ) ) {
                last = ctl;
                base = dispatch.rtc->thr;
                if( base->flags.executable ) {
                    retn = base;
                }
            }
#ifdef FS_REGISTRATION
        }
#endif
    }
    if( retn == 0 ) {
        retn = dispatch.rtc->thr;
        if( retn == 0 ) {
            retn = &_RWD_ThreadData;
        }
    }
    *a_last = last;
    return retn;
}
Пример #10
0
_WPRTLINK
void CPPLIB(pure_error)(        // TRAP NON-OVERRIDDEN PURE VIRTUAL CALLS
    void )
{
    if( !_RWD_PureErrorFlag ) {
        _RWD_PureErrorFlag = 1;
        CPPLIB(fatal_runtime_error)( RTMSG_PURE_ERR, 1 );
    }
}
Пример #11
0
_EXC_PR_FREE::~_EXC_PR_FREE     // _EXC_PR_FREE DESTRUCTOR
    ( void )
{
    if( NULL != _exc ) {
        ACTIVE_EXC* exc = _exc;
        _exc = 0;
        CPPLIB( free_exc )( _rtc, exc );
    }
}
Пример #12
0
void CPPLIB( dtor_free_exc )    // DESTRUCT AND FREE EXCEPTION
    ( ACTIVE_EXC* active        // - exception
    , _RTCTL* rtc )             // - R/T control
{
    if( 0 != active ) {
        RT_TYPE_SIG sig = CPPLIB( ts_refed )( active->sig );
        if( sig->hdr.type == THROBJ_CLASS
         || sig->hdr.type == THROBJ_CLASS_VIRT ) {
            pFUNdtor dtor = sig->clss.dtor;
            if( dtor != NULL ) {
                _EXC_PR_FREE marker( rtc, 0, EXCSTATE_DTOR, active );
                active->state = EXCSTATE_DTOR;
                (*dtor)( active->data, DTOR_NULL );
                marker._exc = 0;
            }
        }
        CPPLIB( free_exc )( rtc, active );
    }
}
Пример #13
0
void CPPLIB( raise_exception )  // RAISE AN EXCEPTION
    ( FsExcRec* excrec )        // - exception record
{
    RW_DTREG* curr;             // - current R/W block
    THREAD_CTL* ctl;            // - thread control
    unsigned retn;              // - search return

    ctl = excrec->dispatch->rtc->thr;
    for( curr = ctl->registered; ; curr = curr->base.prev ) {
        retn = CPPLIB( fs_handler_rtn )( excrec, curr, NULL, 0 );
        if( retn != EXC_HAND_CONTINUE ) break;
    }
}
Пример #14
0
_WPRTLINK
void CPPLIB( catch_done )(      // COMPLETION OF CATCH
#ifdef RW_REGISTRATION
    void
#else
    RW_DTREG *rw                // - current R/W block
#endif
    )
{
    _RTCTL rt_ctl;              // - R/T control
#ifdef RW_REGISTRATION
    RW_DTREG* rw = RwTop( rt_ctl.thr );
#endif
    rt_ctl.setRwRo( rw );
    RO_STATE* state = CPPLIB( stab_entry )( rw->base.ro
                                          , rw->fun.base.state_var );
    DTOR_CMD* cmd = TryFromCatch( state->u.cmd_addr );
    ACTIVE_EXC* exc = CPPLIB( find_active )( &rt_ctl, rw, cmd );
    CPPLIB( dtor_free_exc )( exc, &rt_ctl );
    STAB_TRAVERSE traverse;
    CPPLIB( stab_trav_init )( &traverse, &rt_ctl );
    CPPLIB( stab_trav_next )( &traverse );
    rw->fun.base.state_var = traverse.state_var;
}
Пример #15
0
void * CPPLIB( new_array )(         // CALL CONSTRUCTORS FOR NEW ARRAY ELEMENTS
    ARRAY_STORAGE *new_alloc,       // - what was allocated
    unsigned count,                 // - number of elements
    RT_TYPE_SIG sig )               // - type signature for array type
{
    void *retn;                     // - return: NULL or first element

    if( new_alloc == NULL ) {
        retn = NULL;
    } else {
        new_alloc->element_count = count;
        retn = new_alloc->apparent_address;
        retn = CPPLIB( ctor_array )( retn, count, sig );
    }
    return( retn );
}
Пример #16
0
void CPPLIB( unwind_global )    // GLOBAL UNWIND ROUTINE
    ( RW_DTREG* rw              // - bounding R/W block
    , uint_32                   // - return address (not used)
    , FsExcRec* excrec )        // - exception record
{
    RW_DTREG* curr;             // - current R/W block
    THREAD_CTL* ctl;            // - thread control

    excrec->flags = EXC_TYPE_UNWIND_NORMAL;
    ctl = excrec->dispatch->rtc->thr;
    for( curr = ctl->registered; curr != rw; ) {
        CPPLIB( fs_handler_rtn )( excrec, curr, NULL, 0 );
        curr = curr->base.prev;
        ctl->registered = curr;
    }
}
Пример #17
0
_EXC_PR::_EXC_PR                // _EXC_PR CONSTRUCTOR
    ( _RTCTL* rtc               // - run-time control
    , RW_DTREG *rw              // - current read/write
    , EXCSTATE state )          // - state
    : _state( state )
    , _rw( rw )
    , _prev( rtc->thr->exc_pr )
    , _rtc( rtc )
#ifndef NDEBUG
    , _type( EXCPR_BASIC )
#endif
{
    rtc->thr->exc_pr = this;
    if( 0 == rw ) {
#ifdef RW_REGISTRATION
        _rw = FsTop();
#else
        _rw = CPPLIB( pd_top )();
#endif
    }
}
Пример #18
0
  _WPRTLINK
  void terminate( void )          // HANDLE TERMINATE
  {
    PFV handler;                // - NULL or handler set by "set_terminate"
    THREAD_CTL *thr;            // - thread ptr
    char* msg;                  // - error message

    thr = &_RWD_ThreadData;
    handler = thr->terminate;
    if( NULL == handler ) {
        thr = PgmThread();
        msg = thr->abort_msg;
        if( msg == NULL ) {
            __exit( 1 );
        }
    } else {
        (*handler)();
        msg = RTMSG_RET_TERMIN;
    }
    CPPLIB(fatal_runtime_error)( msg, 1 );
  }
Пример #19
0
void CPPLIB( PdUnwind )         // UNWIND USING PROCEDURE DESCRIPTORS
    ( FsExcRec* exc_rec )       // - exception record
{
    DISPATCH_EXC* dispatch;     // - dispatch control
    RW_DTREG* rw;               // - R/W block being dispatched
    void* frame;                // - frame for rtn. (SP or FP)
    void* pc;                   // - PC for continuation (after the setjmp)
    _CONTEXT ctx;               // - context for function
    unsigned save_area[3*2];    // - save area

    RtlCaptureContext( &ctx );
    pc = CPPLIB( PdCtx )( &ctx, save_area );
    if( pc ) {
        dispatch = exc_rec->dispatch;
        rw = dispatch->rw;
        frame = (void*)( (char*)rw - rw->base.ro->fun.rw_offset );
        if( procSetsFP( dispatch->pdata ) ) {
            RtlUnwindRfp( frame, pc, exc_rec, save_area );
        } else {
            RtlUnwind( frame, pc, exc_rec, save_area );
        }
    }
}
Пример #20
0
_WPRTLINK
unsigned CPPLIB( pd_handler_rtn )  // HANDLER FOR FS REGISTRATIONS
    ( FsExcRec* rec_exc         // - exception record
    , void* sp                  // - frame pointer function entry
    , _CONTEXT*                 // - context record
    , PD_DISP_CTX* dctx         // - dispatch context
    )
{
    unsigned retn;              // - return code
    __EXC_INFO info;            // - procedure exception information

    if( 0 == sp ) {
        // sp == 0 only when called from pd_lookup
        THREAD_CTL* ctl = &_RWD_ThreadData;
        retn = unsigned( ctl );
    } else {
        getProcInfo( &info, dctx );
        if( rec_exc->flags & EXC_TYPE_UNWIND_NORMAL ) {
            if( rec_exc->parm_count != 1
             || rec_exc->object     != sp
             || EXCREC_CODE_SETJMP  != ( EXCREC_CODE_MASK & rec_exc->code )
              ) {
                CPPLIB( destruct_internal )( 0, info.rw );
            }
            retn = EXC_HAND_CONTINUE;
        } else if( rec_exc->flags & EXC_TYPE_UNWIND_EXIT ) {
            if( info.ro->base.reg_type == DTRG_STATIC_INITLS ) {
                // always unwind static initialization
                CPPLIB( destruct_internal )( 0, info.rw );
            }
            retn = EXC_HAND_CONTINUE;
        } else if( EXCREC_CODE_WATCOM
                == ( EXCREC_CODE_MASK & rec_exc->code ) ) {
            // WATCOM C++ Exception raised
#if 0
            DISPATCHABLE type = CPPLIB( dispatchable )( rec_exc->dispatch
                                                      , info.rw );
            DISPATCH_EXC* dispatch = rec_exc->dispatch;
            if( DISPATCHABLE_NONE == type ) {
                if( info.rw == dispatch->fs_last ) {
                    type = DISPATCHABLE_NO_CATCH;
                    dispatch->type = type;
                    retn = EXC_HAND_CATCH;
                } else {
                    retn = EXC_HAND_CONTINUE;
                }
            } else {
                dispatch->pdata = info.pd;
                dispatch->type = type;
                retn = EXC_HAND_CATCH;
            }
#else
            DISPATCHABLE  type;      // - type of dispatchability
            DISPATCH_EXC  *dispatch; // - dispatch control
            _EXC_PR       *srch_ctl;

            dispatch = rec_exc->dispatch;
            if( dispatch->fnexc_skip == info.rw ) {
                dispatch->fnexc_skip = NULL;
            }
            for( srch_ctl = dispatch->srch_ctl
               ; NULL != srch_ctl && srch_ctl->_rw == info.rw
               ; srch_ctl = srch_ctl->_prev ) {
                if( NULL == dispatch->fnexc_skip ) {
                    switch( srch_ctl->_state ) {
                      case EXCSTATE_UNEXPECTED :
                      case EXCSTATE_BAD_EXC :
                        dispatch->fnexc_skip
                            = ((_EXC_PR_FNEXC*)srch_ctl)->_fnexc_skip;
                        continue;
                    }
                    break;
                }
            }
            if( NULL != srch_ctl && srch_ctl->_rw == info.rw ) {
                type = DISPATCHABLE_STOP;
            } else if( NULL == dispatch->fnexc_skip ) {
                type = CPPLIB( dispatchable )( dispatch, info.rw );
            } else {
                type = DISPATCHABLE_NONE;
            }
            if( DISPATCHABLE_NONE == type ) {
                if( info.rw == dispatch->fs_last ) {
                    type = DISPATCHABLE_NO_CATCH;
                    dispatch->type = type;
                    retn = EXC_HAND_CATCH;
                } else {
                    retn = EXC_HAND_CONTINUE;
                }
            } else {
                dispatch->pdata = info.pd;
                dispatch->type = type;
                retn = EXC_HAND_CATCH;
            }
#endif
        } else {
            // not WATCOM throw / re-throw
            retn = EXC_HAND_CONTINUE;
        }
    }
    return retn;
}
Пример #21
0
static void catchDispatch(      // DISPATCH A CATCH BLOCK
    DISPATCH_EXC *dispatch )    // - dispatch control
{
    RW_DTREG* blk;              // - function block for dispatch
    DTOR_CMD* cmd;              // - try command
    jmp_buf *env;               // - addr[ jmp_buf ]
    ACTIVE_EXC *active;         // - active exception
    void *tgt;                  // - target try variable
    void *src;                  // - source address
    RT_TYPE_SIG sig;            // - signature for catch
    unsigned cnv_offset;        // - conversion offset

    blk = dispatch->rw;
    cmd = dispatch->try_cmd;
    active = dispatch->exc;
    active->state = EXCSTATE_DISPATCH;
    env = (jmp_buf*)( (char*)blk + cmd->try_cmd.jmp_buf );
    sig = cmd->try_cmd.sigs[ dispatch->catch_no ];
    if( sig != NULL ) {
        cnv_offset = dispatch->cnv_try->offset;
        src = cnv_offset + (char*)active->data;
        tgt = (char*)blk + cmd->try_cmd.offset;
        switch( sig->hdr.type ) {
          case THROBJ_PTR_CLASS :
            if( dispatch->zero ) {
                *(void**)tgt = NULL;
            } else {
                *(void**)tgt = *(char**)active->data + cnv_offset;
            }
            break;
          case THROBJ_VOID_STAR :
          case THROBJ_PTR_SCALAR :
          case THROBJ_PTR_FUN :
            if( dispatch->zero ) {
                memset( tgt, 0, sig->scalar.size );
                break;
            }
          case THROBJ_SCALAR :
            memcpy( tgt, src, sig->scalar.size );
            break;
          case THROBJ_CLASS :
            sig = throwCnvSig( dispatch );
            (*sig->clss.copyctor)( tgt, src );
            break;
          case THROBJ_CLASS_VIRT :
            sig = throwCnvSig( dispatch );
            (*sig->clss_v.copyctor)( tgt, CTOR_NULL, src );
            break;
          case THROBJ_REFERENCE :
            sig = CPPLIB( ts_refed )( sig );
            switch( sig->hdr.type ) {
              case THROBJ_PTR_CLASS :
                if( dispatch->zero ) {
                    active->extra_object = NULL;
                } else {
                    active->extra_object = *(char**)active->data + cnv_offset;
                }
                *(void**)tgt = &active->extra_object;
                break;
              case THROBJ_PTR_SCALAR :
              case THROBJ_PTR_FUN :
              case THROBJ_VOID_STAR :
                if( dispatch->zero ) {
                    active->extra_object = NULL;
                    src = &active->extra_object;
                }
              case THROBJ_SCALAR :
              case THROBJ_CLASS :
              case THROBJ_CLASS_VIRT :
                *(void**)tgt = src;
                break;
            }
            break;
          default :
            GOOF_EXC( "unexpected exception type" );
        }
    }
    longjmp( *env, dispatch->catch_no + 1 );
}
Пример #22
0
static void processThrow(       // PROCESS A THROW
    void *object,               // - address of object
    THROW_RO *throw_ro,         // - thrown R/O block
    rboolean is_zero )          // - true ==> thrown object is zero constant
{
    _RTCTL rt_ctl;              // - R/T control
    DISPATCH_EXC dispatch;      // - dispatch control
    auto FsExcRec excrec;       // - system exception record
    volatile rboolean unwound;
    void *force_this_routine_to_have_an_EBP_frame;

//  CPPLIB( DbgRtDumpAutoDtor )();

#if 0
//
// Check for throws under bad circumstances
//
    ACTIVE_EXC *exc = rt_ctl.thr->excepts;
    if( exc == NULL ) {
        if( rt_ctl.thr->flags.terminated ) {
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_TERMIN, 1 );
        }
    } else {
        switch( exc->state ) {
          case EXCSTATE_DISPATCH :
          case EXCSTATE_UNEXPECTED :
          case EXCSTATE_BAD_EXC :
            break;
          case EXCSTATE_UNWIND :
          { CPPLIB( free_exc )( &rt_ctl, exc );
            _EXC_PR marker( &rt_ctl, 0, EXCSTATE_TERMINATE );
            CPPLIB( call_terminate )( RTMSG_THROW_DTOR, rt_ctl.thr );
          }
          case EXCSTATE_TERMINATE :
            CPPLIB( free_exc )( &rt_ctl, exc );
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_TERMIN, 1 );
          case EXCSTATE_CTOR :
            CPPLIB( free_exc )( &rt_ctl, exc );
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_CTOR, 1 );
          case EXCSTATE_DTOR :
            CPPLIB( free_exc )( &rt_ctl, exc );
            CPPLIB( fatal_runtime_error )( RTMSG_EXC_DTOR, 1 );
          default:
            GOOF_EXC( "getActiveExc: unexpected exception state" );
        }
    }
#endif
//
// Setup for dispatch
//
    rt_ctl.thr->abort_msg = NULL;
    CPPLIB( exc_setup )( &dispatch
                       , throw_ro
                       , is_zero
                       , &rt_ctl
                       , object
                       , &excrec );
    force_this_routine_to_have_an_EBP_frame = alloca(16);
    unwound = false;
//
// raising exception locates the catch/fn-exception to be dispatched
// also fills in excrec.addr
//
    if( 0 == dispatch.fs_last ) {
        // no search when no R/W blocks
        dispatch.type = DISPATCHABLE_NO_CATCH;
    } else {
        FS_RAISE_EXCEPTION( &excrec );
    }
//
// comes here twice, unless an error situation:
//  unwound == 0 : after catch located, before unwinding
//  unwound == 1 : after unwinding
//
    switch( dispatch.type ) {
      case DISPATCHABLE_STOP :
        if( NULL == dispatch.srch_ctl ) {
            GOOF_EXC( "DISPATCHABLE_STOP: no srch_ctl" );
        }
        switch( dispatch.srch_ctl->_state ) {
          case EXCSTATE_UNWIND :
          { _EXC_PR_FREE marker( &rt_ctl
                               , 0
                               , EXCSTATE_TERMINATE
                               , dispatch.rethrow ? 0 : rt_ctl.thr->excepts );
            CPPLIB( call_terminate )( RTMSG_THROW_DTOR, rt_ctl.thr );
          }
          case EXCSTATE_TERMINATE :
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_TERMIN, 1 );
          case EXCSTATE_CTOR :
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_CTOR, 1 );
          case EXCSTATE_DTOR :
            CPPLIB( fatal_runtime_error )( RTMSG_EXC_DTOR, 1 );
          default:
            GOOF_EXC( "DISPATCHABLE_STOP: unexpected exception state" );
        }
      case DISPATCHABLE_FNEXC :
      case DISPATCHABLE_CATCH :
        if( ! unwound ) {
            ACTIVE_EXC *active; // - saved exception
            unwound = true;
            if( dispatch.rethrow ) {
// do we still need fnexc_state ?
                dispatch.exc->fnexc_state = dispatch.exc->state;
                if( dispatch.popped ) {
                    active = dispatch.exc;
                    active->cat_try = dispatch.try_cmd;
                    active->rw = dispatch.rw;
                }
            } else {
                active = CPPLIB( alloc_exc )( object
                                            , dispatch.ro
                                            , &rt_ctl );
                dispatch.exc = active;
                active->cat_try = dispatch.try_cmd;
                active->rw = dispatch.rw;
            }
            if( dispatch.type == DISPATCHABLE_FNEXC ) {
                if( dispatch.rethrow ) {
                    dispatch.exc->state = dispatch.exc->fnexc_state;
                }
                break;
            }
            dispatch.exc->state = EXCSTATE_UNWIND;
#ifdef RW_REGISTRATION
            FS_UNWIND_GLOBAL( dispatch.rw, excrec.addr, &excrec );
#endif
#ifdef PD_REGISTRATION
            CPPLIB( PdUnwind )( &excrec );
#endif
        }
        // NT returns here instead of after RAISE_EXCEPTION if
        // there are no blocks to pop
        // nb. need to execute same code as after RAISE_EXCEPTION
        CPPLIB( destruct_internal )( dispatch.state_var, dispatch.rw );
        break;
    }
//
// dispatch the exception
//
    switch( dispatch.type ) {
      case DISPATCHABLE_FNEXC :
        fneDispatch( &dispatch );
      case DISPATCHABLE_CATCH :
        catchDispatch( &dispatch );
      case DISPATCHABLE_NO_CATCH :
        if( dispatch.rethrow ) {
            CPPLIB( fatal_runtime_error )( RTMSG_RETHROW, 1 );
        } else {
          { _EXC_PR marker( &rt_ctl, 0, EXCSTATE_TERMINATE );
            CPPLIB( call_terminate )( RTMSG_NO_HANDLER, rt_ctl.thr );
          }
        }
#if 0 // not now
      case DISPATCHABLE_SYS_EXC :
      {
        char buffer[ sizeof( RTMSG_SYS_EXC ) ];
        ::memcpy( buffer, RTMSG_SYS_EXC, sizeof( buffer ) );
        ltoa( dispatch.system_exc, buffer + sizeof( buffer) - 9, 16 );
        CPPLIB( fatal_runtime_error )( buffer, 1 );
      }
#endif
      default :
        GOOF_EXC( "throw: invalid DISPATCHABLE" );
    }
}
Пример #23
0
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;
}
Пример #24
0
rboolean CPPLIB( ts_equiv )(    // TEST IF TYPE SIG.S ARE EQUIVALENT
    RT_TYPE_SIG tgt,            // - target type signature
    RT_TYPE_SIG src,            // - source type signature
    rboolean zero_thrown )      // - TRUE ==> zero was thrown
{
    rboolean retn;              // - TRUE ==> conversion possible

    if( tgt == NULL ) {
        retn = TRUE;
    } else {
        tgt = CPPLIB( ts_refed )( tgt );
        retn = FALSE;
        if( zero_thrown ) {
            switch( tgt->hdr.type ) {
              case THROBJ_PTR_SCALAR :
              case THROBJ_VOID_STAR :
              case THROBJ_PTR_CLASS :
                retn = TRUE;
                break;
            }
        }
        if( ! retn ) {
            src = CPPLIB( ts_refed )( src );
            if( src == tgt ) {
                retn = TRUE;
            } else if( tgt->hdr.type != src->hdr.type ) {
                retn = FALSE;
            } else switch( tgt->hdr.type ) {
              case THROBJ_VOID_STAR :
              case THROBJ_ANYTHING :
                retn = TRUE;
                break;
              case THROBJ_PTR_SCALAR :
                if( tgt->base.indirect != src->base.indirect ) {
                    retn = FALSE;
                    break;
                }
                // drops thru
              case THROBJ_PTR_CLASS :
                retn = CPPLIB( ts_equiv )( CPPLIB( ts_pnted )( tgt )
                                         , CPPLIB( ts_pnted )( src )
                                         , zero_thrown );
                break;
              case THROBJ_CLASS :
              case THROBJ_CLASS_VIRT :
                if( tgt->clss.size == src->clss.size ) {
                    if( 0 == strcmp( tgt->clss.name, src->clss.name ) ) {
                        retn = TRUE;
                    } else {
                        retn = FALSE;
                    }
                } else {
                    retn = FALSE;
                }
                break;
              case THROBJ_PTR_FUN :
              case THROBJ_SCALAR :
                if( tgt->scalar.size == src->scalar.size ) {
                    if( 0 == strcmp( tgt->scalar.name, src->scalar.name ) ) {
                        retn = TRUE;
                    } else {
                        retn = FALSE;
                    }
                } else {
                    retn = FALSE;
                }
                break;
              default :
                GOOF( "TsEquiv -- bad THROBJ_..." );
            }
        }
    }
    return retn;
}
Пример #25
0
ACTIVE_EXC *CPPLIB( alloc_exc )(// ALLOCATE AN EXCEPTION
    void *object,               // - address of object
    THROW_RO *throw_ro,         // - throw R/O block
    _RTCTL* rtc )               // - R/T control
{
    FREE_AREA *fr;              // - a freed area
    FREE_AREA **owner;          // - previous freed area
    FREE_AREA *next;            // - next freed area
    RT_TYPE_SIG sig;            // - type signature of thrown item
    ACTIVE_EXC *active;         // - active exception
    unsigned size;              // - size required
    THREAD_CTL *thr;            // - thread control

    #ifdef __MT__
        __EXC_AREA.semaphore.p();
    #endif
    if( __EXC_AREA.freed == NULL ) {
        fr = (FREE_AREA*)((char*)&__EXC_AREA + sizeof( EXC_AREA )); // initial free list entry
        fr->next = NULL;
        fr->size = __EXC_AREA.size - sizeof( EXC_AREA );
        __EXC_AREA.freed = fr;
#ifndef NDEBUG
        memset( (char*)fr + sizeof(FREE_AREA)
              , 0xEF
              , fr->size - sizeof(FREE_AREA) );
#endif
    }
    sig = CPPLIB( ts_refed )( throw_ro->cnvs[0].signature );
    size = CPPLIB( ts_size )( sig ) + SIZEOF_HDR + sizeof( size_t );
    if( size < sizeof( FREE_AREA ) ) {
        size = sizeof( FREE_AREA );
    }
    size = ( size + 3 ) & -4;
    for( owner = &__EXC_AREA.freed; ; owner = &fr->next ) {
        fr = *owner;
        if( fr == NULL ) {
            CPPLIB(fatal_runtime_error)( RTMSG_EXC_NO_SPACE, 1 );
        }
        for( ;; ) { // coalesce
            next = fr->next;
            if( (FREE_AREA*)((char*)fr + fr->size) != next ) break;
            fr->size += next->size;
            fr->next = next->next;
        }
        if( fr->size == size ) {
            *owner = fr->next;
            active = (ACTIVE_EXC*)fr;
            break;
        } else if( fr->size > ( size + SIZEOF_SPLIT ) ) {
            fr->size -= size;
            active = (ACTIVE_EXC*)( (char*)fr + fr->size );
            break;
        }
    }
    #ifdef __MT__
        __EXC_AREA.semaphore.v();
    #endif
    *(size_t*)active = size;
    active = (ACTIVE_EXC*)( (char*)active + sizeof( size_t ) );
    active->exc_area = &__EXC_AREA;
    thr = rtc->thr;
    active->prev = thr->excepts;
    thr->excepts = active;
    active->sig = throw_ro->cnvs[0].signature;
    active->throw_ro = throw_ro;
    active->state = EXCSTATE_CTOR;
    active->zero_thrown = false;
    active->dispatch = NULL;
    active->rw = NULL;
    switch( sig->hdr.type ) {
      case THROBJ_SCALAR :
      case THROBJ_PTR_FUN :
        memcpy( active->data, object, sig->scalar.size );
        break;
      case THROBJ_CLASS :
      { _EXC_PR_FREE marker( rtc, 0, EXCSTATE_CTOR, active );
        (*sig->clss.copyctor)( active->data, object );
        marker._exc = 0;
      } break;
      case THROBJ_CLASS_VIRT :
      { _EXC_PR_FREE marker( rtc, 0, EXCSTATE_CTOR, active );
        (*sig->clss_v.copyctor)( active->data, CTOR_NULL, object );
        marker._exc = 0;
      } break;
      case THROBJ_PTR_CLASS :
      case THROBJ_PTR_SCALAR :
      case THROBJ_VOID_STAR :
        memcpy( active->data, object, sizeof( void* ) );
        size = sizeof( void* );
        break;
      default :
        GOOF_EXC( "ALLOCEXC: unexpected type signature" );
    }
    return active;
}
Пример #26
0
void CPPLIB( lcl_register )(    // REGISTRATION OF LOCAL INITIALIZATION
    RW_DTREG RT_FAR *rw )       // - read/write block
{
    CPPLIB( mod_register )( rw );
}
Пример #27
0
FSREGAPI unsigned CPPLIB( fs_handler_rtn ) // HANDLER FOR FS REGISTRATIONS
    ( FsExcRec* rec_exc         // - exception record
    , RW_DTREG* rw              // - current R/W block
    , FsCtxRec*                 // - context record
    , unsigned                  // - dispatch context
    )
{
    unsigned retn;              // - return code

#ifdef RT_EXC_ENABLED
    if( 0 == rw ) {
        // rw == 0 only when called from pgm_thread
        THREAD_CTL* ctl = &_RWD_ThreadData;
        rec_exc->dispatch->rtc->thr = ctl;
        retn = EXC_HAND_CATCH;
    } else if( rec_exc->flags & EXC_TYPE_UNWIND_NORMAL ) {
        CPPLIB( destruct_internal )( 0, rw );
        retn = EXC_HAND_CONTINUE;
    } else if( rec_exc->flags & EXC_TYPE_UNWIND_EXIT ) {
        if( rw->base.ro->base.reg_type == DTRG_STATIC_INITLS ) {
            // always unwind static initialization
            CPPLIB( destruct_internal )( 0, rw );
        }
        retn = EXC_HAND_CONTINUE;
    } else if( EXCREC_CODE_WATCOM == ( EXCREC_CODE_MASK & rec_exc->code ) ) {
        // WATCOM EXCEPTION
        DISPATCHABLE type;      // - type of dispatchability
        DISPATCH_EXC* dispatch; // - dispatch control
        dispatch = rec_exc->dispatch;
        if( dispatch->fnexc_skip == rw ) {
            dispatch->fnexc_skip = NULL;
        }
        _EXC_PR* srch_ctl;
        for( srch_ctl = dispatch->srch_ctl
           ; NULL != srch_ctl && srch_ctl->_rw == rw
           ; srch_ctl = srch_ctl->_prev ) {
            if( NULL == dispatch->fnexc_skip ) {
                switch( srch_ctl->_state ) {
                  case EXCSTATE_UNEXPECTED :
                  case EXCSTATE_BAD_EXC :
                    dispatch->fnexc_skip
                        = ((_EXC_PR_FNEXC*)srch_ctl)->_fnexc_skip;
                    continue;
                }
                break;
            }
        }
        if( NULL != srch_ctl && srch_ctl->_rw == rw ) {
            type = DISPATCHABLE_STOP;
        } else if( NULL == dispatch->fnexc_skip ) {
            type = CPPLIB( dispatchable )( dispatch, rw );
        } else {
            type = DISPATCHABLE_NONE;
        }
        if( DISPATCHABLE_NONE == type ) {
            if( rw == dispatch->fs_last ) {
                type = DISPATCHABLE_NO_CATCH;
                dispatch->type = type;
                retn = EXC_HAND_CATCH;
            } else {
                retn = EXC_HAND_CONTINUE;
            }
        } else {
            dispatch->type = type;
            retn = EXC_HAND_CATCH;
        }
    } else {
#if 0
// future support for catch(...) to catch anything
        // not WATCOM throw / re-throw
        DISPATCHABLE type = CPPLIB( catch_any )( rec_exc, rw );
        if( DISPATCHABLE_NONE == type ) {
            retn = EXC_HAND_CONTINUE;
        } else {
            retn = EXC_HAND_CATCH;
        }
#else
        retn = EXC_HAND_CONTINUE;
#endif
    }
#else
    rw = rw;
    rec_exc = rec_exc;
    retn = EXC_HAND_CONTINUE;
#endif
    return retn;
}