dbgprint.c

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

C
1,008
字号
/****************************************************************************
*
*                            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 'print' command.
*
****************************************************************************/


#include <string.h>
#include <ctype.h>
#include "dbgdefn.h"
#include "dbgreg.h"
#include "dbgtoken.h"
#include "dbginfo.h"
#include "dbgstk.h"
#include "dbglit.h"
#include "dbgerr.h"
#include "dbgitem.h"
#include "dbgtoggl.h"
#include "ldsupp.h"
#include "mad.h"
#include "dui.h"
#include "i64.h"

#define BUFLEN  UTIL_LEN

#define PREC_LONG_FLOAT 15
#define PREC_FLOAT      7

#define MAX_WIDTH       40
#define NAME_WIDTH      25

extern void             ChkExpr( void );
extern void             NormalExpr( void );
extern void             ExprValue( stack_entry * );
extern void             PopEntry( void );
extern void             DupStack( void );
extern void             DoGivenField( sym_handle * );
extern void             ReqEOC( void );
extern void             Scan( void );
extern unsigned int     ScanCmd( char * );
extern bool             ScanQuote( char **, unsigned int * );
extern bool             ScanEOC( void );
extern char             *LineAddr( address *, char * );
extern char             *StrAddr( address *, char *, unsigned );
extern void             FindRadixSpec( unsigned char, char **, unsigned int * );
extern void             WriteToPgmScreen( void *, unsigned int );
extern void             GraphicDisplay( void );
extern void             ConvertTo( stack_entry *, type_kind, type_modifier, unsigned );
extern void             PushNum( long );
extern void             DoPlus( void );
extern void             DoPoints( type_kind );
extern void             DefAddr( memory_expr, address * );
extern void             ChkBreak( void );
extern void             PushType( type_handle * );
extern void             MoveSP( int );
extern char             *StrCopy( char *src, char *dst );
extern bool             TokenName( unsigned, char **, unsigned * );
extern void             SetTokens( bool );
extern void             MakeMemoryAddr( bool, memory_expr, address * );
extern void             AddrFix( address * );
extern void             StartSubscript( void );
extern void             AddSubscript( void );
extern void             EndSubscript( void );
extern void             DlgNewWithSym( char *, char *, int);
extern char             *ReScan( char * );
extern unsigned         ProgPeek( address, void *, unsigned int );
extern char             *GetCmdName( int );
extern void             GetMADTypeDefaultAt( address a, mad_type_kind mtk, mad_type_info *mti );

// Brian!!!! NYI NYI NYI
#define _SetMaxPrec( x )


extern stack_entry      *ExprSP;
extern tokens           CurrToken;
extern unsigned char    CurrRadix;
extern unsigned char    DefRadix;
extern machine_state    *DbgRegs;


static char             *OutPtr;
static char             *OutBuff;
static unsigned         OutLen;
static bool             OutPgm;
static bool             First;

static char PrintOps[] = { "Program\0Window\0" };

extern void PrintValue( void );

typedef enum { NUM_SIGNED, NUM_UNSIGNED, NUM_CHECK } sign_class;


extern void StartPrintBuff( char *buff, unsigned len )
{
    OutPtr = buff;
    OutBuff = buff;
    OutLen = len;
    *buff = 'F'; /* no buffer flush */
}


static void PrtBuff( void )
{
    if( OutPgm ) {
        WriteToPgmScreen( OutBuff, OutPtr - OutBuff );
    } else {
        *OutPtr = NULLCHAR;
        DUIDlgTxt( OutBuff );
    }
    OutPtr = OutBuff;
    *OutPtr = NULLCHAR; /* indicate buffer flush */
}


static void PrtChar( unsigned ch )
{
    unsigned    len;

    len = OutPtr - OutBuff;
    if( len >= OutLen ) {
        PrtBuff();
        len = 0;
    }
    //NYI: cheesy Unicode support
    if( len < BUFLEN ) {
        *OutPtr++ = ch;
    }
}


extern void EndPrintBuff( void )
{
    PrtChar( '\0' );
}


static void PrtNeed( unsigned len )
{
    if( OutPtr + len > OutBuff + OutLen ) {
        PrtBuff();
    }
}


static void EndBuff( void )
{
    if( OutBuff != OutPtr || *OutPtr != NULLCHAR ) {
        PrtBuff();
    }
}


static void PrtStr( char *start, unsigned len )
{
    PrtNeed( len );
    for( ; len > 0; --len ) PrtChar( *start++ );
}


/*
 * CnvRadix -- convert an unsigned number of a given radix to a string
 */

