mirror of https://gitlab.com/basile.b/dexed.git
#97 try to separate inferior output from gdb output + fix CLI scanning
+ parse ^error,msg=
This commit is contained in:
parent
c38ffa76f0
commit
a6e8f00f2b
101
src/ce_gdb.pas
101
src/ce_gdb.pas
|
@ -169,6 +169,7 @@ type
|
||||||
fAutoGetVariables: boolean;
|
fAutoGetVariables: boolean;
|
||||||
fCommandsHistory: TStringList;
|
fCommandsHistory: TStringList;
|
||||||
fIgnoredSignals: TStringList;
|
fIgnoredSignals: TStringList;
|
||||||
|
fShowGdbOutput: boolean;
|
||||||
fShowOutput: boolean;
|
fShowOutput: boolean;
|
||||||
procedure setIgnoredSignals(value: TStringList);
|
procedure setIgnoredSignals(value: TStringList);
|
||||||
procedure setCommandsHistory(value: TStringList);
|
procedure setCommandsHistory(value: TStringList);
|
||||||
|
@ -179,6 +180,7 @@ type
|
||||||
property autoGetVariables: boolean read fAutoGetVariables write fAutoGetVariables;
|
property autoGetVariables: boolean read fAutoGetVariables write fAutoGetVariables;
|
||||||
property commandsHistory: TStringList read fCommandsHistory write setCommandsHistory;
|
property commandsHistory: TStringList read fCommandsHistory write setCommandsHistory;
|
||||||
property ignoredSignals: TStringList read fIgnoredSignals write setIgnoredSignals;
|
property ignoredSignals: TStringList read fIgnoredSignals write setIgnoredSignals;
|
||||||
|
property showGdbOutput: boolean read fShowGdbOutput write fShowGdbOutput;
|
||||||
property showOutput: boolean read fShowOutput write fShowOutput;
|
property showOutput: boolean read fShowOutput write fShowOutput;
|
||||||
public
|
public
|
||||||
constructor create(aOwner: TComponent); override;
|
constructor create(aOwner: TComponent); override;
|
||||||
|
@ -252,7 +254,7 @@ type
|
||||||
procedure gdboutJsonize(sender: TObject);
|
procedure gdboutJsonize(sender: TObject);
|
||||||
procedure interpretJson;
|
procedure interpretJson;
|
||||||
// GDB commands & actions
|
// GDB commands & actions
|
||||||
procedure gdbCommand(aCommand: string; gdboutProcessor: TNotifyEvent = nil);
|
procedure gdbCommand(aCommand: string; gdbOutProcessor: TNotifyEvent = nil);
|
||||||
procedure infoRegs;
|
procedure infoRegs;
|
||||||
procedure infoStack;
|
procedure infoStack;
|
||||||
procedure sendCustomCommand;
|
procedure sendCustomCommand;
|
||||||
|
@ -293,7 +295,7 @@ begin
|
||||||
fAutoGetCallStack:= true;
|
fAutoGetCallStack:= true;
|
||||||
fAutoGetRegisters:= true;
|
fAutoGetRegisters:= true;
|
||||||
fAutoGetVariables:= true;
|
fAutoGetVariables:= true;
|
||||||
fShowOutput:=true;
|
fShowGdbOutput:=true;
|
||||||
fIgnoredSignals := TStringList.Create;
|
fIgnoredSignals := TStringList.Create;
|
||||||
fCommandsHistory := TStringList.Create;
|
fCommandsHistory := TStringList.Create;
|
||||||
end;
|
end;
|
||||||
|
@ -326,6 +328,7 @@ begin
|
||||||
fAutoGetCallStack:=src.fAutoGetCallStack;
|
fAutoGetCallStack:=src.fAutoGetCallStack;
|
||||||
fAutoGetRegisters:=src.fAutoGetRegisters;
|
fAutoGetRegisters:=src.fAutoGetRegisters;
|
||||||
fAutoGetVariables:=src.autoGetVariables;
|
fAutoGetVariables:=src.autoGetVariables;
|
||||||
|
fShowGdbOutput:=src.fShowGdbOutput;
|
||||||
fShowOutput:=src.fShowOutput;
|
fShowOutput:=src.fShowOutput;
|
||||||
fIgnoredSignals.Assign(src.fIgnoredSignals);
|
fIgnoredSignals.Assign(src.fIgnoredSignals);
|
||||||
fCommandsHistory.Assign(src.fCommandsHistory);
|
fCommandsHistory.Assign(src.fCommandsHistory);
|
||||||
|
@ -690,6 +693,7 @@ end;
|
||||||
procedure TCEGdbWidget.startDebugging;
|
procedure TCEGdbWidget.startDebugging;
|
||||||
var
|
var
|
||||||
str: string;
|
str: string;
|
||||||
|
gdb: string;
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
// protect
|
// protect
|
||||||
|
@ -700,13 +704,21 @@ begin
|
||||||
str := fProj.outputFilename;
|
str := fProj.outputFilename;
|
||||||
if not str.fileExists then
|
if not str.fileExists then
|
||||||
exit;
|
exit;
|
||||||
|
gdb := exeFullName('gdb');
|
||||||
|
if not gdb.fileExists then
|
||||||
|
exit;
|
||||||
subjDebugStart(fSubj, self as ICEDebugger);
|
subjDebugStart(fSubj, self as ICEDebugger);
|
||||||
// gdb process
|
// gdb process
|
||||||
killGdb;
|
killGdb;
|
||||||
fGdb := TCEProcess.create(nil);
|
fGdb := TCEProcess.create(nil);
|
||||||
fGdb.Executable:= 'gdb' + exeExt;
|
fGdb.Executable:= gdb;
|
||||||
fgdb.Options:= [poUsePipes, poStderrToOutPut];
|
fgdb.Options:= [poUsePipes, poStderrToOutPut];
|
||||||
fgdb.Parameters.Add(str);
|
fgdb.Parameters.Add(str);
|
||||||
|
|
||||||
|
//TODO-cGDB: debugee environment
|
||||||
|
//TODO-cGDB: debugee command line
|
||||||
|
//TODO-cGDB: pass input to debugee
|
||||||
|
|
||||||
fgdb.Parameters.Add('--interpreter=mi');
|
fgdb.Parameters.Add('--interpreter=mi');
|
||||||
fGdb.OnReadData:= @gdboutQuiet;
|
fGdb.OnReadData:= @gdboutQuiet;
|
||||||
fGdb.OnTerminate:= @gdboutJsonize;
|
fGdb.OnTerminate:= @gdboutJsonize;
|
||||||
|
@ -797,11 +809,27 @@ procedure parseGdbout(const str: string; var json: TJSONObject);
|
||||||
begin
|
begin
|
||||||
r^.popFront;
|
r^.popFront;
|
||||||
if r^.front = #10 then
|
if r^.front = #10 then
|
||||||
|
begin
|
||||||
|
r^.popFront;
|
||||||
break;
|
break;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure parseInferior(node: TJSONObject; r: PStringRange);
|
||||||
|
begin
|
||||||
|
while true do
|
||||||
|
begin
|
||||||
|
// TODO-cGDB: detect invalid command after GDB prefix, maybe inferior output
|
||||||
|
if r^.empty or (r^.front in ['~','^','*','=','&',(*'+',*)'@']) then
|
||||||
|
break;
|
||||||
|
node.Arrays['OUT'].Add(r^.takeUntil(#10).yield);
|
||||||
|
if not r^.empty then
|
||||||
|
r^.popFront;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure parseProperty(node: TJSONArray; r: PStringRange);
|
procedure parseProperty(node: TJSONArray; r: PStringRange);
|
||||||
var
|
var
|
||||||
c: char;
|
c: char;
|
||||||
|
@ -835,6 +863,11 @@ procedure parseGdbout(const str: string; var json: TJSONObject);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
',': r^.popFront;
|
',': r^.popFront;
|
||||||
|
#10:
|
||||||
|
begin
|
||||||
|
r^.popFront;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -898,8 +931,9 @@ begin
|
||||||
json.Clear;
|
json.Clear;
|
||||||
if str.length = 0 then
|
if str.length = 0 then
|
||||||
exit;
|
exit;
|
||||||
json.Arrays['CLI'] := TJSONArray.Create;
|
|
||||||
rng.init(str);
|
rng.init(str);
|
||||||
|
json.Arrays['OUT'] := TJSONArray.Create;
|
||||||
|
json.Arrays['CLI'] := TJSONArray.Create;
|
||||||
while true do
|
while true do
|
||||||
begin
|
begin
|
||||||
if rng.empty then
|
if rng.empty then
|
||||||
|
@ -920,11 +954,29 @@ begin
|
||||||
begin
|
begin
|
||||||
parseCLI(json, rng.popFront);
|
parseCLI(json, rng.popFront);
|
||||||
end;
|
end;
|
||||||
|
// internal gdb messages
|
||||||
|
'&':
|
||||||
|
begin
|
||||||
|
rng.popUntil(#10);
|
||||||
|
if not rng.empty then
|
||||||
|
rng.popFront;
|
||||||
|
end;
|
||||||
|
// async notify / status / out stream when remote (@)
|
||||||
|
'=', (*'+',*)'@':
|
||||||
|
begin
|
||||||
|
rng.popUntil(#10);
|
||||||
|
if not rng.empty then
|
||||||
|
rng.popFront;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if rng.startsWith('(gdb)') then
|
||||||
|
rng.popFrontN(7)
|
||||||
|
// empty line, inferior output
|
||||||
|
else
|
||||||
|
parseInferior(json, @rng);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
// else line is not interesting
|
|
||||||
rng.popUntil(#10);
|
|
||||||
if not rng.empty then
|
|
||||||
rng.popFront;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -948,7 +1000,6 @@ var
|
||||||
line: integer = -1;
|
line: integer = -1;
|
||||||
// registers data
|
// registers data
|
||||||
number: integer = 0;
|
number: integer = 0;
|
||||||
gprval: PtrUInt = 0;
|
|
||||||
// signal data
|
// signal data
|
||||||
sigmean: string;
|
sigmean: string;
|
||||||
signame: string;
|
signame: string;
|
||||||
|
@ -983,6 +1034,7 @@ begin
|
||||||
infoRegs;
|
infoRegs;
|
||||||
subjDebugBreak(fSubj, fullname, line, brkreason);
|
subjDebugBreak(fSubj, fullname, line, brkreason);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else if reason = 'signal-received' then
|
else if reason = 'signal-received' then
|
||||||
|
@ -1043,6 +1095,12 @@ begin
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
val := fJson.Find('msg');
|
||||||
|
if val.isNotNil then
|
||||||
|
begin
|
||||||
|
fMsg.message(val.AsString, nil, amcMisc, amkAuto);
|
||||||
|
end;
|
||||||
|
|
||||||
val := fJson.Find('register-values');
|
val := fJson.Find('register-values');
|
||||||
if val.isNotNil and (val.JSONType = jtArray) then
|
if val.isNotNil and (val.JSONType = jtArray) then
|
||||||
begin
|
begin
|
||||||
|
@ -1107,7 +1165,7 @@ begin
|
||||||
fStackItems.assignToList(lstCallStack);
|
fStackItems.assignToList(lstCallStack);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if fOptions.showOutput then
|
if fOptions.showGdbOutput then
|
||||||
begin
|
begin
|
||||||
arr := TJSONArray(fJson.Find('CLI'));
|
arr := TJSONArray(fJson.Find('CLI'));
|
||||||
if arr.isNotNil then
|
if arr.isNotNil then
|
||||||
|
@ -1115,6 +1173,14 @@ begin
|
||||||
fMsg.message(arr.Strings[i], nil, amcMisc, amkBub);
|
fMsg.message(arr.Strings[i], nil, amcMisc, amkBub);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if fOptions.showOutput then
|
||||||
|
begin
|
||||||
|
arr := TJSONArray(fJson.Find('OUT'));
|
||||||
|
if arr.isNotNil then
|
||||||
|
for i := 0 to arr.Count-1 do
|
||||||
|
fMsg.message(arr.Strings[i], nil, amcMisc, amkBub);
|
||||||
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.gdboutJsonize(sender: TObject);
|
procedure TCEGdbWidget.gdboutJsonize(sender: TObject);
|
||||||
|
@ -1127,8 +1193,8 @@ begin
|
||||||
|
|
||||||
fLog.Clear;
|
fLog.Clear;
|
||||||
fGdb.getFullLines(fLog);
|
fGdb.getFullLines(fLog);
|
||||||
for str in fLog do
|
//for str in fLog do
|
||||||
fMsg.message(str, nil, amcMisc, amkAuto);
|
// fMsg.message(str, nil, amcMisc, amkAuto);
|
||||||
|
|
||||||
if flog.Text.isEmpty then
|
if flog.Text.isEmpty then
|
||||||
exit;
|
exit;
|
||||||
|
@ -1155,14 +1221,13 @@ end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGIOn GDB commands & actions ------------------------------------------------}
|
{$REGIOn GDB commands & actions ------------------------------------------------}
|
||||||
procedure TCEGdbWidget.gdbCommand(aCommand: string; gdboutProcessor: TNotifyEvent = nil);
|
procedure TCEGdbWidget.gdbCommand(aCommand: string; gdbOutProcessor: TNotifyEvent = nil);
|
||||||
begin
|
begin
|
||||||
if fGdb = nil then exit;
|
if fGdb.isNil or not fGdb.Running then
|
||||||
if not fGdb.Running then exit;
|
exit;
|
||||||
//
|
|
||||||
aCommand += #10;
|
aCommand += #10;
|
||||||
if assigned(gdboutProcessor) then
|
if assigned(gdbOutProcessor) then
|
||||||
fGdb.OnReadData := gdboutProcessor;
|
fGdb.OnReadData := gdbOutProcessor;
|
||||||
fGdb.Input.Write(aCommand[1], aCommand.length);
|
fGdb.Input.Write(aCommand[1], aCommand.length);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue