mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 14:59:15 +02:00
debugger: clean up, removed TGDBMIExpression (an never finished attempt to support pre gdb 5.2)
git-svn-id: trunk@42424 -
This commit is contained in:
parent
16c296ef1d
commit
8ad2de8e3a
@ -1509,130 +1509,6 @@ type
|
||||
|
||||
{%endregion ^^^^^ Threads ^^^^^ }
|
||||
|
||||
{%region ***** TGDBMIExpression ***** }
|
||||
|
||||
{ TGDBMIExpression }
|
||||
// TGDBMIExpression was an attempt to make expression evaluation on Objects possible for GDB <= 5.2
|
||||
// It is not completed and buggy. Since 5.3 expression evaluation is OK, so maybe in future the
|
||||
// TGDBMIExpression will be completed to support older gdb versions
|
||||
|
||||
TDBGExpressionOperator = (
|
||||
eoNone,
|
||||
eoNegate,
|
||||
eoPlus,
|
||||
eoSubstract,
|
||||
eoAdd,
|
||||
eoMultiply,
|
||||
eoPower,
|
||||
eoDivide,
|
||||
eoDereference,
|
||||
eoAddress,
|
||||
eoEqual,
|
||||
eoLess,
|
||||
eoLessOrEqual,
|
||||
eoGreater,
|
||||
eoGreaterOrEqual,
|
||||
eoNotEqual,
|
||||
eoIn,
|
||||
eoIs,
|
||||
eoAs,
|
||||
eoDot,
|
||||
eoComma,
|
||||
eoBracket,
|
||||
eoIndex,
|
||||
eoClose,
|
||||
eoAnd,
|
||||
eoOr,
|
||||
eoMod,
|
||||
eoNot,
|
||||
eoDiv,
|
||||
eoXor,
|
||||
eoShl,
|
||||
eoShr
|
||||
);
|
||||
|
||||
const
|
||||
OPER_LEVEL: array[TDBGExpressionOperator] of Byte = (
|
||||
{eoNone } 0,
|
||||
{eoNegate } 5,
|
||||
{eoPlus } 5,
|
||||
{eoSubstract } 7,
|
||||
{eoAdd } 7,
|
||||
{eoMultiply } 6,
|
||||
{eoPower } 4,
|
||||
{eoDivide } 6,
|
||||
{eoDereference } 2,
|
||||
{eoAddress } 4,
|
||||
{eoEqual } 8,
|
||||
{eoLess } 8,
|
||||
{eoLessOrEqual } 8,
|
||||
{eoGreater } 8,
|
||||
{eoGreaterOrEqual } 8,
|
||||
{eoNotEqual } 8,
|
||||
{eoIn } 8,
|
||||
{eoIs } 8,
|
||||
{eoAs } 6,
|
||||
{eoDot } 2,
|
||||
{eoComma } 9,
|
||||
{eoBracket } 1,
|
||||
{eoIndex } 3,
|
||||
{eoClose } 9,
|
||||
{eoAnd } 6,
|
||||
{eoOr } 7,
|
||||
{eoMod } 6,
|
||||
{eoNot } 5,
|
||||
{eoDiv } 6,
|
||||
{eoXor } 7,
|
||||
{eoShl } 6,
|
||||
{eoShr } 6
|
||||
);
|
||||
|
||||
type
|
||||
PGDBMISubExpression = ^TGDBMISubExpression;
|
||||
TGDBMISubExpression = record
|
||||
Opertor: TDBGExpressionOperator;
|
||||
Operand: String;
|
||||
Next, Prev: PGDBMISubExpression;
|
||||
end;
|
||||
|
||||
PGDBMIExpressionResult = ^TGDBMIExpressionResult;
|
||||
TGDBMIExpressionResult = record
|
||||
Opertor: TDBGExpressionOperator;
|
||||
// Operand: String;
|
||||
Value: String;
|
||||
Info: TGDBType;
|
||||
Next, Prev: PGDBMIExpressionResult;
|
||||
end;
|
||||
|
||||
|
||||
TGDBMIExpression = class(TObject)
|
||||
private
|
||||
FList: PGDBMISubExpression;
|
||||
FStack: PGDBMIExpressionResult;
|
||||
FStackPtr: PGDBMIExpressionResult;
|
||||
procedure Push(var AResult: PGDBMIExpressionResult);
|
||||
procedure Pop(var AResult: PGDBMIExpressionResult);
|
||||
procedure DisposeList(AList: PGDBMIExpressionResult);
|
||||
|
||||
function Solve(const ADebuggerCommand: TGDBMIDebuggerCommand; ALimit: Byte; const ARight: String; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveAddress(const ADebuggerCommand: TGDBMIDebuggerCommand; ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveMath(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveIn(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveIs(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveAs(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveDeref(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
function SolveDot(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft: PGDBMIExpressionResult; const ARight: String; out AVAlue: String; out AInfo: TGDBType): Boolean;
|
||||
protected
|
||||
function Evaluate(const ADebuggerCommand: TGDBMIDebuggerCommand; const AText: String; out AResult: String; out AResultInfo: TGDBType): Boolean;
|
||||
public
|
||||
constructor Create(const AExpression: String);
|
||||
destructor Destroy; override;
|
||||
function DumpExpression: String;
|
||||
function Evaluate(const ADebuggerCommand: TGDBMIDebuggerCommand; out AResult: String; out AResultInfo: TGDBType): Boolean;
|
||||
end;
|
||||
|
||||
{%endregion *^^^* TGDBMIExpression *^^^* }
|
||||
|
||||
{ TGDBStringIterator }
|
||||
|
||||
TGDBStringIterator=class
|
||||
@ -9672,730 +9548,6 @@ begin
|
||||
FreeAndNil(FCommandList);
|
||||
end;
|
||||
|
||||
{ =========================================================================== }
|
||||
{ TGDBMIExpression }
|
||||
{ =========================================================================== }
|
||||
|
||||
function GetSubExpression(var AExpression: PChar; var ALength: Integer; out AOperator: TDBGExpressionOperator; out AOperand: String): Boolean;
|
||||
type
|
||||
TScanState = (
|
||||
ssNone, // start scanning
|
||||
ssString, // inside string
|
||||
ssEndString, // just left a string, we may reenter if another ' is present
|
||||
ssOperand, // reading operand
|
||||
ssOperator // delimeter found, next must be operator
|
||||
);
|
||||
var
|
||||
State: TScanState;
|
||||
|
||||
function GetOperand(const AOperand: String): String;
|
||||
begin
|
||||
if (AOperand = '')
|
||||
or (AOperand[1] <> '''')
|
||||
then Result := AOperand
|
||||
else Result := ConvertToCString(AOperand);
|
||||
end;
|
||||
|
||||
function GetOperator(AOperator: PChar; ALen: Integer): TDBGExpressionOperator;
|
||||
begin
|
||||
case AOperator[0] of
|
||||
'-': Result := eoSubstract;
|
||||
'+': Result := eoAdd;
|
||||
'*': begin
|
||||
if ALen = 1
|
||||
then Result := eoMultiply
|
||||
else Result := eoPower;
|
||||
end;
|
||||
'/': Result := eoDivide;
|
||||
'^': Result := eoDereference;
|
||||
'@': Result := eoAddress;
|
||||
'=': Result := eoEqual;
|
||||
'<': begin
|
||||
if ALen = 1
|
||||
then Result := eoLess
|
||||
else if AOperator[1] = '='
|
||||
then Result := eoLessOrEqual
|
||||
else Result := eoNotEqual;
|
||||
end;
|
||||
'>': begin
|
||||
if ALen = 1
|
||||
then Result := eoGreater
|
||||
else Result := eoGreaterOrEqual;
|
||||
end;
|
||||
'.': Result := eoDot;
|
||||
',': Result := eoComma;
|
||||
'(': Result := eoBracket;
|
||||
'[': Result := eoIndex;
|
||||
')': Result := eoClose;
|
||||
']': Result := eoClose;
|
||||
'a', 'A': begin
|
||||
if AOperator[1] in ['s', 'S']
|
||||
then Result := eoAs
|
||||
else Result := eoAnd;
|
||||
end;
|
||||
'o', 'O': Result := eoOr;
|
||||
'i', 'I': begin
|
||||
if AOperator[1] in ['s', 'S']
|
||||
then Result := eoIs
|
||||
else Result := eoIn;
|
||||
end;
|
||||
'm', 'M': Result := eoMod;
|
||||
'n', 'N': Result := eoNot;
|
||||
'd', 'D': Result := eoDiv;
|
||||
'x', 'X': Result := eoXor;
|
||||
's', 'S': begin
|
||||
if AOperator[2] in ['l', 'L']
|
||||
then Result := eoShl
|
||||
else Result := eoShr;
|
||||
end;
|
||||
end;
|
||||
Inc(AExpression, ALen);
|
||||
Dec(ALength, ALen);
|
||||
end;
|
||||
|
||||
function CheckOperator(const AOperator: String): Boolean;
|
||||
var
|
||||
len: Integer;
|
||||
begin
|
||||
len := Length(AOperator);
|
||||
if ALength <= len then Exit(False); // net char after operator too
|
||||
if not (AExpression[len] in [' ', #9, '(']) then Exit(False);
|
||||
if StrLIComp(AExpression, @AOperator[1], len) <> 0 then Exit(False);
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
var
|
||||
Sub: String;
|
||||
len: Integer;
|
||||
begin
|
||||
while (ALength > 0) and (AExpression^ in [#9, ' ']) do
|
||||
begin
|
||||
Dec(ALength);
|
||||
Inc(AExpression);
|
||||
end;
|
||||
if ALength = 0 then Exit;
|
||||
|
||||
State := ssNone;
|
||||
Sub:='';
|
||||
while ALength > 0 do
|
||||
begin
|
||||
if AExpression^ = ''''
|
||||
then begin
|
||||
case State of
|
||||
ssOperand,
|
||||
ssOperator: Exit(False); //illegal
|
||||
ssNone: State := ssString;
|
||||
ssString:State := ssEndString;
|
||||
ssEndString: State := ssString;
|
||||
end;
|
||||
Sub := Sub + AExpression^;
|
||||
Inc(AExpression);
|
||||
Dec(ALength);
|
||||
Continue;
|
||||
end;
|
||||
|
||||
case State of
|
||||
ssString: begin
|
||||
Sub := Sub + AExpression^;
|
||||
Inc(AExpression);
|
||||
Dec(ALength);
|
||||
Continue;
|
||||
end;
|
||||
ssEndString: State := ssOperator;
|
||||
ssNone: State := ssOperand;
|
||||
end;
|
||||
|
||||
case AExpression^ of
|
||||
' ', #9: begin
|
||||
State := ssOperator;
|
||||
Inc(AExpression);
|
||||
Dec(ALength);
|
||||
Continue;
|
||||
end;
|
||||
'(', '[': begin
|
||||
AOperand := GetOperand(Sub);
|
||||
AOperator := GetOperator(AExpression, 1);
|
||||
Exit(True);
|
||||
end;
|
||||
')', ']': begin
|
||||
AOperand := GetOperand(Sub);
|
||||
AOperator := GetOperator(AExpression, 1);
|
||||
Exit(True);
|
||||
end;
|
||||
'-', '+': begin
|
||||
if Sub = ''
|
||||
then begin
|
||||
//unary
|
||||
AOperand := '';
|
||||
if AExpression^ = '-'
|
||||
then AOperator := eoNegate
|
||||
else AOperator := eoPlus;
|
||||
Inc(AExpression);
|
||||
Dec(ALength);
|
||||
end
|
||||
else begin
|
||||
AOperand := GetOperand(Sub);
|
||||
end;
|
||||
Exit(True);
|
||||
end;
|
||||
'/', '^', '@', '=', ',': begin
|
||||
AOperand := GetOperand(Sub);
|
||||
AOperator := GetOperator(AExpression, 1);
|
||||
Exit(True);
|
||||
end;
|
||||
'*', '<', '>': begin
|
||||
AOperand := GetOperand(Sub);
|
||||
if ALength > 1
|
||||
then begin
|
||||
if AExpression[0] = '*'
|
||||
then begin
|
||||
if AExpression[1] = '*'
|
||||
then AOperator := GetOperator(AExpression, 2)
|
||||
else AOperator := GetOperator(AExpression, 1);
|
||||
end
|
||||
else begin
|
||||
if AExpression[1] = '='
|
||||
then AOperator := GetOperator(AExpression, 2)
|
||||
else AOperator := GetOperator(AExpression, 1);
|
||||
end;
|
||||
end
|
||||
else AOperator := GetOperator(AExpression, 1);
|
||||
Exit(True);
|
||||
end;
|
||||
'.': begin
|
||||
if (State <> ssOperand) or (Length(Sub) = 0) or not (Sub[1] in ['0'..'9'])
|
||||
then begin
|
||||
AOperand := GetOperand(Sub);
|
||||
AOperator := GetOperator(AExpression, 1);
|
||||
Exit(True);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (State = ssOperator)
|
||||
then begin
|
||||
len := 3;
|
||||
case AExpression^ of
|
||||
'a', 'A': begin
|
||||
if not CheckOperator('and') then Exit(False);
|
||||
if not CheckOperator('as') then Exit(False);
|
||||
end;
|
||||
'o', 'O': begin
|
||||
if not CheckOperator('or') then Exit(False);
|
||||
len := 2;
|
||||
end;
|
||||
'i', 'I': begin
|
||||
if not CheckOperator('in') then Exit(False);
|
||||
if not CheckOperator('is') then Exit(False);
|
||||
end;
|
||||
'm', 'M': begin
|
||||
if not CheckOperator('mod') then Exit(False);
|
||||
end;
|
||||
'd', 'D': begin
|
||||
if not CheckOperator('div') then Exit(False);
|
||||
end;
|
||||
'x', 'X': begin
|
||||
if not CheckOperator('xor') then Exit(False);
|
||||
end;
|
||||
's', 'S': begin
|
||||
if not (CheckOperator('shl') or CheckOperator('shr')) then Exit(False);
|
||||
end;
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
AOperand := GetOperand(Sub);
|
||||
AOperator := GetOperator(AExpression, len);
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
if (State = ssOperand)
|
||||
and (Sub = '')
|
||||
and CheckOperator('not')
|
||||
then begin
|
||||
AOperand := '';
|
||||
AOperator := GetOperator(AExpression, 3);
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
Sub := Sub + AExpression^;
|
||||
Inc(AExpression);
|
||||
Dec(ALength);
|
||||
end;
|
||||
|
||||
if not (State in [ssOperator, ssOperand, ssEndString]) then Exit(False);
|
||||
|
||||
AOperand := GetOperand(Sub);
|
||||
AOperator := eoNone;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
constructor TGDBMIExpression.Create(const AExpression: String);
|
||||
var
|
||||
len: Integer;
|
||||
P: PChar;
|
||||
Run, Work: PGDBMISubExpression;
|
||||
Opertor: TDBGExpressionOperator;
|
||||
Operand: String;
|
||||
begin
|
||||
inherited Create;
|
||||
len := Length(AExpression);
|
||||
p := PChar(AExpression);
|
||||
Run := nil;
|
||||
while (len > 0) and GetSubExpression(p, len, Opertor, Operand) do
|
||||
begin
|
||||
New(Work);
|
||||
Work^.Opertor := Opertor;
|
||||
Work^.Operand := Operand;
|
||||
Work^.Prev := Run;
|
||||
Work^.Next := nil;
|
||||
|
||||
if FList = nil
|
||||
then FList := Work
|
||||
else Run^.Next := Work;
|
||||
Run := Work;
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TGDBMIExpression.Destroy;
|
||||
var
|
||||
Run, Work: PGDBMISubExpression;
|
||||
begin
|
||||
Run := FList;
|
||||
while Run <> nil do
|
||||
begin
|
||||
Work := Run;
|
||||
Run := Work^.Next;
|
||||
Dispose(Work);
|
||||
end;
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TGDBMIExpression.DisposeList(AList: PGDBMIExpressionResult);
|
||||
var
|
||||
Temp: PGDBMIExpressionResult;
|
||||
begin
|
||||
while AList <> nil do
|
||||
begin
|
||||
AList^.Info.Free;
|
||||
Temp := AList;
|
||||
AList := Alist^.Next;
|
||||
Dispose(Temp);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.DumpExpression: String;
|
||||
// Mainly used for debugging purposes
|
||||
var
|
||||
Sub: PGDBMISubExpression;
|
||||
s: string;
|
||||
begin
|
||||
Result := '';
|
||||
Sub := FList;
|
||||
while Sub <> nil do
|
||||
begin
|
||||
WriteStr(s, Sub^.Opertor);
|
||||
Result := Result + Sub^.Operand + ' ' + s + ' ';
|
||||
Sub := Sub^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.Evaluate(const ADebuggerCommand: TGDBMIDebuggerCommand; out AResult: String; out AResultInfo: TGDBType): Boolean;
|
||||
|
||||
const
|
||||
OPER_UNARY = [eoNot, eoNegate, eoPlus, eoAddress, eoBracket];
|
||||
|
||||
var
|
||||
Sub: PGDBMISubExpression;
|
||||
R: PGDBMIExpressionResult;
|
||||
begin
|
||||
Result := True;
|
||||
Sub := FList;
|
||||
FStack := nil;
|
||||
FStackPtr := nil;
|
||||
New(R);
|
||||
FillByte(R^, SizeOf(R^), 0);
|
||||
while Sub <> nil do
|
||||
begin
|
||||
R^.Opertor := Sub^.Opertor;
|
||||
if Sub^.Operand = ''
|
||||
then begin
|
||||
if not (Sub^.OperTor in OPER_UNARY)
|
||||
then begin
|
||||
// check if we have a 2nd operator
|
||||
Result := False;
|
||||
if FStackPtr = nil then Break;
|
||||
case FStackPtr^.OperTor of
|
||||
eoClose, eoDereference: begin
|
||||
if not (Sub^.OperTor in [eoDot, eoDereference, eoIndex]) then Break;
|
||||
end;
|
||||
eoBracket: begin
|
||||
if Sub^.OperTor <> eoBracket then Break;
|
||||
end;
|
||||
end;
|
||||
Result := True;
|
||||
end;
|
||||
Push(R);
|
||||
Sub := Sub^.Next;
|
||||
Continue;
|
||||
end;
|
||||
if Sub^.OperTor in OPER_UNARY then Break;
|
||||
|
||||
if (FStackPtr = nil)
|
||||
or (OPER_LEVEL[Sub^.OperTor] < OPER_LEVEL[FStackPtr^.OperTor])
|
||||
then begin
|
||||
if not Evaluate(ADebuggerCommand, Sub^.Operand, R^.Value, R^.Info)
|
||||
then begin
|
||||
Result := False;
|
||||
Break;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
if not Solve(ADebuggerCommand, OPER_LEVEL[Sub^.OperTor], Sub^.Operand, R^.Value, R^.Info)
|
||||
then begin
|
||||
Result := False;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
Push(R);
|
||||
Sub := Sub^.Next;
|
||||
end;
|
||||
|
||||
|
||||
if Result and (FStackPtr <> nil)
|
||||
then begin
|
||||
New(R);
|
||||
FillByte(R^, SizeOf(R^), 0);
|
||||
Result := Solve(ADebuggerCommand, 255, '', R^.Value, R^.Info);
|
||||
Push(R); // make sure it gets cleaned later
|
||||
end;
|
||||
|
||||
if Result
|
||||
then begin
|
||||
AResult := R^.Value;
|
||||
AResultInfo := R^.Info;
|
||||
R^.Info := nil;
|
||||
end;
|
||||
|
||||
while FStackPtr <> nil do
|
||||
begin
|
||||
Pop(R);
|
||||
R^.Info.Free;
|
||||
Dispose(R);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.Evaluate(const ADebuggerCommand: TGDBMIDebuggerCommand; const AText: String; out AResult: String; out AResultInfo: TGDBType): Boolean;
|
||||
var
|
||||
R: TGDBMIExecResult;
|
||||
ResultList: TGDBMINameValueList;
|
||||
begin
|
||||
// special cases
|
||||
if ATExt = ''
|
||||
then begin
|
||||
AResult := '';
|
||||
AResultInfo := nil;
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
if AText = '""'
|
||||
then begin
|
||||
AResult := '0x0';
|
||||
AResultInfo := TGDBType.Create(skPointer, '^character');
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
Result := ADebuggerCommand.ExecuteCommand('-data-evaluate-expression %s', [Quote(AText)], R)
|
||||
and (R.State <> dsError);
|
||||
|
||||
ResultList := TGDBMINameValueList.Create(R);
|
||||
if R.State = dsError
|
||||
then AResult := ResultList.Values['msg']
|
||||
else AResult := ResultList.Values['value'];
|
||||
// AResult := DeleteEscapeChars(AResult);
|
||||
ResultList.Free;
|
||||
if Result
|
||||
then AResultInfo := ADebuggerCommand.GetGDBTypeInfo(AText)
|
||||
else AResultInfo := nil;
|
||||
|
||||
if AResultInfo = nil then Exit;
|
||||
|
||||
//post format some results (for inscance a char is returned as "ord 'Value'"
|
||||
if AResultInfo.Kind <> skSimple then Exit;
|
||||
|
||||
case StringCase(AResultInfo.TypeName, ['character'], true, false) of
|
||||
0: AResult := GetPart([' '], [], AResult);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TGDBMIExpression.Pop(var AResult: PGDBMIExpressionResult);
|
||||
begin
|
||||
AResult := FStackPtr;
|
||||
if AResult = nil then Exit;
|
||||
FStackPtr := AResult^.Prev;
|
||||
if FStackPtr = nil
|
||||
then FStack := nil;
|
||||
AResult^.Next := nil;
|
||||
AResult^.Prev := nil;
|
||||
end;
|
||||
|
||||
procedure TGDBMIExpression.Push(var AResult: PGDBMIExpressionResult);
|
||||
begin
|
||||
if FStack = nil
|
||||
then begin
|
||||
FStack := AResult;
|
||||
FStackPtr := AResult;
|
||||
end
|
||||
else begin
|
||||
FStackPtr^.Next := AResult;
|
||||
AResult^.Prev := FStackPtr;
|
||||
FStackPtr := AResult;
|
||||
end;
|
||||
|
||||
New(AResult);
|
||||
FillByte(AResult^, SizeOf(AResult^), 0);
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.Solve(const ADebuggerCommand: TGDBMIDebuggerCommand; ALimit: Byte; const ARight: String; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
var
|
||||
StartPtr, Left: PGDBMIExpressionResult;
|
||||
Right: TGDBMIExpressionResult;
|
||||
Value: String;
|
||||
Info: TGDBType;
|
||||
begin
|
||||
StartPtr := FStackPtr;
|
||||
while (ALimit >= OPER_LEVEL[StartPtr^.OperTor]) and (StartPtr^.Prev <> nil) do
|
||||
StartPtr := StartPtr^.Prev;
|
||||
|
||||
// we will solve this till end of stack
|
||||
FStackPtr := StartPtr^.Prev;
|
||||
if FStackPtr = nil
|
||||
then FStack := nil
|
||||
else FStackPtr^.Next := nil;
|
||||
StartPtr^.Prev := nil;
|
||||
|
||||
Left := StartPtr;
|
||||
FillChar(Right, SizeOf(Right), 0);
|
||||
|
||||
repeat
|
||||
Info := nil;
|
||||
Value := '';
|
||||
case Left^.Opertor of
|
||||
eoNone: begin
|
||||
// only posible as first and only item on stack
|
||||
Result := (FStackPtr = nil) and (Left = StartPtr) and (ARight = '');
|
||||
if Result
|
||||
then begin
|
||||
Value := Left^.Value;
|
||||
Info := Left^.Info;
|
||||
Left^.Info := nil;
|
||||
end;
|
||||
end;
|
||||
eoNegate, eoPlus, eoSubstract, eoAdd,
|
||||
eoMultiply, eoPower, eoDivide, eoEqual,
|
||||
eoLess, eoLessOrEqual, eoGreater, eoGreaterOrEqual,
|
||||
eoNotEqual, eoAnd, eoOr, eoMod,
|
||||
eoNot, eoDiv, eoXor, eoShl,
|
||||
eoShr: begin
|
||||
if Left^.Next = nil
|
||||
then begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Right.Value, Right.Info)
|
||||
and SolveMath(ADebuggerCommand, Left, @Right, Value, Info);
|
||||
FreeAndNil(Right.Info);
|
||||
end
|
||||
else Result := SolveMath(ADebuggerCommand, Left, Left^.Next, Value, Info);
|
||||
end;
|
||||
eoDereference: begin
|
||||
Result := (ARight = '') // right part can not have value
|
||||
and SolveDeref(ADebuggerCommand, Left, Value, Info);
|
||||
end;
|
||||
eoAddress: begin
|
||||
Result := (Left^.Info = nil);
|
||||
if not Result then Break;
|
||||
|
||||
if Left^.Next = nil
|
||||
then begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Right.Value, Right.Info)
|
||||
and SolveAddress(ADebuggerCommand, @Right, Value, Info);
|
||||
FreeAndNil(Right.Info);
|
||||
end
|
||||
else Result := SolveIn(ADebuggerCommand, Left, Left^.Next, Value, Info);
|
||||
end;
|
||||
eoDot: begin
|
||||
// its impossible to have next already resolved. Its a member of left
|
||||
Result := (Left^.Next = nil) and SolveDot(ADebuggerCommand, Left, ARight, Value, Info);
|
||||
end;
|
||||
// eoComma: begin
|
||||
// end;
|
||||
eoBracket: begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Value, Info);
|
||||
// we can finish when closed
|
||||
end;
|
||||
eoIndex: begin
|
||||
if Left^.Info = nil
|
||||
then begin
|
||||
// only possible when part of "in"
|
||||
Result := (Left^.Prev <> nil)
|
||||
and (Left^.Prev^.OperTor = eoIn)
|
||||
and Evaluate(ADebuggerCommand, ARight, Value, Info);
|
||||
end
|
||||
else begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Value, Info);
|
||||
// we can finish when closed
|
||||
end;
|
||||
end;
|
||||
eoIn: begin
|
||||
if Left^.Next = nil
|
||||
then begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Right.Value, Right.Info)
|
||||
and SolveIn(ADebuggerCommand, Left, @Right, Value, Info);
|
||||
FreeAndNil(Right.Info);
|
||||
end
|
||||
else Result := SolveIn(ADebuggerCommand, Left, Left^.Next, Value, Info);
|
||||
end;
|
||||
eoIs: begin
|
||||
if Left^.Next = nil
|
||||
then begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Right.Value, Right.Info)
|
||||
and SolveIs(ADebuggerCommand, Left, @Right, Value, Info);
|
||||
FreeAndNil(Right.Info);
|
||||
end
|
||||
else Result := SolveIs(ADebuggerCommand, Left, Left^.Next, Value, Info);
|
||||
end;
|
||||
eoAs: begin
|
||||
if Left^.Next = nil
|
||||
then begin
|
||||
Result := Evaluate(ADebuggerCommand, ARight, Right.Value, Right.Info)
|
||||
and SolveAs(ADebuggerCommand, Left, @Right, Value, Info);
|
||||
FreeAndNil(Right.Info);
|
||||
end
|
||||
else Result := SolveAs(ADebuggerCommand, Left, Left^.Next, Value, Info);
|
||||
end;
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
if not Result then Break;
|
||||
if Left^.Next = nil then Break;
|
||||
Left := Left^.Next;
|
||||
|
||||
Left^.Info.Free;
|
||||
Left^.Info := Info;
|
||||
Left^.Value := Value;
|
||||
until False;
|
||||
|
||||
DisposeList(StartPtr);
|
||||
if Result
|
||||
then begin
|
||||
AValue := Value;
|
||||
AInfo := Info;
|
||||
end
|
||||
else begin
|
||||
AValue := '';
|
||||
AInfo := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveAddress(const ADebuggerCommand: TGDBMIDebuggerCommand; ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveAs(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveDeref(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
var
|
||||
Eval: String;
|
||||
begin
|
||||
Result := ALeft^.Info.Kind = skPointer;
|
||||
if not Result then Exit;
|
||||
|
||||
Eval := '^' + ALeft^.Info.TypeName + '(' + ALeft^.Value + ')^';
|
||||
Result := Evaluate(ADebuggerCommand, Eval, AValue, AInfo);
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveDot(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft: PGDBMIExpressionResult; const ARight: String; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
var
|
||||
Prefix: String;
|
||||
begin
|
||||
if not (ALeft^.Info.Kind in [skClass, skRecord]) then Exit(False);
|
||||
|
||||
Prefix := '^' + ALeft^.Info.TypeName + '(' + ALeft^.Value + ')^.';
|
||||
Result := Evaluate(ADebuggerCommand, Prefix + ARight, AValue, AInfo);
|
||||
if Result then Exit;
|
||||
|
||||
// maybe property
|
||||
Result := Evaluate(ADebuggerCommand, Prefix + 'F' + ARight, AValue, AInfo);
|
||||
|
||||
//todo: method call
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveIn(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveIs(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TGDBMIExpression.SolveMath(const ADebuggerCommand: TGDBMIDebuggerCommand; ALeft, ARight: PGDBMIExpressionResult; out AValue: String; out AInfo: TGDBType): Boolean;
|
||||
const
|
||||
OPERATOR_TEXT: array[TDBGExpressionOperator] of string = (
|
||||
{eoNone } '',
|
||||
{eoNegate } '-',
|
||||
{eoPlus } '',
|
||||
{eoSubstact } '-',
|
||||
{eoAdd } '+',
|
||||
{eoMultiply } '*',
|
||||
{eoPower } '',
|
||||
{eoDivide } '/',
|
||||
{eoDereference } '',
|
||||
{eoAddress } '',
|
||||
{eoEqual } '=',
|
||||
{eoLess } '<',
|
||||
{eoLessOrEqual } '<=',
|
||||
{eoGreater } '>',
|
||||
{eoGreaterOrEqual } '>=',
|
||||
{eoNotEqual } '<>',
|
||||
{eoIn } '',
|
||||
{eoIs } '',
|
||||
{eoAs } '',
|
||||
{eoDot } '',
|
||||
{eoComma } '',
|
||||
{eoBracket } '',
|
||||
{eoIndex } '',
|
||||
{eoClose } '',
|
||||
{eoAnd } 'and',
|
||||
{eoOr } 'or',
|
||||
{eoMod } 'mod',
|
||||
{eoNot } 'not',
|
||||
{eoDiv } 'div',
|
||||
{eoXor } 'xor',
|
||||
{eoShl } 'shl',
|
||||
{eoShr } 'shr'
|
||||
);
|
||||
var
|
||||
Eval: String;
|
||||
begin
|
||||
case ALeft^.Opertor of
|
||||
eoAnd, eoOr, eoMod, eoNot,
|
||||
eoDiv, eoXor, eoShl, eoShr: begin
|
||||
Eval := '(' + ALeft^.Value + ')' + OPERATOR_TEXT[ALeft^.Opertor] + '(' + ARight^.Value + ')';
|
||||
end
|
||||
else
|
||||
Eval := ALeft^.Value + OPERATOR_TEXT[ALeft^.Opertor] + ARight^.Value;
|
||||
end;
|
||||
|
||||
Result := Evaluate(ADebuggerCommand, Eval, AValue, AInfo);
|
||||
end;
|
||||
|
||||
{ TGDBStringIterator }
|
||||
|
||||
constructor TGDBStringIterator.Create(const AParsableData: String);
|
||||
@ -13264,7 +12416,6 @@ var
|
||||
var
|
||||
S: String;
|
||||
ResultList: TGDBMINameValueList;
|
||||
Expr: TGDBMIExpression;
|
||||
frameidx: Integer;
|
||||
{$IFDEF DBG_WITH_GDB_WATCHES} R: TGDBMIExecResult; {$ENDIF}
|
||||
begin
|
||||
@ -13284,19 +12435,6 @@ begin
|
||||
S := StripExprNewlines(FExpression);
|
||||
|
||||
if S = '' then Exit(false);
|
||||
if S[1] = '!'
|
||||
then begin
|
||||
//TESTING...
|
||||
Delete(S, 1, 1);
|
||||
Expr := TGDBMIExpression.Create(S);
|
||||
FTextValue := Expr.DumpExpression;
|
||||
FTextValue := FTextValue + LineEnding;
|
||||
Expr.Evaluate(Self, S, FTypeInfo);
|
||||
FreeAndNil(FTypeInfo);
|
||||
FTextValue := FTextValue + S;
|
||||
Expr.Free;
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
{$IFDEF DBG_WITH_GDB_WATCHES}
|
||||
(* This code is experimental. No support will be provided.
|
||||
|
Loading…
Reference in New Issue
Block a user