Merged revision(s) 48148 #67ffa45db5 from trunk:

Fix some Regression from Revision: 47581 Debugger: GDB more fixes for gdb 7.7 and up. Uppercase expressions
Do not modify string literals


........

git-svn-id: branches/fixes_1_4@48149 -
This commit is contained in:
martin 2015-03-05 22:58:52 +00:00
parent 2e35a42362
commit f336054352
4 changed files with 92 additions and 41 deletions

View File

@ -57,6 +57,7 @@ function Quote(const AValue: String; AForce: Boolean=False): String;
function ConvertGdbPathAndFile(const AValue: String): String; // fix path, delim, unescape, and to utf8 function ConvertGdbPathAndFile(const AValue: String): String; // fix path, delim, unescape, and to utf8
function ParseGDBString(const AValue: String): String; // remove quotes(') and convert #dd chars: #9'ab'#9'x' 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 GetLeadingAddr(var AValue: String; out AnAddr: TDBGPtr; ARemoveFromValue: Boolean = False): Boolean;
function UpperCaseSymbols(s: string): string;
procedure SmartWriteln(const s: string); procedure SmartWriteln(const s: string);
@ -325,7 +326,7 @@ begin
SetLength(Result, Dst - @Result[1]); // adjust to actual length SetLength(Result, Dst - @Result[1]); // adjust to actual length
end; end;
function Unquote(const AValue: String): String; function UnQuote(const AValue: String): String;
var var
len: Integer; len: Integer;
begin begin
@ -430,6 +431,35 @@ begin
end; end;
end; end;
function UpperCaseSymbols(s: string): string;
var
i, l: Integer;
begin
Result := s;
i := 1;
l := Length(Result);
while (i <= l) do begin
if Result[i] = '''' then begin
inc(i);
while (i <= l) and (Result[i] <> '''') do
inc(i);
end
else
if Result[i] = '"' then begin
inc(i);
while (i < l) and (Result[i] <> '"') do
inc(i);
end;
(* uppercase due to https://sourceware.org/bugzilla/show_bug.cgi?id=17835
gdb 7.7 and 7.8 fail to find members, if lowercased
Alternative prefix with "self." if gdb returns &"Type TCLASSXXXX has no component named EXPRESSION.\n"
*)
if (i<=l) and (Result[i] in ['a'..'z']) then
Result[i] := UpperCase(Result[i])[1];
inc(i);
end;
end;
function DeleteEscapeChars(const AValue: String; const AEscapeChar: Char): String; function DeleteEscapeChars(const AValue: String; const AEscapeChar: Char): String;
var var
cnt, len: Integer; cnt, len: Integer;

View File

@ -8250,7 +8250,7 @@ begin
end; end;
R := GDBMIExecResultDefault; R := GDBMIExecResultDefault;
Result := ExecuteCommandFull('-gdb-set var %s := %s', [UpperCase(AExpression), S], [cfscIgnoreError], @GDBModifyDone, 0, R) Result := ExecuteCommandFull('-gdb-set var %s := %s', [UpperCaseSymbols(AExpression), S], [cfscIgnoreError], @GDBModifyDone, 0, R)
and (R.State <> dsError); and (R.State <> dsError);
FTypeRequestCache.Clear; FTypeRequestCache.Clear;
@ -9110,7 +9110,7 @@ begin
Result := False; Result := False;
if ABreakID = 0 then Exit; if ABreakID = 0 then Exit;
Result := ExecuteCommand('-break-condition %d %s', [ABreakID, UpperCase(AnExpression)], []); Result := ExecuteCommand('-break-condition %d %s', [ABreakID, UpperCaseSymbols(AnExpression)], []);
end; end;
{ TGDBMIDebuggerCommandBreakInsert } { TGDBMIDebuggerCommandBreakInsert }
@ -9153,7 +9153,7 @@ begin
bpkData: bpkData:
begin begin
if (FWatchData = '') then exit; if (FWatchData = '') then exit;
WatchExpr := UpperCase(WatchData); WatchExpr := UpperCaseSymbols(WatchData);
if FWatchScope = wpsGlobal then begin if FWatchScope = wpsGlobal then begin
Result := ExecuteCommand('ptype %s', [WatchExpr], R); Result := ExecuteCommand('ptype %s', [WatchExpr], R);
Result := Result and (R.State <> dsError); Result := Result and (R.State <> dsError);