static char *CnvRadix( unsigned_64 *value, unsigned radix, char base,
                char *buff, int len )
{
    char        internal[ 65 ];
    char        *ptr;
    unsigned    dig;
    unsigned_64 big_radix;
    unsigned_64 remainder;

    ptr = &internal[ 64 ];
    U32ToU64( radix, &big_radix );
    while( (len > 0) || (U64Test( value ) != 0) ) {
        U64Div( value, &big_radix, value, &remainder );
        dig = U32FetchTrunc( remainder );
        *ptr = (dig <= 9) ? dig + '0' : dig - 10 + base;
        --ptr;
        --len;
    }
    len = &internal[64] - ptr;
    memcpy( buff, ptr + 1, len );
    buff[ len ] = NULLCHAR;
    return( buff + len );
}


static char *FmtNum( unsigned_64 num, unsigned radix, char base_letter,
                     sign_class sign_type, char *buff, unsigned len,
                     char *prefix, unsigned pref_len )
{
    char        *ptr;

    if( sign_type == NUM_SIGNED && I64Test( &num ) < 0 ) {
        *buff = '-';
        ++buff;
        U64Neg( &num, &num );
    }
    if( radix != DefRadix && prefix == NULL ) {
        FindRadixSpec( radix, &prefix, &pref_len );
    }
    ptr = buff;
    if( prefix != NULL ) {
        memcpy( ptr, prefix, pref_len );
        ptr = buff + pref_len;
    }
    return( CnvRadix( &num, radix, base_letter, ptr, len ) );
}


/*
 * PrintRadix -- print expression in given radix
 */

static void PrintRadix( unsigned radix, char base_letter, sign_class sign_type,
                        char *prefix, unsigned pref_len )
{
    char                buff[BUFLEN];
    char                *ptr;
    mad_type_info       mti;
    unsigned            mad_max;
    item_mach           item;
    mad_type_info       host;
    mad_type_handle     mth;

    if( sign_type == NUM_CHECK ) {
        if( radix != 10 ) {
            sign_type = NUM_UNSIGNED;
        } else {
            switch( ExprSP->info.kind ) {
            case TK_BOOL:
            case TK_CHAR:
            case TK_INTEGER:
            case TK_ENUM:
                if( (ExprSP->info.modifier & TM_MOD_MASK) == TM_UNSIGNED ) {
                    sign_type = NUM_UNSIGNED;
                } else {
                    sign_type = NUM_SIGNED;
                }
                break;
            default:
                sign_type = NUM_UNSIGNED;
                break;
            }
        }
    }
    ptr = buff;
    switch( ExprSP->info.kind ) {
    case TK_BOOL:
    case TK_CHAR:
    case TK_ENUM:
    case TK_INTEGER:
        /* this is to get proper sign extension for 16-bit numbers */
        if( sign_type == NUM_SIGNED ) {
            ExprSP->info.modifier = TM_SIGNED;
        } else {
            ExprSP->info.modifier = TM_UNSIGNED;
        }
        ConvertTo( ExprSP, TK_INTEGER, TM_UNSIGNED, sizeof( ExprSP->v.uint ) );
        ptr = FmtNum( ExprSP->v.uint, radix, base_letter, sign_type,
                        ptr, 1, prefix, pref_len );
        break;
    case TK_ARRAY:
    case TK_FUNCTION:
    case TK_ADDRESS:
    case TK_POINTER:
        AddrFix( &ExprSP->v.addr );
        if( (ExprSP->info.modifier & TM_MOD_MASK) == TM_NEAR ) {
            mth = MADTypeDefault( MTK_ADDRESS, MAF_OFFSET, &DbgRegs->mr, &ExprSP->v.addr );
        } else {
            mth = MADTypeDefault( MTK_ADDRESS, MAF_FULL, &DbgRegs->mr, &ExprSP->v.addr );
        }
        MADTypeInfo( mth, &mti );
        MADTypeInfoForHost( MTK_ADDRESS, sizeof( address ), &host );
        MADTypeConvert( &host, &ExprSP->v.addr, &mti, &item, 0 );
        mad_max = sizeof( buff );
        MADTypeToString( radix, &mti, &item, &mad_max, ptr );
        ptr += mad_max;
        break;
    case TK_REAL:
        {
            signed_64   tmp;

            I32ToI64( LDToD( &ExprSP->v.real ), &tmp );
            ptr = FmtNum( tmp, radix, base_letter,
                        NUM_SIGNED, ptr, 1, prefix, pref_len );
        }
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
    }
    PrtStr( buff, ptr - buff );
}

/*
 * PrintAddress -- print expression as a symbolic address
 */

static void PrintAddress( char fmt )
{
    char        buff[ BUFLEN ];
    char        *ptr;
    address     addr;

    if( fmt == 'l' ) {
        MakeMemoryAddr( TRUE, EXPR_CODE, &addr );
        ptr = LineAddr( &addr, buff );
        if( ptr == NULL ) {
            ptr = StrAddr( &addr, buff, sizeof( buff ) );
        }
    } else {
        MakeMemoryAddr( TRUE, EXPR_DATA, &addr );
        ptr = StrAddr( &addr, buff, sizeof( buff ) );
    }
    PrtStr( buff, ptr - buff );
}


