DBG: initial implementation of display-styles for watches

git-svn-id: trunk@28468 -
This commit is contained in:
martin 2010-11-24 21:48:42 +00:00
parent 6aa94b7db4
commit 795b3b3fb5
6 changed files with 531 additions and 174 deletions

View File

@ -562,34 +562,60 @@ type
(******************************************************************************)
(******************************************************************************)
TWatchDisplayFormat =
(wdfDefault,
wdfStructure,
wdfChar, wdfString,
wdfDecimal, wdfUnsigned, wdfFloat, wdfHex,
wdfPointer,
wdfMemDump
);
const
TWatchDisplayFormatNames: array [TWatchDisplayFormat] of string =
('wdfDefault',
'wdfStructure',
'wdfChar', 'wdfString',
'wdfDecimal', 'wdfUnsigned', 'wdfFloat', 'wdfHex',
'wdfPointer',
'wdfMemDump'
);
type
{ TBaseWatch }
TBaseWatch = class(TDelayedUdateItem)
private
FEnabled: Boolean;
FExpression: String;
FDisplayFormat: TWatchDisplayFormat;
FValid: TValidState;
function GetEnabled: Boolean;
protected
procedure AssignTo(Dest: TPersistent); override;
procedure DoEnableChange; virtual;
procedure DoExpressionChange; virtual;
procedure DoDisplayFormatChanged; virtual;
procedure SetValid(const AValue: TValidState);
protected
// virtual properties
function GetExpression: String; virtual;
function GetDisplayFormat: TWatchDisplayFormat; virtual;
function GetValid: TValidState; virtual;
function GetValue: String; virtual;
function GetTypeInfo: TDBGType; virtual;
procedure SetEnabled(const AValue: Boolean); virtual;
procedure SetExpression(const AValue: String); virtual;
procedure SetDisplayFormat(const AValue: TWatchDisplayFormat); virtual;
public
constructor Create(ACollection: TCollection); override;
public
property Enabled: Boolean read GetEnabled write SetEnabled;
property Expression: String read GetExpression write SetExpression;
property DisplayFormat: TWatchDisplayFormat read GetDisplayFormat write SetDisplayFormat;
property Valid: TValidState read GetValid;
property Value: String read GetValue;
property TypeInfo: TDBGType read GetTypeInfo;
@ -3356,6 +3382,7 @@ begin
then begin
TBaseWatch(Dest).SetExpression(FExpression);
TBaseWatch(Dest).SetEnabled(FEnabled);
TBaseWatch(Dest).SetDisplayFormat(FDisplayFormat);
end
else inherited;
end;
@ -3378,11 +3405,28 @@ begin
Changed;
end;
procedure TBaseWatch.DoDisplayFormatChanged;
begin
Changed;
end;
function TBaseWatch.GetEnabled: Boolean;
begin
Result := FEnabled;
end;
function TBaseWatch.GetDisplayFormat: TWatchDisplayFormat;
begin
Result := FDisplayFormat;
end;
procedure TBaseWatch.SetDisplayFormat(const AValue: TWatchDisplayFormat);
begin
if AValue = FDisplayFormat then exit;
FDisplayFormat := AValue;
DoDisplayFormatChanged;
end;
function TBaseWatch.GetExpression: String;
begin
Result := FExpression;
@ -3456,15 +3500,25 @@ begin
end;
procedure TIDEWatch.LoadFromXMLConfig(const AConfig: TXMLConfig; const APath: string);
var
i: Integer;
begin
Expression := AConfig.GetValue(APath + 'Expression/Value', '');
Enabled := AConfig.GetValue(APath + 'Enabled/Value', true);
i := StringCase
(AConfig.GetValue(APath + 'DisplayStyle/Value', TWatchDisplayFormatNames[wdfDefault]),
TWatchDisplayFormatNames);
if i >= 0
then DisplayFormat := TWatchDisplayFormat(i)
else DisplayFormat := wdfDefault;
end;
procedure TIDEWatch.SaveToXMLConfig(const AConfig: TXMLConfig; const APath: string);
begin
AConfig.SetDeleteValue(APath + 'Expression/Value', Expression, '');
AConfig.SetDeleteValue(APath + 'Enabled/Value', Enabled, true);
AConfig.SetDeleteValue(APath + 'DisplayStyle/Value',
TWatchDisplayFormatNames[DisplayFormat], TWatchDisplayFormatNames[wdfDefault]);
end;

View File

