mirror of https://gitlab.com/basile.b/dexed.git
add editor and db for the inferior env and args, close #97
This commit is contained in:
parent
e914d9d9aa
commit
3ad9b0f682
|
@ -58,7 +58,7 @@ inherited CEGdbWidget: TCEGdbWidget
|
||||||
Cursor = crVSplit
|
Cursor = crVSplit
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 6
|
Height = 6
|
||||||
Top = 0
|
Top = 200
|
||||||
Width = 517
|
Width = 517
|
||||||
Align = alTop
|
Align = alTop
|
||||||
ResizeAnchor = akTop
|
ResizeAnchor = akTop
|
||||||
|
@ -66,7 +66,7 @@ inherited CEGdbWidget: TCEGdbWidget
|
||||||
object PageControl2: TPageControl
|
object PageControl2: TPageControl
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 200
|
Height = 200
|
||||||
Top = 6
|
Top = 0
|
||||||
Width = 517
|
Width = 517
|
||||||
ActivePage = TabSheet3
|
ActivePage = TabSheet3
|
||||||
Align = alTop
|
Align = alTop
|
||||||
|
@ -200,6 +200,7 @@ inherited CEGdbWidget: TCEGdbWidget
|
||||||
object PageControl1: TPageControl[3]
|
object PageControl1: TPageControl[3]
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 200
|
Height = 200
|
||||||
|
Hint = 'edit the command line and the environment of the debuger target'
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 517
|
Width = 517
|
||||||
ActivePage = TabSheet1
|
ActivePage = TabSheet1
|
||||||
|
@ -298,6 +299,27 @@ inherited CEGdbWidget: TCEGdbWidget
|
||||||
OnDblClick = lstThreadsDblClick
|
OnDblClick = lstThreadsDblClick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
object TabSheet5: TTabSheet
|
||||||
|
Caption = 'Debugee options'
|
||||||
|
ClientHeight = 164
|
||||||
|
ClientWidth = 509
|
||||||
|
object dbgeeOptsEd: TTIPropertyGrid
|
||||||
|
Left = 2
|
||||||
|
Height = 160
|
||||||
|
Top = 2
|
||||||
|
Width = 505
|
||||||
|
Align = alClient
|
||||||
|
BorderSpacing.Around = 2
|
||||||
|
CheckboxForBoolean = True
|
||||||
|
DefaultValueFont.Color = clWindowText
|
||||||
|
Filter = [tkInteger, tkChar, tkEnumeration, tkFloat, tkSet, tkMethod, tkSString, tkLString, tkAString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkClass, tkObject, tkWChar, tkBool, tkInt64, tkQWord, tkDynArray, tkInterfaceRaw, tkProcVar, tkUString, tkUChar, tkHelper, tkFile, tkClassRef, tkPointer]
|
||||||
|
Indent = 10
|
||||||
|
NameFont.Color = clWindowText
|
||||||
|
PreferredSplitterX = 190
|
||||||
|
SplitterX = 190
|
||||||
|
ValueFont.Color = clGreen
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
inherited toolbar: TCEToolBar
|
inherited toolbar: TCEToolBar
|
||||||
|
|
206
src/ce_gdb.pas
206
src/ce_gdb.pas
|
@ -324,6 +324,46 @@ type
|
||||||
|
|
||||||
TAddWatchPointKind = (wpkRead, wpkWrite, wpkReadWrite);
|
TAddWatchPointKind = (wpkRead, wpkWrite, wpkReadWrite);
|
||||||
|
|
||||||
|
// Persistent command line & environment of the inferior.
|
||||||
|
TCEDebugeeOption = class(TCollectionItem)
|
||||||
|
strict private
|
||||||
|
fQueryArguments: boolean;
|
||||||
|
fFname: string;
|
||||||
|
fWorkingDir: TCEPathname;
|
||||||
|
fAgruments: TStringList;
|
||||||
|
fEnvPaths: TStringList;
|
||||||
|
procedure setOptions(value: TStringList);
|
||||||
|
procedure setEnvPaths(value: TStringList);
|
||||||
|
published
|
||||||
|
property environmentPaths: TStringList read fEnvPaths write fEnvPaths;
|
||||||
|
property filename: string read fFname write fFname;
|
||||||
|
property arguments: TStringList read fAgruments write setOptions;
|
||||||
|
property queryArguments: boolean read fQueryArguments write fQueryArguments default false;
|
||||||
|
property workingDirectory: TCEPathname read fWorkingDir write fWorkingDir;
|
||||||
|
public
|
||||||
|
constructor Create(ACollection: TCollection); override;
|
||||||
|
destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Store for the command line & environment of the inferior.
|
||||||
|
TCEDebugeeOptions = class(TWritableLfmTextComponent)
|
||||||
|
strict private
|
||||||
|
fProjects: TCollection;
|
||||||
|
procedure setProjects(value: TCollection);
|
||||||
|
function getProjectByIndex(index: integer): TCEDebugeeOption;
|
||||||
|
function getProjectByFile(const fname: string): TCEDebugeeOption;
|
||||||
|
procedure cleanup;
|
||||||
|
protected
|
||||||
|
procedure beforeSave; override;
|
||||||
|
published
|
||||||
|
property projects: TCollection read fProjects write setProjects;
|
||||||
|
public
|
||||||
|
constructor Create(AOwner: TComponent); override;
|
||||||
|
destructor Destroy; override;
|
||||||
|
property projectByIndex[index: integer]: TCEDebugeeOption read getProjectByIndex;
|
||||||
|
property projectByFile[const fname: string]: TCEDebugeeOption read getProjectByFile; default;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TCEGdbWidget }
|
{ TCEGdbWidget }
|
||||||
TCEGdbWidget = class(TCEWidget, ICEProjectObserver, ICEDocumentObserver, ICEDebugger)
|
TCEGdbWidget = class(TCEWidget, ICEProjectObserver, ICEDocumentObserver, ICEDebugger)
|
||||||
btnContinue: TCEToolButton;
|
btnContinue: TCEToolButton;
|
||||||
|
@ -367,6 +407,8 @@ type
|
||||||
Splitter3: TSplitter;
|
Splitter3: TSplitter;
|
||||||
Splitter4: TSplitter;
|
Splitter4: TSplitter;
|
||||||
lstAsm: TListView;
|
lstAsm: TListView;
|
||||||
|
TabSheet5: TTabSheet;
|
||||||
|
dbgeeOptsEd: TTIPropertyGrid;
|
||||||
varListFlt: TListViewFilterEdit;
|
varListFlt: TListViewFilterEdit;
|
||||||
procedure btnContClick(Sender: TObject);
|
procedure btnContClick(Sender: TObject);
|
||||||
procedure btnVariablesClick(Sender: TObject);
|
procedure btnVariablesClick(Sender: TObject);
|
||||||
|
@ -422,6 +464,7 @@ type
|
||||||
fLastOffset: string;
|
fLastOffset: string;
|
||||||
fLastLine: string;
|
fLastLine: string;
|
||||||
fCommandProcessed: boolean;
|
fCommandProcessed: boolean;
|
||||||
|
fDebugeeOptions: TCEDebugeeOptions;
|
||||||
procedure waitCommandProcessed;
|
procedure waitCommandProcessed;
|
||||||
procedure clearDisplays;
|
procedure clearDisplays;
|
||||||
procedure updateMenu;
|
procedure updateMenu;
|
||||||
|
@ -432,6 +475,7 @@ type
|
||||||
procedure startDebugging;
|
procedure startDebugging;
|
||||||
procedure killGdb;
|
procedure killGdb;
|
||||||
procedure storeObserversBreakpoints;
|
procedure storeObserversBreakpoints;
|
||||||
|
procedure updateDebugeeOptionsEditor;
|
||||||
// GDB output processors
|
// GDB output processors
|
||||||
procedure gdboutQuiet(sender: TObject);
|
procedure gdboutQuiet(sender: TObject);
|
||||||
procedure gdboutJsonize(sender: TObject);
|
procedure gdboutJsonize(sender: TObject);
|
||||||
|
@ -516,11 +560,11 @@ type
|
||||||
implementation
|
implementation
|
||||||
{$R *.lfm}
|
{$R *.lfm}
|
||||||
|
|
||||||
{$REGION TCEDebugOption --------------------------------------------------------}
|
|
||||||
const optFname = 'gdbcommander.txt';
|
const optFname = 'gdbcommander.txt';
|
||||||
const bpFname = 'breakpoints.txt';
|
const bpFname = 'breakpoints.txt';
|
||||||
|
const prjFname = 'projectsgdboptions.txt';
|
||||||
|
|
||||||
|
{$REGION TCEDebugOption --------------------------------------------------------}
|
||||||
procedure TCEDebugShortcuts.assign(source: TPersistent);
|
procedure TCEDebugShortcuts.assign(source: TPersistent);
|
||||||
var
|
var
|
||||||
src: TCEDebugShortcuts;
|
src: TCEDebugShortcuts;
|
||||||
|
@ -967,6 +1011,96 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
|
{$REGION TCEDebugeeOption ------------------------------------------------------}
|
||||||
|
constructor TCEDebugeeOption.Create(ACollection: TCollection);
|
||||||
|
begin
|
||||||
|
inherited create(ACollection);
|
||||||
|
fAgruments := TStringList.Create;
|
||||||
|
fEnvPaths := TStringList.Create;
|
||||||
|
fAgruments.Delimiter:= ' ';
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TCEDebugeeOption.Destroy;
|
||||||
|
begin
|
||||||
|
fAgruments.Free;
|
||||||
|
fEnvPaths.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCEDebugeeOption.setOptions(value: TStringList);
|
||||||
|
begin
|
||||||
|
fAgruments.Assign(value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCEDebugeeOption.setEnvPaths(value: TStringList);
|
||||||
|
begin
|
||||||
|
fEnvPaths.Assign(value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TCEDebugeeOptions.Create(AOwner: TComponent);
|
||||||
|
var
|
||||||
|
fname: string;
|
||||||
|
begin
|
||||||
|
inherited create(AOwner);
|
||||||
|
fProjects := TCollection.Create(TCEDebugeeOption);
|
||||||
|
fname := getCoeditDocPath + prjFname;
|
||||||
|
if fname.fileExists then
|
||||||
|
loadFromFile(fname);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TCEDebugeeOptions.Destroy;
|
||||||
|
begin
|
||||||
|
saveToFile(getCoeditDocPath + prjFname);
|
||||||
|
fProjects.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCEDebugeeOptions.cleanup;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
p: TCEDebugeeOption;
|
||||||
|
begin
|
||||||
|
for i:= fProjects.Count-1 downto 0 do
|
||||||
|
begin
|
||||||
|
p := projectByIndex[i];
|
||||||
|
if not p.filename.fileExists or p.filename.isEmpty then
|
||||||
|
fProjects.Delete(i);
|
||||||
|
if (p.arguments.Count = 0) and (p.environmentPaths.Count = 0) and
|
||||||
|
(p.workingDirectory = '') and (p.queryArguments = false) then
|
||||||
|
fProjects.Delete(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCEDebugeeOptions.beforeSave;
|
||||||
|
begin
|
||||||
|
cleanup;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCEDebugeeOptions.setProjects(value: TCollection);
|
||||||
|
begin
|
||||||
|
fProjects.Assign(value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCEDebugeeOptions.getProjectByIndex(index: integer): TCEDebugeeOption;
|
||||||
|
begin
|
||||||
|
exit(TCEDebugeeOption(fProjects.Items[index]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCEDebugeeOptions.getProjectByFile(const fname: string): TCEDebugeeOption;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to fProjects.Count-1 do
|
||||||
|
begin
|
||||||
|
result := projectByIndex[i];
|
||||||
|
if result.filename = fname then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
result := TCEDebugeeOption(fProjects.Add);
|
||||||
|
result.filename:=fname;
|
||||||
|
end;
|
||||||
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGION Common/standard comp --------------------------------------------------}
|
{$REGION Common/standard comp --------------------------------------------------}
|
||||||
constructor TCEGdbWidget.create(aOwner: TComponent);
|
constructor TCEGdbWidget.create(aOwner: TComponent);
|
||||||
begin
|
begin
|
||||||
|
@ -983,6 +1117,7 @@ begin
|
||||||
fSubj:= TCEDebugObserverSubject.Create;
|
fSubj:= TCEDebugObserverSubject.Create;
|
||||||
fOptions:= TCEDebugOptions.create(self);
|
fOptions:= TCEDebugOptions.create(self);
|
||||||
fOptions.onChangesApplied:=@optionsChangesApplied;
|
fOptions.onChangesApplied:=@optionsChangesApplied;
|
||||||
|
fDebugeeOptions:= TCEDebugeeOptions.Create(self);
|
||||||
Edit1.Items.Assign(fOptions.commandsHistory);
|
Edit1.Items.Assign(fOptions.commandsHistory);
|
||||||
fAddWatchPointKind := wpkWrite;
|
fAddWatchPointKind := wpkWrite;
|
||||||
fBreakPoints := TPersistentBreakPoints.create(self);
|
fBreakPoints := TPersistentBreakPoints.create(self);
|
||||||
|
@ -1190,6 +1325,7 @@ begin
|
||||||
if fProj <> project then
|
if fProj <> project then
|
||||||
exit;
|
exit;
|
||||||
fProj := nil;
|
fProj := nil;
|
||||||
|
updateDebugeeOptionsEditor;
|
||||||
if not fDbgRunnable then
|
if not fDbgRunnable then
|
||||||
begin
|
begin
|
||||||
if fOutputName.fileExists then
|
if fOutputName.fileExists then
|
||||||
|
@ -1202,6 +1338,7 @@ end;
|
||||||
procedure TCEGdbWidget.projFocused(project: ICECommonProject);
|
procedure TCEGdbWidget.projFocused(project: ICECommonProject);
|
||||||
begin
|
begin
|
||||||
fProj := project;
|
fProj := project;
|
||||||
|
updateDebugeeOptionsEditor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.projCompiling(project: ICECommonProject);
|
procedure TCEGdbWidget.projCompiling(project: ICECommonProject);
|
||||||
|
@ -1221,6 +1358,7 @@ end;
|
||||||
procedure TCEGdbWidget.docFocused(document: TCESynMemo);
|
procedure TCEGdbWidget.docFocused(document: TCESynMemo);
|
||||||
begin
|
begin
|
||||||
fDoc := document;
|
fDoc := document;
|
||||||
|
updateDebugeeOptionsEditor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.docChanged(document: TCESynMemo);
|
procedure TCEGdbWidget.docChanged(document: TCESynMemo);
|
||||||
|
@ -1232,6 +1370,7 @@ begin
|
||||||
if fDoc <> document then
|
if fDoc <> document then
|
||||||
exit;
|
exit;
|
||||||
fDoc := nil;
|
fDoc := nil;
|
||||||
|
updateDebugeeOptionsEditor;
|
||||||
if fDbgRunnable then
|
if fDbgRunnable then
|
||||||
begin
|
begin
|
||||||
if fOutputName.fileExists then
|
if fOutputName.fileExists then
|
||||||
|
@ -1407,12 +1546,14 @@ procedure TCEGdbWidget.mnuSelProjClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
fDbgRunnable := false;
|
fDbgRunnable := false;
|
||||||
mnuSelRunnable.Checked:=false;
|
mnuSelRunnable.Checked:=false;
|
||||||
|
updateDebugeeOptionsEditor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.mnuSelRunnableClick(Sender: TObject);
|
procedure TCEGdbWidget.mnuSelRunnableClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
fDbgRunnable := true;
|
fDbgRunnable := true;
|
||||||
mnuSelProj.Checked:=false;
|
mnuSelProj.Checked:=false;
|
||||||
|
updateDebugeeOptionsEditor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.mnuWriteWClick(Sender: TObject);
|
procedure TCEGdbWidget.mnuWriteWClick(Sender: TObject);
|
||||||
|
@ -1454,6 +1595,7 @@ var
|
||||||
gdb: string;
|
gdb: string;
|
||||||
i: integer;
|
i: integer;
|
||||||
b: TPersistentBreakPoint;
|
b: TPersistentBreakPoint;
|
||||||
|
o: TCEDebugeeOption;
|
||||||
const
|
const
|
||||||
asmFlavorStr: array[TAsmSyntax] of string = ('intel','att');
|
asmFlavorStr: array[TAsmSyntax] of string = ('intel','att');
|
||||||
begin
|
begin
|
||||||
|
@ -1506,16 +1648,16 @@ begin
|
||||||
deletefile(fInputName);
|
deletefile(fInputName);
|
||||||
fInput:= TFileStream.Create(fInputName, fmCreate or fmShareExclusive);
|
fInput:= TFileStream.Create(fInputName, fmCreate or fmShareExclusive);
|
||||||
subjDebugStart(fSubj, self as ICEDebugger);
|
subjDebugStart(fSubj, self as ICEDebugger);
|
||||||
|
case fDbgRunnable of
|
||||||
|
true: o := fDebugeeOptions.projectByFile[fDoc.fileName];
|
||||||
|
false:o := fDebugeeOptions.projectByFile[fProj.fileName];
|
||||||
|
end;
|
||||||
// gdb process
|
// gdb process
|
||||||
killGdb;
|
killGdb;
|
||||||
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(fExe);
|
fgdb.Parameters.Add(fExe);
|
||||||
|
|
||||||
//TODO-cGDB: debugee environment
|
|
||||||
//TODO-cGDB: debugee command line
|
|
||||||
|
|
||||||
fgdb.Parameters.Add('--interpreter=mi');
|
fgdb.Parameters.Add('--interpreter=mi');
|
||||||
fGdb.OnReadData:= @gdboutQuiet;
|
fGdb.OnReadData:= @gdboutQuiet;
|
||||||
fGdb.OnTerminate:= @gdboutJsonize;
|
fGdb.OnTerminate:= @gdboutJsonize;
|
||||||
|
@ -1557,14 +1699,62 @@ begin
|
||||||
else
|
else
|
||||||
gdbCommand('-gdb-set non-stop off');
|
gdbCommand('-gdb-set non-stop off');
|
||||||
fGdb.OnReadData := @gdboutJsonize;
|
fGdb.OnReadData := @gdboutJsonize;
|
||||||
// launch
|
|
||||||
cpuViewer.TIObject := fInspState;
|
cpuViewer.TIObject := fInspState;
|
||||||
cpuViewer.RefreshPropertyValues;
|
cpuViewer.RefreshPropertyValues;
|
||||||
gdbCommand('set args >' + fOutputName + '< ' + fInputName);
|
// inferior options
|
||||||
|
if o.environmentPaths.Count <> 0 then
|
||||||
|
begin
|
||||||
|
str := '';
|
||||||
|
for i:= 0 to o.environmentPaths.Count-1 do
|
||||||
|
str += o.environmentPaths[i] + ' ';
|
||||||
|
str := fSyms.expand(str[1..str.length-1]);
|
||||||
|
gdbCommand('-environment-path ' + str);
|
||||||
|
end;
|
||||||
|
if DirectoryExists(o.workingDirectory) then
|
||||||
|
gdbCommand('-environment-cd ' + fSyms.expand(o.workingDirectory));
|
||||||
|
if (o.arguments.Count <> 0) or (o.queryArguments) then
|
||||||
|
begin
|
||||||
|
str := '';
|
||||||
|
if o.queryArguments and not InputQuery('Command line arguments', 'GDB commander', str) then
|
||||||
|
str := ''
|
||||||
|
else
|
||||||
|
str += ' ';
|
||||||
|
for i := 0 to o.arguments.Count-1 do
|
||||||
|
str += o.arguments[i] + ' ';
|
||||||
|
str := fSyms.expand(str);
|
||||||
|
end;
|
||||||
|
gdbCommand('set args '+ str + '> ' + fOutputName + '< ' + fInputName);
|
||||||
// non-MI command "run" has the same problem as https://sourceware.org/bugzilla/show_bug.cgi?id=18077
|
// non-MI command "run" has the same problem as https://sourceware.org/bugzilla/show_bug.cgi?id=18077
|
||||||
gdbCommand('-exec-run');
|
gdbCommand('-exec-run');
|
||||||
setState(gsRunning);
|
setState(gsRunning);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCEGdbWidget.updateDebugeeOptionsEditor;
|
||||||
|
var
|
||||||
|
nme: string = '';
|
||||||
|
opt: TCEDebugeeOption;
|
||||||
|
begin
|
||||||
|
dbgeeOptsEd.ItemIndex:=-1;
|
||||||
|
dbgeeOptsEd.TIObject := nil;
|
||||||
|
if not fDbgRunnable then
|
||||||
|
begin
|
||||||
|
if fProj = nil then
|
||||||
|
exit
|
||||||
|
else nme := fProj.filename;
|
||||||
|
if not nme.fileExists then
|
||||||
|
exit;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if fDoc = nil then
|
||||||
|
exit
|
||||||
|
else nme := fDoc.filename;
|
||||||
|
if not nme.fileExists then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
opt := fDebugeeOptions.projectByFile[nme];
|
||||||
|
dbgeeOptsEd.TIObject := opt;
|
||||||
|
end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGION GDB output processors -------------------------------------------------}
|
{$REGION GDB output processors -------------------------------------------------}
|
||||||
|
|
Loading…
Reference in New Issue