stubdb.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 976 行 · 第 1/2 页

C
976
字号
/****************************************************************************
*
*                            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:  Debugger stub functions.
*
****************************************************************************/


#define INCL_DOS
#include <os2.h>
#include "dbgdefn.h"
#include "dbgmem.h"
#include "dbginfo.h"
#include "bool.h"
#include "ambigsym.h"
#include "dbgtoggl.h"
#include "dbglit.h"
#include "mad.h"
#include "dui.h"
#include "dbgvar.h"
#include "dbgstk.h"

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <process.h>

extern void             FlushEOC( void );
extern char             *DupStr( char * );
extern void             DoCmd( char * );
extern bool             InsMemRef( mad_disasm_data *dd );
extern address          GetCodeDot( void );
extern void             *WndAsmInspect( address addr );
extern void             DebugMain( void );
extern void             DebugFini( void );
extern void             DoInput( void );
extern void             UnAsm( address addr, unsigned max, char *buff );
extern char             *DupStr( char * );
extern bool             DUIGetSourceLine( cue_handle *ch, char *buff, unsigned len );
extern void             ExecTrace( trace_cmd_type type, debug_level level );
extern unsigned         Go( bool );
extern void             *OpenSrcFile( cue_handle * );
extern int              FReadLine( void *, int, int, char *, int );
extern void             FDoneSource( void * );
extern void             ExprValue( stack_entry * );

extern debug_level      DbgLevel;
extern char             *TxtBuff;
extern unsigned char    CurrRadix;
static bool             Done;
extern char             *TrpFile;
extern char             *CmdData;
extern stack_entry      *ExprSP;

unsigned                NumLines;
unsigned                NumColumns;

char *_LITDOS_invalid_function = "invalid function";
char *_LITDOS_file_not_found = "file not found";
char *_LITDOS_path_not_found = "path not found";
char *_LITDOS_too_many_open_files = "too many open files";
char *_LITDOS_access_denied = "access denied";
char *_LITDOS_invalid_handle = "invalid handle";
char *_LITDOS_memory_control = "memory control";
char *_LITDOS_insufficient_memory = "insufficient memory";
char *_LITDOS_invalid_address = "invalid address";
char *_LITDOS_invalid_environment = "invalid environment";
char *_LITDOS_invalid_format = "invalid format";
char *_LITDOS_invalid_access_code = "invalid access code";
char *_LITDOS_invalid_data = "invalid data";
char *_LITDOS_invalid_drive = "invalid drive";
char *_LITDOS_remove_cd = "remove cd";
char *_LITDOS_not_same_device = "not same device";

void WndMemInit( void )
{
}

void InitScreen( void )
{
}

void FiniScreen( void )
{
}

unsigned ConfigScreen( void )
{
    return( 0 );
}

bool DUIClose( void )
{
    Done = TRUE;
    return( TRUE );
}

// The following routine is cut & pasted verbatim from dbgwvar.c
// (which we really don't want to drag in here)
var_node *VarGetDisplayPiece( var_info *i, int row, int piece, int *pdepth, int *pinherit )
{
    var_node    *row_v;
    var_node    *v;

    if( piece >= VAR_PIECE_LAST ) return( NULL );
    if( VarFirstNode( i ) == NULL ) return( NULL );
    if( row >= VarRowTotal( i ) ) return( NULL );
    row_v = VarFindRowNode( i, row );
    if( !row_v->value_valid ) {
        VarSetValue( row_v, LIT( Quest_Marks ) );
        row_v->value_valid = FALSE;
    }
    if( !row_v->gadget_valid ) {
        VarSetGadget( row_v, VARGADGET_NONE );
        row_v->gadget_valid = FALSE;
    }
    v = row_v;
    if( piece == VAR_PIECE_NAME ||
        ( piece == VAR_PIECE_GADGET && row_v->gadget_valid ) ||
        ( piece == VAR_PIECE_VALUE && row_v->value_valid ) ) {
        VarError = FALSE;
    } else if( !_IsOn( SW_TASK_RUNNING ) ) {
        if( row == i->exprsp_cacherow && i->exprsp_cache != NULL ) {
            VarError = FALSE;
            v = i->exprsp_cache;
        } else if( row == i->exprsp_cacherow && i->exprsp_cache_is_error ) {
            VarError = TRUE;
            v = NULL;
        } else {
            VarErrState();
            v = VarFindRow( i, row );
            VarOldErrState();
            i->exprsp_cacherow = row;
            i->exprsp_cache = v;
            i->exprsp_cache_is_error = VarError;
        }
        if( v == NULL ) {
            if( !VarError ) return( NULL );
            v = row_v;
        }
        VarNodeInvalid( v );
        VarErrState();
        ExprValue( ExprSP );
        VarSetGadget( v, VarGetGadget( v ) );
        VarSetOnTop( v, VarGetOnTop( v ) );
        VarSetValue( v, VarGetValue( i, v ) );
        VarOldErrState();
        VarDoneRow( i );
    }
    VarGetDepths( i, v, pdepth, pinherit );
    return( v );
}