View File

@ -1751,8 +1751,28 @@ begin
EndPtr := AText + ATextLen; EndPtr := AText + ATextLen;
while (CurPtr < EndPtr) and not(CurPtr^ in ['[', '(', ',', '%', '&', '$', '0']) do inc(CurPtr); while (CurPtr < EndPtr) and not(CurPtr^ in ['[', '(', ',', '%', '&', '$', '0', '''', '"']) do begin
if CurPtr = EndPtr then exit; // no fixup needed if CurPtr^ = '''' then begin
inc(CurPtr);
while (CurPtr < EndPtr) and (CurPtr^ <> '''') do
inc(CurPtr);
end
else
if CurPtr^ = '"' then begin
inc(CurPtr);
while (CurPtr < EndPtr) and (CurPtr^ <> '"') do
inc(CurPtr);
end;
(* uppercase due to https://sourceware.org/bugzilla/show_bug.cgi?id=17835
gdb 7.7 and 7.8 fail to find members, if lowercased
Alternative prefix with "self." if gdb returns &"Type TCLASSXXXX has no component named EXPRESSION.\n"
*)
if (CurPtr < EndPtr) and (CurPtr^ in ['a'..'z']) then
CurPtr^ := UpperCase(CurPtr^)[1];
inc(CurPtr);
end;
if CurPtr = EndPtr then
exit; // no fixup needed
CurPtr := AText; CurPtr := AText;
CurList:= TGDBExpressionPartList.Create; CurList:= TGDBExpressionPartList.Create;
@ -2026,6 +2046,7 @@ end;
constructor TGDBExpression.Create(ATextStr: String); constructor TGDBExpression.Create(ATextStr: String);
begin begin
FTextStr := ATextStr; FTextStr := ATextStr;
UniqueString(FTextStr);
Create(PChar(FTextStr), length(FTextStr)); Create(PChar(FTextStr), length(FTextStr));
end; end;
@ -2232,11 +2253,7 @@ begin
Create(skSimple, ''); // initialize Create(skSimple, ''); // initialize
FInternalTypeName := ''; FInternalTypeName := '';
FEvalError := False; FEvalError := False;
(* uppercase due to https://sourceware.org/bugzilla/show_bug.cgi?id=17835 FExpression := AnExpression;
gdb 7.7 and 7.8 fail to find members, if lowercased
Alternative prefix with "self." if gdb returns &"Type TCLASSXXXX has no component named EXPRESSION.\n"
*)
FExpression := UpperCase(AnExpression);
FOrigExpression := FExpression; FOrigExpression := FExpression;
FCreationFlags := AFlags; FCreationFlags := AFlags;
FExprEvaluateFormat := AFormat; FExprEvaluateFormat := AFormat;

View File

@ -605,6 +605,10 @@ begin
end; end;
procedure TTestGdbType.TestExpressionBreaker; procedure TTestGdbType.TestExpressionBreaker;
procedure AssertEqualsLc(n,s1,s2: string);
begin
AssertEquals(n, LowerCase(s1), LowerCase(s2));
end;
procedure InitExpr(e: String; var b: TGDBExpression; out r: PGDBPTypeRequest; out v: Boolean; rewritten: string = ''); procedure InitExpr(e: String; var b: TGDBExpression; out r: PGDBPTypeRequest; out v: Boolean; rewritten: string = '');
begin begin
@ -614,8 +618,8 @@ procedure TTestGdbType.TestExpressionBreaker;
debugln('##### '+e); debugln('##### '+e);
DumpGExp(b); DumpGExp(b);
if rewritten <> '' if rewritten <> ''
then AssertEquals(e+' as text', rewritten, b.Text) then AssertEqualsLc(e+' as text', rewritten, b.Text)
else AssertEquals(e+' as text', e, b.Text); else AssertEqualsLc(e+' as text', e, b.Text);
v := b.NeedValidation(r); v := b.NeedValidation(r);
if r <> nil then DumpReq(r); if r <> nil then DumpReq(r);
debugln; debugln;
@ -641,18 +645,18 @@ begin
n := 'abc[123].x'; n := 'abc[123].x';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
AssertTrue(n + ' is array', b.Parts[0] is TGDBExpressionPartArray); AssertTrue(n + ' is array', b.Parts[0] is TGDBExpressionPartArray);
AssertTrue(n + ' ptype', (r <> nil) and (r^.Request = 'ptype abc')); AssertTrue(n + ' ptype', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc'));
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array', not v); AssertTrue(n + ' Needexp after dyn array', not v);
AssertEquals(n + ' text after dyn array', 'TFoo(abc^[123]).x', b.Text); AssertEqualsLc(n + ' text after dyn array', 'TFoo(abc^[123]).x', b.Text);
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = array [0..1000] of TFoo'); r^.Result := ParseTypeFromGdb('type = array [0..1000] of TFoo');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after stat array', not v); AssertTrue(n + ' Needexp after stat array', not v);
AssertEquals(n + ' text after stat array', 'TFoo(abc[123]).x', b.Text); AssertEqualsLc(n + ' text after stat array', 'TFoo(abc[123]).x', b.Text);
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = ^TFoo'); r^.Result := ParseTypeFromGdb('type = ^TFoo');
@ -661,14 +665,14 @@ begin
r^.Result := ParseTypeFromGdb('type = array of TFoo'); r^.Result := ParseTypeFromGdb('type = array of TFoo');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array(dwarf)', not v); AssertTrue(n + ' Needexp after dyn array(dwarf)', not v);
AssertEquals(n + ' text after dyn array(dwarf)', 'TFoo(abc^[123]).x', b.Text); AssertEqualsLc(n + ' text after dyn array(dwarf)', 'TFoo(abc^[123]).x', b.Text);
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = array [0..1000] of ^TFoo'); r^.Result := ParseTypeFromGdb('type = array [0..1000] of ^TFoo');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after stat array ^TFoo', not v); AssertTrue(n + ' Needexp after stat array ^TFoo', not v);
AssertEquals(n + ' text after stat array ^TFoo', '^TFoo(abc[123]).x', b.Text); AssertEqualsLc(n + ' text after stat array ^TFoo', '^TFoo(abc[123]).x', b.Text);
// with NO need for typecast // with NO need for typecast
n := 'abc[123]'; n := 'abc[123]';
@ -676,63 +680,63 @@ begin
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array', not v); AssertTrue(n + ' Needexp after dyn array', not v);
AssertEquals(n + ' text after dyn array', 'abc^[123]', b.Text); AssertEqualsLc(n + ' text after dyn array', 'abc^[123]', b.Text);
n := 'a(abc[123])'; n := 'a(abc[123])';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array', not v); AssertTrue(n + ' Needexp after dyn array', not v);
AssertEquals(n + ' text after dyn array', 'a(abc^[123])', b.Text); AssertEqualsLc(n + ' text after dyn array', 'a(abc^[123])', b.Text);
n := 'abc[123]+1'; n := 'abc[123]+1';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array', not v); AssertTrue(n + ' Needexp after dyn array', not v);
AssertEquals(n + ' text after dyn array', 'abc^[123]+1', b.Text); AssertEqualsLc(n + ' text after dyn array', 'abc^[123]+1', b.Text);
// multi index // multi index
n := 'abc[123][456]'; n := 'abc[123][456]';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
AssertTrue(n + ' ptype 1', (r <> nil) and (r^.Request = 'ptype abc')); AssertTrue(n + ' ptype 1', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc'));
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFooA)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFooA)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array 1', v); AssertTrue(n + ' Needexp after dyn array 1', v);
//AssertTrue(n + ' ptype 2', (r <> nil) and (r^.Request = 'ptype TFooA(abc^[123])')); //AssertTrue(n + ' ptype 2', (r <> nil) and (r^.Request = 'ptype TFooA(abc^[123])'));
AssertTrue(n + ' ptype 2', (r <> nil) and (r^.Request = 'ptype abc^[0]')); AssertTrue(n + ' ptype 2', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc^[0]'));
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array 2', not v); AssertTrue(n + ' Needexp after dyn array 2', not v);
//AssertEquals(n + ' text after dyn array 2', 'TFooA(abc^[123])^[456]', b.Text); //AssertEqualsLc(n + ' text after dyn array 2', 'TFooA(abc^[123])^[456]', b.Text);
AssertEquals(n + ' text after dyn array 2', 'abc^[123]^[456]', b.Text); AssertEqualsLc(n + ' text after dyn array 2', 'abc^[123]^[456]', b.Text);
n := 'abc[123][456]'; n := 'abc[123][456]';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = array [3..1000] of TFooA'); r^.Result := ParseTypeFromGdb('type = array [3..1000] of TFooA');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after stat array 1', v); AssertTrue(n + ' Needexp after stat array 1', v);
//AssertTrue(n + ' ptype 2a', (r <> nil) and (r^.Request = 'ptype TFooA(abc[123])')); //AssertTrue(n + ' ptype 2a', (r <> nil) and (LowerCase(r^.Request) = 'ptype TFooA(abc[123])'));
AssertTrue(n + ' ptype 2a', (r <> nil) and (r^.Request = 'ptype abc[3]')); AssertTrue(n + ' ptype 2a', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc[3]'));
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFoo)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after stat,dyn array 2', not v); AssertTrue(n + ' Needexp after stat,dyn array 2', not v);
//AssertEquals(n + ' text after dyn array 2', 'TFooA(abc[123])^[456]', b.Text); //AssertEqualsLc(n + ' text after dyn array 2', 'TFooA(abc[123])^[456]', b.Text);
AssertEquals(n + ' text after dyn array 2', 'abc[123]^[456]', b.Text); AssertEqualsLc(n + ' text after dyn array 2', 'abc[123]^[456]', b.Text);
n := 'abc[123][456]'; n := 'abc[123][456]';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFooA)'); r^.Result := ParseTypeFromGdb('type = ^(array [0..-1] of TFooA)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn array 1', v); AssertTrue(n + ' Needexp after dyn array 1', v);
//AssertTrue(n + ' ptype 2b', (r <> nil) and (r^.Request = 'ptype TFooA(abc^[123])')); //AssertTrue(n + ' ptype 2b', (r <> nil) and (LowerCase(r^.Request) = 'ptype TFooA(abc^[123])'));
AssertTrue(n + ' ptype 2b', (r <> nil) and (r^.Request = 'ptype abc^[0]')); AssertTrue(n + ' ptype 2b', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc^[0]'));
r^.Result := ParseTypeFromGdb('type = array [0..1000] of TFoo'); r^.Result := ParseTypeFromGdb('type = array [0..1000] of TFoo');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' Needexp after dyn,stat array 2', not v); AssertTrue(n + ' Needexp after dyn,stat array 2', not v);
//AssertEquals(n + ' text after dyn array 2', 'TFooA(abc^[123])[456]', b.Text); //AssertEqualsLc(n + ' text after dyn array 2', 'TFooA(abc^[123])[456]', b.Text);
AssertEquals(n + ' text after dyn array 2', 'abc^[123][456]', b.Text); AssertEqualsLc(n + ' text after dyn array 2', 'abc^[123][456]', b.Text);
@ -746,7 +750,7 @@ begin
r^.Result := ParseTypeFromGdb('type = ^^(array [0..-1] of TRECFORARRAY1)'); r^.Result := ParseTypeFromGdb('type = ^^(array [0..-1] of TRECFORARRAY1)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + 'No Need expr, after ^^ dyn array 1', not v); AssertTrue(n + 'No Need expr, after ^^ dyn array 1', not v);
AssertEquals(n + ' text after ^^ dyn array', '^^TRECFORARRAY1(qwe)[1][2]', b.Text); AssertEqualsLc(n + ' text after ^^ dyn array', '^^TRECFORARRAY1(qwe)[1][2]', b.Text);
n := 'qwe[3][2].a'; n := 'qwe[3][2].a';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
@ -754,7 +758,7 @@ begin
r^.Result := ParseTypeFromGdb('type = array [3..5] of ^(array of TRECFORARRAY1)'); r^.Result := ParseTypeFromGdb('type = array [3..5] of ^(array of TRECFORARRAY1)');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + 'No Need expr, after stat dyn array 1', not v); AssertTrue(n + 'No Need expr, after stat dyn array 1', not v);
AssertEquals(n + ' text after stat dyn array', 'TRECFORARRAY1(qwe[3]^[2]).a', b.Text); AssertEqualsLc(n + ' text after stat dyn array', 'TRECFORARRAY1(qwe[3]^[2]).a', b.Text);
n := 'qwe[3]'; n := 'qwe[3]';
@ -766,26 +770,26 @@ begin
r^.Result := ParseTypeFromGdb('type = char'); r^.Result := ParseTypeFromGdb('type = char');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + 'No Need expr', not v); AssertTrue(n + 'No Need expr', not v);
AssertEquals(n + ' text after', 'qwe[3]', b.Text); AssertEqualsLc(n + ' text after', 'qwe[3]', b.Text);
AssertEquals(n + ' maybe string ', True, b.MayNeedStringFix); AssertEquals(n + ' maybe string ', True, b.MayNeedStringFix);
AssertEquals(n + ' text after as string', 'qwe[3-1]', b.TextStrFixed); AssertEqualsLc(n + ' text after as string', 'qwe[3-1]', b.TextStrFixed);
n := 'abc()[123]'; n := 'abc()[123]';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
AssertTrue(n + ' is array', b.Parts[0] is TGDBExpressionPartArray); AssertTrue(n + ' is array', b.Parts[0] is TGDBExpressionPartArray);
AssertTrue(n + ' ptype', (r <> nil) and (r^.Request = 'ptype abc()')); AssertTrue(n + ' ptype', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc()'));
n := 'abc(x[1])[123]'; n := 'abc(x[1])[123]';
InitExpr(n, b, r, v); InitExpr(n, b, r, v);
AssertTrue(n + ' is array', b.Parts[0] is TGDBExpressionPartArray); AssertTrue(n + ' is array', b.Parts[0] is TGDBExpressionPartArray);
AssertTrue(n + ' r.next', (r <> nil) and (r^.Next = nil)); AssertTrue(n + ' r.next', (r <> nil) and (r^.Next = nil));
AssertTrue(n + ' ptype', (r <> nil) and (r^.Request = 'ptype x')); // cant eval the outer array yet AssertTrue(n + ' ptype', (r <> nil) and (LowerCase(r^.Request) = 'ptype x')); // cant eval the outer array yet
r^.Result := ParseTypeFromGdb('type = array [0..1000] of TFoo'); r^.Result := ParseTypeFromGdb('type = array [0..1000] of TFoo');
ContinueExpr(b, r, v); ContinueExpr(b, r, v);
AssertTrue(n + ' ptype outer ', (r <> nil) and (r^.Request = 'ptype abc(x[0])')); AssertTrue(n + ' ptype outer ', (r <> nil) and (LowerCase(r^.Request) = 'ptype abc(x[0])'));
n := 'abc()[x[123]]'; n := 'abc()[x[123]]';
@ -802,7 +806,7 @@ begin
n := 'abc[1,2,3].x[1]'; n := 'abc[1,2,3].x[1]';
InitExpr(n, b, r, v, 'abc[1][2][3].x[1]'); InitExpr(n, b, r, v, 'abc[1][2][3].x[1]');
AssertEquals(n+' toSkipArrayIdx', 'abc[0][0][0].x[0]', b.TextEx[[toSkipArrayIdx]]); AssertEqualsLc(n+' toSkipArrayIdx', 'abc[0][0][0].x[0]', b.TextEx[[toSkipArrayIdx]]);
n := 'abc[1,2,3].x and abc[1,2][3].y'; n := 'abc[1,2,3].x and abc[1,2][3].y';
InitExpr(n, b, r, v, 'abc[1][2][3].x and abc[1][2][3].y'); InitExpr(n, b, r, v, 'abc[1][2][3].x and abc[1][2][3].y');