dbgevent.c

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

C
324
字号
/****************************************************************************
*
*                            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:  Record or replay debugger events.
*
****************************************************************************/


#include "dbgdefn.h"
#include "dbglit.h"
#include "dbginfo.h"
#include "dbgtoggl.h"
#include "dbgmem.h"
#include "dbginp.h"
#include "dbgrep.h"
#include "dbgevent.h"
#include "dui.h"
#include <string.h>


extern void             RecordPointStart( void );
extern void             RecordNewProg( void );
extern cmd_list         *AllocCmdList( char *start, unsigned len );
extern void             FreeCmdList( cmd_list *cmds );
extern void             PointFini( void );
extern void             PushCmdList( cmd_list *cmds );
extern void             TypeInpStack( input_type set );
extern int              GetStackPos( void );
extern char             *Format( char *buff, char *fmt, ... );
extern char             *GetCmdName( int index );
extern unsigned         UndoLevel( void );
extern address          GetRegIP( void );
extern void             CreateInvokeFile( char *name, void (*rtn)( void ) );
extern void             InvokeAFile( char * );
extern bool             ScanEOC( void );
extern bool             ScanItem( bool blank_delim, char **start, unsigned *len );
extern void             ReqEOC( void );
extern char             *StrCopy( char *src, char *dest );
extern char             *StrAddr( address *addr, char *p, unsigned);
extern unsigned         NewCurrRadix( unsigned rad );
extern unsigned         ReqExpr( void );
extern void             PushInpStack( void *handle, bool (*rtn)( void *, inp_rtn_action  ), bool save_lang );
extern char             *ScanPos( void );
extern char             *DupStr( char *str );
extern void             UnAsm( address addr, unsigned, char *buff );
extern char             *CopySourceLine( cue_handle *ch );
extern char             *GetEventAddress( event_record *ev );
extern void             ReplayTo( event_record *ev );
extern void             ProcInput( void );
extern void             DbgUpdate( update_list );

extern char             *TxtBuff;
extern address          NilAddr;
extern unsigned char    CurrRadix;

event_record *EventList;
static event_record **LastOwner;

static event_record **FindOwner( event_record *of )
{
    event_record **owner;
    owner = &EventList;
    while( *owner != of ) {
        owner = &((*owner)->next);
    }
    return( owner );
}

static void FreeOneEvent( event_record *junk )
{
    event_record **owner;

    owner = FindOwner( junk );
    *owner = junk->next;
    FreeCmdList( junk->cmd );
    _Free( junk->addr_string );
    _Free( junk->cue );
    _Free( junk );
}

void RecordInit( void )
{
    EventList = NULL;
}

void RecordFini( void )
{
    _SwitchOff( SW_HAD_ASYNCH_EVENT );
    while( EventList != NULL ) {
        FreeOneEvent( EventList );
    }
}

void ShowReplay( void )
{
    event_record        *ev;
    for( ev = EventList; ev != NULL; ev = ev->next ) {
        Format( TxtBuff, "%s %d {%s}", GetCmdName( CMD_RECORD ), ev->rad, ev->cmd->buff );
        DUIDlgTxt( TxtBuff );
    }
}

bool OkToSaveReplay( void )
{
    if( _IsOff( SW_HAD_ASYNCH_EVENT ) ) return( TRUE );
    if( DUIAskIfAsynchOk() ) return( TRUE );
    return( FALSE );
}

void SaveReplayToFile( char *name )
{
    CreateInvokeFile( name, ShowReplay );
}

void RestoreReplayFromFile( char *name )
{
    RecordFini();
    InvokeAFile( name );
    ProcInput();
    ReplayTo( NULL );
}

static void AddEvent( char *start, unsigned len, address ip )
{
    event_record        **owner;
    event_record        *new;

    owner = FindOwner( NULL );
    _Alloc( new, sizeof( *new ) );
    new->addr_string = NULL;
    new->cue = NULL;
    new->next = NULL;
    new->cmd = AllocCmdList( start, len );
    new->ip = ip;
    new->after_asynch = FALSE;
    new->rad = CurrRadix;
    if( _IsOn( SW_HAD_ASYNCH_EVENT ) ) {
        if( _IsOn( SW_EVENT_RECORDED_SINCE_ASYNCH ) ) {
            new->after_asynch = TRUE;
        }
    }
    *owner = new;
}

