mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-11 13:28:04 +02:00
debugger, gdb: improve break conditions for charvalue='a'
git-svn-id: trunk@48151 -
This commit is contained in:
parent
f44411bd31
commit
c4f6dcb1fa
@ -58,6 +58,7 @@ function ConvertGdbPathAndFile(const AValue: String): String; // fix path, delim
|
||||
function ParseGDBString(const AValue: String): String; // remove quotes(') and convert #dd chars: #9'ab'#9'x'
|
||||
function GetLeadingAddr(var AValue: String; out AnAddr: TDBGPtr; ARemoveFromValue: Boolean = False): Boolean;
|
||||
function UpperCaseSymbols(s: string): string;
|
||||
function ConvertPascalExpression(var AExpression: String): Boolean;
|
||||
|
||||
procedure SmartWriteln(const s: string);
|
||||
|
||||
@ -460,6 +461,170 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ConvertPascalExpression(var AExpression: String): Boolean;
|
||||
var
|
||||
QuoteChar, R: String;
|
||||
P: PChar;
|
||||
InString, WasString, IsText, ValIsChar: Boolean;
|
||||
n: Integer;
|
||||
ValMode: Char;
|
||||
Value: QWord;
|
||||
|
||||
function AppendValue: Boolean;
|
||||
var
|
||||
S: String;
|
||||
begin
|
||||
if ValMode = #0 then Exit(True);
|
||||
if not (ValMode in ['h', 'd', 'o', 'b']) then Exit(False);
|
||||
|
||||
if ValIsChar
|
||||
then begin
|
||||
if not IsText
|
||||
then begin
|
||||
R := R + '"';
|
||||
IsText := True;
|
||||
end;
|
||||
R := R + '\' + OctStr(Value, 3);
|
||||
ValIsChar := False;
|
||||
end
|
||||
else begin
|
||||
if IsText
|
||||
then begin
|
||||
R := R + '"';
|
||||
IsText := False;
|
||||
end;
|
||||
Str(Value, S);
|
||||
R := R + S;
|
||||
end;
|
||||
Result := True;
|
||||
ValMode := #0;
|
||||
end;
|
||||
|
||||
begin
|
||||
R := '';
|
||||
Instring := False;
|
||||
WasString := False;
|
||||
IsText := False;
|
||||
QuoteChar := '"';
|
||||
ValIsChar := False;
|
||||
ValMode := #0;
|
||||
Value := 0;
|
||||
|
||||
P := PChar(AExpression);
|
||||
for n := 1 to Length(AExpression) do
|
||||
begin
|
||||
if InString
|
||||
then begin
|
||||
case P^ of
|
||||
'''': begin
|
||||
InString := False;
|
||||
// delay setting terminating ", more characters defined through # may follow
|
||||
WasString := True;
|
||||
end;
|
||||
#0..#31,
|
||||
'\',
|
||||
#128..#255: begin
|
||||
R := R + '\' + OctStr(Ord(P^), 3);
|
||||
end;
|
||||
else begin
|
||||
if p^ = QuoteChar then
|
||||
R := R + '\' + OctStr(Ord(P^), 3)
|
||||
else
|
||||
R := R + P^;
|
||||
end;
|
||||
end;
|
||||
Inc(P);
|
||||
Continue;
|
||||
end;
|
||||
|
||||
case P^ of
|
||||
'''': begin
|
||||
if WasString
|
||||
then begin
|
||||
R := R + '\' + OctStr(Ord(''''), 3)
|
||||
end
|
||||
else begin
|
||||
if not AppendValue then Exit(False);
|
||||
if not IsText
|
||||
then begin
|
||||
QuoteChar := '"';
|
||||
// single CHAR ?
|
||||
if ( ((p+1)^ <> '''') and ((p+2)^ = '''') and not((p+3)^ in ['#', '''']) ) or
|
||||
( ((p+1)^ = '''') and ((p+2)^ = '''') and ((p+3)^ = '''') and not((p+4)^ in ['#', '''']) )
|
||||
then
|
||||
QuoteChar := '''';
|
||||
R := R + QuoteChar;
|
||||
end
|
||||
end;
|
||||
IsText := True;
|
||||
InString := True;
|
||||
end;
|
||||
'#': begin
|
||||
if not AppendValue then Exit(False);
|
||||
Value := 0;
|
||||
ValMode := 'D';
|
||||
ValIsChar := True;
|
||||
end;
|
||||
'$', '&', '%': begin
|
||||
if not (ValMode in [#0, 'D']) then Exit(False);
|
||||
ValMode := P^;
|
||||
end;
|
||||
else
|
||||
case ValMode of
|
||||
'D', 'd': begin
|
||||
case P^ of
|
||||
'0'..'9': Value := Value * 10 + Ord(P^) - Ord('0');
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'd';
|
||||
end;
|
||||
'$', 'h': begin
|
||||
case P^ of
|
||||
'0'..'9': Value := Value * 16 + Ord(P^) - Ord('0');
|
||||
'a'..'f': Value := Value * 16 + Ord(P^) - Ord('a');
|
||||
'A'..'F': Value := Value * 16 + Ord(P^) - Ord('A');
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'h';
|
||||
end;
|
||||
'&', 'o': begin
|
||||
case P^ of
|
||||
'0'..'7': Value := Value * 8 + Ord(P^) - Ord('0');
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'o';
|
||||
end;
|
||||
'%', 'b': begin
|
||||
case P^ of
|
||||
'0': Value := Value shl 1;
|
||||
'1': Value := Value shl 1 or 1;
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'b';
|
||||
end;
|
||||
else
|
||||
if IsText
|
||||
then begin
|
||||
R := R + QuoteChar;
|
||||
IsText := False;
|
||||
end;
|
||||
R := R + P^;
|
||||
end;
|
||||
end;
|
||||
WasString := False;
|
||||
Inc(p);
|
||||
end;
|
||||
|
||||
if not AppendValue then Exit(False);
|
||||
if IsText then R := R + QuoteChar;
|
||||
AExpression := R;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function DeleteEscapeChars(const AValue: String; const AEscapeChar: Char): String;
|
||||
var
|
||||
cnt, len: Integer;
|
||||
|
@ -770,7 +770,6 @@ type
|
||||
procedure LockRelease;
|
||||
procedure UnlockRelease;
|
||||
|
||||
function ConvertPascalExpression(var AExpression: String): Boolean;
|
||||
// ---
|
||||
procedure ClearSourceInfo;
|
||||
function FindBreakpoint(const ABreakpoint: Integer): TDBGBreakPoint;
|
||||
@ -8968,157 +8967,6 @@ begin
|
||||
FSourceNames.Clear;
|
||||
end;
|
||||
|
||||
function TGDBMIDebugger.ConvertPascalExpression(var AExpression: String): Boolean;
|
||||
var
|
||||
R: String;
|
||||
P: PChar;
|
||||
InString, WasString, IsText, ValIsChar: Boolean;
|
||||
n: Integer;
|
||||
ValMode: Char;
|
||||
Value: QWord;
|
||||
|
||||
function AppendValue: Boolean;
|
||||
var
|
||||
S: String;
|
||||
begin
|
||||
if ValMode = #0 then Exit(True);
|
||||
if not (ValMode in ['h', 'd', 'o', 'b']) then Exit(False);
|
||||
|
||||
if ValIsChar
|
||||
then begin
|
||||
if not IsText
|
||||
then begin
|
||||
R := R + '"';
|
||||
IsText := True;
|
||||
end;
|
||||
R := R + '\' + OctStr(Value, 3);
|
||||
ValIsChar := False;
|
||||
end
|
||||
else begin
|
||||
if IsText
|
||||
then begin
|
||||
R := R + '"';
|
||||
IsText := False;
|
||||
end;
|
||||
Str(Value, S);
|
||||
R := R + S;
|
||||
end;
|
||||
Result := True;
|
||||
ValMode := #0;
|
||||
end;
|
||||
|
||||
begin
|
||||
R := '';
|
||||
Instring := False;
|
||||
WasString := False;
|
||||
IsText := False;
|
||||
ValIsChar := False;
|
||||
ValMode := #0;
|
||||
Value := 0;
|
||||
|
||||
P := PChar(AExpression);
|
||||
for n := 1 to Length(AExpression) do
|
||||
begin
|
||||
if InString
|
||||
then begin
|
||||
case P^ of
|
||||
'''': begin
|
||||
InString := False;
|
||||
// delay setting terminating ", more characters defined through # may follow
|
||||
WasString := True;
|
||||
end;
|
||||
#0..#31,
|
||||
'"', '\',
|
||||
#128..#255: begin
|
||||
R := R + '\' + OctStr(Ord(P^), 3);
|
||||
end;
|
||||
else
|
||||
R := R + P^;
|
||||
end;
|
||||
Inc(P);
|
||||
Continue;
|
||||
end;
|
||||
|
||||
case P^ of
|
||||
'''': begin
|
||||
if WasString
|
||||
then begin
|
||||
R := R + '\' + OctStr(Ord(''''), 3)
|
||||
end
|
||||
else begin
|
||||
if not AppendValue then Exit(False);
|
||||
if not IsText
|
||||
then R := R + '"';
|
||||
end;
|
||||
IsText := True;
|
||||
InString := True;
|
||||
end;
|
||||
'#': begin
|
||||
if not AppendValue then Exit(False);
|
||||
Value := 0;
|
||||
ValMode := 'D';
|
||||
ValIsChar := True;
|
||||
end;
|
||||
'$', '&', '%': begin
|
||||
if not (ValMode in [#0, 'D']) then Exit(False);
|
||||
ValMode := P^;
|
||||
end;
|
||||
else
|
||||
case ValMode of
|
||||
'D', 'd': begin
|
||||
case P^ of
|
||||
'0'..'9': Value := Value * 10 + Ord(P^) - Ord('0');
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'd';
|
||||
end;
|
||||
'$', 'h': begin
|
||||
case P^ of
|
||||
'0'..'9': Value := Value * 16 + Ord(P^) - Ord('0');
|
||||
'a'..'f': Value := Value * 16 + Ord(P^) - Ord('a');
|
||||
'A'..'F': Value := Value * 16 + Ord(P^) - Ord('A');
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'h';
|
||||
end;
|
||||
'&', 'o': begin
|
||||
case P^ of
|
||||
'0'..'7': Value := Value * 8 + Ord(P^) - Ord('0');
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'o';
|
||||
end;
|
||||
'%', 'b': begin
|
||||
case P^ of
|
||||
'0': Value := Value shl 1;
|
||||
'1': Value := Value shl 1 or 1;
|
||||
else
|
||||
Exit(False);
|
||||
end;
|
||||
ValMode := 'b';
|
||||
end;
|
||||
else
|
||||
if IsText
|
||||
then begin
|
||||
R := R + '"';
|
||||
IsText := False;
|
||||
end;
|
||||
R := R + P^;
|
||||
end;
|
||||
end;
|
||||
WasString := False;
|
||||
Inc(p);
|
||||
end;
|
||||
|
||||
if not AppendValue then Exit(False);
|
||||
if IsText then R := R + '"';
|
||||
AExpression := R;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TGDBMIDebugger.StartDebugging(AContinueCommand: TGDBMIExecCommandType): Boolean;
|
||||
begin
|
||||
Result := StartDebugging(TGDBMIDebuggerCommandExecute.Create(Self, AContinueCommand));
|
||||
@ -9587,7 +9435,7 @@ var
|
||||
S: String;
|
||||
begin
|
||||
S := Expression;
|
||||
if TGDBMIDebugger(Debugger).ConvertPascalExpression(S)
|
||||
if ConvertPascalExpression(S)
|
||||
then FParsedExpression := S
|
||||
else FParsedExpression := Expression;
|
||||
if (FBreakID = 0) and Enabled and
|
||||
|
@ -18,6 +18,7 @@ type
|
||||
procedure TestPTypeParser;
|
||||
procedure TestExpressionBreaker;
|
||||
procedure TestUnEscape;
|
||||
procedure TestConvertPascalExpression;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -829,6 +830,23 @@ begin
|
||||
AssertEquals('4:a\102\tc\\d (no oct)', 'a\102 c\d', UnEscapeBackslashed('a\102\tc\\d', [uefTab],4));
|
||||
end;
|
||||
|
||||
procedure TTestGdbType.TestConvertPascalExpression;
|
||||
procedure AssertEqualsConv(n, s1, s2: string);
|
||||
begin
|
||||
AssertTrue(n, ConvertPascalExpression(s2));
|
||||
AssertEquals(n, s1, s2);
|
||||
end;
|
||||
begin
|
||||
AssertEqualsConv('', 'a=1', 'a=1');
|
||||
AssertEqualsConv('', 'a="11"', 'a=''11''');
|
||||
AssertEqualsConv('', 'a="1\0471"', 'a=''1''''1''');
|
||||
AssertEqualsConv('', 'a="11"', 'a="11"');
|
||||
AssertEqualsConv('', 'a="11\061"', 'a=''11''#49');
|
||||
AssertEqualsConv('', 'a="1\061"', 'a=''1''#49');
|
||||
|
||||
AssertEqualsConv('', 'a=''1''', 'a=''1''');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user