@ -162,6 +162,7 @@ type
FState : TGDBMIDebuggerCommandState;
FSeenStates: TGDBMIDebuggerCommandStates;
FTheDebugger: TGDBMIDebugger; // Set during Execute
FLastExecResult: TGDBMIExecResult;
function GetDebuggerState: TDBGState;
function GetTargetInfo: PGDBMITargetInfo;
procedure SetKeepFinished(const AValue: Boolean);
@ -201,6 +202,8 @@ type
function GetFrame(const AIndex: Integer): String;
function GetText(const ALocation: TDBGPtr): String; overload;
function GetText(const AExpression: String; const AValues: array of const): String; overload;
function GetChar(const AExpression: String; const AValues: array of const): String; overload;
function GetFloat(const AExpression: String; const AValues: array of const): String;
function GetWideText(const ALocation: TDBGPtr): String;
function GetGDBTypeInfo(const AExpression: String): TGDBType;
function GetClassName(const AClass: TDBGPtr): String; overload;
@ -211,10 +214,11 @@ type
function GetData(const AExpression: String; const AValues: array of const): TDbgPtr; overload;
function GetStrValue(const AExpression: String; const AValues: array of const): String;
function GetIntValue(const AExpression: String; const AValues: array of const): Integer;
function GetPtrValue(const AExpression: String; const AValues: array of const): TDbgPtr;
function GetPtrValue(const AExpression: String; const AValues: array of const; ConvertNegative: Boolean = False): TDbgPtr;
procedure ProcessFrame(const AFrame: String = '');
procedure DoDbgEvent(const ACategory: TDBGEventCategory; const AText: String);
property TargetInfo: PGDBMITargetInfo read GetTargetInfo;
property LastExecResult: TGDBMIExecResult read FLastExecResult;
public
constructor Create(AOwner: TGDBMIDebugger);
destructor Destroy; override;
@ -436,6 +440,7 @@ type
TGDBMIMemoryDumpResultList = class(TGDBMINameValueBasedList)
private
FAddr: TDBGPtr;
function GetItem(Index: Integer): TPCharWithLen;
function GetItemNum(Index: Integer): Integer;
function GetItemTxt(Index: Integer): string;
protected
@ -443,9 +448,11 @@ type
public
// Expected input format: 1 row with hex values
function Count: Integer;
property Item[Index: Integer]: TPCharWithLen read GetItem;
property ItemTxt[Index: Integer]: string read GetItemTxt;
property ItemNum[Index: Integer]: Integer read GetItemNum;
property Addr: TDBGPtr read FAddr;
function AsText(AStartOffs, ACount: Integer; AAddrWidth: Integer): string;
end;
{%endregion *^^^* TGDBMINameValueList and Parsers *^^^* }
@ -783,14 +790,17 @@ type
TGDBMIDebuggerCommandEvaluate = class(TGDBMIDebuggerCommand)
private
FExpression: String;
FDisplayFormat: TWatchDisplayFormat;
FTextValue: String;
FTypeInfo: TGDBType;
protected
function DoExecute: Boolean; override;
public
constructor Create(AOwner: TGDBMIDebugger;const AExpression: String);
constructor Create(AOwner: TGDBMIDebugger; const AExpression: String;
const ADisplayFormat: TWatchDisplayFormat);
function DebugText: String; override;
property Expression: String read FExpression;
property DisplayFormat: TWatchDisplayFormat read FDisplayFormat;
property TextValue: String read FTextValue;
property TypeInfo: TGDBType read FTypeInfo;
end;
@ -812,6 +822,7 @@ type
protected
procedure DoEnableChange; override;
procedure DoExpressionChange; override;
procedure DoDisplayFormatChanged; override;
procedure DoChange; override;
procedure DoStateChange(const AOldState: TDBGState); override;
function GetValue: String; override;
@ -1237,6 +1248,17 @@ begin
Result := '"' + Result + '"';
end;
function PCLenPartToString(const AVal: TPCharWithLen; AStartOffs, ALen: Integer): String;
begin
if AStartOffs + ALen > AVal.Len
then ALen := AVal.Len - AStartOffs;
if ALen <= 0
then exit('');
SetLength(Result, ALen);
Move((AVal.Ptr+AStartOffs)^, Result[1], aLen)
end;
function PCLenToString(const AVal: TPCharWithLen; UnQuote: Boolean = False): String;
begin
if UnQuote and (AVal.Len >= 2) and (AVal.Ptr[0] = '"') and (AVal.Ptr[AVal.Len-1] = '"')
@ -1629,6 +1651,11 @@ begin
Result := PCLenToInt(FNameValueList.Items[Index]^.Name, 0);
end;
function TGDBMIMemoryDumpResultList.GetItem(Index: Integer): TPCharWithLen;
begin
Result := FNameValueList.Items[Index]^.Name;
end;
function TGDBMIMemoryDumpResultList.GetItemTxt(Index: Integer): string;
begin
Result := PCLenToString(FNameValueList.Items[Index]^.Name, True);
@ -1648,6 +1675,20 @@ begin
Result := FNameValueList.Count;
end;
function TGDBMIMemoryDumpResultList.AsText(AStartOffs, ACount: Integer;
AAddrWidth: Integer): string;
var
i: LongInt;
begin
if AAddrWidth > 0
then Result := IntToHex(addr + AStartOffs, AAddrWidth) + ':'
else Result := '';
for i := AStartOffs to AStartOffs + ACount do begin
if i >= ACount then exit;
Result := Result + ' ' + PCLenPartToString(Item[i], 3, 2);
end;
end;
{ TGDBMIDisassembler }
procedure TGDBMIDisassembler.DoDisassembleDestroyed(Sender: TObject);
@ -4854,7 +4895,7 @@ function TGDBMIDebugger.GDBEvaluate(const AExpression: String; var AResult: Stri
var
CommandObj: TGDBMIDebuggerCommandEvaluate;
begin
CommandObj := TGDBMIDebuggerCommandEvaluate.Create(Self, AExpression);
CommandObj := TGDBMIDebuggerCommandEvaluate.Create(Self, AExpression, wdfDefault);
CommandObj.KeepFinished := True;
QueueCommand(CommandObj);
Result := CommandObj.State in [dcsExecuting, dcsFinished];
@ -6459,6 +6500,12 @@ begin
inherited;
end;
procedure TGDBMIWatch.DoDisplayFormatChanged;
begin
CancelEvaluation;
inherited;
end;
procedure TGDBMIWatch.DoChange;
begin
Changed;
@ -6512,7 +6559,8 @@ begin
FEvaluatedState := esRequested;
ClearOwned;
SetValid(vsValid);
FEvaluationCmdObj := TGDBMIDebuggerCommandEvaluate.Create(TGDBMIDebugger(Debugger), Expression);
FEvaluationCmdObj := TGDBMIDebuggerCommandEvaluate.Create
(TGDBMIDebugger(Debugger), Expression, DisplayFormat);
FEvaluationCmdObj.OnExecuted := @DoEvaluationFinished;
FEvaluationCmdObj.OnDestroy := @DoEvaluationDestroyed;
TGDBMIDebugger(Debugger).QueueCommand(FEvaluationCmdObj);
@ -7774,6 +7822,7 @@ begin
FTheDebugger.SendCmdLn(ACommand);
Result := ProcessResult(AResult);
FLastExecResult := AResult;
if not Result
then begin
@ -8084,6 +8133,32 @@ begin
Result := ProcessGDBResultText(StripLN(R.Values));
end;
function TGDBMIDebuggerCommand.GetChar(const AExpression: String;
const AValues: array of const): String;
var
R: TGDBMIExecResult;
begin
if not ExecuteCommand('x/c ' + AExpression, AValues, R)
then begin
Result := '';
Exit;
end;
Result := ProcessGDBResultText(StripLN(R.Values));
end;
function TGDBMIDebuggerCommand.GetFloat(const AExpression: String;
const AValues: array of const): String;
var
R: TGDBMIExecResult;
begin
if not ExecuteCommand('x/f ' + AExpression, AValues, R)
then begin
Result := '';
Exit;
end;
Result := ProcessGDBResultText(StripLN(R.Values));
end;
function TGDBMIDebuggerCommand.GetWideText(const ALocation: TDBGPtr): String;
function GetWideChar(const ALocation: TDBGPtr): WideChar;
@ -8238,12 +8313,20 @@ begin
end;
function TGDBMIDebuggerCommand.GetPtrValue(const AExpression: String;
const AValues: array of const): TDbgPtr;
const AValues: array of const; ConvertNegative: Boolean = False): TDbgPtr;
var
e: Integer;
i: Int64;
s: String;
begin
Result := 0;
Val(GetStrValue(AExpression, AValues), Result, e);
s := GetStrValue(AExpression, AValues);
if (s <> '') and (s[1] = '-')
then begin
Val(s, i, e);
Result := TDBGPtr(i);
end
else Val(s, Result, e);
if e=0 then ;
end;
@ -8986,16 +9069,310 @@ function TGDBMIDebuggerCommandEvaluate.DoExecute: Boolean;
end;
end;
procedure FixUpResult(AnExpression: string);
var
ResultInfo: TGDBType;
addr: TDbgPtr;
e: Integer;
PrintableString: String;
begin
// Check for strings
ResultInfo := GetGDBTypeInfo(AnExpression);
if (ResultInfo = nil) then Exit;
case ResultInfo.Kind of
skPointer: begin
AnExpression := GetPart([], [' '], FTextValue, False, False);
Val(AnExpression, addr, e);
if e <> 0 then begin
FreeAndNil(ResultInfo);
Exit;
end;
AnExpression := Lowercase(ResultInfo.TypeName);
case StringCase(AnExpression, ['char', 'character', 'ansistring', '__vtbl_ptr_type', 'wchar', 'widechar', 'pointer']) of
0, 1, 2: begin
if Addr = 0
then
FTextValue := ''''''
else
FTextValue := MakePrintable(GetText(Addr));
PrintableString := FTextValue;
end;
3: begin
if Addr = 0
then FTextValue := 'nil'
else begin
AnExpression := GetClassName(Addr);
if AnExpression = '' then AnExpression := '???';
FTextValue := 'class of ' + AnExpression + ' ' + FTextValue;
end;
end;
4,5: begin
// widestring handling
if Addr = 0
then FTextValue := ''''''
else FTextValue := MakePrintable(GetWideText(Addr));
PrintableString := FTextValue;
end;
6: begin // pointer
if Addr = 0
then FTextValue := 'nil';
FTextValue := PascalizePointer(FTextValue);
end;
else
if Addr = 0
then FTextValue := 'nil';
if (Length(AnExpression) > 0)
then begin
if AnExpression[1] = 't'
then begin
AnExpression[1] := 'T';
if Length(AnExpression) > 1 then AnExpression[2] := UpperCase(AnExpression[2])[1];
end;
FTextValue := PascalizePointer(FTextValue, '^' + AnExpression);
end;
end;
ResultInfo.Value.AsPointer := Pointer(PtrUint(Addr));
AnExpression := Format('$%x', [Addr]);
if PrintableString <> ''
then AnExpression := AnExpression + ' ' + PrintableString;
ResultInfo.Value.AsString := AnExpression;
end;
skClass: begin
Val(FTextValue, addr, e); //Get the class mem address
if e = 0 then begin //No error ?
if Addr = 0
then FTextValue := 'nil'
else begin
AnExpression := GetInstanceClassName(Addr);
if AnExpression = '' then AnExpression := '???'; //No instanced class found
FTextValue := 'class ' + AnExpression + ' ' + FTextValue;
end;
end;
end;
skVariant: begin
FTextValue := GetVariantValue(FTextValue);
end;
skRecord: begin
FTextValue := 'record ' + ResultInfo.TypeName + ' '+ FTextValue;
end;
skSimple: begin
if ResultInfo.TypeName = 'CURRENCY' then
FTextValue := FormatCurrency(FTextValue)
else
if (ResultInfo.TypeName = '&ShortString') then
FTextValue := GetStrValue('ShortString(%s)', [AnExpression]) // we have an address here, so we need to typecast
else
FTextValue := FTextValue;
end;
end;
FTypeInfo := ResultInfo;
PutValuesInTree;
FTextValue := FormatResult(FTextValue);
end;
function AddAddressOfToExpression(const AnExpression: string; TypeInfo: TGDBType): String;
var
UseAt: Boolean;
begin
UseAt := True;
case TypeInfo.Kind of // (skClass, skRecord, skEnum, skSet, skProcedure, skFunction, skSimple, skPointer, skVariant)
skPointer: begin
case StringCase(Lowercase(TypeInfo.TypeName),
['char', 'character', 'ansistring', '__vtbl_ptr_type', 'wchar', 'widechar', 'pointer']
)
of
2: UseAt := False;
3: UseAt := False;
end;
end;
end;
if UseAt
then Result := '@(' + AnExpression + ')'
else Result := AnExpression;
end;
function QuoteExpr(const AnExpression: string): string;
var
i, j, Cnt: integer;
begin
if pos(' ', AnExpression) < 1
then exit(AnExpression);
Cnt := length(AnExpression);
SetLength(Result, 2 * Cnt + 2);
Result[1] := '"';
i := 1;
j := 2;
while i <= Cnt do begin
if AnExpression[i] in ['"', '\']
then begin
Result[j] := '\';
inc(j);
end;
Result[j] := AnExpression[i];
inc(i);
inc(j);
end;
Result[j] := '"';
SetLength(Result, j + 1);
end;
function TryExecute(AnExpression: string; StoreError: Boolean): Boolean;
function PrepareExpr(var expr: string; NoAddressOp: Boolean = False): boolean;
var
ResultInfo: TGDBType;
begin
ResultInfo := GetGDBTypeInfo(expr);
Result := ResultInfo <> nil;
if (not Result) and StoreError
then FTextValue := '<error>';
if not Result
then exit;
if NoAddressOp
then expr := QuoteExpr(expr)
else expr := QuoteExpr(AddAddressOfToExpression(expr, ResultInfo));
FreeAndNil(ResultInfo);
end;
var
ResultList: TGDBMINameValueList;
R: TGDBMIExecResult;
MemDump: TGDBMIMemoryDumpResultList;
Size: integer;
begin
Result := False;
case FDisplayFormat of
wdfStructure:
begin
Result := ExecuteCommand('-data-evaluate-expression %s', [AnExpression], R);
Result := Result and (R.State <> dsError);
if (not Result) and (not StoreError)
then exit;
ResultList := TGDBMINameValueList.Create(R.Values);
if Result
then FTextValue := ResultList.Values['value']
else FTextValue := ResultList.Values['msg'];
FTextValue := DeleteEscapeChars(FTextValue);
ResultList.Free;
if Result
then FixUpResult(AnExpression);
end;
wdfChar:
begin
Result := PrepareExpr(AnExpression);
if not Result
then exit;
FTextValue := GetChar(AnExpression, []);
if LastExecResult.State = dsError
then FTextValue := '<error>';
end;
wdfString:
begin
Result := PrepareExpr(AnExpression);
if not Result
then exit;
FTextValue := GetText(AnExpression, []); // GetText takes Addr
if LastExecResult.State = dsError
then FTextValue := '<error>';
end;
wdfDecimal:
begin
Result := PrepareExpr(AnExpression, True);
if not Result
then exit;
FTextValue := IntToStr(Int64(GetPtrValue(AnExpression, [], True)));
if LastExecResult.State = dsError
then FTextValue := '<error>';
end;
wdfUnsigned:
begin
Result := PrepareExpr(AnExpression, True);
if not Result
then exit;
FTextValue := IntToStr(GetPtrValue(AnExpression, [], True));
if LastExecResult.State = dsError
then FTextValue := '<error>';
end;
//wdfFloat:
// begin
// Result := PrepareExpr(AnExpression);
// if not Result
// then exit;
// FTextValue := GetFloat(AnExpression, []); // GetFloat takes address
// if LastExecResult.State = dsError
// then FTextValue := '<error>';
// end;
wdfHex:
begin
Result := PrepareExpr(AnExpression, True);
if not Result
then exit;
FTextValue := IntToHex(GetPtrValue(AnExpression, [], True), 2);
if length(FTextValue) mod 2 = 1
then FTextValue := '0'+FTextValue; // make it an even number of digets
if LastExecResult.State = dsError
then FTextValue := '<error>';
end;
wdfPointer:
begin
Result := PrepareExpr(AnExpression, True);
if not Result
then exit;
FTextValue := IntToHex(GetPtrValue(AnExpression, [], True), TargetInfo^.TargetPtrSize*2);
if LastExecResult.State = dsError
then FTextValue := '<error>';
end;
wdfMemDump:
begin
Result := PrepareExpr(AnExpression);
if not Result
then exit;
Size := 256;
ExecuteCommand('-data-read-memory %s x 1 1 %u', [AnExpression, Size], R);
MemDump := TGDBMIMemoryDumpResultList.Create(R);
FTextValue := MemDump.AsText(0, MemDump.Count, TargetInfo^.TargetPtrSize*2);
MemDump.Free;
end;
else // wdfDefault
begin
Result := ExecuteCommand('-data-evaluate-expression %s', [AnExpression], R);
Result := Result and (R.State <> dsError);
if (not Result) and (not StoreError)
then exit;
ResultList := TGDBMINameValueList.Create(R.Values);
if Result
then FTextValue := ResultList.Values['value']
else FTextValue := ResultList.Values['msg'];
FTextValue := DeleteEscapeChars(FTextValue);
ResultList.Free;
if Result
then FixUpResult(AnExpression);
end;
end;
end;
var
R, Rtmp: TGDBMIExecResult;
R: TGDBMIExecResult;
S: String;
ResultList: TGDBMINameValueList;
ResultInfo: TGDBType;
addr: TDbgPtr;
e: Integer;
Expr: TGDBMIExpression;
frame, frameidx: Integer;
PrintableString: String;
begin
FTextValue:='';
FTypeInfo:=nil;
@ -9021,154 +9398,41 @@ begin
// original
frame := -1;
frameidx := -1;
repeat
Result := ExecuteCommand('-data-evaluate-expression %s', [S], R);
if (R.State <> dsError)
then Break;
// check if there is a parentfp and try to evaluate there
if frame = -1
then begin
// store current
ExecuteCommand('-stack-info-frame', Rtmp);
ResultList.Init(Rtmp.Values);
ResultList.SetPath('frame');
frame := StrToIntDef(ResultList.Values['level'], -1);
if frame = -1 then Break;
frameidx := frame;
end;
until not SelectParentFrame(frameidx);
if frameidx <> frame
then begin
// Restore current frame
ExecuteCommand('-stack-select-frame %u', [frame], []);
end;
ResultList.Init(R.Values);
if R.State = dsError
then FTextValue := ResultList.Values['msg']
else FTextValue := ResultList.Values['value'];
FTextValue := DeleteEscapeChars(FTextValue);
ResultList.Free;
if R.State = dsError
then Exit;
// Check for strings
ResultInfo := GetGDBTypeInfo(S);
if (ResultInfo = nil) then Exit;
try
case ResultInfo.Kind of
skPointer: begin
S := GetPart([], [' '], FTextValue, False, False);
Val(S, addr, e);
if e <> 0 then begin
FreeAndNil(ResultInfo);
Exit;
end;
repeat
if TryExecute(S, frame = -1)
then Break;
S := Lowercase(ResultInfo.TypeName);
case StringCase(S, ['char', 'character', 'ansistring', '__vtbl_ptr_type', 'wchar', 'widechar']) of
0, 1, 2: begin
if Addr = 0
then
FTextValue := ''''''
else
FTextValue := MakePrintable(GetText(Addr));
PrintableString := FTextValue;
end;
3: begin
if Addr = 0
then FTextValue := 'nil'
else begin
S := GetClassName(Addr);
if S = '' then S := '???';
FTextValue := 'class of ' + S + ' ' + FTextValue;
end;
end;
4,5: begin
// widestring handling
if Addr = 0
then FTextValue := ''''''
else FTextValue := MakePrintable(GetWideText(Addr));
PrintableString := FTextValue;
end;
else
if Addr = 0
then FTextValue := 'nil';
if (Length(S) > 0)
then begin
if (S <> 'pointer')
then begin
if S[1] = 't'
then begin
S[1] := 'T';
if Length(S) > 1 then S[2] := UpperCase(S[2])[1];
end;
FTextValue := PascalizePointer(FTextValue, '^' + S);
end
else FTextValue := PascalizePointer(FTextValue);
end;
end;
ResultInfo.Value.AsPointer := Pointer(PtrUint(Addr));
S := Format('$%x', [Addr]);
if PrintableString <> ''
then S := S + ' ' + PrintableString;
ResultInfo.Value.AsString := S;
// check if there is a parentfp and try to evaluate there
if frame = -1
then begin
// store current
ExecuteCommand('-stack-info-frame', R);
ResultList.Init(R.Values);
ResultList.SetPath('frame');
frame := StrToIntDef(ResultList.Values['level'], -1);
if frame = -1 then Break;
frameidx := frame;
end;
skClass: begin
Val(FTextValue, addr, e); //Get the class mem address
if e = 0 then begin //No error ?
if Addr = 0
then FTextValue := 'nil'
else begin
S := GetInstanceClassName(Addr);
if S = '' then S := '???'; //No instanced class found
FTextValue := 'class ' + S + ' ' + FTextValue;
end;
end;
end;
skVariant: begin
FTextValue := GetVariantValue(FTextValue);
end;
skRecord: begin
FTextValue := 'record ' + ResultInfo.TypeName + ' '+ FTextValue;
end;
skSimple: begin
if ResultInfo.TypeName = 'CURRENCY' then
FTextValue := FormatCurrency(FTextValue)
else
if (ResultInfo.TypeName = '&ShortString') then
FTextValue := GetStrValue('ShortString(%s)', [S]) // we have an address here, so we need to typecast
else
FTextValue := FTextValue;
end;
end;
until not SelectParentFrame(frameidx);
finally
if frameidx <> frame
then begin
// Restore current frame
ExecuteCommand('-stack-select-frame %u', [frame], []);
end
end;
FreeAndNil(ResultList);
end;
FTypeInfo := ResultInfo;
PutValuesInTree;
FTextValue := FormatResult(FTextValue);
Result := True;
end;
constructor TGDBMIDebuggerCommandEvaluate.Create(AOwner: TGDBMIDebugger;
const AExpression: String);
const AExpression: String; const ADisplayFormat: TWatchDisplayFormat);
begin
inherited Create(AOwner);
FExpression := AExpression;
FDisplayFormat := ADisplayFormat;
FTextValue := '';
FTypeInfo:=nil;
end;