/*
 * PrintDouble -- print a real number, or a component of a complex number
 */

static void PrintDouble( char format, xreal *val )
{
    char        *start, *ptr, *back;
    char        buff[ MAX_WIDTH+1 ];
    bool        found_dot;

    switch( tolower( format ) ) {
    case 'f':
        LDToS( buff, val, 16, 0, MAX_WIDTH, 0, 0, 0, 'F' );
        break;
    case 'e':
        LDToS( buff, val, 16, 0, MAX_WIDTH, 1, 0, format, 'E' );
        break;
    case 'g':
        LDToS( buff, val, 16, 0, MAX_WIDTH, 1, 0, format - 2, 'G' );
        break;
    }
    buff[ MAX_WIDTH ] = NULLCHAR;
    for( start = buff; *start == ' '; ++start )
        ;
    found_dot = FALSE;
    ptr = start;
    for( ;; ) {
        if( *ptr == '\0' ) break;
        if( *ptr == 'e' ) break;
        if( *ptr == 'E' ) break;
        if( *ptr == '.' ) found_dot = TRUE;
        ++ptr;
    }
    back = ptr;
    if( found_dot ) {
        while( *--ptr == '0' )
            ;
        ++ptr;
    }
    while( *ptr = *back ) {
        ++ptr;
        ++back;
    }
    PrtStr( start, ptr - start );
}


/*
 * PrintReal -- print a real number
 */

static void PrintReal( char format )
{
    if( ExprSP->info.kind == TK_REAL ) {
        if( ExprSP->info.size == sizeof( float ) ) {
            _SetMaxPrec( PREC_FLOAT );
        } else {
            _SetMaxPrec( PREC_LONG_FLOAT );
        }
    } else {
        ConvertTo( ExprSP, TK_REAL, TM_NONE, sizeof( ExprSP->v.real ) );
        _SetMaxPrec( PREC_LONG_FLOAT );
    }
    PrintDouble( format, &ExprSP->v.real );
}


/*
 * PrintComplex -- print a complex number
 */

static void PrintComplex( char format )
{
    if( ExprSP->info.kind == TK_COMPLEX ) {
        if( ExprSP->info.size == sizeof( float )*2 ) {
            _SetMaxPrec( PREC_FLOAT );
        } else {
            _SetMaxPrec( PREC_LONG_FLOAT );
        }
    } else {
        ConvertTo( ExprSP, TK_COMPLEX, TM_NONE, sizeof( ExprSP->v.cmplx ) );
        _SetMaxPrec( PREC_LONG_FLOAT );
    }
    PrtChar( '(' );
    PrintDouble( format, &ExprSP->v.cmplx.re );
    PrtChar( ',' );
    PrtChar( ' ' );
    PrintDouble( format, &ExprSP->v.cmplx.im );
    PrtChar( ')' );
}


/*
 * PrintChar -- print expression as a character
 */
void PrintChar( void )
{
    PrtChar( '\'' );
    switch( ExprSP->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_INTEGER:
        PrtChar( (char) U32FetchTrunc( ExprSP->v.uint ) );
        break;
    case TK_CHAR:
        switch( ExprSP->info.kind ) {
        case 4:
            /* 4 byte Unicode */
            PrtChar( (unsigned_32) U32FetchTrunc( ExprSP->v.uint ) );
            break;
        case 2:
            /* 2 byte Unicode */
            PrtChar( (unsigned_16) U32FetchTrunc( ExprSP->v.uint ) );
            break;
        default:
            PrtChar( (char) U32FetchTrunc( ExprSP->v.uint ) );
            break;
        }
        break;
    case TK_ADDRESS:
    case TK_POINTER:
        PrtChar( (char) ExprSP->v.addr.mach.offset );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
    }
    PrtChar( '\'' );
}

/*
 * PrintString -- print expression as a string
 */

#define MAX_PRINTSTRING_LEN  100

static void DoPrintString( bool force )
{
    int         count;
    address     addr;
    char        buff[MAX_PRINTSTRING_LEN+10];
    char        *p;

    MakeMemoryAddr( FALSE, EXPR_DATA, &addr );
    if( IS_NIL_ADDR( addr ) && !force ) {
        Error( ERR_NONE, LIT( ERR_NOT_PRINTABLE ), addr );
    }
    count = ProgPeek( addr, buff, MAX_PRINTSTRING_LEN );
    if( count == 0 && !force ) {
        Error( ERR_NONE, LIT( ERR_NOT_PRINTABLE ), addr );
    }
    p = buff;
    while( --count >= 0 ) {
        if( *p == '\0' ) break;
        if( !force ) {
            if( count == 0 ) {
                Error( ERR_NONE, LIT( ERR_NOT_PRINTABLE ), addr );
            }
        }
        PrtChar( *p );
        ++p;

⌨️ 快捷键说明

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