void ProcRecord( void )
{
    char        *start;
    unsigned    len;
    unsigned    rad;
    unsigned    old;

    old = NewCurrRadix( 10 );
    rad = ReqExpr();
    NewCurrRadix( old );
    if( !ScanEOC() ) {
        if( ScanItem( FALSE, &start, &len ) ) {
            ReqEOC();
            old = NewCurrRadix( rad );
            AddEvent( start, len, NilAddr );
            NewCurrRadix( old );
        }
    }
}

void RecordStart( void )
{
    RecordFini();
    RecordNewProg();
    RecordPointStart();
}

OVL_EXTERN bool DoneRadix( void *parm, inp_rtn_action action )
{
    switch( action ) {
    case INP_RTN_INIT:
    case INP_RTN_FINI:
        return( TRUE );
    case INP_RTN_EOL:
        NewCurrRadix( (unsigned)parm );
        return( FALSE );
    default:
        return( FALSE );
    }
}


static void PushRadChange( unsigned rad )
{
    PushInpStack( (void *)rad, DoneRadix, FALSE );
    TypeInpStack( INP_NO_CMD );
}

void ReplayTo( event_record *ev )
{
    event_record *prev;

    if( ev != NULL && ev->after_asynch && !DUIAskIfAsynchOk() ) return;
    PointFini();
    if( EventList != NULL ) {
        if( ev == NULL ) {
            for( ev = EventList; ev->next != NULL; ev = ev->next ) ;
        }
        for( ;; ) {
            PushCmdList( ev->cmd );
            TypeInpStack( INP_REPLAYED );
            PushRadChange( ev->rad );
            TypeInpStack( INP_REPLAYED );
            if( ev == EventList ) break;
            for( prev = EventList; prev->next != ev; prev = prev->next ) ;
            ev = prev;
        }
    }
    PushRadChange( CurrRadix );
    TypeInpStack( INP_REPLAYED );
    RecordFini();
}


void CheckEventRecorded( void )
{
    if( _IsOn( SW_EXECUTE_ABORTED ) ) {
        while( *LastOwner != NULL ) {
            FreeOneEvent( *LastOwner );
        }
    }
}

void RecordEvent( char *p )
{
    int                 stackpos;
    unsigned            undo;
    char                buff[40];

    if( _IsOn( SW_HAD_ASYNCH_EVENT ) ) {
        _SwitchOn( SW_EVENT_RECORDED_SINCE_ASYNCH );
    }
    _SwitchOff( SW_EXECUTE_ABORTED );
    if( _IsOn( SW_CMD_INTERACTIVE ) ) {
        LastOwner = FindOwner( NULL );
        undo = UndoLevel();
        if( undo != 0 ) {
            Format( buff, "%s %d", GetCmdName( CMD_UNDO ), undo );
            AddEvent( buff, strlen( buff ), GetRegIP() );
        }
        stackpos = GetStackPos();
        if( stackpos != 0 ) {
            Format( buff, "%s %d", GetCmdName( CMD_STACKPOS ), stackpos );
            AddEvent( buff, strlen( buff ), GetRegIP() );
        }
        AddEvent( p, strlen( p ), GetRegIP() );
        DbgUpdate( UP_EVENT_CHANGE );
    }
}


void RecordAsynchEvent( void )
{
    _SwitchOn( SW_HAD_ASYNCH_EVENT );
    _SwitchOff( SW_EVENT_RECORDED_SINCE_ASYNCH );
}

void RecordGo( char *p )
{
    if( _IsOn( SW_HAD_ASYNCH_EVENT ) && _IsOff( SW_EVENT_RECORDED_SINCE_ASYNCH ) ) {
        _SwitchOff( SW_HAD_ASYNCH_EVENT );
    }
    RecordEvent( p );
}

void RecordCommand( char *startpos, int cmd )
{
    char        *endpos;
    char        *p;

    endpos = ScanPos();
    p = StrCopy( GetCmdName( cmd ), TxtBuff );
    *p++ = ' ';
    memcpy( p, startpos, endpos-startpos );
    p += endpos-startpos;
    *p = '\0';
    RecordEvent( TxtBuff );
}

void SetRecord( bool on )
{
    _SwitchSet( SW_CMD_INTERACTIVE, on );
}

char *GetEventAddress( event_record *ev )
{
    char        *p;

    if( IS_NIL_ADDR( ev->ip ) ) {
        p = StrCopy( LIT( Quest_Marks ), TxtBuff );
    } else {
        p = StrAddr( &ev->ip, TxtBuff, TXT_LEN );
    }
    StrCopy( ":", p );
    return( TxtBuff );
}

⌨️ 快捷键说明

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