var_info        Locals;
HEV             Requestsem;
HEV             Requestdonesem;

static void DumpLocals( void )
{
    address     addr;
    int         row;
    int         depth;
    int         inherit;
    var_node    *v;

    if( !_IsOn( SW_TASK_RUNNING ) ) {
        VarErrState();
        VarInfoRefresh( VAR_LOCALS, &Locals, &addr, NULL );
        VarOkToCache( &Locals, TRUE );
    }
    for( row = 0;; ++row ) {
        v = VarGetDisplayPiece( &Locals, row, VAR_PIECE_GADGET, &depth, &inherit );
        if( v == NULL ) break;
        v = VarGetDisplayPiece( &Locals, row, VAR_PIECE_NAME, &depth, &inherit );
        v = VarGetDisplayPiece( &Locals, row, VAR_PIECE_VALUE, &depth, &inherit );
        switch( v->gadget ) {
        case VARGADGET_NONE:
            printf( "  " );
            break;
        case VARGADGET_OPEN:
            printf( "+ " );
            break;
        case VARGADGET_CLOSED:
            printf( "- " );
            break;
        case VARGADGET_POINTS:
            printf( "->" );
            break;
        case VARGADGET_UNPOINTS:
            printf( "<-" );
            break;
        }
        VarBuildName( &Locals, v, TRUE );
        printf( " %-20s %s\n", TxtBuff, v->value );
    }
    if( !_IsOn( SW_TASK_RUNNING ) ) {
        VarOkToCache( &Locals, FALSE );
        VarOldErrState();
    }
}

static void DumpSource( void )
{
    char        buff[256];
    DIPHDL( cue, ch );

    if( _IsOn( SW_TASK_RUNNING ) ) {
        printf( "I don't know where the task is. It's running\n" );
    }
    if( DeAliasAddrCue( NO_MOD, GetCodeDot(), ch ) == SR_NONE ||
        !DUIGetSourceLine( ch, buff, sizeof( buff ) ) ) {
        UnAsm( GetCodeDot(), sizeof( buff ), buff );
    }
    printf( "%s\n", buff );
}

enum {
    REQ_NONE,
    REQ_BYE,
    REQ_GO,
    REQ_TRACE_OVER,
    REQ_TRACE_INTO
} Req = REQ_NONE;

bool RequestDone;

VOID APIENTRY ControlFunc( ULONG parm )
{
    ULONG   ulCount;

    parm = parm;
    do {
        DosWaitEventSem( Requestsem, SEM_INDEFINITE_WAIT ); // wait for Request
        DosResetEventSem( Requestsem, &ulCount );
        switch( Req ) {
        case REQ_GO:
            Go( TRUE );
            break;
        case REQ_TRACE_OVER:
            ExecTrace( TRACE_OVER, DbgLevel );
            break;
        case REQ_TRACE_INTO:
            ExecTrace( TRACE_INTO, DbgLevel );
            break;
        }
        DoInput();
        _SwitchOff( SW_TASK_RUNNING );
        DosPostEventSem( Requestdonesem );
    } while( Req != REQ_BYE );
    return; // thread over!
}

void RunRequest( int req )
{
    ULONG   ulCount;

    if( _IsOn( SW_TASK_RUNNING ) ) return;
    DosWaitEventSem( Requestdonesem, SEM_INDEFINITE_WAIT ); // wait for last request to finish
    DosResetEventSem( Requestdonesem, &ulCount );
    Req = req;
    _SwitchOn( SW_TASK_RUNNING );
    DosPostEventSem( Requestsem ); // tell worker to go
}

