#97, redirect inferior output to file

This commit is contained in:
Basile Burg 2016-10-28 10:45:06 +02:00
parent ae740f0782
commit 49ecb0aa0a
No known key found for this signature in database
GPG Key ID: 1868039F415CB8CF
1 changed files with 63 additions and 33 deletions

View File

@ -338,7 +338,10 @@ type
procedure Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
protected protected
procedure setToolBarFlat(value: boolean); override; procedure setToolBarFlat(value: boolean); override;
procedure updateLoop; override;
private private
fExe: string;
fOutputName: string;
fUpdateMenu: boolean; fUpdateMenu: boolean;
fGdbState: TGdbState; fGdbState: TGdbState;
fSubj: TCEDebugObserverSubject; fSubj: TCEDebugObserverSubject;
@ -350,6 +353,7 @@ type
fDocHandler: ICEMultiDocHandler; fDocHandler: ICEMultiDocHandler;
fMsg: ICEMessagesDisplay; fMsg: ICEMessagesDisplay;
fGdb: TCEProcess; fGdb: TCEProcess;
fOutput: TFileStream;
fInspState: TInspectableCPU; fInspState: TInspectableCPU;
fStackItems: TStackItems; fStackItems: TStackItems;
fCatchPause: boolean; fCatchPause: boolean;
@ -379,6 +383,7 @@ type
procedure setFpr(reg: TFpuRegister; val: extended); procedure setFpr(reg: TFpuRegister; val: extended);
procedure setSsr(reg: TSegRegister; val: TCPUSegValue); procedure setSsr(reg: TSegRegister; val: TCPUSegValue);
procedure setFlag(val: PtrUint); procedure setFlag(val: PtrUint);
procedure readOutput;
// //
procedure projNew(project: ICECommonProject); procedure projNew(project: ICECommonProject);
procedure projChanged(project: ICECommonProject); procedure projChanged(project: ICECommonProject);
@ -498,6 +503,12 @@ begin
if fname.fileExists then if fname.fileExists then
loadFromFile(fname); loadFromFile(fname);
EntitiesConnector.addObserver(self); EntitiesConnector.addObserver(self);
fShowGdbOutput:=false;
fShowOutput:= true;
fAutoDemangle:= true;
fAutoGetCallStack:= true;
fAutoGetRegisters:= true;
fAutoGetVariables:= true;
end; end;
destructor TCEDebugOptions.destroy; destructor TCEDebugOptions.destroy;
@ -833,6 +844,7 @@ end;
destructor TCEGdbWidget.destroy; destructor TCEGdbWidget.destroy;
begin begin
fOutput.Free;
fOptions.commandsHistory.Assign(edit1.Items); fOptions.commandsHistory.Assign(edit1.Items);
fOptions.Free; fOptions.Free;
fFileLineBrks.Free; fFileLineBrks.Free;
@ -1033,6 +1045,8 @@ begin
if fProj <> project then if fProj <> project then
exit; exit;
fProj := nil; fProj := nil;
if fOutputName.fileExists then
deleteFile(fOutputName);
end; end;
procedure TCEGdbWidget.projFocused(project: ICECommonProject); procedure TCEGdbWidget.projFocused(project: ICECommonProject);
@ -1196,8 +1210,9 @@ begin
exit; exit;
if fProj.binaryKind <> executable then if fProj.binaryKind <> executable then
exit; exit;
str := fProj.outputFilename; fExe := fProj.outputFilename;
if not str.fileExists then fOutputName := fExe + '.gdbout';
if not fExe.fileExists then
exit; exit;
gdb := exeFullName('gdb'); gdb := exeFullName('gdb');
if not gdb.fileExists then if not gdb.fileExists then
@ -1208,7 +1223,7 @@ begin
fGdb := TCEProcess.create(nil); fGdb := TCEProcess.create(nil);
fGdb.Executable:= gdb; fGdb.Executable:= gdb;
fgdb.Options:= [poUsePipes, poStderrToOutPut]; fgdb.Options:= [poUsePipes, poStderrToOutPut];
fgdb.Parameters.Add(str); fgdb.Parameters.Add(fExe);
//TODO-cGDB: debugee environment //TODO-cGDB: debugee environment
//TODO-cGDB: debugee command line //TODO-cGDB: debugee command line
@ -1247,7 +1262,10 @@ begin
gdbCommand('-gdb-set mi-async on'); gdbCommand('-gdb-set mi-async on');
fGdb.OnReadData := @gdboutJsonize; fGdb.OnReadData := @gdboutJsonize;
// launch // launch
gdbCommand('run'); gdbCommand('run >' + fExe + '.gdbout');
FreeAndNil(fOutput);
if fOutputName.fileExists then
fOutput := TFileStream.Create(fOutputName, 0);
setState(gsRunning); setState(gsRunning);
end; end;
{$ENDREGION} {$ENDREGION}
@ -1293,19 +1311,6 @@ procedure parseGdbout(const str: string; var json: TJSONObject);
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;
@ -1455,7 +1460,7 @@ begin
rng.popFront; rng.popFront;
end; end;
// async notify / status / out stream when remote (@) // async notify / status / out stream when remote (@)
'=', (*'+',*)'@': '=', '+','@':
begin begin
rng.popUntil(#10); rng.popUntil(#10);
if not rng.empty then if not rng.empty then
@ -1463,11 +1468,9 @@ begin
end end
else else
begin begin
if rng.startsWith('(gdb)') then rng.popUntil(#10);
rng.popFrontN(7) if not rng.empty then
// empty line, inferior output rng.popFront;
else
parseInferior(json, @rng);
end; end;
end; end;
end; end;
@ -1532,6 +1535,7 @@ begin
fDocHandler.openDocument(fullname); fDocHandler.openDocument(fullname);
setState(gsPaused); setState(gsPaused);
autoGetStuff; autoGetStuff;
readOutput;
subjDebugBreak(fSubj, fullname, line, brkreason); subjDebugBreak(fSubj, fullname, line, brkreason);
end; end;
@ -1567,6 +1571,7 @@ begin
fDocHandler.openDocument(fullname); fDocHandler.openDocument(fullname);
autoGetStuff; autoGetStuff;
setState(gsPaused); setState(gsPaused);
readOutput;
subjDebugBreak(fSubj, fullname, line, dbSignal); subjDebugBreak(fSubj, fullname, line, dbSignal);
end end
else else
@ -1584,6 +1589,7 @@ begin
fDocHandler.openDocument(fullname); fDocHandler.openDocument(fullname);
autoGetStuff; autoGetStuff;
setState(gsPaused); setState(gsPaused);
readOutput;
subjDebugBreak(fSubj, fullname, line, dbSignal); subjDebugBreak(fSubj, fullname, line, dbSignal);
end; end;
end; end;
@ -1591,6 +1597,9 @@ begin
else if (reason = 'exited-normally') or (reason = 'exited-signalled') then else if (reason = 'exited-normally') or (reason = 'exited-signalled') then
begin begin
readOutput;
if not fOptions.showGdbOutput then
fMsg.message('debugging terminated: ' + reason, nil, amcMisc, amkInf);
setState(gsNone); setState(gsNone);
subjDebugStop(fSubj); subjDebugStop(fSubj);
end; end;
@ -1718,14 +1727,6 @@ 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);
@ -1738,8 +1739,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;
@ -1758,6 +1759,35 @@ begin
end; end;
procedure TCEGdbWidget.updateLoop;
begin
if fGdbState <> gsNone then
readOutput;
end;
procedure TCEGdbWidget.readOutput;
var
str: TMemoryStream;
lst: TStringList;
lne: string;
begin
if (fGdbState = gsNone) or not fOptions.showOutput or fOutput.isNil then
exit;
str := TMemoryStream.Create;
lst := TStringList.Create;
try
str.size := fOutput.Size - fOutput.Position;
fOutput.Read(str.Memory^, str.Size);
lst.LoadFromStream(str);
for lne in lst do
fMsg.message(lne, nil, amcMisc, amkBub);
finally
lst.Free;
str.Free;
end;
end;
procedure TCEGdbWidget.gdboutQuiet(sender: TObject); procedure TCEGdbWidget.gdboutQuiet(sender: TObject);
begin begin
fGdb.OutputStack.Clear; fGdb.OutputStack.Clear;