123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- {
- $Id$
- This file is part of the Free Pascal Integrated Development Environment
- Copyright (c) 1998 by Berczi Gabor
- Debugger call routines for the IDE
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit FPDebug;
- interface
- uses
- Views,Objects,GDBCon,GDBInt;
- type
- PDebugController=^TDebugController;
- TDebugController=object(TGDBController)
- InvalidSourceLine : boolean;
- LastFileName : string;
- LastSource : PView; {PsourceWindow !! }
- HiddenStepsCount : longint;
- constructor Init(const exefn:string);
- destructor Done;
- procedure DoSelectSourceline(const fn:string;line:longint);virtual;
- { procedure DoStartSession;virtual;
- procedure DoBreakSession;virtual;}
- procedure DoEndSession(code:longint);virtual;
- procedure AnnotateError;
- procedure InsertBreakpoints;
- procedure RemoveBreakpoints;
- procedure DoDebuggerScreen;virtual;
- procedure DoUserScreen;virtual;
- procedure Reset;virtual;
- procedure Run;virtual;
- procedure Continue;virtual;
- end;
- BreakpointType = (bt_function,bt_file_line,bt_watch,bt_awatch,bt_rwatch,bt_invalid);
- BreakpointState = (bs_enabled,bs_disabled,bs_deleted);
- PBreakpointCollection=^TBreakpointCollection;
- PBreakpoint=^TBreakpoint;
- TBreakpoint=object(TObject)
- typ : BreakpointType;
- state : BreakpointState;
- owner : PBreakpointCollection;
- Name : PString; { either function name or file name }
- Line : Longint; { only used for bt_file_line type }
- Conditions : PString; { conditions relative to that breakpoint }
- IgnoreCount : Longint; { how many counts should be ignored }
- Commands : pchar; { commands that should be executed on breakpoint }
- GDBIndex : longint;
- GDBState : BreakpointState;
- constructor Init_function(Const AFunc : String);
- constructor Init_file_line(AFile : String; ALine : longint);
- constructor Init_type(atyp : BreakpointType;Const AFunc : String);
- procedure Insert;
- procedure Remove;
- procedure Enable;
- procedure Disable;
- destructor Done;virtual;
- end;
- TBreakpointCollection=object(TCollection)
- function At(Index: Integer): PBreakpoint;
- function ToggleFileLine(Const FileName: String;LineNr : Longint) : boolean;
- procedure Update;
- procedure FreeItem(Item: Pointer); virtual;
- end;
- var
- Debugger : PDebugController;
- BreakpointCollection : PBreakpointCollection;
-
- procedure InitDebugger;
- procedure DoneDebugger;
- implementation
- uses
- Dos,Mouse,Video,
- App,Strings,
- FPViews,FPVars,FPUtils,FPConst,
- FPIntf,FPCompile,FPIde;
- {****************************************************************************
- TDebugController
- ****************************************************************************}
- constructor TDebugController.Init(const exefn:string);
- var f: string;
- begin
- inherited Init;
- f := exefn;
- LoadFile(f);
- SetArgs(GetRunParameters);
- Debugger:=@self;
- InsertBreakpoints;
- end;
- procedure TDebugController.InsertBreakpoints;
- procedure DoInsert(PB : PBreakpoint);
- begin
- PB^.Insert;
- end;
-
- begin
- BreakpointCollection^.ForEach(@DoInsert);
- end;
- procedure TDebugController.RemoveBreakpoints;
- procedure DoDelete(PB : PBreakpoint);
- begin
- PB^.Remove;
- end;
- begin
- BreakpointCollection^.ForEach(@DoDelete);
- end;
- destructor TDebugController.Done;
- begin
- { kill the program if running }
- Reset;
- RemoveBreakpoints;
- inherited Done;
- end;
- procedure TDebugController.Run;
- begin
- inherited Run;
- MyApp.SetCmdState([cmResetDebugger],true);
- end;
- procedure TDebugController.Continue;
- begin
- if not debugger_started then
- Run;
- inherited Continue;
- end;
- procedure TDebugController.Reset;
- var
- W : PSourceWindow;
- begin
- inherited Reset;
- MyApp.SetCmdState([cmResetDebugger],false);
- W:=PSourceWindow(LastSource);
- if assigned(W) then
- W^.Editor^.SetHighlightRow(-1);
- end;
- procedure TDebugController.AnnotateError;
- var errornb : longint;
- begin
- if error then
- begin
- errornb:=error_num;
- ErrorBox(#3'Error within GDB'#13#3'Error code = %d',@errornb);
- end;
- end;
- procedure TDebugController.DoSelectSourceLine(const fn:string;line:longint);
- var
- W: PSourceWindow;
- Found : boolean;
-
- begin
- Desktop^.Lock;
- if Line>0 then
- dec(Line);
- if (fn=LastFileName) then
- begin
- W:=PSourceWindow(LastSource);
- if assigned(W) then
- begin
- W^.Editor^.SetCurPtr(0,Line);
- W^.Editor^.TrackCursor(true);
- W^.Editor^.SetHighlightRow(Line);
- W^.Select;
- InvalidSourceLine:=false;
- end
- else
- InvalidSourceLine:=true;
- end
- else
- begin
- W:=TryToOpenFile(nil,fn,0,Line);
- if assigned(W) then
- begin
- W^.Editor^.SetHighlightRow(Line);
- W^.Editor^.TrackCursor(true);
- W^.Select;
- LastSource:=W;
- InvalidSourceLine:=false;
- end
- { only search a file once }
- else
- begin
- Desktop^.UnLock;
- Found:=MyApp.OpenSearch(fn);
- Desktop^.Lock;
- if not Found then
- begin
- InvalidSourceLine:=true;
- LastSource:=Nil;
- end
- else
- begin
- { should now be open }
- W:=TryToOpenFile(nil,fn,0,Line);
- W^.Editor^.SetHighlightRow(Line);
- W^.Editor^.TrackCursor(true);
- W^.Select;
- LastSource:=W;
- InvalidSourceLine:=false;
- end;
- end;
- end;
- LastFileName:=fn;
- Desktop^.UnLock;
- end;
- procedure TDebugController.DoEndSession(code:longint);
- var P :Array[1..2] of longint;
- W : PSourceWindow;
- begin
- MyApp.SetCmdState([cmResetDebugger],false);
- W:=PSourceWindow(LastSource);
- if assigned(W) then
- W^.Editor^.SetHighlightRow(-1);
- If HiddenStepsCount=0 then
- InformationBox(#3'Program exited with '#13#3'exitcode = %d',@code)
- else
- begin
- P[1]:=code;
- P[2]:=HiddenStepsCount;
- WarningBox(#3'Program exited with '#13+
- #3'exitcode = %d'#13+
- #3'hidden steps = %d',@P);
- end;
- end;
- procedure TDebugController.DoDebuggerScreen;
- begin
- MyApp.ShowIDEScreen;
- end;
- procedure TDebugController.DoUserScreen;
- begin
- MyApp.ShowUserScreen;
- end;
- {****************************************************************************
- TBreakpoint
- ****************************************************************************}
- constructor TBreakpoint.Init_function(Const AFunc : String);
- begin
- typ:=bt_function;
- state:=bs_enabled;
- GDBState:=bs_deleted;
- Name:=NewStr(AFunc);
- IgnoreCount:=0;
- Commands:=nil;
- Conditions:=nil;
- end;
- constructor TBreakpoint.Init_type(atyp : BreakpointType;Const AFunc : String);
- begin
- typ:=atyp;
- state:=bs_enabled;
- GDBState:=bs_deleted;
- Name:=NewStr(AFunc);
- IgnoreCount:=0;
- Commands:=nil;
- Conditions:=nil;
- end;
- constructor TBreakpoint.Init_file_line(AFile : String; ALine : longint);
- begin
- typ:=bt_file_line;
- state:=bs_enabled;
- GDBState:=bs_deleted;
- AFile:=NameAndExtOf(AFile);
- { d:test.pas:12 does not work !! }
- { I do not know how to solve this if
- if (Length(AFile)>1) and (AFile[2]=':') then
- AFile:=Copy(AFile,3,255);
- Only use base name for now !! PM }
- Name:=NewStr(AFile);
- Line:=ALine;
- IgnoreCount:=0;
- Commands:=nil;
- Conditions:=nil;
- end;
- procedure TBreakpoint.Insert;
- begin
- If not assigned(Debugger) then Exit;
- Remove;
- Debugger^.last_breakpoint_number:=0;
- if (GDBState=bs_deleted) and (state=bs_enabled) then
- begin
- if (typ=bt_file_line) then
- Debugger^.Command('break '+name^+':'+IntToStr(Line))
- else if typ=bt_function then
- Debugger^.Command('break '+name^)
- else if typ=bt_watch then
- Debugger^.Command('watch '+name^)
- else if typ=bt_awatch then
- Debugger^.Command('awatch '+name^)
- else if typ=bt_rwatch then
- Debugger^.Command('rwatch '+name^);
- if Debugger^.last_breakpoint_number<>0 then
- begin
- GDBIndex:=Debugger^.last_breakpoint_number;
- GDBState:=bs_enabled;
- Debugger^.Command('cond '+IntToStr(GDBIndex)+' '+GetStr(Conditions));
- Debugger^.Command('ignore '+IntToStr(GDBIndex)+' '+IntToStr(IgnoreCount));
- If Assigned(Commands) then
- begin
- {Commands are not handled yet }
- end;
- end
- else
- { Here there was a problem !! }
- begin
- GDBIndex:=0;
- state:=bs_disabled;
- end;
- end
- else if (GDBState=bs_disabled) and (state=bs_enabled) then
- Enable
- else if (GDBState=bs_enabled) and (state=bs_disabled) then
- Disable;
- end;
- procedure TBreakpoint.Remove;
- begin
- If not assigned(Debugger) then Exit;
- if GDBIndex>0 then
- Debugger^.Command('delete '+IntToStr(GDBIndex));
- GDBIndex:=0;
- GDBState:=bs_deleted;
- end;
- procedure TBreakpoint.Enable;
- begin
- If not assigned(Debugger) then Exit;
- if GDBIndex>0 then
- Debugger^.Command('enable '+IntToStr(GDBIndex));
- GDBState:=bs_enabled;
- end;
- procedure TBreakpoint.Disable;
- begin
- If not assigned(Debugger) then Exit;
- if GDBIndex>0 then
- Debugger^.Command('disable '+IntToStr(GDBIndex));
- GDBState:=bs_disabled;
- end;
- destructor TBreakpoint.Done;
- begin
- Remove;
- if assigned(Name) then
- DisposeStr(Name);
- if assigned(Conditions) then
- DisposeStr(Conditions);
- if assigned(Commands) then
- StrDispose(Commands);
- inherited Done;
- end;
- {****************************************************************************
- TBreakpointCollection
- ****************************************************************************}
- function TBreakpointCollection.At(Index: Integer): PBreakpoint;
- begin
- At:=inherited At(Index);
- end;
- procedure TBreakpointCollection.FreeItem(Item: Pointer);
- begin
- if Item<>nil then
- Dispose(PBreakpoint(Item),Done);
- end;
- procedure TBreakpointCollection.Update;
- begin
- if assigned(Debugger) then
- begin
- Debugger^.RemoveBreakpoints;
- Debugger^.InsertBreakpoints;
- end;
- end;
- function TBreakpointCollection.ToggleFileLine(Const FileName: String;LineNr : Longint) : boolean;
- var PB : PBreakpoint;
- function IsThere(P : PBreakpoint) : boolean;
- begin
- IsThere:=(P^.typ=bt_file_line) and (P^.Name^=FileName) and (P^.Line=LineNr);
- end;
- begin
- PB:=FirstThat(@IsThere);
- ToggleFileLine:=false;
- If Assigned(PB) then
- if PB^.state=bs_disabled then
- begin
- PB^.state:=bs_enabled;
- ToggleFileLine:=true;
- end
- else if PB^.state=bs_enabled then
- PB^.state:=bs_disabled;
- If not assigned(PB) then
- begin
- PB:= New(PBreakpoint,Init_file_line(FileName,LineNr));
- if assigned(PB) then
- Begin
- Insert(PB);
- ToggleFileLine:=true;
- End;
- end;
- Update;
- end;
- {****************************************************************************
- Initialize
- ****************************************************************************}
- procedure InitDebugger;
- begin
- Assign(gdb_file,'gdb$$$.out');
- Rewrite(gdb_file);
- Use_gdb_file:=true;
- if (not ExistsFile(ExeFile)) or (CompilationPhase<>cpDone) then
- DoCompile(cRun);
- if CompilationPhase<>cpDone then
- Exit;
- if (EXEFile='') then
- begin
- ErrorBox('Oooops, nothing to debug.',nil);
- Exit;
- end;
- { init debugcontroller }
- if assigned(Debugger) then
- dispose(Debugger,Done);
- new(Debugger,Init(ExeFile));
- end;
- procedure DoneDebugger;
- begin
- if assigned(Debugger) then
- dispose(Debugger,Done);
- Debugger:=nil;
- If Use_gdb_file then
- Close(GDB_file);
- Use_gdb_file:=false;
- end;
- begin
- New(BreakpointCollection,init(10,10));
- end.
- {
- $Log$
- Revision 1.9 1999-02-08 17:43:43 pierre
- * RestDebugger or multiple running of debugged program now works
- + added DoContToCursor(F4)
- * Breakpoints are now inserted correctly (was mainlyy a problem
- of directories)
- Revision 1.8 1999/02/05 17:21:52 pierre
- Invalid_line renamed InvalidSourceLine
- Revision 1.7 1999/02/05 13:08:41 pierre
- + new breakpoint types added
- Revision 1.6 1999/02/05 12:11:53 pierre
- + SourceDir that stores directories for sources that the
- compiler should not know about
- Automatically asked for addition when a new file that
- needed filedialog to be found is in an unknown directory
- Stored and retrieved from INIFile
- + Breakpoints conditions added to INIFile
- * Breakpoints insterted and removed at debin and end of debug session
- Revision 1.5 1999/02/04 17:54:22 pierre
- + several commands added
- Revision 1.4 1999/02/04 13:32:02 pierre
- * Several things added (I cannot commit them independently !)
- + added TBreakpoint and TBreakpointCollection
- + added cmResetDebugger,cmGrep,CmToggleBreakpoint
- + Breakpoint list in INIFile
- * Select items now also depend of SwitchMode
- * Reading of option '-g' was not possible !
- + added search for -Fu args pathes in TryToOpen
- + added code for automatic opening of FileDialog
- if source not found
- Revision 1.3 1999/02/02 16:41:38 peter
- + automatic .pas/.pp adding by opening of file
- * better debuggerscreen changes
- Revision 1.2 1999/01/22 18:14:09 pierre
- * adaptd to changes in gdbint and gdbcon for to /
- Revision 1.1 1999/01/22 10:24:03 peter
- * first debugger things
- }
|