void DlgCmd( void )
{
    char        buff[256];

    printf( "DBG>" );
    fflush( stdout );   // not really necessary
    gets( buff );
    if( buff[0] != '\0' && buff[1] == '\0' ) {
        switch( tolower( buff[0] ) ) {
        case 'u':
            WndAsmInspect( GetCodeDot() );
            break;
        case 's':
            DumpSource();
            break;
        case 'l':
            DumpLocals();
            break;
        case 'i':
            RunRequest( REQ_TRACE_INTO );
            break;
        case 'o':
            RunRequest( REQ_TRACE_OVER );
            break;
        case 'g':
            RunRequest( REQ_GO );
            break;
        case 'x':
            if( _IsOn( SW_REMOTE_LINK ) ) {
                printf( "Can't break remote task!\n" );
            } else {
                HMODULE hmod;
                PFN     proc = NULL;

                DosQueryModuleHandle( TrpFile, &hmod );
                DosQueryProcAddr( hmod, 5, 0, &proc );
//                if( proc != NULL )
//                    proc();
            }
            // break the task
            break;
        default:
            printf( "Error - unrecognized command\n" );
        }
    } else {
        DoCmd( DupStr( buff ) );
        DoInput();
    }
}

int main( int argc, char **argv )
{
    char        buff[256];
    TID         tid;
    APIRET      rc;

    MemInit();
    getcmd( buff );
    CmdData = buff;
    DebugMain();
    _SwitchOff( SW_ERROR_STARTUP );
    DoInput();
    VarInitInfo( &Locals );
    DosCreateEventSem( NULL, &Requestsem, 0, FALSE );
    DosCreateEventSem( NULL, &Requestdonesem, 0, FALSE );
    DosPostEventSem( Requestdonesem ); // signal req done
    rc = DosCreateThread( &tid, ControlFunc, 0, 0, 32768 );
    if( rc != 0 ) {
        printf( "Stubugger: Error creating thread!\n" );
    }
    while( !Done ) {
        DlgCmd();
    }
    DosCloseEventSem( Requestsem );
    DosCloseEventSem( Requestdonesem );
    DebugFini();
    RunRequest( REQ_BYE );
    MemFini();
    return( 0 );
}

// Minimalist DUI callback routines

extern char *DUILoadString( int id )
{
    char        buff[256];
    char        *ret;
    int         size;

    size = WinLoadString( 0, NULLHANDLE, id, sizeof( buff ), buff );
//    size = LoadString( GetModuleHandle( NULL ), id, buff, sizeof( buff ) );
    buff[size]='\0';
    ret = DbgAlloc( size+1 );
    strcpy( ret, buff );
    return( ret );
}

void DUIMsgBox( char *text )
{
    printf( "MSG %s\n", text );
}

bool DUIDlgTxt( char *text )
{
    printf( "DLG %s\n", text );
    return( TRUE );
}

void DUIInfoBox( char *text )
{
    printf( "INF %s\n", text );
}

void DUIErrorBox( char *text )
{
    printf( "ERR %s\n", text );
}

void DUIStatusText( char *text )
{
    printf( "STA %s\n", text );
}

bool DlgGivenAddr( char *title, address *value )
{
    // needed when segment's don't map (from new/sym command)
    return( FALSE );
}

void DlgNewWithSym( char *text, char *buff, int buff_len )
{
    // used by print command with no arguments
}

bool DlgUpTheStack( void )
{
    // used when trying to trace, but we've unwound the stack a bit
    return( FALSE );
}

bool DlgAreYouNuts( unsigned long mult )
{
    // used when too many break on write points are set
    return( FALSE );
}

bool DlgBackInTime( void )
{
    // used when trying to trace, but we've backed up over a call or asynch
    return( FALSE );
}

bool DlgIncompleteUndo( void )
{
    // used when trying to trace, but we've backed up over a call or asynch
    return( FALSE );
}

bool DlgBreak( address addr )
{
    // used when an error occurs in the break point expression or it is entered wrong
    return( FALSE );
}

bool DUIInfoRelease( void )
{
    // used when we're low on memory
    return( FALSE );
}
void DUIUpdate( update_list flags )
{
    // flags indicates what conditions have changed.  They should be saved
    // until an appropriate time, then windows updated accordingly
}

void DUIStop( void )
{
    // close down the UI - we're about to change modes.
}

void DUIFini( void )
{
    // finish up the UI
}

void DUIInit( void )
{
    // Init the UI
}

extern void DUIFreshAll( void )
{
    // refresh all screens - initialization has been done
}

extern bool DUIStopRefresh( bool stop )
{
    // temporarily turn off/on screen refreshing, cause we're going to run a
    // big command file and we don't want flashing.
    return( FALSE );
}

⌨️ 快捷键说明

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