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 + -
显示快捷键?