dbgwmem.c

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

C
1,074
字号
/****************************************************************************
*
*                            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 <string.h>
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include "dbgdefn.h"
#include "dbgwind.h"
#include "dbgtoggl.h"
#include "dbgitem.h"
#include "dbgio.h"
#include "dbgreg.h"
#include "dbgerr.h"
#include "dbginfo.h"
#include "madcli.h"
#include "mad.h"
#include "ldsupp.h"
#include "memtypes.h"

extern char             *StrCopy(char*,char*);
extern address          AddrAddWrap(address,long);
extern unsigned         ProgPeek(address ,void *,unsigned int );
extern char             *CnvULongDec(unsigned long,char *);
extern char             *CnvULong(unsigned long,char *);
extern char             *StrAddr(address *,char * ,unsigned);
extern void             SetDataDot( address );
extern bool             DlgLongExpr( char *, long * );
extern unsigned         NewCurrRadix(unsigned int );
extern bool             DlgDataAddr( char *title, address *value );
extern bool             DlgDataAddrFormat( char *, void *, void (*fmt)(void*,char*));
extern long             AddrDiff( address a, address b );
extern unsigned         ChangeMemUndoable( address addr, void *data, unsigned len );
extern bool             DlgMadTypeExpr( char *title, item_mach *value, mad_type_handle th );
extern bool             DlgString( char *title, char *buff );
extern char             *DupStr( char *str );
extern int              AddrComp(address,address);
extern void             Warn( char *p );
extern bool             BreakWrite( address addr, mad_type_handle, char *comment );
extern a_window         *WndAsmInspect(address addr);
extern bool             DlgScanGivenAddr( char *str, address *value );
extern void             MemFiniTypes( mem_type_walk_data *data );
extern void             MemInitTypes( mad_type_kind mas, mem_type_walk_data *data );
extern mad_type_handle  GetMADTypeHandleDefaultAt( address a, mad_type_kind mtk );
extern char             *Format( char *buff, char *fmt, ... );
extern char             *AddrToString( address *a, mad_address_format af, char *p, unsigned );
extern unsigned         ProgPeekWrap(address addr,char * buff,unsigned length );


extern machine_state    *DbgRegs;
extern char             *TxtBuff;
extern address          NilAddr;

typedef gui_ord (MEMHEADER)(a_window *,int);

#define TITLE_SIZE      1


static mem_type_walk_data       MemData;
static gui_menu_struct *MemTypeMenu = NULL;
static gui_menu_struct DummyMenu[1];

#include "menudef.h"
static gui_menu_struct MemMenu[] = {
    #include "menumem.h"
};

#define PIECE_TYPE( x ) ( (x)-MENU_MEMORY_FIRST_TYPE )

static unsigned         MemByteType;

static  MEMHEADER       MemHeader;
static  MEMHEADER       BinHeader;

static MEMHEADER *HeadTab[] =
{
    MemHeader,
    BinHeader
};

typedef struct mem_backout {
    struct mem_backout *next;
    address             home;
    address             addr;
    unsigned            curr_offset;
    unsigned            total_size;
    char                *follow;
    unsigned            has_current : 1;
} mem_backout;

typedef struct mem_window {
    union {
        struct {
            address     addr;  // this is the current top of window address
            address     home;  // this is the first address looked at
            void        *contents;
            int         size;
            char        *follow;
            mem_backout *backout;
        } m;
        struct {
            handle      filehndl;
            long        offset;
            long        size;
        } f;
    } u;
    unsigned    curr_offset;
    unsigned    items_per_line;
    unsigned    item_size;
    unsigned    item_width;
    unsigned    total_size;
    int         piece_type;
    int         last_type_popup;
    gui_ord     address_end;
    long        bp_offset;
    long        sp_offset;
    wnd_row     cursor_row;
    int         cursor_piece;
    int         shadow_piece;
    mad_type_handle     init_type;      //MAD: what if active MAD changes?
    unsigned    file    : 1;
    unsigned    stack   : 1;
} mem_window;
#define WndMem( wnd ) ( (mem_window *)WndExtra( wnd ) )

static void MemValidAddr( address addr )
{
    char        ch;

    if( _IsOff( SW_RUNNING_PROFILE ) ) {
        if( ProgPeekWrap( addr, &ch, 1 ) != 1 ) {
            Error( ERR_NONE, LIT( ERR_NO_READ_MEM ), addr );
        }
    }
}

static char *MemGetTitle( mem_window *mem )
{
    char        *p;

    p = StrCopy( LIT( WindowMemory ), TxtBuff );
    p = StrCopy( " (", p );
    p = AddrToString( &mem->u.m.home, MAF_FULL, p, TXT_LEN - ( p - TxtBuff ) );
    p = StrCopy( ")", p );
    return( TxtBuff );
}

static unsigned MemCurrOffset( a_window *wnd )
{
    wnd_row     row;
    int         piece;
    mem_window  *mem = WndMem( wnd );

    WndGetCurrent( wnd, &row, &piece );
    if( row < 0 ) return( 0 );
    --piece;
    if( piece >= mem->items_per_line ) piece -= mem->items_per_line;
    return( ( row * mem->items_per_line + piece ) * mem->item_size );
}

static gui_ord MemHeader( a_window *wnd, int piece )
{
    address     addr;
    mem_window  *mem = WndMem( wnd );
    gui_ord     len;
    char        buff[TXT_LEN];

    if( mem->stack && piece > 0 ) return( -1 );
    if( mem->file ) {
        if( piece > 0 ) return( -1 );
        CnvULong( MemCurrOffset( wnd ), TxtBuff );
        return( 0 );
    }
    if( piece > 1 ) return( -1 );
    addr = AddrAddWrap( mem->u.m.addr, MemCurrOffset( wnd ) );
    AddrToString( &addr, MAF_FULL, buff, sizeof( buff ) );
    switch( piece ) {
    case 0:
        StrCopy( buff, TxtBuff );
        return( 0 );
    case 1:
        StrAddr( &addr, TxtBuff, TXT_LEN );
        if( strcmp( buff, TxtBuff ) == 0 ) break;
        len = WndExtentX( wnd, buff ) + 2*WndMidCharX( wnd );
        return( len );
    }
    return( -1 );
}


static gui_ord BinHeader( a_window *wnd, int piece )
{
    mem_window  *mem = WndMem( wnd );

    if( piece != 0 ) return( -1 );
    CnvULongDec( mem->u.f.offset + MemCurrOffset( wnd ), TxtBuff );
    return( 0 );
}

static void MemGetContents( a_window *wnd, bool make_dirty )
{
    int         size;
    mem_window  *mem = WndMem( wnd );
    void        *old;
    int         old_size;

    old = mem->u.m.contents;
    old_size = mem->u.m.size;
    size = mem->items_per_line * mem->item_size * WndRows( wnd );
    mem->u.m.contents = WndAlloc( size );
    if( mem->u.m.contents == NULL ) {
        mem->u.m.size = 0;
    } else {
        mem->u.m.size = ProgPeekWrap( mem->u.m.addr, mem->u.m.contents, size );
    }
    AddrToString( &mem->u.m.addr, MAF_OFFSET, TxtBuff, TXT_LEN );
    mem->address_end = ( strlen( TxtBuff ) + 1 ) * WndMidCharX( wnd );
    if( mem->stack ) {
        mem->sp_offset = AddrDiff( Context.stack, mem->u.m.addr );
        mem->bp_offset = AddrDiff( Context.frame, mem->u.m.addr );
    }
    if( make_dirty ) {
        WndNoSelect( wnd );
        if( mem->u.m.size != old_size ||
            old == NULL ||
            mem->u.m.contents == NULL ) {
            WndRepaint( wnd );
        } else {
            for( size = 0; size < old_size; ++size ) {
                if( ((char*)old)[size] != ((char*)mem->u.m.contents)[size] ) {
                    WndRowDirty( wnd, size / ( mem->items_per_line * mem->item_size ) );
                }
            }
        }
    }
    WndFree( old );
}

static void MemSetStartAddr( a_window *wnd, address addr, bool new_home )
{
    mem_window  *mem = WndMem( wnd );

    if( new_home ) mem->u.m.home = addr;
    mem->u.m.addr = addr;
    MemGetContents( wnd, FALSE );
}

static WNDREFRESH MemRefresh;
static  void MemRefresh( a_window *wnd )
{
    mem_window  *mem = WndMem( wnd );

    if( !mem->file ) {
        MemGetContents( wnd, TRUE );
    } else {
        CnvULong( ULONG_MAX, TxtBuff );
        mem->address_end = ( strlen( TxtBuff ) + 1 ) * WndMidCharX( wnd );
    }
    if( !WndHasCurrent( wnd ) ) WndFirstCurrent( wnd );
}

static void MemGetNewAddr( a_window *wnd )
{
    address     addr;
    long        offset;
    mem_window  *mem = WndMem( wnd );
    unsigned    old;

    if( mem->file ) {
        offset = mem->u.f.offset;
        old = NewCurrRadix( 10 );
        if( !DlgLongExpr( LIT( New_Offset ), &offset ) ) return;
        NewCurrRadix( old );
        if( offset > mem->u.f.size ) return;
        mem->u.f.offset = offset;
    } else {
        addr = mem->u.m.home;
        if( !DlgDataAddr( LIT( New_Addr ), &addr ) ) return;
        MemValidAddr( addr );
        MemSetStartAddr( wnd, addr, TRUE );
        WndNoCurrent( wnd );
        MemRefresh( wnd );
        SetDataDot( addr );
    }
    WndSetTitle( wnd, MemGetTitle( mem ) );
    WndZapped( wnd );
}


extern void MemSetLength( a_window *wnd, unsigned size )
{
    WndMem( wnd )->total_size = size;
}


extern void MemSetFollow( a_window *wnd, char *follow )
{
    mem_window  *mem = WndMem( wnd );

    WndFree( mem->u.m.follow );
    mem->u.m.follow = follow;
}


static  void    MemSetType( a_window *wnd, unsigned idx )
{
    mem_window  *mem = WndMem( wnd );

    mem->piece_type = idx;
    if( mem->stack ) {
        mem->items_per_line = 1;
    } else {
        mem->items_per_line = MemData.info[ mem->piece_type ].items_per_line;
    }
    mem->item_size = MemData.info[ mem->piece_type ].item_size;
    mem->item_width = MemData.info[ mem->piece_type ].item_width;
}


static  bool    CanModify( a_window *wnd, int row, int piece )
{
    piece = piece;
    if( row < 0 ) return( FALSE );
    if( WndMem( wnd )->file ) return( FALSE );
    return( TRUE );
}

static void SetNewDataDot( a_window *wnd )
{

⌨️ 快捷键说明

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