View File

@ -1,7 +1,7 @@
object WatchPropertyDlg: TWatchPropertyDlg
Left = 331
Left = 542
Height = 210
Top = 184
Top = 214
Width = 420
ActiveControl = chkAllowFunc
BorderIcons = [biSystemMenu]
@ -16,9 +16,9 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideTop.Control = txtExpression
AnchorSideTop.Side = asrCenter
Left = 6
Height = 14
Height = 16
Top = 9
Width = 57
Width = 59
BorderSpacing.Left = 6
Caption = 'Expression:'
ParentColor = False
@ -28,9 +28,9 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideTop.Control = txtRepCount
AnchorSideTop.Side = asrCenter
Left = 6
Height = 14
Top = 36
Width = 72
Height = 16
Top = 38
Width = 76
BorderSpacing.Left = 6
Caption = 'Repeat Count:'
ParentColor = False
@ -41,9 +41,9 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideTop.Control = txtDigits
AnchorSideTop.Side = asrCenter
Left = 171
Height = 14
Top = 36
Width = 31
Height = 16
Top = 38
Width = 34
BorderSpacing.Left = 6
Caption = 'Digits:'
ParentColor = False
@ -53,7 +53,7 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 105
Height = 21
Height = 23
Top = 6
Width = 309
Anchors = [akTop, akLeft, akRight]
@ -65,8 +65,8 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideTop.Control = txtExpression
AnchorSideTop.Side = asrBottom
Left = 105
Height = 21
Top = 33
Height = 23
Top = 35
Width = 60
BorderSpacing.Top = 6
TabOrder = 2
@ -77,9 +77,9 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = txtExpression
AnchorSideTop.Side = asrBottom
Left = 208
Height = 21
Top = 33
Left = 211
Height = 23
Top = 35
Width = 60
BorderSpacing.Left = 6
BorderSpacing.Top = 6
@ -90,9 +90,9 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = chkAllowFunc
Left = 6
Height = 17
Top = 60
Width = 56
Height = 19
Top = 64
Width = 62
AllowGrayed = True
BorderSpacing.Left = 6
Caption = 'Enabled'
@ -102,9 +102,9 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideTop.Control = txtRepCount
AnchorSideTop.Side = asrBottom
Left = 105
Height = 17
Top = 60
Width = 112
Height = 19
Top = 64
Width = 128
AllowGrayed = True
BorderSpacing.Top = 6
Caption = 'Allow Function Calls'
@ -118,7 +118,7 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideRight.Side = asrBottom
Left = 6
Height = 78
Top = 83
Top = 89
Width = 408
Anchors = [akTop, akLeft, akRight]
AutoFill = True
@ -143,7 +143,7 @@ object WatchPropertyDlg: TWatchPropertyDlg
'String'
'Decimal'
'Hexadecimal'
'Floating Point'
'Unsigned'
'Pointer'
'Record/Structure'
'Default'
@ -155,10 +155,19 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideTop.Control = rgStyle
AnchorSideTop.Side = asrBottom
Left = 6
Height = 37
Top = 167
Height = 31
Top = 173
Width = 408
Anchors = [akTop, akLeft, akRight, akBottom]
OKButton.Name = 'OKButton'
OKButton.Caption = '&OK'
HelpButton.Name = 'HelpButton'
HelpButton.Caption = '&Help'
CloseButton.Name = 'CloseButton'
CloseButton.Caption = '&Close'
CloseButton.Enabled = False
CancelButton.Name = 'CancelButton'
CancelButton.Caption = 'Cancel'
TabOrder = 6
ShowButtons = [pbOK, pbCancel, pbHelp]
ShowBevel = False

View File

@ -77,6 +77,12 @@ uses
{ TWatchPropertyDlg }
procedure TWatchPropertyDlg.btnOKClick(Sender: TObject);
const
StyleToDispFormat: Array [0..8] of TWatchDisplayFormat =
(wdfChar, wdfString, wdfDecimal,
wdfHex, wdfUnsigned, wdfPointer,
wdfStructure, wdfDefault, wdfMemDump
);
begin
if FWatch = nil
then begin
@ -85,7 +91,12 @@ begin
else begin
FWatch.Expression := txtExpression.Text;
end;
if (rgStyle.ItemIndex >= low(StyleToDispFormat))
and (rgStyle.ItemIndex <= High(StyleToDispFormat))
then FWatch.DisplayFormat := StyleToDispFormat[rgStyle.ItemIndex]
else FWatch.DisplayFormat := wdfDefault;
FWatch.Enabled := chkEnabled.Checked;
end;
@ -96,6 +107,14 @@ end;
constructor TWatchPropertyDlg.Create(AOwner: TComponent; const AWatch: TIDEWatch;
const AWatchExpression: String = '');
const
DispFormatToStyle: Array [TWatchDisplayFormat] of Integer =
(7, 6, //wdfDefault, wdfStructure,
0, 1, //wdfChar, wdfString,
2, 4, //wdfDecimal, wdfUnsigned, (TODO unsigned)
7, 3, //wdfFloat, wdfHex,
5, 8 //wdfPointer, wdfMemDump
);
begin
FWatch := AWatch;
inherited Create(AOwner);
@ -103,19 +122,20 @@ begin
then begin
chkEnabled.Checked := True;
txtExpression.Text := AWatchExpression;
rgStyle.ItemIndex := 7;
end
else begin
txtExpression.Text := FWatch.Expression;
chkEnabled.Checked := FWatch.Enabled;
rgStyle.ItemIndex := DispFormatToStyle[FWatch.DisplayFormat];
end;
lblRepCount.Enabled := False;
txtRepCount.Enabled := False;
lblDigits.Enabled := False;
txtDigits.Enabled := False;
chkAllowFunc.Enabled := False;
rgStyle.Enabled := False;
Caption:= lisWatchPropert;
lblExpression.Caption:= lisExpression;
lblRepCount.Caption:= lisRepeatCount;
@ -127,11 +147,12 @@ begin
rgStyle.Items[1]:= lisString;
rgStyle.Items[2]:= lisDecimal;
rgStyle.Items[3]:= lisHexadecimal;
rgStyle.Items[4]:= lisFloatingPoin;
rgStyle.Items[4]:= lisUnsigned;
rgStyle.Items[5]:= lisPointer;
rgStyle.Items[6]:= lisRecordStruct;
rgStyle.Items[7]:= dlgAssemblerDefault;
rgStyle.Items[8]:= lisMemoryDump;
//rgStyle.Items[9]:= lisFloatingPoin;
ButtonPanel.OKButton.OnClick := @btnOKClick;
ButtonPanel.HelpButton.OnClick := @btnHelpClick;

View File

@ -275,6 +275,7 @@ type
function GetTypeInfo: TDBGType; override;
procedure SetEnabled(const AValue: Boolean); override;
procedure SetExpression(const AValue: String); override;
procedure SetDisplayFormat(const AValue: TWatchDisplayFormat); override;
public
destructor Destroy; override;
procedure ResetMaster;
@ -827,6 +828,13 @@ begin
if FMaster <> nil then FMaster.Expression := AValue;
end;
procedure TManagedWatch.SetDisplayFormat(const AValue: TWatchDisplayFormat);
begin
if AValue = DisplayFormat then Exit;
inherited SetDisplayFormat(AValue);
if FMaster <> nil then FMaster.DisplayFormat := AValue;
end;
destructor TManagedWatch.Destroy;
begin
ResetMaster;

View File

@ -4581,6 +4581,7 @@ resourcestring
lisCharacter = 'Character';
lisString = 'String';
lisDecimal = 'Decimal';
lisUnsigned = 'Unsigned';
lisHexadecimal = 'Hexadecimal';
lisFloatingPoin = 'Floating Point';
lisPointer = 'Pointer';