mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-21 14:42:38 +02:00
202 lines
5.8 KiB
ObjectPascal
202 lines
5.8 KiB
ObjectPascal
unit FpDebuggerResultData;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, FpWatchResultData, FpDbgInfo, FpdMemoryTools,
|
|
FpErrorMessages, DbgIntfBaseTypes, LazClasses, FpDebugValueConvertors,
|
|
FpDebugDebuggerBase, LazDebuggerIntf;
|
|
|
|
type
|
|
|
|
{ TFpLazDbgWatchResultConvertor }
|
|
|
|
TFpLazDbgWatchResultConvertor = class(TFpWatchResultConvertor)
|
|
private
|
|
FDebugger: TFpDebugDebuggerBase;
|
|
FExpressionScope: TFpDbgSymbolScope;
|
|
FValConvList: TFpDbgConverterConfigList;
|
|
FValConfig: TFpDbgConverterConfig;
|
|
|
|
FExtraDephtLevelIsArray: Boolean; // defExtraDepth / RecurseCnt=-1
|
|
FExtraDephtLevelItemConv: TFpDbgValueConverter;
|
|
FLevelZeroKind: TDbgSymbolKind;
|
|
FLevelZeroArrayConv: TFpDbgValueConverter; // All itens in array have same type / optimize and keep converter
|
|
FInArray, FInNonConvert: Boolean;
|
|
FMaxTotalConv, FMaxArrayConv, FCurMaxArrayConv: Integer;
|
|
FNoConvert: Boolean;
|
|
|
|
function GetValConv(AnFpValue: TFpValue): TFpDbgValueConverter; inline;
|
|
procedure SetMaxArrayConv(AValue: Integer);
|
|
procedure SetMaxTotalConv(AValue: Integer);
|
|
public
|
|
destructor Destroy; override;
|
|
|
|
function DoValueToResData(AnFpValue: TFpValue;
|
|
AnResData: TLzDbgWatchDataIntf): Boolean; override;
|
|
property ValConvList: TFpDbgConverterConfigList read FValConvList write FValConvList;
|
|
property ValConfig: TFpDbgConverterConfig read FValConfig write FValConfig;
|
|
property Debugger: TFpDebugDebuggerBase read FDebugger write FDebugger;
|
|
property ExpressionScope: TFpDbgSymbolScope read FExpressionScope write FExpressionScope;
|
|
property MaxArrayConv: Integer read FMaxArrayConv write SetMaxArrayConv;
|
|
property MaxTotalConv: Integer read FMaxTotalConv write SetMaxTotalConv;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TFpLazDbgWatchResultConvertor }
|
|
|
|
function TFpLazDbgWatchResultConvertor.GetValConv(AnFpValue: TFpValue
|
|
): TFpDbgValueConverter;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := nil;
|
|
if (FNoConvert) or
|
|
(FInArray and (FMaxArrayConv <= 0))
|
|
then
|
|
exit;
|
|
|
|
if (ValConfig <> nil) then begin
|
|
if ValConfig.CheckMatch(AnFpValue) then
|
|
Result := ValConfig.Converter;
|
|
if Result <> nil then
|
|
Result.AddReference;
|
|
end;
|
|
if (ValConvList <> nil) then begin
|
|
ValConvList.Lock;
|
|
try
|
|
i := ValConvList.Count - 1;
|
|
while (i >= 0) and (not ValConvList[i].CheckMatch(AnFpValue)) do
|
|
dec(i);
|
|
if i >= 0 then
|
|
Result := ValConvList[i].Converter;
|
|
if Result <> nil then
|
|
Result.AddReference;
|
|
finally
|
|
ValConvList.Unlock;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TFpLazDbgWatchResultConvertor.SetMaxArrayConv(AValue: Integer);
|
|
begin
|
|
if FMaxArrayConv = AValue then Exit;
|
|
FMaxArrayConv := AValue;
|
|
FCurMaxArrayConv := AValue;
|
|
end;
|
|
|
|
procedure TFpLazDbgWatchResultConvertor.SetMaxTotalConv(AValue: Integer);
|
|
begin
|
|
if FMaxTotalConv = AValue then Exit;
|
|
FMaxTotalConv := AValue;
|
|
FNoConvert := FMaxTotalConv <= 0;
|
|
end;
|
|
|
|
destructor TFpLazDbgWatchResultConvertor.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
FExtraDephtLevelItemConv.ReleaseReference;
|
|
FLevelZeroArrayConv.ReleaseReference;
|
|
end;
|
|
|
|
function TFpLazDbgWatchResultConvertor.DoValueToResData(AnFpValue: TFpValue;
|
|
AnResData: TLzDbgWatchDataIntf): Boolean;
|
|
var
|
|
NewFpVal: TFpValue;
|
|
CurConv: TFpDbgValueConverter;
|
|
AnResFld: TLzDbgWatchDataIntf;
|
|
WasInArray, WasInNonConvert: Boolean;
|
|
begin
|
|
Result := False;
|
|
|
|
if (RecurseCnt = -1) and (AnFpValue.Kind in [skArray]) then
|
|
FExtraDephtLevelIsArray := True;
|
|
|
|
if RecurseCnt = 0 then begin
|
|
FLevelZeroKind := AnFpValue.Kind;
|
|
FCurMaxArrayConv := FMaxArrayConv;
|
|
if not FExtraDephtLevelIsArray then
|
|
ReleaseRefAndNil(FLevelZeroArrayConv);
|
|
end;
|
|
|
|
WasInArray := FInArray;
|
|
WasInNonConvert := FInNonConvert;
|
|
if (RecurseCnt >= 0) and (AnFpValue.Kind in [skArray]) then
|
|
FInArray := True;
|
|
|
|
|
|
if not FInNonConvert then begin
|
|
CurConv := nil;
|
|
NewFpVal := nil;
|
|
try
|
|
if (RecurseCnt = 0) and (FExtraDephtLevelIsArray) then begin
|
|
if FExtraDephtLevelItemConv = nil then
|
|
FExtraDephtLevelItemConv := GetValConv(AnFpValue);
|
|
CurConv := FExtraDephtLevelItemConv;
|
|
end
|
|
else
|
|
if (RecurseCnt = 1) and (FLevelZeroKind = skArray) then begin
|
|
if FLevelZeroArrayConv = nil then
|
|
FLevelZeroArrayConv := GetValConv(AnFpValue);
|
|
CurConv := FLevelZeroArrayConv;
|
|
end
|
|
else begin
|
|
CurConv := GetValConv(AnFpValue);
|
|
end;
|
|
|
|
if (CurConv <> nil) then begin
|
|
if (FMaxTotalConv <= 0) then
|
|
CurConv := nil
|
|
else
|
|
dec(FMaxTotalConv);
|
|
|
|
if FInArray then begin
|
|
if (FCurMaxArrayConv <= 0) then
|
|
CurConv := nil
|
|
else
|
|
dec(FCurMaxArrayConv);
|
|
end;
|
|
|
|
AnResData.CreateStructure(dstInternal);
|
|
AnResFld := AnResData.AddField('', dfvUnknown, []);
|
|
if (CurConv <> nil) then begin
|
|
FInNonConvert := True;
|
|
|
|
NewFpVal := CurConv.ConvertValue(AnFpValue, Debugger, ExpressionScope);
|
|
if NewFpVal <> nil then begin
|
|
Result := inherited DoValueToResData(NewFpVal, AnResFld);
|
|
end
|
|
else begin
|
|
if IsError(CurConv.LastErrror) then
|
|
AnResFld.CreateError(ErrorHandler.ErrorAsString(CurConv.LastErrror))
|
|
else
|
|
AnResFld.CreateError('Conversion failed');
|
|
Result := True;
|
|
end;
|
|
end
|
|
else
|
|
AnResFld.CreateError('');
|
|
|
|
AnResData := AnResData.AddField('', dfvUnknown, []);
|
|
end;
|
|
finally
|
|
if (CurConv <> FExtraDephtLevelItemConv) and
|
|
(CurConv <> FLevelZeroArrayConv)
|
|
then
|
|
CurConv.ReleaseReference;
|
|
NewFpVal.ReleaseReference;
|
|
end;
|
|
end;
|
|
|
|
if inherited DoValueToResData(AnFpValue, AnResData) then
|
|
Result := True;
|
|
FInArray := WasInArray;
|
|
FInNonConvert := WasInNonConvert;
|
|
end;
|
|
|
|
end.
|
|
|