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;
|
||||
fCommandsHistory: TStringList;
|
||||
fIgnoredSignals: TStringList;
|
||||
fShowGdbOutput: boolean;
|
||||
fShowOutput: boolean;
|
||||
procedure setIgnoredSignals(value: TStringList);
|
||||
procedure setCommandsHistory(value: TStringList);
|
||||
|
@ -179,6 +180,7 @@ type
|
|||
property autoGetVariables: boolean read fAutoGetVariables write fAutoGetVariables;
|
||||
property commandsHistory: TStringList read fCommandsHistory write setCommandsHistory;
|
||||
property ignoredSignals: TStringList read fIgnoredSignals write setIgnoredSignals;
|
||||
property showGdbOutput: boolean read fShowGdbOutput write fShowGdbOutput;
|
||||
property showOutput: boolean read fShowOutput write fShowOutput;
|
||||
public
|
||||
constructor create(aOwner: TComponent); override;
|
||||
|
@ -252,7 +254,7 @@ type
|
|||
procedure gdboutJsonize(sender: TObject);
|
||||
procedure interpretJson;
|
||||
// GDB commands & actions
|
||||
procedure gdbCommand(aCommand: string; gdboutProcessor: TNotifyEvent = nil);
|
||||
procedure gdbCommand(aCommand: string; gdbOutProcessor: TNotifyEvent = nil);
|
||||
procedure infoRegs;
|
||||
procedure infoStack;
|
||||
procedure sendCustomCommand;
|
||||
|
@ -293,7 +295,7 @@ begin
|
|||
fAutoGetCallStack:= true;
|
||||
fAutoGetRegisters:= true;
|
||||
fAutoGetVariables:= true;
|
||||
fShowOutput:=true;
|
||||
fShowGdbOutput:=true;
|
||||
fIgnoredSignals := TStringList.Create;
|
||||
fCommandsHistory := TStringList.Create;
|
||||
end;
|
||||
|
@ -326,6 +328,7 @@ begin
|
|||
fAutoGetCallStack:=src.fAutoGetCallStack;
|
||||
fAutoGetRegisters:=src.fAutoGetRegisters;
|
||||
fAutoGetVariables:=src.autoGetVariables;
|
||||
fShowGdbOutput:=src.fShowGdbOutput;
|
||||
fShowOutput:=src.fShowOutput;
|
||||
fIgnoredSignals.Assign(src.fIgnoredSignals);
|
||||
fCommandsHistory.Assign(src.fCommandsHistory);
|
||||
|
@ -690,6 +693,7 @@ end;
|
|||
procedure TCEGdbWidget.startDebugging;
|
||||
var
|
||||
str: string;
|
||||
gdb: string;
|
||||
i: integer;
|
||||
begin
|
||||
// protect
|
||||
|
@ -700,13 +704,21 @@ begin
|
|||
str := fProj.outputFilename;
|
||||
if not str.fileExists then
|
||||
exit;
|
||||
gdb := exeFullName('gdb');
|
||||
if not gdb.fileExists then
|
||||
exit;
|
||||
subjDebugStart(fSubj, self as ICEDebugger);
|
||||
// gdb process
|
||||
killGdb;
|
||||
fGdb := TCEProcess.create(nil);
|
||||
fGdb.Executable:= 'gdb' + exeExt;
|
||||
fGdb.Executable:= gdb;
|
||||
fgdb.Options:= [poUsePipes, poStderrToOutPut];
|
||||
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.OnReadData:= @gdboutQuiet;
|
||||
fGdb.OnTerminate:= @gdboutJsonize;
|
||||
|
@ -797,11 +809,27 @@ procedure parseGdbout(const str: string; var json: TJSONObject);
|
|||
begin
|
||||
r^.popFront;
|
||||
if r^.front = #10 then
|
||||
begin
|
||||
r^.popFront;
|
||||
break;
|
||||
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);
|
||||
var
|
||||
c: char;
|
||||
|
@ -835,6 +863,11 @@ procedure parseGdbout(const str: string; var json: TJSONObject);
|
|||
exit;
|
||||
end;
|
||||
',': r^.popFront;
|
||||
#10:
|
||||
begin
|
||||
r^.popFront;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -898,8 +931,9 @@ begin
|
|||
json.Clear;
|
||||
if str.length = 0 then
|
||||
exit;
|
||||
json.Arrays['CLI'] := TJSONArray.Create;
|
||||
rng.init(str);
|
||||
json.Arrays['OUT'] := TJSONArray.Create;
|
||||
json.Arrays['CLI'] := TJSONArray.Create;
|
||||
while true do
|
||||
begin
|
||||
if rng.empty then
|
||||
|
@ -920,11 +954,29 @@ begin
|
|||
begin
|
||||
parseCLI(json, rng.popFront);
|
||||
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;
|
||||
// else line is not interesting
|
||||
rng.popUntil(#10);
|
||||
if not rng.empty then
|
||||
rng.popFront;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -948,7 +1000,6 @@ var
|
|||
line: integer = -1;
|
||||
// registers data
|
||||
number: integer = 0;
|
||||
gprval: PtrUInt = 0;
|
||||
// signal data
|
||||
sigmean: string;
|
||||
signame: string;
|
||||
|
@ -983,6 +1034,7 @@ begin
|
|||
infoRegs;
|
||||
subjDebugBreak(fSubj, fullname, line, brkreason);
|
||||
end;
|
||||
|
||||
end
|
||||
|
||||
else if reason = 'signal-received' then
|
||||
|
@ -1043,6 +1095,12 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
val := fJson.Find('msg');
|
||||
if val.isNotNil then
|
||||
begin
|
||||
fMsg.message(val.AsString, nil, amcMisc, amkAuto);
|
||||
end;
|
||||
|
||||
val := fJson.Find('register-values');
|
||||
if val.isNotNil and (val.JSONType = jtArray) then
|
||||
begin
|
||||
|
@ -1107,7 +1165,7 @@ begin
|
|||
fStackItems.assignToList(lstCallStack);
|
||||
end;
|
||||
|
||||
if fOptions.showOutput then
|
||||
if fOptions.showGdbOutput then
|
||||
begin
|
||||
arr := TJSONArray(fJson.Find('CLI'));
|
||||
if arr.isNotNil then
|
||||
|
@ -1115,6 +1173,14 @@ begin
|
|||
fMsg.message(arr.Strings[i], nil, amcMisc, amkBub);
|
||||
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;
|
||||
|
||||
procedure TCEGdbWidget.gdboutJsonize(sender: TObject);
|
||||
|
@ -1127,8 +1193,8 @@ begin
|
|||
|
||||
fLog.Clear;
|
||||
fGdb.getFullLines(fLog);
|
||||
for str in fLog do
|
||||
fMsg.message(str, nil, amcMisc, amkAuto);
|
||||
//for str in fLog do
|
||||
// fMsg.message(str, nil, amcMisc, amkAuto);
|
||||
|
||||
if flog.Text.isEmpty then
|
||||
exit;
|
||||
|
@ -1155,14 +1221,13 @@ end;
|
|||
{$ENDREGION}
|
||||
|
||||
{$REGIOn GDB commands & actions ------------------------------------------------}
|
||||
procedure TCEGdbWidget.gdbCommand(aCommand: string; gdboutProcessor: TNotifyEvent = nil);
|
||||
procedure TCEGdbWidget.gdbCommand(aCommand: string; gdbOutProcessor: TNotifyEvent = nil);
|
||||
begin
|
||||
if fGdb = nil then exit;
|
||||
if not fGdb.Running then exit;
|
||||
//
|
||||
if fGdb.isNil or not fGdb.Running then
|
||||
exit;
|
||||
aCommand += #10;
|
||||
if assigned(gdboutProcessor) then
|
||||
fGdb.OnReadData := gdboutProcessor;
|
||||
if assigned(gdbOutProcessor) then
|
||||
fGdb.OnReadData := gdbOutProcessor;
|
||||
fGdb.Input.Write(aCommand[1], aCommand.length);
|
||||
end;
|
||||
|
||||
|
|
Loading…
Reference in New Issue