fpdebug.pas 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998-2000 by Pierre Muller
  5. Debugger call routines for the IDE
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit FPDebug;
  13. interface
  14. {$i globdir.inc}
  15. uses
  16. {$ifdef win32}
  17. Windows,
  18. {$endif win32}
  19. Objects,Dialogs,Drivers,Views,
  20. GDBCon,GDBInt,Menus,
  21. WViews,WEditor,
  22. FPViews;
  23. type
  24. PDebugController=^TDebugController;
  25. TDebugController=object(TGDBController)
  26. InvalidSourceLine : boolean;
  27. { if true the current debugger raw will stay in middle of
  28. editor window when debugging PM }
  29. CenterDebuggerRow : boolean;
  30. Disableallinvalidbreakpoints : boolean;
  31. LastFileName : string;
  32. LastSource : PView; {PsourceWindow !! }
  33. HiddenStepsCount : longint;
  34. { no need to switch if using another terminal }
  35. NoSwitch : boolean;
  36. HasExe : boolean;
  37. RunCount : longint;
  38. WindowWidth : longint;
  39. FPCBreakErrorNumber : longint;
  40. constructor Init;
  41. procedure SetExe(const exefn:string);
  42. procedure SetWidth(AWidth : longint);
  43. procedure SetDirectories;
  44. destructor Done;
  45. procedure DoSelectSourceline(const fn:string;line:longint);virtual;
  46. { procedure DoStartSession;virtual;
  47. procedure DoBreakSession;virtual;}
  48. procedure DoEndSession(code:longint);virtual;
  49. procedure DoUserSignal;virtual;
  50. procedure AnnotateError;
  51. procedure InsertBreakpoints;
  52. procedure RemoveBreakpoints;
  53. procedure ReadWatches;
  54. procedure RereadWatches;
  55. procedure ResetBreakpointsValues;
  56. procedure DoDebuggerScreen;virtual;
  57. procedure DoUserScreen;virtual;
  58. procedure Reset;virtual;
  59. procedure ResetDebuggerRows;
  60. procedure Run;virtual;
  61. procedure Continue;virtual;
  62. procedure UntilReturn;virtual;
  63. procedure CommandBegin(const s:string);virtual;
  64. procedure CommandEnd(const s:string);virtual;
  65. function IsRunning : boolean;
  66. function AllowQuit : boolean;virtual;
  67. function GetValue(Const expr : string) : pchar;
  68. function GetFramePointer : CORE_ADDR;
  69. function GetLongintAt(addr : CORE_ADDR) : longint;
  70. function GetPointerAt(addr : CORE_ADDR) : CORE_ADDR;
  71. end;
  72. BreakpointType = (bt_function,bt_file_line,bt_watch,
  73. bt_awatch,bt_rwatch,bt_address,bt_invalid);
  74. BreakpointState = (bs_enabled,bs_disabled,bs_deleted,bs_delete_after);
  75. PBreakpointCollection=^TBreakpointCollection;
  76. PBreakpoint=^TBreakpoint;
  77. TBreakpoint=object(TObject)
  78. typ : BreakpointType;
  79. state : BreakpointState;
  80. owner : PBreakpointCollection;
  81. Name : PString; { either function name or expr to watch }
  82. FileName : PString;
  83. OldValue,CurrentValue : Pstring;
  84. Line : Longint; { only used for bt_file_line type }
  85. Conditions : PString; { conditions relative to that breakpoint }
  86. IgnoreCount : Longint; { how many counts should be ignored }
  87. Commands : pchar; { commands that should be executed on breakpoint }
  88. GDBIndex : longint;
  89. GDBState : BreakpointState;
  90. constructor Init_function(Const AFunc : String);
  91. constructor Init_Address(Const AAddress : String);
  92. constructor Init_Empty;
  93. constructor Init_file_line(AFile : String; ALine : longint);
  94. constructor Init_type(atyp : BreakpointType;Const AnExpr : String);
  95. constructor Load(var S: TStream);
  96. procedure Store(var S: TStream);
  97. procedure Insert;
  98. procedure Remove;
  99. procedure Enable;
  100. procedure Disable;
  101. procedure UpdateSource;
  102. procedure ResetValues;
  103. destructor Done;virtual;
  104. end;
  105. TBreakpointCollection=object(TCollection)
  106. function At(Index: Integer): PBreakpoint;
  107. function GetGDB(index : longint) : PBreakpoint;
  108. function GetType(typ : BreakpointType;Const s : String) : PBreakpoint;
  109. function ToggleFileLine(FileName: String;LineNr : Longint) : boolean;
  110. procedure Update;
  111. procedure ShowBreakpoints(W : PFPWindow);
  112. function FindBreakpointAt(Editor : PSourceEditor; Line : longint) : PBreakpoint;
  113. procedure AdaptBreakpoints(Editor : PSourceEditor; Pos, Change : longint);
  114. procedure ShowAllBreakpoints;
  115. end;
  116. PBreakpointItem = ^TBreakpointItem;
  117. TBreakpointItem = object(TObject)
  118. Breakpoint : PBreakpoint;
  119. constructor Init(ABreakpoint : PBreakpoint);
  120. function GetText(MaxLen: Sw_integer): string; virtual;
  121. procedure Selected; virtual;
  122. function GetModuleName: string; virtual;
  123. end;
  124. PBreakpointsListBox = ^TBreakpointsListBox;
  125. TBreakpointsListBox = object(THSListBox)
  126. Transparent : boolean;
  127. NoSelection : boolean;
  128. MaxWidth : Sw_integer;
  129. (* ModuleNames : PStoreCollection; *)
  130. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  131. procedure AddBreakpoint(P: PBreakpointItem); virtual;
  132. function GetText(Item,MaxLen: Sw_Integer): String; virtual;
  133. function GetLocalMenu: PMenu;virtual;
  134. procedure Clear; virtual;
  135. procedure TrackSource; virtual;
  136. procedure EditNew; virtual;
  137. procedure EditCurrent; virtual;
  138. procedure DeleteCurrent; virtual;
  139. procedure ToggleCurrent;
  140. procedure Draw; virtual;
  141. procedure HandleEvent(var Event: TEvent); virtual;
  142. constructor Load(var S: TStream);
  143. procedure Store(var S: TStream);
  144. destructor Done; virtual;
  145. end;
  146. PBreakpointsWindow = ^TBreakpointsWindow;
  147. TBreakpointsWindow = object(TFPDlgWindow)
  148. BreakLB : PBreakpointsListBox;
  149. constructor Init;
  150. procedure AddBreakpoint(ABreakpoint : PBreakpoint);
  151. procedure ClearBreakpoints;
  152. procedure ReloadBreakpoints;
  153. procedure Close; virtual;
  154. procedure SizeLimits(var Min, Max: TPoint);virtual;
  155. procedure HandleEvent(var Event: TEvent); virtual;
  156. procedure Update; virtual;
  157. constructor Load(var S: TStream);
  158. procedure Store(var S: TStream);
  159. destructor Done; virtual;
  160. end;
  161. PBreakpointItemDialog = ^TBreakpointItemDialog;
  162. TBreakpointItemDialog = object(TCenterDialog)
  163. constructor Init(ABreakpoint: PBreakpoint);
  164. function Execute: Word; virtual;
  165. private
  166. Breakpoint : PBreakpoint;
  167. TypeRB : PRadioButtons;
  168. NameIL : PEditorInputLine;
  169. ConditionsIL: PEditorInputLine;
  170. LineIL : PEditorInputLine;
  171. IgnoreIL : PEditorInputLine;
  172. end;
  173. PWatch = ^TWatch;
  174. TWatch = Object(TObject)
  175. constructor Init(s : string);
  176. constructor Load(var S: TStream);
  177. procedure Store(var S: TStream);
  178. procedure rename(s : string);
  179. procedure Get_new_value;
  180. procedure Force_new_value;
  181. destructor done;virtual;
  182. expr : pstring;
  183. private
  184. GDBRunCount : longint;
  185. last_value,current_value : pchar;
  186. end;
  187. PWatchesCollection = ^TWatchesCollection;
  188. TWatchesCollection = Object(TCollection)
  189. constructor Init;
  190. procedure Insert(Item: Pointer); virtual;
  191. function At(Index: Integer): PWatch;
  192. procedure Update;
  193. private
  194. MaxW : integer;
  195. end;
  196. PWatchesListBox = ^TWatchesListBox;
  197. TWatchesListBox = object(THSListBox)
  198. Transparent : boolean;
  199. MaxWidth : Sw_integer;
  200. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  201. (* procedure AddWatch(P: PWatch); virtual; *)
  202. procedure Update(AMaxWidth : integer);
  203. function GetText (Item: Sw_Integer; MaxLen: Sw_Integer): String; Virtual;
  204. function GetIndentedText(Item,Indent,MaxLen: Sw_Integer;var Modified : boolean): String; virtual;
  205. function GetLocalMenu: PMenu;virtual;
  206. (* procedure Clear; virtual;
  207. procedure TrackSource; virtual;*)
  208. procedure EditNew; virtual;
  209. procedure EditCurrent; virtual;
  210. procedure DeleteCurrent; virtual;
  211. (*procedure ToggleCurrent; *)
  212. procedure Draw; virtual;
  213. procedure HandleEvent(var Event: TEvent); virtual;
  214. constructor Load(var S: TStream);
  215. procedure Store(var S: TStream);
  216. destructor Done; virtual;
  217. end;
  218. PWatchItemDialog = ^TWatchItemDialog;
  219. TWatchItemDialog = object(TCenterDialog)
  220. constructor Init(AWatch: PWatch);
  221. function Execute: Word; virtual;
  222. private
  223. Watch : PWatch;
  224. NameIL : PEditorInputLine;
  225. TextST : PAdvancedStaticText;
  226. end;
  227. PWatchesWindow = ^TWatchesWindow;
  228. TWatchesWindow = Object(TFPDlgWindow)
  229. WLB : PWatchesListBox;
  230. Constructor Init;
  231. constructor Load(var S: TStream);
  232. procedure Store(var S: TStream);
  233. procedure Update; virtual;
  234. destructor Done; virtual;
  235. end;
  236. PFramesListBox = ^TFramesListBox;
  237. TFramesListBox = object(TMessageListBox)
  238. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  239. procedure Update;
  240. function GetLocalMenu: PMenu;virtual;
  241. procedure GotoSource; virtual;
  242. procedure GotoAssembly; virtual;
  243. procedure HandleEvent(var Event: TEvent); virtual;
  244. destructor Done; virtual;
  245. end;
  246. PStackWindow = ^TStackWindow;
  247. TStackWindow = Object(TFPDlgWindow)
  248. FLB : PFramesListBox;
  249. Constructor Init;
  250. constructor Load(var S: TStream);
  251. procedure Store(var S: TStream);
  252. procedure Update; virtual;
  253. destructor Done; virtual;
  254. end;
  255. procedure InitStackWindow;
  256. procedure DoneStackWindow;
  257. function ActiveBreakpoints : boolean;
  258. function GDBFileName(st : string) : string;
  259. function OSFileName(st : string) : string;
  260. const
  261. BreakpointTypeStr : Array[BreakpointType] of String[9]
  262. = ( 'function','file-line','watch','awatch','rwatch','address','invalid');
  263. BreakpointStateStr : Array[BreakpointState] of String[8]
  264. = ( 'enabled','disabled','invalid',''{'to be deleted' should never be used});
  265. var
  266. Debugger : PDebugController;
  267. BreakpointsCollection : PBreakpointCollection;
  268. WatchesCollection : PwatchesCollection;
  269. procedure InitDebugger;
  270. procedure DoneDebugger;
  271. procedure InitGDBWindow;
  272. procedure DoneGDBWindow;
  273. procedure InitDisassemblyWindow;
  274. procedure DoneDisassemblyWindow;
  275. procedure InitBreakpoints;
  276. procedure DoneBreakpoints;
  277. procedure InitWatches;
  278. procedure DoneWatches;
  279. procedure RegisterFPDebugViews;
  280. procedure UpdateDebugViews;
  281. implementation
  282. uses
  283. Dos,
  284. {$ifdef fpc}
  285. Video,
  286. {$endif fpc}
  287. {$ifdef DOS}
  288. fpusrscr,
  289. {$endif DOS}
  290. App,Strings,
  291. {$ifdef FVISION}
  292. FVConsts,
  293. {$else}
  294. Commands,HelpCtx,
  295. {$endif}
  296. {$ifdef win32}
  297. Windebug,
  298. {$endif win32}
  299. {$ifdef Unix}
  300. {$ifdef VER1_0}
  301. Linux,
  302. {$else}
  303. Unix,
  304. {$endif}
  305. {$endif Unix}
  306. Systems,Globals,
  307. FPRegs,
  308. FPString,FPVars,FPUtils,FPConst,FPSwitch,
  309. FPIntf,FPCompil,FPIde,FPHelp,
  310. Validate,WUtils,Wconsts;
  311. const
  312. RBreakpointsWindow: TStreamRec = (
  313. ObjType: 1701;
  314. VmtLink: Ofs(TypeOf(TBreakpointsWindow)^);
  315. Load: @TBreakpointsWindow.Load;
  316. Store: @TBreakpointsWindow.Store
  317. );
  318. RBreakpointsListBox : TStreamRec = (
  319. ObjType: 1702;
  320. VmtLink: Ofs(TypeOf(TBreakpointsListBox)^);
  321. Load: @TBreakpointsListBox.Load;
  322. Store: @TBreakpointsListBox.Store
  323. );
  324. RWatchesWindow: TStreamRec = (
  325. ObjType: 1703;
  326. VmtLink: Ofs(TypeOf(TWatchesWindow)^);
  327. Load: @TWatchesWindow.Load;
  328. Store: @TWatchesWindow.Store
  329. );
  330. RWatchesListBox: TStreamRec = (
  331. ObjType: 1704;
  332. VmtLink: Ofs(TypeOf(TWatchesListBox)^);
  333. Load: @TWatchesListBox.Load;
  334. Store: @TWatchesListBox.Store
  335. );
  336. RStackWindow: TStreamRec = (
  337. ObjType: 1705;
  338. VmtLink: Ofs(TypeOf(TStackWindow)^);
  339. Load: @TStackWindow.Load;
  340. Store: @TStackWindow.Store
  341. );
  342. RFramesListBox: TStreamRec = (
  343. ObjType: 1706;
  344. VmtLink: Ofs(TypeOf(TFramesListBox)^);
  345. Load: @TFramesListBox.Load;
  346. Store: @TFramesListBox.Store
  347. );
  348. RBreakpoint: TStreamRec = (
  349. ObjType: 1707;
  350. VmtLink: Ofs(TypeOf(TBreakpoint)^);
  351. Load: @TBreakpoint.Load;
  352. Store: @TBreakpoint.Store
  353. );
  354. RWatch: TStreamRec = (
  355. ObjType: 1708;
  356. VmtLink: Ofs(TypeOf(TWatch)^);
  357. Load: @TWatch.Load;
  358. Store: @TWatch.Store
  359. );
  360. RBreakpointCollection: TStreamRec = (
  361. ObjType: 1709;
  362. VmtLink: Ofs(TypeOf(TBreakpointCollection)^);
  363. Load: @TBreakpointCollection.Load;
  364. Store: @TBreakpointCollection.Store
  365. );
  366. RWatchesCollection: TStreamRec = (
  367. ObjType: 1710;
  368. VmtLink: Ofs(TypeOf(TWatchesCollection)^);
  369. Load: @TWatchesCollection.Load;
  370. Store: @TWatchesCollection.Store
  371. );
  372. {$ifdef I386}
  373. const
  374. FrameName = '$ebp';
  375. {$define FrameNameKnown}
  376. {$endif i386}
  377. {$ifdef m68k}
  378. const
  379. FrameName = '$fp';
  380. {$define FrameNameKnown}
  381. {$endif m68k}
  382. {$ifdef powerpc}
  383. { stack and frame registers are the same on powerpc,
  384. so I am not sure that this will work PM }
  385. const
  386. FrameName = '$r1';
  387. {$define FrameNameKnown}
  388. {$endif powerpc}
  389. {$ifdef TP}
  390. function HexStr(Value: longint; Len: byte): string;
  391. begin
  392. HexStr:=IntToHex(Value,Len);
  393. end;
  394. {$endif}
  395. function GDBFileName(st : string) : string;
  396. {$ifndef Unix}
  397. var i : longint;
  398. {$endif Unix}
  399. begin
  400. {$ifdef Unix}
  401. GDBFileName:=st;
  402. {$else}
  403. { should we also use / chars ? }
  404. for i:=1 to Length(st) do
  405. if st[i]='\' then
  406. {$ifdef win32}
  407. { Don't touch at '\ ' used to escapes spaces in windows file names PM }
  408. if (i=length(st)) or (st[i+1]<>' ') then
  409. {$endif win32}
  410. st[i]:='/';
  411. {$ifdef win32}
  412. { for win32 we should convert e:\ into //e/ PM }
  413. if (length(st)>2) and (st[2]=':') and (st[3]='/') then
  414. st:=CygDrivePrefix+'/'+st[1]+copy(st,3,length(st));
  415. { support spaces in the name by escaping them but without changing '\ ' into '\\ ' }
  416. for i:=Length(st) downto 1 do
  417. if (st[i]=' ') and ((i=1) or (st[i-1]<>'\')) then
  418. st:=copy(st,1,i-1)+'\'+copy(st,i,length(st));
  419. {$endif win32}
  420. {$ifdef go32v2}
  421. { for go32v2 we should convert //e/ back into e:/ PM }
  422. if (length(st)>3) and (st[1]='/') and (st[2]='/') and (st[4]='/') then
  423. st:=st[3]+':/'+copy(st,5,length(st));
  424. {$endif go32v2}
  425. GDBFileName:=LowerCaseStr(st);
  426. {$endif}
  427. end;
  428. function OSFileName(st : string) : string;
  429. {$ifndef Unix}
  430. var i : longint;
  431. {$endif Unix}
  432. begin
  433. {$ifdef Unix}
  434. OSFileName:=st;
  435. {$else}
  436. {$ifdef win32}
  437. { for win32 we should convert /cygdrive/e/ into e:\ PM }
  438. if pos(CygDrivePrefix+'/',st)=1 then
  439. st:=st[Length(CygdrivePrefix)+2]+':\'+copy(st,length(CygdrivePrefix)+4,length(st));
  440. {$endif win32}
  441. { support spaces in the name by escaping them but without changing '\ ' into '\\ ' }
  442. for i:=Length(st) downto 2 do
  443. if (st[i]=' ') and (st[i-1]='\') then
  444. st:=copy(st,1,i-2)+copy(st,i,length(st));
  445. {$ifdef go32v2}
  446. { for go32v2 we should convert //e/ back into e:/ PM }
  447. if (length(st)>3) and (st[1]='/') and (st[2]='/') and (st[4]='/') then
  448. st:=st[3]+':\'+copy(st,5,length(st));
  449. {$endif go32v2}
  450. { should we also use / chars ? }
  451. for i:=1 to Length(st) do
  452. if st[i]='/' then
  453. st[i]:='\';
  454. OSFileName:=LowerCaseStr(st);
  455. {$endif}
  456. end;
  457. {****************************************************************************
  458. TDebugController
  459. ****************************************************************************}
  460. procedure UpdateDebugViews;
  461. begin
  462. {$ifdef SUPPORT_REMOTE}
  463. PushStatus(msg_getting_info_on+RemoteMachine);
  464. {$endif SUPPORT_REMOTE}
  465. DeskTop^.Lock;
  466. If assigned(StackWindow) then
  467. StackWindow^.Update;
  468. If assigned(RegistersWindow) then
  469. RegistersWindow^.Update;
  470. If assigned(Debugger) then
  471. Debugger^.ReadWatches;
  472. If assigned(FPUWindow) then
  473. FPUWindow^.Update;
  474. DeskTop^.UnLock;
  475. {$ifdef SUPPORT_REMOTE}
  476. PopStatus;
  477. {$endif SUPPORT_REMOTE}
  478. end;
  479. constructor TDebugController.Init;
  480. begin
  481. inherited Init;
  482. CenterDebuggerRow:=IniCenterDebuggerRow;
  483. Disableallinvalidbreakpoints:=false;
  484. NoSwitch:=False;
  485. HasExe:=false;
  486. Debugger:=@self;
  487. WindowWidth:=-1;
  488. {$ifndef GABOR}
  489. switch_to_user:=true;
  490. {$endif}
  491. Command('set print object off');
  492. end;
  493. procedure TDebugController.SetExe(const exefn:string);
  494. var f : string;
  495. begin
  496. f := GDBFileName(GetShortName(exefn));
  497. if (f<>'') and ExistsFile(exefn) then
  498. begin
  499. LoadFile(f);
  500. HasExe:=true;
  501. Command('b FPC_BREAK_ERROR');
  502. FPCBreakErrorNumber:=last_breakpoint_number;
  503. {$ifdef FrameNameKnown}
  504. { this fails in GDB 5.1 because
  505. GDB replies that there is an attempt to dereference
  506. a generic pointer...
  507. test delayed in DoSourceLine... PM
  508. Command('cond '+IntToStr(FPCBreakErrorNumber)+
  509. ' (('+FrameName+' + 8)^ <> 0) or'+
  510. ' (('+FrameName+' + 12)^ <> 0)'); }
  511. {$endif FrameNameKnown}
  512. SetArgs(GetRunParameters);
  513. SetDirectories;
  514. InsertBreakpoints;
  515. ReadWatches;
  516. end
  517. else
  518. begin
  519. HasExe:=false;
  520. Command('file');
  521. end;
  522. end;
  523. procedure TDebugController.SetWidth(AWidth : longint);
  524. begin
  525. WindowWidth:=AWidth;
  526. Command('set width '+inttostr(WindowWidth));
  527. end;
  528. procedure TDebugController.SetDirectories;
  529. var f,s: string;
  530. i : longint;
  531. Dir : SearchRec;
  532. begin
  533. f:=GetSourceDirectories;
  534. repeat
  535. i:=pos(';',f);
  536. if i=0 then
  537. s:=f
  538. else
  539. begin
  540. s:=copy(f,1,i-1);
  541. system.delete(f,1,i);
  542. end;
  543. DefaultReplacements(s);
  544. if (pos('*',s)=0) and ExistsDir(s) then
  545. Command('dir '+GDBFileName(GetShortName(s)))
  546. { we should also handle the /* cases of -Fu option }
  547. else if pos('*',s)>0 then
  548. begin
  549. Dos.FindFirst(s,Directory,Dir);
  550. { the '*' can only be in the last dir level }
  551. s:=DirOf(s);
  552. while Dos.DosError=0 do
  553. begin
  554. if ((Dir.attr and Directory) <> 0) and ExistsDir(s+Dir.Name) then
  555. Command('dir '+GDBFileName(GetShortName(s+Dir.Name)));
  556. Dos.FindNext(Dir);
  557. end;
  558. {$ifdef FPC}
  559. Dos.FindClose(Dir);
  560. {$endif def FPC}
  561. end;
  562. until i=0;
  563. end;
  564. procedure TDebugController.InsertBreakpoints;
  565. procedure DoInsert(PB : PBreakpoint);
  566. begin
  567. PB^.Insert;
  568. end;
  569. begin
  570. BreakpointsCollection^.ForEach(@DoInsert);
  571. Disableallinvalidbreakpoints:=false;
  572. end;
  573. procedure TDebugController.ReadWatches;
  574. procedure DoRead(PB : PWatch);
  575. begin
  576. PB^.Get_new_value;
  577. end;
  578. begin
  579. WatchesCollection^.ForEach(@DoRead);
  580. If Assigned(WatchesWindow) then
  581. WatchesWindow^.Update;
  582. end;
  583. procedure TDebugController.RereadWatches;
  584. procedure DoRead(PB : PWatch);
  585. begin
  586. PB^.Force_new_value;
  587. end;
  588. begin
  589. WatchesCollection^.ForEach(@DoRead);
  590. If Assigned(WatchesWindow) then
  591. WatchesWindow^.Update;
  592. end;
  593. procedure TDebugController.RemoveBreakpoints;
  594. procedure DoDelete(PB : PBreakpoint);
  595. begin
  596. PB^.Remove;
  597. end;
  598. begin
  599. BreakpointsCollection^.ForEach(@DoDelete);
  600. end;
  601. procedure TDebugController.ResetBreakpointsValues;
  602. procedure DoResetVal(PB : PBreakpoint);
  603. begin
  604. PB^.ResetValues;
  605. end;
  606. begin
  607. BreakpointsCollection^.ForEach(@DoResetVal);
  608. end;
  609. function ActiveBreakpoints : boolean;
  610. var
  611. IsActive : boolean;
  612. procedure TestActive(PB : PBreakpoint);
  613. begin
  614. If PB^.state=bs_enabled then
  615. IsActive:=true;
  616. end;
  617. begin
  618. IsActive:=false;
  619. If assigned(BreakpointsCollection) then
  620. BreakpointsCollection^.ForEach(@TestActive);
  621. ActiveBreakpoints:=IsActive;
  622. end;
  623. destructor TDebugController.Done;
  624. begin
  625. { kill the program if running }
  626. Reset;
  627. RemoveBreakpoints;
  628. inherited Done;
  629. end;
  630. procedure TDebugController.Run;
  631. {$ifdef Unix}
  632. var
  633. Debuggeefile : text;
  634. ResetOK, TTYUsed : boolean;
  635. {$endif Unix}
  636. {$ifdef SUPPORT_REMOTE}
  637. var
  638. S,ErrorStr : string;
  639. {$endif SUPPORT_REMOTE}
  640. begin
  641. ResetBreakpointsValues;
  642. {$ifdef SUPPORT_REMOTE}
  643. NoSwitch:=true;
  644. {$ifndef CROSSGDB}
  645. If (RemoteMachine<>'') and (RemotePort<>'') then
  646. {$else CROSSGDB}
  647. if true then
  648. {$endif CROSSGDB}
  649. begin
  650. S:=RemoteMachine;
  651. If pos('@',S)>0 then
  652. S:=copy(S,pos('@',S)+1,High(S));
  653. Command('target remote '+S+':'+RemotePort);
  654. if Error then
  655. begin
  656. ErrorStr:=strpas(GetError);
  657. ErrorBox(#3'Error in "target remote"'#13#3+ErrorStr,nil);
  658. exit;
  659. end;
  660. end
  661. else
  662. begin
  663. {$endif SUPPORT_REMOTE}
  664. {$ifdef win32}
  665. { Run the debugge in another console }
  666. if DebuggeeTTY<>'' then
  667. Command('set new-console on')
  668. else
  669. Command('set new-console off');
  670. NoSwitch:=DebuggeeTTY<>'';
  671. {$endif win32}
  672. {$ifdef Unix}
  673. { Run the debuggee in another tty }
  674. if DebuggeeTTY <> '' then
  675. begin
  676. {$I-}
  677. Assign(Debuggeefile,DebuggeeTTY);
  678. system.Reset(Debuggeefile);
  679. ResetOK:=IOResult=0;
  680. If ResetOK and IsATTY(textrec(Debuggeefile).handle) then
  681. begin
  682. Command('tty '+DebuggeeTTY);
  683. TTYUsed:=true;
  684. end
  685. else
  686. begin
  687. Command('tty ');
  688. TTYUsed:=false;
  689. end;
  690. if ResetOK then
  691. close(Debuggeefile);
  692. if TTYUsed and (DebuggeeTTY<>TTYName(stdout)) then
  693. NoSwitch:= true
  694. else
  695. NoSwitch:=false;
  696. end
  697. else
  698. begin
  699. if TTYName(input)<>'' then
  700. Command('tty '+TTYName(input));
  701. NoSwitch := false;
  702. end;
  703. {$endif Unix}
  704. {$ifdef SUPPORT_REMOTE}
  705. end;
  706. {$endif SUPPORT_REMOTE}
  707. { Switch to user screen to get correct handles }
  708. UserScreen;
  709. { Don't try to print GDB messages while in User Screen mode }
  710. If assigned(GDBWindow) then
  711. GDBWindow^.Editor^.Lock;
  712. {$ifndef SUPPORT_REMOTE}
  713. inherited Run;
  714. {$else SUPPORT_REMOTE}
  715. inc(init_count);
  716. { pass the stop in start code }
  717. Command('continue');
  718. {$endif SUPPORT_REMOTE}
  719. DebuggerScreen;
  720. If assigned(GDBWindow) then
  721. GDBWindow^.Editor^.UnLock;
  722. IDEApp.SetCmdState([cmResetDebugger,cmUntilReturn],true);
  723. IDEApp.UpdateRunMenu(true);
  724. UpdateDebugViews;
  725. end;
  726. function TDebugController.IsRunning : boolean;
  727. begin
  728. IsRunning:=debuggee_started;
  729. end;
  730. procedure TDebugController.Continue;
  731. begin
  732. {$ifdef NODEBUG}
  733. NoDebugger;
  734. {$else}
  735. if not debuggee_started then
  736. Run
  737. else
  738. inherited Continue;
  739. UpdateDebugViews;
  740. {$endif NODEBUG}
  741. end;
  742. procedure TDebugController.UntilReturn;
  743. begin
  744. Command('finish');
  745. UpdateDebugViews;
  746. { We could try to get the return value !
  747. Not done yet }
  748. end;
  749. procedure TDebugController.CommandBegin(const s:string);
  750. begin
  751. if assigned(GDBWindow) and (in_command>1) then
  752. begin
  753. { We should do something special for errors !! }
  754. If StrLen(GetError)>0 then
  755. GDBWindow^.WriteErrorText(GetError);
  756. GDBWindow^.WriteOutputText(GetOutput);
  757. end;
  758. if assigned(GDBWindow) then
  759. GDBWindow^.WriteString(S);
  760. end;
  761. procedure TDebugController.CommandEnd(const s:string);
  762. begin
  763. if assigned(GDBWindow) and (in_command<=1) then
  764. begin
  765. { We should do something special for errors !! }
  766. If StrLen(GetError)>0 then
  767. GDBWindow^.WriteErrorText(GetError);
  768. GDBWindow^.WriteOutputText(GetOutput);
  769. GDBWindow^.Editor^.TextEnd;
  770. end;
  771. end;
  772. function TDebugController.AllowQuit : boolean;
  773. begin
  774. if IsRunning then
  775. begin
  776. if ConfirmBox('Really quit GDB window'#13+
  777. 'and kill running program?',nil,true)=cmYes then
  778. begin
  779. Reset;
  780. DoneGDBWindow;
  781. {AllowQuit:=true;}
  782. AllowQuit:=false;
  783. end
  784. else
  785. AllowQuit:=false;
  786. end
  787. else if ConfirmBox('Really quit GDB window?',nil,true)=cmYes then
  788. begin
  789. DoneGDBWindow;
  790. {AllowQuit:=true;}
  791. AllowQuit:=false;
  792. end
  793. else
  794. AllowQuit:=false;
  795. end;
  796. procedure TDebugController.ResetDebuggerRows;
  797. procedure ResetDebuggerRow(P: PView); {$ifndef FPC}far;{$endif}
  798. begin
  799. if assigned(P) and
  800. (TypeOf(P^)=TypeOf(TSourceWindow)) then
  801. PSourceWindow(P)^.Editor^.SetLineFlagExclusive(lfDebuggerRow,-1);
  802. end;
  803. begin
  804. Desktop^.ForEach(@ResetDebuggerRow);
  805. end;
  806. procedure TDebugController.Reset;
  807. begin
  808. inherited Reset;
  809. { we need to free the executable
  810. if we want to recompile it }
  811. SetExe('');
  812. NoSwitch:=false;
  813. { In case we have something that the compiler touched }
  814. If IDEApp.IsRunning then
  815. begin
  816. IDEApp.SetCmdState([cmResetDebugger,cmUntilReturn],false);
  817. IDEApp.UpdateRunMenu(false);
  818. AskToReloadAllModifiedFiles;
  819. ResetDebuggerRows;
  820. end;
  821. end;
  822. procedure TDebugController.AnnotateError;
  823. var errornb : longint;
  824. begin
  825. if error then
  826. begin
  827. errornb:=error_num;
  828. UpdateDebugViews;
  829. ErrorBox(#3'Error within GDB'#13#3'Error code = %d',@errornb);
  830. end;
  831. end;
  832. function TDebugController.GetValue(Const expr : string) : pchar;
  833. var
  834. p,p2,p3 : pchar;
  835. begin
  836. if WindowWidth<>-1 then
  837. Command('set width 0xffffffff');
  838. Command('p '+expr);
  839. p:=GetOutput;
  840. p3:=nil;
  841. if assigned(p) and (p[strlen(p)-1]=#10) then
  842. begin
  843. p3:=p+strlen(p)-1;
  844. p3^:=#0;
  845. end;
  846. if assigned(p) then
  847. p2:=strpos(p,'=')
  848. else
  849. p2:=nil;
  850. if assigned(p2) then
  851. p:=p2+1;
  852. while p^ in [' ',TAB] do
  853. inc(p);
  854. { get rid of type }
  855. if p^ = '(' then
  856. p:=strpos(p,')')+1;
  857. while p^ in [' ',TAB] do
  858. inc(p);
  859. if assigned(p) then
  860. GetValue:=StrNew(p)
  861. else
  862. GetValue:=StrNew(GetError);
  863. if assigned(p3) then
  864. p3^:=#10;
  865. got_error:=false;
  866. if WindowWidth<>-1 then
  867. Command('set width '+IntToStr(WindowWidth));
  868. end;
  869. function TDebugController.GetFramePointer : CORE_ADDR;
  870. var
  871. st : string;
  872. p : longint;
  873. begin
  874. {$ifdef FrameNameKnown}
  875. Command('p /d '+FrameName);
  876. st:=strpas(GetOutput);
  877. p:=pos('=',st);
  878. while (p<length(st)) and (st[p+1] in [' ',#9]) do
  879. inc(p);
  880. Delete(st,1,p);
  881. p:=1;
  882. while (st[p] in ['0'..'9']) do
  883. inc(p);
  884. Delete(st,p,High(st));
  885. GetFramePointer:=StrToCard(st);
  886. {$else not FrameNameKnown}
  887. GetFramePointer:=0;
  888. {$endif not FrameNameKnown}
  889. end;
  890. function TDebugController.GetLongintAt(addr : CORE_ADDR) : longint;
  891. var
  892. st : string;
  893. p : longint;
  894. begin
  895. Command('x /wd 0x'+hexstr(longint(addr),8));
  896. st:=strpas(GetOutput);
  897. p:=pos(':',st);
  898. while (p<length(st)) and (st[p+1] in [' ',#9]) do
  899. inc(p);
  900. Delete(st,1,p);
  901. p:=1;
  902. while (st[p] in ['0'..'9']) do
  903. inc(p);
  904. Delete(st,p,High(st));
  905. GetLongintAt:=StrToInt(st);
  906. end;
  907. function TDebugController.GetPointerAt(addr : CORE_ADDR) : CORE_ADDR;
  908. var
  909. val : CORE_ADDR;
  910. st : string;
  911. p : longint;
  912. begin
  913. Command('x /wx 0x'+hexstr(longint(addr),8));
  914. st:=strpas(GetOutput);
  915. p:=pos(':',st);
  916. while (p<length(st)) and (st[p+1] in [' ',#9]) do
  917. inc(p);
  918. if (p<length(st)) and (st[p+1]='$') then
  919. inc(p);
  920. Delete(st,1,p);
  921. p:=1;
  922. while (st[p] in ['0'..'9','A'..'F','a'..'f']) do
  923. inc(p);
  924. Delete(st,p,High(st));
  925. GetPointerAt:=HexToCard(st);
  926. end;
  927. procedure TDebugController.DoSelectSourceLine(const fn:string;line:longint);
  928. var
  929. W: PSourceWindow;
  930. Found : boolean;
  931. PB : PBreakpoint;
  932. S : String;
  933. BreakIndex : longint;
  934. ebp,stop_addr : CORE_ADDR;
  935. i,ExitCode : longint;
  936. ExitAddr,ExitFrame : CORE_ADDR;
  937. const
  938. FirstArgOffset = 2 * sizeof(CORE_ADDR);
  939. SecondArgOffset = 3 * sizeof(CORE_ADDR);
  940. ThirdArgOffset = 4 * sizeof(CORE_ADDR);
  941. begin
  942. BreakIndex:=stop_breakpoint_number;
  943. Desktop^.Lock;
  944. { 0 based line count in Editor }
  945. if Line>0 then
  946. dec(Line);
  947. S:=fn;
  948. stop_addr:=current_pc;
  949. if (BreakIndex=FPCBreakErrorNumber) then
  950. begin
  951. { Procedure HandleErrorAddrFrame
  952. (Errno : longint;addr,frame : longint);
  953. [public,alias:'FPC_BREAK_ERROR']; }
  954. {$ifdef FrameNameKnown}
  955. ExitCode:=GetLongintAt(GetFramePointer+FirstArgOffset);
  956. ExitAddr:=GetPointerAt(GetFramePointer+SecondArgOffset);
  957. ExitFrame:=GetPointerAt(GetFramePointer+ThirdArgOffset);
  958. if (ExitCode=0) and (ExitAddr=0) then
  959. begin
  960. Desktop^.Unlock;
  961. Command('continue');
  962. exit;
  963. end;
  964. { forget all old frames }
  965. clear_frames;
  966. { record new frames }
  967. Command('backtrace');
  968. for i:=0 to frame_count-1 do
  969. begin
  970. with frames[i]^ do
  971. begin
  972. if ExitAddr=address then
  973. begin
  974. Command('f '+IntToStr(i));
  975. if assigned(file_name) then
  976. begin
  977. s:=strpas(file_name);
  978. line:=line_number;
  979. stop_addr:=address;
  980. end;
  981. break;
  982. end;
  983. end;
  984. end;
  985. {$endif FrameNameKnown}
  986. end;
  987. { Update Disassembly position }
  988. if Assigned(DisassemblyWindow) then
  989. DisassemblyWindow^.SetCurAddress(stop_addr);
  990. if (fn=LastFileName) then
  991. begin
  992. W:=PSourceWindow(LastSource);
  993. if assigned(W) then
  994. begin
  995. W^.Editor^.SetCurPtr(0,Line);
  996. W^.Editor^.TrackCursor(CenterDebuggerRow);
  997. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,Line);
  998. UpdateDebugViews;
  999. {if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  1000. handled by SelectInDebugSession}
  1001. W^.SelectInDebugSession;
  1002. InvalidSourceLine:=false;
  1003. end
  1004. else
  1005. InvalidSourceLine:=true;
  1006. end
  1007. else
  1008. begin
  1009. if s='' then
  1010. W:=nil
  1011. else
  1012. W:=TryToOpenFile(nil,s,0,Line,false);
  1013. if assigned(W) then
  1014. begin
  1015. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,Line);
  1016. W^.Editor^.TrackCursor(CenterDebuggerRow);
  1017. UpdateDebugViews;
  1018. {if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  1019. handled by SelectInDebugSession}
  1020. W^.SelectInDebugSession;
  1021. LastSource:=W;
  1022. InvalidSourceLine:=false;
  1023. end
  1024. { only search a file once }
  1025. else
  1026. begin
  1027. Desktop^.UnLock;
  1028. if s='' then
  1029. Found:=false
  1030. else
  1031. { it is easier to handle with a * at the end }
  1032. Found:=IDEApp.OpenSearch(s+'*');
  1033. Desktop^.Lock;
  1034. if not Found then
  1035. begin
  1036. InvalidSourceLine:=true;
  1037. LastSource:=Nil;
  1038. { Show the stack in that case }
  1039. InitStackWindow;
  1040. UpdateDebugViews;
  1041. StackWindow^.MakeFirst;
  1042. end
  1043. else
  1044. begin
  1045. { should now be open }
  1046. W:=TryToOpenFile(nil,s,0,Line,true);
  1047. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,Line);
  1048. W^.Editor^.TrackCursor(CenterDebuggerRow);
  1049. UpdateDebugViews;
  1050. {if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  1051. handled by SelectInDebugSession}
  1052. W^.SelectInDebugSession;
  1053. LastSource:=W;
  1054. InvalidSourceLine:=false;
  1055. end;
  1056. end;
  1057. end;
  1058. LastFileName:=s;
  1059. Desktop^.UnLock;
  1060. if BreakIndex>0 then
  1061. begin
  1062. PB:=BreakpointsCollection^.GetGDB(BreakIndex);
  1063. if (BreakIndex=FPCBreakErrorNumber) then
  1064. begin
  1065. if (ExitCode<>0) or (ExitAddr<>0) then
  1066. WarningBox(#3'Run Time Error '+IntToStr(ExitCode)+#13+
  1067. #3'Error address $'+IntToHex(ExitAddr,8),nil)
  1068. else
  1069. WarningBox(#3'Run Time Error',nil);
  1070. end
  1071. else if not assigned(PB) then
  1072. begin
  1073. WarningBox(#3'Stopped by breakpoint '+IntToStr(BreakIndex),nil);
  1074. end
  1075. { For watch we should get old and new value !! }
  1076. else if (Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive)) and
  1077. (PB^.typ<>bt_file_line) and (PB^.typ<>bt_function) and
  1078. (PB^.typ<>bt_address) then
  1079. begin
  1080. Command('p '+GetStr(PB^.Name));
  1081. S:=GetPChar(GetOutput);
  1082. got_error:=false;
  1083. If Pos('=',S)>0 then
  1084. S:=Copy(S,Pos('=',S)+1,255);
  1085. If S[Length(S)]=#10 then
  1086. Delete(S,Length(S),1);
  1087. if Assigned(PB^.OldValue) then
  1088. DisposeStr(PB^.OldValue);
  1089. PB^.OldValue:=PB^.CurrentValue;
  1090. PB^.CurrentValue:=NewStr(S);
  1091. If PB^.typ=bt_function then
  1092. WarningBox(#3'GDB stopped due to'#13+
  1093. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name),nil)
  1094. else if (GetStr(PB^.OldValue)<>S) then
  1095. WarningBox(#3'GDB stopped due to'#13+
  1096. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name)+#13+
  1097. #3+'Old value = '+GetStr(PB^.OldValue)+#13+
  1098. #3+'New value = '+GetStr(PB^.CurrentValue),nil)
  1099. else
  1100. WarningBox(#3'GDB stopped due to'#13+
  1101. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name)+#13+
  1102. #3+' value = '+GetStr(PB^.CurrentValue),nil);
  1103. end;
  1104. end;
  1105. end;
  1106. procedure TDebugController.DoUserSignal;
  1107. var P :Array[1..2] of pstring;
  1108. S1, S2 : string;
  1109. begin
  1110. S1:=strpas(signal_name);
  1111. S2:=strpas(signal_string);
  1112. P[1]:=@S1;
  1113. P[2]:=@S2;
  1114. WarningBox(msg_programsignal,@P);
  1115. end;
  1116. procedure TDebugController.DoEndSession(code:longint);
  1117. var P :Array[1..2] of longint;
  1118. begin
  1119. IDEApp.SetCmdState([cmUntilReturn,cmResetDebugger],false);
  1120. IDEApp.UpdateRunMenu(false);
  1121. ResetDebuggerRows;
  1122. LastExitCode:=Code;
  1123. If HiddenStepsCount=0 then
  1124. InformationBox(msg_programexitedwithexitcode,@code)
  1125. else
  1126. begin
  1127. P[1]:=code;
  1128. P[2]:=HiddenStepsCount;
  1129. WarningBox(msg_programexitedwithcodeandsteps,@P);
  1130. end;
  1131. { In case we have something that the compiler touched }
  1132. AskToReloadAllModifiedFiles;
  1133. {$ifdef win32}
  1134. main_pid_valid:=false;
  1135. {$endif win32}
  1136. end;
  1137. procedure TDebugController.DoDebuggerScreen;
  1138. {$ifdef win32}
  1139. var
  1140. IdeMode : DWord;
  1141. {$endif win32}
  1142. begin
  1143. if NoSwitch then
  1144. begin
  1145. PopStatus;
  1146. end
  1147. else
  1148. begin
  1149. IDEApp.ShowIDEScreen;
  1150. Message(Application,evBroadcast,cmDebuggerStopped,pointer(RunCount));
  1151. PopStatus;
  1152. end;
  1153. {$ifdef win32}
  1154. if NoSwitch then
  1155. begin
  1156. { Ctrl-C as normal char }
  1157. GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @IdeMode);
  1158. IdeMode:=(IdeMode or ENABLE_MOUSE_INPUT or ENABLE_WINDOW_INPUT) and not ENABLE_PROCESSED_INPUT;
  1159. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), IdeMode);
  1160. end;
  1161. ChangeDebuggeeWindowTitleTo(Stopped_State);
  1162. {$endif win32}
  1163. end;
  1164. procedure TDebugController.DoUserScreen;
  1165. {$ifdef win32}
  1166. var
  1167. IdeMode : DWord;
  1168. {$endif win32}
  1169. begin
  1170. Inc(RunCount);
  1171. if NoSwitch then
  1172. begin
  1173. {$ifdef SUPPORT_REMOTE}
  1174. PushStatus(msg_runningremotely+RemoteMachine);
  1175. {$else not SUPPORT_REMOTE}
  1176. {$ifdef Unix}
  1177. PushStatus(msg_runninginanotherwindow+DebuggeeTTY);
  1178. {$else not Unix}
  1179. PushStatus(msg_runninginanotherwindow);
  1180. {$endif Unix}
  1181. {$endif not SUPPORT_REMOTE}
  1182. end
  1183. else
  1184. begin
  1185. PushStatus(msg_runningprogram);
  1186. IDEApp.ShowUserScreen;
  1187. end;
  1188. {$ifdef win32}
  1189. if NoSwitch then
  1190. begin
  1191. { Ctrl-C as interrupt }
  1192. GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @IdeMode);
  1193. IdeMode:=(IdeMode or ENABLE_MOUSE_INPUT or ENABLE_PROCESSED_INPUT or ENABLE_WINDOW_INPUT);
  1194. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), IdeMode);
  1195. end;
  1196. ChangeDebuggeeWindowTitleTo(Running_State);
  1197. {$endif win32}
  1198. end;
  1199. {****************************************************************************
  1200. TBreakpoint
  1201. ****************************************************************************}
  1202. constructor TBreakpoint.Init_function(Const AFunc : String);
  1203. begin
  1204. typ:=bt_function;
  1205. state:=bs_enabled;
  1206. GDBState:=bs_deleted;
  1207. Name:=NewStr(AFunc);
  1208. FileName:=nil;
  1209. Line:=0;
  1210. IgnoreCount:=0;
  1211. Commands:=nil;
  1212. Conditions:=nil;
  1213. OldValue:=nil;
  1214. CurrentValue:=nil;
  1215. end;
  1216. constructor TBreakpoint.Init_Address(Const AAddress : String);
  1217. begin
  1218. typ:=bt_address;
  1219. state:=bs_enabled;
  1220. GDBState:=bs_deleted;
  1221. Name:=NewStr(AAddress);
  1222. FileName:=nil;
  1223. Line:=0;
  1224. IgnoreCount:=0;
  1225. Commands:=nil;
  1226. Conditions:=nil;
  1227. OldValue:=nil;
  1228. CurrentValue:=nil;
  1229. end;
  1230. constructor TBreakpoint.Init_Empty;
  1231. begin
  1232. typ:=bt_function;
  1233. state:=bs_enabled;
  1234. GDBState:=bs_deleted;
  1235. Name:=Nil;
  1236. FileName:=nil;
  1237. Line:=0;
  1238. IgnoreCount:=0;
  1239. Commands:=nil;
  1240. Conditions:=nil;
  1241. OldValue:=nil;
  1242. CurrentValue:=nil;
  1243. end;
  1244. constructor TBreakpoint.Init_type(atyp : BreakpointType;Const AnExpr : String);
  1245. begin
  1246. typ:=atyp;
  1247. state:=bs_enabled;
  1248. GDBState:=bs_deleted;
  1249. Name:=NewStr(AnExpr);
  1250. IgnoreCount:=0;
  1251. Commands:=nil;
  1252. Conditions:=nil;
  1253. OldValue:=nil;
  1254. CurrentValue:=nil;
  1255. end;
  1256. constructor TBreakpoint.Init_file_line(AFile : String; ALine : longint);
  1257. var
  1258. CurDir : String;
  1259. begin
  1260. typ:=bt_file_line;
  1261. state:=bs_enabled;
  1262. GDBState:=bs_deleted;
  1263. { d:test.pas:12 does not work !! }
  1264. { I do not know how to solve this if
  1265. if (Length(AFile)>1) and (AFile[2]=':') then
  1266. AFile:=Copy(AFile,3,255); }
  1267. {$ifdef Unix}
  1268. CurDir:=GetCurDir;
  1269. {$else}
  1270. CurDir:=LowerCaseStr(GetCurDir);
  1271. {$endif Unix}
  1272. if Pos(CurDir,OSFileName(FEXpand(AFile)))=1 then
  1273. FileName:=NewStr(Copy(OSFileName(FExpand(AFile)),length(CurDir)+1,255))
  1274. else
  1275. FileName:=NewStr(OSFileName(FExpand(AFile)));
  1276. Name:=nil;
  1277. Line:=ALine;
  1278. IgnoreCount:=0;
  1279. Commands:=nil;
  1280. Conditions:=nil;
  1281. OldValue:=nil;
  1282. CurrentValue:=nil;
  1283. end;
  1284. constructor TBreakpoint.Load(var S: TStream);
  1285. var
  1286. FName : PString;
  1287. begin
  1288. S.Read(typ,SizeOf(BreakpointType));
  1289. S.Read(state,SizeOf(BreakpointState));
  1290. GDBState:=bs_deleted;
  1291. case typ of
  1292. bt_file_line :
  1293. begin
  1294. { convert to current target }
  1295. FName:=S.ReadStr;
  1296. FileName:=NewStr(OSFileName(GetStr(FName)));
  1297. If Assigned(FName) then
  1298. DisposeStr(FName);
  1299. S.Read(Line,SizeOf(Line));
  1300. Name:=nil;
  1301. end;
  1302. else
  1303. begin
  1304. Name:=S.ReadStr;
  1305. Line:=0;
  1306. FileName:=nil;
  1307. end;
  1308. end;
  1309. S.Read(IgnoreCount,SizeOf(IgnoreCount));
  1310. Commands:=S.StrRead;
  1311. Conditions:=S.ReadStr;
  1312. OldValue:=nil;
  1313. CurrentValue:=nil;
  1314. end;
  1315. procedure TBreakpoint.Store(var S: TStream);
  1316. var
  1317. St : String;
  1318. begin
  1319. S.Write(typ,SizeOf(BreakpointType));
  1320. S.Write(state,SizeOf(BreakpointState));
  1321. case typ of
  1322. bt_file_line :
  1323. begin
  1324. st:=OSFileName(GetStr(FileName));
  1325. S.WriteStr(@St);
  1326. S.Write(Line,SizeOf(Line));
  1327. end;
  1328. else
  1329. begin
  1330. S.WriteStr(Name);
  1331. end;
  1332. end;
  1333. S.Write(IgnoreCount,SizeOf(IgnoreCount));
  1334. S.StrWrite(Commands);
  1335. S.WriteStr(Conditions);
  1336. end;
  1337. procedure TBreakpoint.Insert;
  1338. var
  1339. p,p2 : pchar;
  1340. st : string;
  1341. begin
  1342. If not assigned(Debugger) then Exit;
  1343. Remove;
  1344. Debugger^.last_breakpoint_number:=0;
  1345. if (GDBState=bs_deleted) and (state=bs_enabled) then
  1346. begin
  1347. if (typ=bt_file_line) and assigned(FileName) then
  1348. Debugger^.Command('break '+GDBFileName(NameAndExtOf(GetStr(FileName)))+':'+IntToStr(Line))
  1349. else if (typ=bt_function) and assigned(name) then
  1350. Debugger^.Command('break '+name^)
  1351. else if (typ=bt_address) and assigned(name) then
  1352. Debugger^.Command('break *0x'+name^)
  1353. else if (typ=bt_watch) and assigned(name) then
  1354. Debugger^.Command('watch '+name^)
  1355. else if (typ=bt_awatch) and assigned(name) then
  1356. Debugger^.Command('awatch '+name^)
  1357. else if (typ=bt_rwatch) and assigned(name) then
  1358. Debugger^.Command('rwatch '+name^);
  1359. if Debugger^.last_breakpoint_number<>0 then
  1360. begin
  1361. GDBIndex:=Debugger^.last_breakpoint_number;
  1362. GDBState:=bs_enabled;
  1363. Debugger^.Command('cond '+IntToStr(GDBIndex)+' '+GetStr(Conditions));
  1364. If IgnoreCount>0 then
  1365. Debugger^.Command('ignore '+IntToStr(GDBIndex)+' '+IntToStr(IgnoreCount));
  1366. If Assigned(Commands) then
  1367. begin
  1368. {Commands are not handled yet }
  1369. Debugger^.Command('command '+IntToStr(GDBIndex));
  1370. p:=commands;
  1371. while assigned(p) do
  1372. begin
  1373. p2:=strscan(p,#10);
  1374. if assigned(p2) then
  1375. p2^:=#0;
  1376. st:=strpas(p);
  1377. Debugger^.command(st);
  1378. if assigned(p2) then
  1379. p2^:=#10;
  1380. p:=p2;
  1381. if assigned(p) then
  1382. inc(p);
  1383. end;
  1384. Debugger^.Command('end');
  1385. end;
  1386. end
  1387. else
  1388. { Here there was a problem !! }
  1389. begin
  1390. GDBIndex:=0;
  1391. if not Debugger^.Disableallinvalidbreakpoints then
  1392. begin
  1393. if (typ=bt_file_line) and assigned(FileName) then
  1394. begin
  1395. ClearFormatParams;
  1396. AddFormatParamStr(NameAndExtOf(FileName^));
  1397. AddFormatParamInt(Line);
  1398. if ChoiceBox(msg_couldnotsetbreakpointat,@FormatParams,[btn_ok,button_DisableAllBreakpoints],false)=cmUserBtn2 then
  1399. Debugger^.Disableallinvalidbreakpoints:=true;
  1400. end
  1401. else
  1402. begin
  1403. ClearFormatParams;
  1404. AddFormatParamStr(BreakpointTypeStr[typ]);
  1405. AddFormatParamStr(GetStr(Name));
  1406. if ChoiceBox(msg_couldnotsetbreakpointtype,@FormatParams,[btn_ok,button_DisableAllBreakpoints],false)=cmUserBtn2 then
  1407. Debugger^.Disableallinvalidbreakpoints:=true;
  1408. end;
  1409. end;
  1410. state:=bs_disabled;
  1411. UpdateSource;
  1412. end;
  1413. end
  1414. else if (GDBState=bs_disabled) and (state=bs_enabled) then
  1415. Enable
  1416. else if (GDBState=bs_enabled) and (state=bs_disabled) then
  1417. Disable;
  1418. end;
  1419. procedure TBreakpoint.Remove;
  1420. begin
  1421. If not assigned(Debugger) then Exit;
  1422. if GDBIndex>0 then
  1423. Debugger^.Command('delete '+IntToStr(GDBIndex));
  1424. GDBIndex:=0;
  1425. GDBState:=bs_deleted;
  1426. end;
  1427. procedure TBreakpoint.Enable;
  1428. begin
  1429. If not assigned(Debugger) then Exit;
  1430. if GDBIndex>0 then
  1431. Debugger^.Command('enable '+IntToStr(GDBIndex))
  1432. else
  1433. Insert;
  1434. GDBState:=bs_enabled;
  1435. end;
  1436. procedure TBreakpoint.Disable;
  1437. begin
  1438. If not assigned(Debugger) then Exit;
  1439. if GDBIndex>0 then
  1440. Debugger^.Command('disable '+IntToStr(GDBIndex));
  1441. GDBState:=bs_disabled;
  1442. end;
  1443. procedure TBreakpoint.ResetValues;
  1444. begin
  1445. if assigned(OldValue) then
  1446. DisposeStr(OldValue);
  1447. OldValue:=nil;
  1448. if assigned(CurrentValue) then
  1449. DisposeStr(CurrentValue);
  1450. CurrentValue:=nil;
  1451. end;
  1452. procedure TBreakpoint.UpdateSource;
  1453. var W: PSourceWindow;
  1454. b : boolean;
  1455. begin
  1456. if typ=bt_file_line then
  1457. begin
  1458. W:=SearchOnDesktop(FExpand(OSFileName(GetStr(FileName))),false);
  1459. If assigned(W) then
  1460. begin
  1461. if state=bs_enabled then
  1462. b:=true
  1463. else
  1464. b:=false;
  1465. W^.Editor^.SetLineFlagState(Line-1,lfBreakpoint,b);
  1466. end;
  1467. end;
  1468. end;
  1469. destructor TBreakpoint.Done;
  1470. begin
  1471. Remove;
  1472. ResetValues;
  1473. if assigned(Name) then
  1474. DisposeStr(Name);
  1475. if assigned(FileName) then
  1476. DisposeStr(FileName);
  1477. if assigned(Conditions) then
  1478. DisposeStr(Conditions);
  1479. if assigned(Commands) then
  1480. StrDispose(Commands);
  1481. inherited Done;
  1482. end;
  1483. {****************************************************************************
  1484. TBreakpointCollection
  1485. ****************************************************************************}
  1486. function TBreakpointCollection.At(Index: Integer): PBreakpoint;
  1487. begin
  1488. At:=inherited At(Index);
  1489. end;
  1490. procedure TBreakpointCollection.Update;
  1491. begin
  1492. if assigned(Debugger) then
  1493. begin
  1494. Debugger^.RemoveBreakpoints;
  1495. Debugger^.InsertBreakpoints;
  1496. end;
  1497. if assigned(BreakpointsWindow) then
  1498. BreakpointsWindow^.Update;
  1499. end;
  1500. function TBreakpointCollection.GetGDB(index : longint) : PBreakpoint;
  1501. function IsNum(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1502. begin
  1503. IsNum:=P^.GDBIndex=index;
  1504. end;
  1505. begin
  1506. if index=0 then
  1507. GetGDB:=nil
  1508. else
  1509. GetGDB:=FirstThat(@IsNum);
  1510. end;
  1511. procedure TBreakpointCollection.ShowBreakpoints(W : PFPWindow);
  1512. procedure SetInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1513. begin
  1514. If assigned(P^.FileName) and
  1515. (OSFileName(FExpand(P^.FileName^))=OSFileName(FExpand(PSourceWindow(W)^.Editor^.FileName))) then
  1516. PSourceWindow(W)^.Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,P^.state=bs_enabled);
  1517. end;
  1518. procedure SetInDisassembly(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1519. var
  1520. PDL : PDisasLine;
  1521. S : string;
  1522. ps,qs,i : longint;
  1523. begin
  1524. for i:=0 to PDisassemblyWindow(W)^.Editor^.GetLineCount-1 do
  1525. begin
  1526. PDL:=PDisasLine(PDisassemblyWindow(W)^.Editor^.GetLine(i));
  1527. if PDL^.Address=0 then
  1528. begin
  1529. if (P^.typ=bt_file_line) then
  1530. begin
  1531. S:=PDisassemblyWindow(W)^.Editor^.GetDisplayText(i);
  1532. ps:=pos(':',S);
  1533. qs:=pos(' ',copy(S,ps+1,High(S)));
  1534. if (GDBFileName(FExpand(P^.FileName^))=GDBFileName(FExpand(Copy(S,1,ps-1)))) and
  1535. (StrToInt(copy(S,ps+1,qs-1))=P^.line) then
  1536. PDisassemblyWindow(W)^.Editor^.SetLineFlagState(i,lfBreakpoint,P^.state=bs_enabled);
  1537. end;
  1538. end
  1539. else
  1540. begin
  1541. If (P^.typ=bt_address) and (PDL^.Address=HexToCard(P^.Name^)) then
  1542. PDisassemblyWindow(W)^.Editor^.SetLineFlagState(i,lfBreakpoint,P^.state=bs_enabled);
  1543. end;
  1544. end;
  1545. end;
  1546. begin
  1547. if W=PFPWindow(DisassemblyWindow) then
  1548. ForEach(@SetInDisassembly)
  1549. else
  1550. ForEach(@SetInSource);
  1551. end;
  1552. procedure TBreakpointCollection.AdaptBreakpoints(Editor : PSourceEditor; Pos, Change : longint);
  1553. procedure AdaptInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1554. begin
  1555. If assigned(P^.FileName) and
  1556. (OSFileName(FExpand(P^.FileName^))=OSFileName(FExpand(Editor^.FileName))) then
  1557. begin
  1558. if P^.state=bs_enabled then
  1559. Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,false);
  1560. if P^.Line-1>=Pos then
  1561. begin
  1562. if (Change>0) or (P^.Line-1>=Pos-Change) then
  1563. P^.line:=P^.Line+Change
  1564. else
  1565. begin
  1566. { removing inside a ForEach call leads to problems }
  1567. { so we do that after PM }
  1568. P^.state:=bs_delete_after;
  1569. end;
  1570. end;
  1571. if P^.state=bs_enabled then
  1572. Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,true);
  1573. end;
  1574. end;
  1575. var
  1576. I : longint;
  1577. begin
  1578. ForEach(@AdaptInSource);
  1579. I:=Count-1;
  1580. While (I>=0) do
  1581. begin
  1582. if At(I)^.state=bs_delete_after then
  1583. AtFree(I);
  1584. Dec(I);
  1585. end;
  1586. end;
  1587. function TBreakpointCollection.FindBreakpointAt(Editor : PSourceEditor; Line : longint) : PBreakpoint;
  1588. function IsAtLine(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1589. begin
  1590. If assigned(P^.FileName) and
  1591. (OSFileName(FExpand(P^.FileName^))=OSFileName(FExpand(Editor^.FileName))) and
  1592. (Line=P^.Line) then
  1593. IsAtLine:=true
  1594. else
  1595. IsAtLine:=false;
  1596. end;
  1597. begin
  1598. FindBreakpointAt:=FirstThat(@IsAtLine);
  1599. end;
  1600. procedure TBreakpointCollection.ShowAllBreakpoints;
  1601. procedure SetInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1602. var
  1603. W : PSourceWindow;
  1604. begin
  1605. If assigned(P^.FileName) then
  1606. begin
  1607. W:=SearchOnDesktop(P^.FileName^,false);
  1608. if assigned(W) then
  1609. W^.Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,P^.state=bs_enabled);
  1610. end;
  1611. end;
  1612. begin
  1613. ForEach(@SetInSource);
  1614. end;
  1615. function TBreakpointCollection.GetType(typ : BreakpointType;Const s : String) : PBreakpoint;
  1616. function IsThis(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1617. begin
  1618. IsThis:=(P^.typ=typ) and (GetStr(P^.Name)=S);
  1619. end;
  1620. begin
  1621. GetType:=FirstThat(@IsThis);
  1622. end;
  1623. function TBreakpointCollection.ToggleFileLine(FileName: String;LineNr : Longint) : boolean;
  1624. var PB : PBreakpoint;
  1625. function IsThere(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1626. begin
  1627. IsThere:=(P^.typ=bt_file_line) and assigned(P^.FileName) and
  1628. (OSFileName(FExpand(P^.FileName^))=FileName) and (P^.Line=LineNr);
  1629. end;
  1630. begin
  1631. FileName:=OSFileName(FileName);
  1632. PB:=FirstThat(@IsThere);
  1633. ToggleFileLine:=false;
  1634. If Assigned(PB) then
  1635. if PB^.state=bs_disabled then
  1636. begin
  1637. PB^.state:=bs_enabled;
  1638. ToggleFileLine:=true;
  1639. end
  1640. else if PB^.state=bs_enabled then
  1641. PB^.state:=bs_disabled;
  1642. If not assigned(PB) then
  1643. begin
  1644. PB:= New(PBreakpoint,Init_file_line(FileName,LineNr));
  1645. if assigned(PB) then
  1646. Begin
  1647. Insert(PB);
  1648. ToggleFileLine:=true;
  1649. End;
  1650. end;
  1651. if assigned(PB) then
  1652. PB^.UpdateSource;
  1653. Update;
  1654. end;
  1655. {****************************************************************************
  1656. TBreakpointItem
  1657. ****************************************************************************}
  1658. constructor TBreakpointItem.Init(ABreakpoint : PBreakpoint);
  1659. begin
  1660. inherited Init;
  1661. Breakpoint:=ABreakpoint;
  1662. end;
  1663. function TBreakpointItem.GetText(MaxLen: Sw_integer): string;
  1664. var S: string;
  1665. begin
  1666. with Breakpoint^ do
  1667. begin
  1668. S:=BreakpointTypeStr[typ];
  1669. While Length(S)<10 do
  1670. S:=S+' ';
  1671. S:=S+'|';
  1672. S:=S+BreakpointStateStr[state]+' ';
  1673. While Length(S)<20 do
  1674. S:=S+' ';
  1675. S:=S+'|';
  1676. if (typ=bt_file_line) then
  1677. S:=S+NameAndExtOf(GetStr(FileName))+':'+IntToStr(Line)
  1678. else
  1679. S:=S+GetStr(name);
  1680. While Length(S)<40 do
  1681. S:=S+' ';
  1682. S:=S+'|';
  1683. if IgnoreCount>0 then
  1684. S:=S+IntToStr(IgnoreCount);
  1685. While Length(S)<49 do
  1686. S:=S+' ';
  1687. S:=S+'|';
  1688. if assigned(Conditions) then
  1689. S:=S+' '+GetStr(Conditions);
  1690. if length(S)>MaxLen then S:=copy(S,1,MaxLen-2)+'..';
  1691. GetText:=S;
  1692. end;
  1693. end;
  1694. procedure TBreakpointItem.Selected;
  1695. begin
  1696. end;
  1697. function TBreakpointItem.GetModuleName: string;
  1698. begin
  1699. if breakpoint^.typ=bt_file_line then
  1700. GetModuleName:=GetStr(breakpoint^.FileName)
  1701. else
  1702. GetModuleName:='';
  1703. end;
  1704. {****************************************************************************
  1705. TBreakpointsListBox
  1706. ****************************************************************************}
  1707. constructor TBreakpointsListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  1708. begin
  1709. inherited Init(Bounds,1,AHScrollBar, AVScrollBar);
  1710. GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  1711. NoSelection:=true;
  1712. end;
  1713. function TBreakpointsListBox.GetLocalMenu: PMenu;
  1714. var M: PMenu;
  1715. begin
  1716. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  1717. M:=NewMenu(
  1718. NewItem(menu_bplocal_gotosource,'',kbNoKey,cmMsgGotoSource,hcMsgGotoSource,
  1719. NewItem(menu_bplocal_editbreakpoint,'',kbNoKey,cmEditBreakpoint,hcEditBreakpoint,
  1720. NewItem(menu_bplocal_newbreakpoint,'',kbNoKey,cmNewBreakpoint,hcNewBreakpoint,
  1721. NewItem(menu_bplocal_deletebreakpoint,'',kbNoKey,cmDeleteBreakpoint,hcDeleteBreakpoint,
  1722. NewItem(menu_bplocal_togglestate,'',kbNoKey,cmToggleBreakpoint,hcToggleBreakpoint,
  1723. nil))))));
  1724. GetLocalMenu:=M;
  1725. end;
  1726. procedure TBreakpointsListBox.HandleEvent(var Event: TEvent);
  1727. var DontClear: boolean;
  1728. begin
  1729. case Event.What of
  1730. evKeyDown :
  1731. begin
  1732. DontClear:=false;
  1733. case Event.KeyCode of
  1734. kbEnter :
  1735. Message(@Self,evCommand,cmMsgGotoSource,nil);
  1736. kbIns :
  1737. Message(@Self,evCommand,cmNewBreakpoint,nil);
  1738. kbDel :
  1739. Message(@Self,evCommand,cmDeleteBreakpoint,nil);
  1740. else
  1741. DontClear:=true;
  1742. end;
  1743. if not DontClear then
  1744. ClearEvent(Event);
  1745. end;
  1746. evBroadcast :
  1747. case Event.Command of
  1748. cmListItemSelected :
  1749. if Event.InfoPtr=@Self then
  1750. Message(@Self,evCommand,cmEditBreakpoint,nil);
  1751. end;
  1752. evCommand :
  1753. begin
  1754. DontClear:=false;
  1755. case Event.Command of
  1756. cmMsgTrackSource :
  1757. if Range>0 then
  1758. TrackSource;
  1759. cmEditBreakpoint :
  1760. EditCurrent;
  1761. cmToggleBreakpoint :
  1762. ToggleCurrent;
  1763. cmDeleteBreakpoint :
  1764. DeleteCurrent;
  1765. cmNewBreakpoint :
  1766. EditNew;
  1767. cmMsgClear :
  1768. Clear;
  1769. else
  1770. DontClear:=true;
  1771. end;
  1772. if not DontClear then
  1773. ClearEvent(Event);
  1774. end;
  1775. end;
  1776. inherited HandleEvent(Event);
  1777. end;
  1778. procedure TBreakpointsListBox.AddBreakpoint(P: PBreakpointItem);
  1779. var W : integer;
  1780. begin
  1781. if List=nil then New(List, Init(20,20));
  1782. W:=length(P^.GetText(255));
  1783. if W>MaxWidth then
  1784. begin
  1785. MaxWidth:=W;
  1786. if HScrollBar<>nil then
  1787. HScrollBar^.SetRange(0,MaxWidth);
  1788. end;
  1789. List^.Insert(P);
  1790. SetRange(List^.Count);
  1791. if Focused=List^.Count-1-1 then
  1792. FocusItem(List^.Count-1);
  1793. P^.Breakpoint^.UpdateSource;
  1794. DrawView;
  1795. end;
  1796. (* function TBreakpointsListBox.AddModuleName(const Name: string): PString;
  1797. var P: PString;
  1798. begin
  1799. if ModuleNames<>nil then
  1800. P:=ModuleNames^.Add(Name)
  1801. else
  1802. P:=nil;
  1803. AddModuleName:=P;
  1804. end; *)
  1805. function TBreakpointsListBox.GetText(Item,MaxLen: Sw_Integer): String;
  1806. var P: PBreakpointItem;
  1807. S: string;
  1808. begin
  1809. P:=List^.At(Item);
  1810. S:=P^.GetText(MaxLen);
  1811. GetText:=copy(S,1,MaxLen);
  1812. end;
  1813. procedure TBreakpointsListBox.Clear;
  1814. begin
  1815. if assigned(List) then
  1816. Dispose(List, Done);
  1817. List:=nil;
  1818. MaxWidth:=0;
  1819. (* if assigned(ModuleNames) then
  1820. ModuleNames^.FreeAll; *)
  1821. SetRange(0); DrawView;
  1822. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1823. end;
  1824. procedure TBreakpointsListBox.TrackSource;
  1825. var W: PSourceWindow;
  1826. P: PBreakpointItem;
  1827. R: TRect;
  1828. (* Row,Col: sw_integer; *)
  1829. begin
  1830. (*Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1831. if Range=0 then Exit;*)
  1832. P:=List^.At(Focused);
  1833. if P^.GetModuleName='' then Exit;
  1834. Desktop^.Lock;
  1835. GetNextEditorBounds(R);
  1836. R.B.Y:=Owner^.Origin.Y;
  1837. W:=EditorWindowFile(P^.GetModuleName);
  1838. if assigned(W) then
  1839. begin
  1840. W^.GetExtent(R);
  1841. R.B.Y:=Owner^.Origin.Y;
  1842. W^.ChangeBounds(R);
  1843. W^.Editor^.SetCurPtr(1,P^.Breakpoint^.Line);
  1844. end
  1845. else
  1846. W:=TryToOpenFile(@R,P^.GetModuleName,1,P^.Breakpoint^.Line,true);
  1847. if W<>nil then
  1848. begin
  1849. W^.Select;
  1850. W^.Editor^.TrackCursor(true);
  1851. W^.Editor^.SetLineFlagExclusive(lfHighlightRow,P^.Breakpoint^.Line);
  1852. end;
  1853. if Assigned(Owner) then
  1854. Owner^.Select;
  1855. Desktop^.UnLock;
  1856. end;
  1857. procedure TBreakpointsListBox.ToggleCurrent;
  1858. var
  1859. P: PBreakpointItem;
  1860. begin
  1861. if Range=0 then Exit;
  1862. P:=List^.At(Focused);
  1863. if P=nil then Exit;
  1864. if P^.Breakpoint^.state=bs_enabled then
  1865. P^.Breakpoint^.state:=bs_disabled
  1866. else if P^.Breakpoint^.state=bs_disabled then
  1867. P^.Breakpoint^.state:=bs_enabled;
  1868. P^.Breakpoint^.UpdateSource;
  1869. BreakpointsCollection^.Update;
  1870. end;
  1871. procedure TBreakpointsListBox.EditCurrent;
  1872. var
  1873. P: PBreakpointItem;
  1874. begin
  1875. if Range=0 then Exit;
  1876. P:=List^.At(Focused);
  1877. if P=nil then Exit;
  1878. Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P^.Breakpoint)),nil);
  1879. P^.Breakpoint^.UpdateSource;
  1880. BreakpointsCollection^.Update;
  1881. end;
  1882. procedure TBreakpointsListBox.DeleteCurrent;
  1883. var
  1884. P: PBreakpointItem;
  1885. begin
  1886. if Range=0 then Exit;
  1887. P:=List^.At(Focused);
  1888. if P=nil then Exit;
  1889. { delete it form source window }
  1890. P^.Breakpoint^.state:=bs_disabled;
  1891. P^.Breakpoint^.UpdateSource;
  1892. BreakpointsCollection^.free(P^.Breakpoint);
  1893. List^.free(P);
  1894. BreakpointsCollection^.Update;
  1895. end;
  1896. procedure TBreakpointsListBox.EditNew;
  1897. var
  1898. P: PBreakpoint;
  1899. begin
  1900. P:=New(PBreakpoint,Init_Empty);
  1901. if Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P)),nil)<>cmCancel then
  1902. begin
  1903. P^.UpdateSource;
  1904. BreakpointsCollection^.Insert(P);
  1905. BreakpointsCollection^.Update;
  1906. end
  1907. else
  1908. dispose(P,Done);
  1909. end;
  1910. procedure TBreakpointsListBox.Draw;
  1911. var
  1912. I, J, Item: Sw_Integer;
  1913. NormalColor, SelectedColor, FocusedColor, Color: Word;
  1914. ColWidth, CurCol, Indent: Integer;
  1915. B: TDrawBuffer;
  1916. Text: String;
  1917. SCOff: Byte;
  1918. TC: byte;
  1919. procedure MT(var C: word); begin if TC<>0 then C:=(C and $ff0f) or (TC and $f0); end;
  1920. begin
  1921. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  1922. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  1923. begin
  1924. NormalColor := GetColor(1);
  1925. FocusedColor := GetColor(3);
  1926. SelectedColor := GetColor(4);
  1927. end else
  1928. begin
  1929. NormalColor := GetColor(2);
  1930. SelectedColor := GetColor(4);
  1931. end;
  1932. if Transparent then
  1933. begin MT(NormalColor); MT(SelectedColor); end;
  1934. if NoSelection then
  1935. SelectedColor:=NormalColor;
  1936. if HScrollBar <> nil then Indent := HScrollBar^.Value
  1937. else Indent := 0;
  1938. ColWidth := Size.X div NumCols + 1;
  1939. for I := 0 to Size.Y - 1 do
  1940. begin
  1941. for J := 0 to NumCols-1 do
  1942. begin
  1943. Item := J*Size.Y + I + TopItem;
  1944. CurCol := J*ColWidth;
  1945. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  1946. (Focused = Item) and (Range > 0) then
  1947. begin
  1948. Color := FocusedColor;
  1949. SetCursor(CurCol+1,I);
  1950. SCOff := 0;
  1951. end
  1952. else if (Item < Range) and IsSelected(Item) then
  1953. begin
  1954. Color := SelectedColor;
  1955. SCOff := 2;
  1956. end
  1957. else
  1958. begin
  1959. Color := NormalColor;
  1960. SCOff := 4;
  1961. end;
  1962. MoveChar(B[CurCol], ' ', Color, ColWidth);
  1963. if Item < Range then
  1964. begin
  1965. Text := GetText(Item, ColWidth + Indent);
  1966. Text := Copy(Text,Indent,ColWidth);
  1967. MoveStr(B[CurCol+1], Text, Color);
  1968. if ShowMarkers then
  1969. begin
  1970. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  1971. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  1972. end;
  1973. end;
  1974. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  1975. end;
  1976. WriteLine(0, I, Size.X, 1, B);
  1977. end;
  1978. end;
  1979. constructor TBreakpointsListBox.Load(var S: TStream);
  1980. begin
  1981. inherited Load(S);
  1982. end;
  1983. procedure TBreakpointsListBox.Store(var S: TStream);
  1984. var OL: PCollection;
  1985. OldR : integer;
  1986. begin
  1987. OL:=List;
  1988. OldR:=Range;
  1989. Range:=0;
  1990. New(List, Init(1,1));
  1991. inherited Store(S);
  1992. Dispose(List, Done);
  1993. Range:=OldR;
  1994. List:=OL;
  1995. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  1996. collection? Pasting here a modified version of TListBox.Store+
  1997. TAdvancedListBox.Store isn't a better solution, since by eventually
  1998. changing the obj-hierarchy you'll always have to modify this, too - BG }
  1999. end;
  2000. destructor TBreakpointsListBox.Done;
  2001. begin
  2002. inherited Done;
  2003. if List<>nil then Dispose(List, Done);
  2004. (* if ModuleNames<>nil then Dispose(ModuleNames, Done);*)
  2005. end;
  2006. {****************************************************************************
  2007. TBreakpointsWindow
  2008. ****************************************************************************}
  2009. constructor TBreakpointsWindow.Init;
  2010. var R,R2: TRect;
  2011. HSB,VSB: PScrollBar;
  2012. ST: PStaticText;
  2013. S: String;
  2014. X,X1 : Sw_integer;
  2015. Btn: PButton;
  2016. const
  2017. NumButtons = 5;
  2018. begin
  2019. Desktop^.GetExtent(R); R.A.Y:=R.B.Y-18;
  2020. inherited Init(R, dialog_breakpointlist, wnNoNumber);
  2021. HelpCtx:=hcBreakpointListWindow;
  2022. GetExtent(R); R.Grow(-1,-1); R.B.Y:=R.A.Y+1;
  2023. S:=label_breakpointpropheader;
  2024. New(ST, Init(R,S));
  2025. ST^.GrowMode:=gfGrowHiX;
  2026. Insert(ST);
  2027. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,1); R.B.Y:=R.A.Y+1;
  2028. New(ST, Init(R, CharStr('Ä', MaxViewWidth)));
  2029. ST^.GrowMode:=gfGrowHiX;
  2030. Insert(ST);
  2031. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,2);Dec(R.B.Y,5);
  2032. R2.Copy(R); Inc(R2.B.Y); R2.A.Y:=R2.B.Y-1;
  2033. New(HSB, Init(R2)); HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX; Insert(HSB);
  2034. HSB^.SetStep(R.B.X-R.A.X-2,1);
  2035. R2.Copy(R); Inc(R2.B.X); R2.A.X:=R2.B.X-1;
  2036. New(VSB, Init(R2)); VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY; Insert(VSB);
  2037. VSB^.SetStep(R.B.Y-R.A.Y-2,1);
  2038. New(BreakLB, Init(R,HSB,VSB));
  2039. BreakLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  2040. BreakLB^.Transparent:=true;
  2041. Insert(BreakLB);
  2042. GetExtent(R);R.Grow(-1,-1);
  2043. Dec(R.B.Y);
  2044. R.A.Y:=R.B.Y-2;
  2045. X:=(R.B.X-R.A.X) div NumButtons;
  2046. X1:=R.A.X+(X div 2);
  2047. R.A.X:=X1-3;R.B.X:=X1+7;
  2048. New(Btn, Init(R, button_Close, cmClose, bfDefault));
  2049. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2050. Insert(Btn);
  2051. X1:=X1+X;
  2052. R.A.X:=X1-3;R.B.X:=X1+7;
  2053. New(Btn, Init(R, button_New, cmNewBreakpoint, bfNormal));
  2054. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2055. Insert(Btn);
  2056. X1:=X1+X;
  2057. R.A.X:=X1-3;R.B.X:=X1+7;
  2058. New(Btn, Init(R, button_Edit, cmEditBreakpoint, bfNormal));
  2059. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2060. Insert(Btn);
  2061. X1:=X1+X;
  2062. R.A.X:=X1-3;R.B.X:=X1+7;
  2063. New(Btn, Init(R, button_ToggleButton, cmToggleBreakInList, bfNormal));
  2064. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2065. Insert(Btn);
  2066. X1:=X1+X;
  2067. R.A.X:=X1-3;R.B.X:=X1+7;
  2068. New(Btn, Init(R, button_Delete, cmDeleteBreakpoint, bfNormal));
  2069. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2070. Insert(Btn);
  2071. BreakLB^.Select;
  2072. Update;
  2073. BreakpointsWindow:=@self;
  2074. end;
  2075. constructor TBreakpointsWindow.Load(var S: TStream);
  2076. begin
  2077. inherited Load(S);
  2078. GetSubViewPtr(S,BreakLB);
  2079. end;
  2080. procedure TBreakpointsWindow.Store(var S: TStream);
  2081. begin
  2082. inherited Store(S);
  2083. PutSubViewPtr(S,BreakLB);
  2084. end;
  2085. procedure TBreakpointsWindow.AddBreakpoint(ABreakpoint : PBreakpoint);
  2086. begin
  2087. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(ABreakpoint)));
  2088. end;
  2089. procedure TBreakpointsWindow.ClearBreakpoints;
  2090. begin
  2091. BreakLB^.Clear;
  2092. ReDraw;
  2093. end;
  2094. procedure TBreakpointsWindow.ReloadBreakpoints;
  2095. procedure InsertInBreakLB(P : PBreakpoint);
  2096. begin
  2097. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(P)));
  2098. end;
  2099. begin
  2100. If not assigned(BreakpointsCollection) then
  2101. exit;
  2102. BreakpointsCollection^.ForEach(@InsertInBreakLB);
  2103. ReDraw;
  2104. end;
  2105. procedure TBreakpointsWindow.SizeLimits(var Min, Max: TPoint);
  2106. begin
  2107. inherited SizeLimits(Min,Max);
  2108. Min.X:=40; Min.Y:=18;
  2109. end;
  2110. procedure TBreakpointsWindow.Close;
  2111. begin
  2112. Hide;
  2113. end;
  2114. procedure TBreakpointsWindow.HandleEvent(var Event: TEvent);
  2115. var DontClear : boolean;
  2116. begin
  2117. case Event.What of
  2118. evKeyDown :
  2119. begin
  2120. if (Event.KeyCode=kbEnter) or (Event.KeyCode=kbEsc) then
  2121. begin
  2122. ClearEvent(Event);
  2123. Hide;
  2124. end;
  2125. end;
  2126. evCommand :
  2127. begin
  2128. DontClear:=False;
  2129. case Event.Command of
  2130. cmNewBreakpoint :
  2131. BreakLB^.EditNew;
  2132. cmEditBreakpoint :
  2133. BreakLB^.EditCurrent;
  2134. cmDeleteBreakpoint :
  2135. BreakLB^.DeleteCurrent;
  2136. cmToggleBreakInList :
  2137. BreakLB^.ToggleCurrent;
  2138. cmClose :
  2139. Hide;
  2140. else
  2141. DontClear:=true;
  2142. end;
  2143. if not DontClear then
  2144. ClearEvent(Event);
  2145. end;
  2146. evBroadcast :
  2147. case Event.Command of
  2148. cmUpdate :
  2149. Update;
  2150. end;
  2151. end;
  2152. inherited HandleEvent(Event);
  2153. end;
  2154. procedure TBreakpointsWindow.Update;
  2155. var
  2156. StoreFocus : longint;
  2157. begin
  2158. StoreFocus:=BreakLB^.Focused;
  2159. ClearBreakpoints;
  2160. ReloadBreakpoints;
  2161. If StoreFocus<BreakLB^.Range then
  2162. BreakLB^.FocusItem(StoreFocus);
  2163. end;
  2164. destructor TBreakpointsWindow.Done;
  2165. begin
  2166. inherited Done;
  2167. BreakpointsWindow:=nil;
  2168. end;
  2169. {****************************************************************************
  2170. TBreakpointItemDialog
  2171. ****************************************************************************}
  2172. constructor TBreakpointItemDialog.Init(ABreakpoint: PBreakpoint);
  2173. var R,R2,R3: TRect;
  2174. Items: PSItem;
  2175. I : BreakpointType;
  2176. KeyCount: sw_integer;
  2177. begin
  2178. KeyCount:=longint(high(BreakpointType));
  2179. R.Assign(0,0,60,Max(9+KeyCount,18));
  2180. inherited Init(R,dialog_modifynewbreakpoint);
  2181. Breakpoint:=ABreakpoint;
  2182. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  2183. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.B.X-3;
  2184. New(NameIL, Init(R, 255)); Insert(NameIL);
  2185. R2.Copy(R); R2.A.X:=R2.B.X; R2.B.X:=R2.A.X+3;
  2186. Insert(New(PHistory, Init(R2, NameIL, hidWatchDialog)));
  2187. R.Copy(R3); Inc(R.A.Y); R.B.Y:=R.A.Y+1;
  2188. R2.Copy(R); R2.Move(-1,-1);
  2189. Insert(New(PLabel, Init(R2, label_breakpoint_name, NameIL)));
  2190. R.Move(0,3);
  2191. New(ConditionsIL, Init(R, 255)); Insert(ConditionsIL);
  2192. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_conditions, ConditionsIL)));
  2193. R.Move(0,3); R.B.X:=R.A.X+36;
  2194. New(LineIL, Init(R, 128)); Insert(LineIL);
  2195. LineIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  2196. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_line, LineIL)));
  2197. R.Move(0,3);
  2198. New(IgnoreIL, Init(R, 128)); Insert(IgnoreIL);
  2199. IgnoreIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  2200. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_ignorecount, IgnoreIL)));
  2201. R.Copy(R3); Inc(R.A.X,38); Inc(R.A.Y,7); R.B.Y:=R.A.Y+KeyCount;
  2202. Items:=nil;
  2203. { don't use invalid type }
  2204. for I:=pred(high(BreakpointType)) downto low(BreakpointType) do
  2205. Items:=NewSItem(BreakpointTypeStr[I], Items);
  2206. New(TypeRB, Init(R, Items));
  2207. R2.Copy(R); R2.Move(-1,-1); R2.B.Y:=R2.A.Y+1;
  2208. Insert(New(PLabel, Init(R2, label_breakpoint_type, TypeRB)));
  2209. Insert(TypeRB);
  2210. InsertButtons(@Self);
  2211. NameIL^.Select;
  2212. end;
  2213. function TBreakpointItemDialog.Execute: Word;
  2214. var R: word;
  2215. S1: string;
  2216. err: word;
  2217. L: longint;
  2218. begin
  2219. R:=longint(Breakpoint^.typ);
  2220. TypeRB^.SetData(R);
  2221. If Breakpoint^.typ=bt_file_line then
  2222. S1:=GetStr(Breakpoint^.FileName)
  2223. else
  2224. S1:=GetStr(Breakpoint^.name);
  2225. NameIL^.SetData(S1);
  2226. If Breakpoint^.typ=bt_file_line then
  2227. S1:=IntToStr(Breakpoint^.Line)
  2228. else
  2229. S1:='0';
  2230. LineIL^.SetData(S1);
  2231. S1:=IntToStr(Breakpoint^.IgnoreCount);
  2232. IgnoreIL^.SetData(S1);
  2233. S1:=GetStr(Breakpoint^.Conditions);
  2234. ConditionsIL^.SetData(S1);
  2235. if assigned(FirstEditorWindow) then
  2236. FindReplaceEditor:=FirstEditorWindow^.Editor;
  2237. R:=inherited Execute;
  2238. FindReplaceEditor:=nil;
  2239. if R=cmOK then
  2240. begin
  2241. TypeRB^.GetData(R);
  2242. L:=R;
  2243. Breakpoint^.typ:=BreakpointType(L);
  2244. NameIL^.GetData(S1);
  2245. If Breakpoint^.typ=bt_file_line then
  2246. begin
  2247. If assigned(Breakpoint^.FileName) then
  2248. DisposeStr(Breakpoint^.FileName);
  2249. Breakpoint^.FileName:=NewStr(S1);
  2250. end
  2251. else
  2252. begin
  2253. If assigned(Breakpoint^.Name) then
  2254. DisposeStr(Breakpoint^.Name);
  2255. Breakpoint^.name:=NewStr(S1);
  2256. end;
  2257. If Breakpoint^.typ=bt_file_line then
  2258. begin
  2259. LineIL^.GetData(S1);
  2260. Val(S1,L,err);
  2261. Breakpoint^.Line:=L;
  2262. end;
  2263. IgnoreIL^.GetData(S1);
  2264. Val(S1,L,err);
  2265. Breakpoint^.IgnoreCount:=L;
  2266. ConditionsIL^.GetData(S1);
  2267. If assigned(Breakpoint^.Conditions) then
  2268. DisposeStr(Breakpoint^.Conditions);
  2269. Breakpoint^.Conditions:=NewStr(S1);
  2270. end;
  2271. Execute:=R;
  2272. end;
  2273. {****************************************************************************
  2274. TWatch
  2275. ****************************************************************************}
  2276. constructor TWatch.Init(s : string);
  2277. begin
  2278. expr:=NewStr(s);
  2279. last_value:=nil;
  2280. current_value:=nil;
  2281. Get_new_value;
  2282. GDBRunCount:=-1;
  2283. end;
  2284. constructor TWatch.Load(var S: TStream);
  2285. begin
  2286. expr:=S.ReadStr;
  2287. last_value:=nil;
  2288. current_value:=nil;
  2289. Get_new_value;
  2290. GDBRunCount:=-1;
  2291. end;
  2292. procedure TWatch.Store(var S: TStream);
  2293. begin
  2294. S.WriteStr(expr);
  2295. end;
  2296. procedure TWatch.rename(s : string);
  2297. begin
  2298. if assigned(expr) then
  2299. begin
  2300. if GetStr(expr)=S then
  2301. exit;
  2302. DisposeStr(expr);
  2303. end;
  2304. expr:=NewStr(s);
  2305. if assigned(last_value) then
  2306. StrDispose(last_value);
  2307. last_value:=nil;
  2308. if assigned(current_value) then
  2309. StrDispose(current_value);
  2310. current_value:=nil;
  2311. GDBRunCount:=-1;
  2312. Get_new_value;
  2313. end;
  2314. procedure TWatch.Get_new_value;
  2315. var p, q : pchar;
  2316. i, j, curframe, startframe : longint;
  2317. s,s2 : string;
  2318. loop_higher, found : boolean;
  2319. last_removed : char;
  2320. function GetValue(var s : string) : boolean;
  2321. begin
  2322. Debugger^.command('p '+s);
  2323. if not Debugger^.Error then
  2324. begin
  2325. s:=StrPas(Debugger^.GetOutput);
  2326. GetValue:=true;
  2327. end
  2328. else
  2329. begin
  2330. s:=StrPas(Debugger^.GetError);
  2331. GetValue:=false;
  2332. { do not open a messagebox for such errors }
  2333. Debugger^.got_error:=false;
  2334. end;
  2335. end;
  2336. begin
  2337. If not assigned(Debugger) or Not Debugger^.HasExe or
  2338. (GDBRunCount=Debugger^.RunCount) then
  2339. exit;
  2340. GDBRunCount:=Debugger^.RunCount;
  2341. if assigned(last_value) then
  2342. strdispose(last_value);
  2343. last_value:=current_value;
  2344. s:=GetStr(expr);
  2345. found:=GetValue(s);
  2346. Debugger^.got_error:=false;
  2347. loop_higher:=not found;
  2348. if not found then
  2349. begin
  2350. curframe:=Debugger^.get_current_frame;
  2351. startframe:=curframe;
  2352. end
  2353. else
  2354. begin
  2355. curframe:=0;
  2356. startframe:=0;
  2357. end;
  2358. while loop_higher do
  2359. begin
  2360. s:='parent_ebp';
  2361. if GetValue(s) then
  2362. begin
  2363. repeat
  2364. inc(curframe);
  2365. if not Debugger^.set_current_frame(curframe) then
  2366. loop_higher:=false;
  2367. {$ifdef FrameNameKnown}
  2368. s2:='/x '+FrameName;
  2369. {$else not FrameNameKnown}
  2370. s2:='/x $ebp';
  2371. {$endif FrameNameKnown}
  2372. getValue(s2);
  2373. j:=pos('=',s2);
  2374. if j>0 then
  2375. s2:=copy(s2,j+1,length(s2));
  2376. while s2[1] in [' ',TAB] do
  2377. delete(s2,1,1);
  2378. if pos(s2,s)>0 then
  2379. loop_higher :=false;
  2380. until not loop_higher;
  2381. { try again at that level }
  2382. s:=GetStr(expr);
  2383. found:=GetValue(s);
  2384. loop_higher:=not found;
  2385. end
  2386. else
  2387. loop_higher:=false;
  2388. end;
  2389. if found then
  2390. p:=StrNew(Debugger^.GetOutput)
  2391. else
  2392. begin
  2393. { get a reasonable output at least }
  2394. s:=GetStr(expr);
  2395. GetValue(s);
  2396. p:=StrNew(Debugger^.GetError);
  2397. end;
  2398. Debugger^.got_error:=false;
  2399. { We should try here to find the expr in parent
  2400. procedure if there are
  2401. I will implement this as I added a
  2402. parent_ebp pseudo local var to local procedure
  2403. in stabs debug info PM }
  2404. { But there are some pitfalls like
  2405. locals redefined in other sublocals that call the function }
  2406. if curframe<>startframe then
  2407. Debugger^.set_current_frame(startframe);
  2408. q:=nil;
  2409. if assigned(p) and (p[0]='$') then
  2410. q:=StrPos(p,'=');
  2411. if not assigned(q) then
  2412. q:=p;
  2413. if assigned(q) then
  2414. i:=strlen(q)
  2415. else
  2416. i:=0;
  2417. if (i>0) and (q[i-1]=#10) then
  2418. begin
  2419. while (i>1) and ((q[i-2]=' ') or (q[i-2]=#9)) do
  2420. dec(i);
  2421. last_removed:=q[i-1];
  2422. q[i-1]:=#0;
  2423. end
  2424. else
  2425. last_removed:=#0;
  2426. if assigned(q) then
  2427. current_value:=strnew(q)
  2428. else
  2429. current_value:=strnew('');
  2430. if last_removed<>#0 then
  2431. q[i-1]:=last_removed;
  2432. strdispose(p);
  2433. GDBRunCount:=Debugger^.RunCount;
  2434. end;
  2435. procedure TWatch.Force_new_value;
  2436. begin
  2437. GDBRunCount:=-1;
  2438. Get_new_value;
  2439. end;
  2440. destructor TWatch.Done;
  2441. begin
  2442. if assigned(expr) then
  2443. disposestr(expr);
  2444. if assigned(last_value) then
  2445. strdispose(last_value);
  2446. if assigned(current_value) then
  2447. strdispose(current_value);
  2448. inherited done;
  2449. end;
  2450. {****************************************************************************
  2451. TWatchesCollection
  2452. ****************************************************************************}
  2453. constructor TWatchesCollection.Init;
  2454. begin
  2455. inherited Init(10,10);
  2456. end;
  2457. procedure TWatchesCollection.Insert(Item: Pointer);
  2458. begin
  2459. PWatch(Item)^.Get_new_value;
  2460. Inherited Insert(Item);
  2461. Update;
  2462. end;
  2463. procedure TWatchesCollection.Update;
  2464. var
  2465. W,W1 : integer;
  2466. procedure GetMax(P : PWatch);
  2467. begin
  2468. if assigned(P^.Current_value) then
  2469. W1:=StrLen(P^.Current_value)+3+Length(GetStr(P^.expr))
  2470. else
  2471. W1:=2+Length(GetStr(P^.expr));
  2472. if W1>W then
  2473. W:=W1;
  2474. end;
  2475. begin
  2476. W:=0;
  2477. ForEach(@GetMax);
  2478. MaxW:=W;
  2479. If assigned(WatchesWindow) then
  2480. WatchesWindow^.WLB^.Update(MaxW);
  2481. end;
  2482. function TWatchesCollection.At(Index: Integer): PWatch;
  2483. begin
  2484. At:=Inherited At(Index);
  2485. end;
  2486. {****************************************************************************
  2487. TWatchesListBox
  2488. ****************************************************************************}
  2489. constructor TWatchesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  2490. begin
  2491. inherited Init(Bounds,1,AHScrollBar,AVScrollBar);
  2492. If assigned(List) then
  2493. dispose(list,done);
  2494. List:=WatchesCollection;
  2495. end;
  2496. procedure TWatchesListBox.Update(AMaxWidth : integer);
  2497. var R : TRect;
  2498. begin
  2499. GetExtent(R);
  2500. MaxWidth:=AMaxWidth;
  2501. if (HScrollBar<>nil) and (R.B.X-R.A.X<MaxWidth) then
  2502. HScrollBar^.SetRange(0,MaxWidth-(R.B.X-R.A.X))
  2503. else
  2504. HScrollBar^.SetRange(0,0);
  2505. if R.B.X-R.A.X>MaxWidth then
  2506. HScrollBar^.Hide
  2507. else
  2508. HScrollBar^.Show;
  2509. SetRange(List^.Count+1);
  2510. if R.B.Y-R.A.Y>Range then
  2511. VScrollBar^.Hide
  2512. else
  2513. VScrollBar^.Show;
  2514. {if Focused=List^.Count-1-1 then
  2515. FocusItem(List^.Count-1);
  2516. What was that for ?? PM }
  2517. DrawView;
  2518. end;
  2519. function TWatchesListBox.GetIndentedText(Item,Indent,MaxLen: Sw_Integer;var Modified : boolean): String;
  2520. var
  2521. PW : PWatch;
  2522. ValOffset : Sw_integer;
  2523. S : String;
  2524. begin
  2525. Modified:=false;
  2526. if Item>=WatchesCollection^.Count then
  2527. begin
  2528. GetIndentedText:='';
  2529. exit;
  2530. end;
  2531. PW:=WatchesCollection^.At(Item);
  2532. ValOffset:=Length(GetStr(PW^.Expr))+2;
  2533. if not assigned(PW^.expr) then
  2534. GetIndentedText:=''
  2535. else if Indent<ValOffset then
  2536. begin
  2537. S:=GetStr(PW^.Expr);
  2538. if Indent=0 then
  2539. S:=' '+S
  2540. else
  2541. S:=Copy(S,Indent,High(S));
  2542. if not assigned(PW^.current_value) then
  2543. S:=S+' <Unknown value>'
  2544. else
  2545. S:=S+' '+GetPChar(PW^.Current_value);
  2546. GetIndentedText:=Copy(S,1,MaxLen);
  2547. end
  2548. else
  2549. begin
  2550. if not assigned(PW^.Current_value) or
  2551. (StrLen(PW^.Current_value)<Indent-Valoffset) then
  2552. S:=''
  2553. else
  2554. S:=GetPchar(@(PW^.Current_Value[Indent-Valoffset]));
  2555. GetIndentedText:=Copy(S,1,MaxLen);
  2556. end;
  2557. if assigned(PW^.current_value) and
  2558. assigned(PW^.last_value) and
  2559. (strcomp(PW^.Last_value,PW^.Current_value)<>0) then
  2560. Modified:=true;
  2561. end;
  2562. procedure TWatchesListBox.EditCurrent;
  2563. var
  2564. P: PWatch;
  2565. begin
  2566. if Range=0 then Exit;
  2567. if Focused<WatchesCollection^.Count then
  2568. P:=WatchesCollection^.At(Focused)
  2569. else
  2570. P:=New(PWatch,Init(''));
  2571. Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil);
  2572. WatchesCollection^.Update;
  2573. end;
  2574. function TWatchesListBox.GetText (Item: Sw_Integer; MaxLen: Sw_Integer): String;
  2575. var
  2576. Dummy_Modified : boolean;
  2577. begin
  2578. GetText:=GetIndentedText(Item, 0, MaxLen, Dummy_Modified);
  2579. end;
  2580. procedure TWatchesListBox.DeleteCurrent;
  2581. var
  2582. P: PWatch;
  2583. begin
  2584. if (Range=0) or
  2585. (Focused>=WatchesCollection^.Count) then
  2586. exit;
  2587. P:=WatchesCollection^.At(Focused);
  2588. WatchesCollection^.free(P);
  2589. WatchesCollection^.Update;
  2590. end;
  2591. procedure TWatchesListBox.EditNew;
  2592. var
  2593. P: PWatch;
  2594. S : string;
  2595. begin
  2596. if Focused<WatchesCollection^.Count then
  2597. begin
  2598. P:=WatchesCollection^.At(Focused);
  2599. S:=GetStr(P^.expr);
  2600. end
  2601. else
  2602. S:='';
  2603. P:=New(PWatch,Init(S));
  2604. if Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil)<>cmCancel then
  2605. begin
  2606. WatchesCollection^.AtInsert(Focused,P);
  2607. WatchesCollection^.Update;
  2608. end
  2609. else
  2610. dispose(P,Done);
  2611. end;
  2612. procedure TWatchesListBox.Draw;
  2613. var
  2614. I, J, Item: Sw_Integer;
  2615. NormalColor, SelectedColor, FocusedColor, Color: Word;
  2616. ColWidth, CurCol, Indent: Integer;
  2617. B: TDrawBuffer;
  2618. Modified : boolean;
  2619. Text: String;
  2620. SCOff: Byte;
  2621. TC: byte;
  2622. procedure MT(var C: word);
  2623. begin
  2624. if TC<>0 then C:=(C and $ff0f) or (TC and $f0);
  2625. end;
  2626. begin
  2627. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  2628. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  2629. begin
  2630. NormalColor := GetColor(1);
  2631. FocusedColor := GetColor(3);
  2632. SelectedColor := GetColor(4);
  2633. end else
  2634. begin
  2635. NormalColor := GetColor(2);
  2636. SelectedColor := GetColor(4);
  2637. end;
  2638. if Transparent then
  2639. begin MT(NormalColor); MT(SelectedColor); end;
  2640. (* if NoSelection then
  2641. SelectedColor:=NormalColor;*)
  2642. if HScrollBar <> nil then Indent := HScrollBar^.Value
  2643. else Indent := 0;
  2644. ColWidth := Size.X div NumCols + 1;
  2645. for I := 0 to Size.Y - 1 do
  2646. begin
  2647. for J := 0 to NumCols-1 do
  2648. begin
  2649. Item := J*Size.Y + I + TopItem;
  2650. CurCol := J*ColWidth;
  2651. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  2652. (Focused = Item) and (Range > 0) then
  2653. begin
  2654. Color := FocusedColor;
  2655. SetCursor(CurCol+1,I);
  2656. SCOff := 0;
  2657. end
  2658. else if (Item < Range) and IsSelected(Item) then
  2659. begin
  2660. Color := SelectedColor;
  2661. SCOff := 2;
  2662. end
  2663. else
  2664. begin
  2665. Color := NormalColor;
  2666. SCOff := 4;
  2667. end;
  2668. MoveChar(B[CurCol], ' ', Color, ColWidth);
  2669. if Item < Range then
  2670. begin
  2671. (* Text := GetText(Item, ColWidth + Indent);
  2672. Text := Copy(Text,Indent,ColWidth); *)
  2673. Text:=GetIndentedText(Item,Indent,ColWidth,Modified);
  2674. if modified then
  2675. begin
  2676. SCOff:=0;
  2677. Color:=(Color and $fff0) or Red;
  2678. end;
  2679. MoveStr(B[CurCol], Text, Color);
  2680. if {ShowMarkers or } Modified then
  2681. begin
  2682. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  2683. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  2684. WordRec(B[CurCol+ColWidth-2]).Hi := Color and $ff;
  2685. end;
  2686. end;
  2687. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  2688. end;
  2689. WriteLine(0, I, Size.X, 1, B);
  2690. end;
  2691. end;
  2692. function TWatchesListBox.GetLocalMenu: PMenu;
  2693. var M: PMenu;
  2694. begin
  2695. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  2696. M:=NewMenu(
  2697. NewItem(menu_watchlocal_edit,'',kbNoKey,cmEdit,hcNoContext,
  2698. NewItem(menu_watchlocal_new,'',kbNoKey,cmNew,hcNoContext,
  2699. NewItem(menu_watchlocal_delete,'',kbNoKey,cmDelete,hcNoContext,
  2700. NewLine(
  2701. NewItem(menu_msglocal_saveas,'',kbNoKey,cmSaveAs,hcSaveAs,
  2702. nil))))));
  2703. GetLocalMenu:=M;
  2704. end;
  2705. procedure TWatchesListBox.HandleEvent(var Event: TEvent);
  2706. var DontClear: boolean;
  2707. begin
  2708. case Event.What of
  2709. evKeyDown :
  2710. begin
  2711. DontClear:=false;
  2712. case Event.KeyCode of
  2713. kbEnter :
  2714. Message(@Self,evCommand,cmEdit,nil);
  2715. kbIns :
  2716. Message(@Self,evCommand,cmNew,nil);
  2717. kbDel :
  2718. Message(@Self,evCommand,cmDelete,nil);
  2719. else
  2720. DontClear:=true;
  2721. end;
  2722. if not DontClear then
  2723. ClearEvent(Event);
  2724. end;
  2725. evBroadcast :
  2726. case Event.Command of
  2727. cmListItemSelected :
  2728. if Event.InfoPtr=@Self then
  2729. Message(@Self,evCommand,cmEdit,nil);
  2730. end;
  2731. evCommand :
  2732. begin
  2733. DontClear:=false;
  2734. case Event.Command of
  2735. cmEdit :
  2736. EditCurrent;
  2737. cmDelete :
  2738. DeleteCurrent;
  2739. cmNew :
  2740. EditNew;
  2741. else
  2742. DontClear:=true;
  2743. end;
  2744. if not DontClear then
  2745. ClearEvent(Event);
  2746. end;
  2747. end;
  2748. inherited HandleEvent(Event);
  2749. end;
  2750. constructor TWatchesListBox.Load(var S: TStream);
  2751. begin
  2752. inherited Load(S);
  2753. If assigned(List) then
  2754. dispose(list,done);
  2755. List:=WatchesCollection;
  2756. { we must set Range PM }
  2757. SetRange(List^.count+1);
  2758. end;
  2759. procedure TWatchesListBox.Store(var S: TStream);
  2760. var OL: PCollection;
  2761. OldRange : Sw_integer;
  2762. begin
  2763. OL:=List;
  2764. OldRange:=Range;
  2765. Range:=0;
  2766. New(List, Init(1,1));
  2767. inherited Store(S);
  2768. Dispose(List, Done);
  2769. List:=OL;
  2770. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  2771. collection? Pasting here a modified version of TListBox.Store+
  2772. TAdvancedListBox.Store isn't a better solution, since by eventually
  2773. changing the obj-hierarchy you'll always have to modify this, too - BG }
  2774. SetRange(OldRange);
  2775. end;
  2776. destructor TWatchesListBox.Done;
  2777. begin
  2778. List:=nil;
  2779. inherited Done;
  2780. end;
  2781. {****************************************************************************
  2782. TWatchesWindow
  2783. ****************************************************************************}
  2784. Constructor TWatchesWindow.Init;
  2785. var
  2786. HSB,VSB: PScrollBar;
  2787. R,R2 : trect;
  2788. begin
  2789. Desktop^.GetExtent(R);
  2790. R.A.Y:=R.B.Y-7;
  2791. inherited Init(R, dialog_watches,SearchFreeWindowNo);
  2792. Palette:=wpCyanWindow;
  2793. GetExtent(R);
  2794. HelpCtx:=hcWatchesWindow;
  2795. R.Grow(-1,-1);
  2796. R2.Copy(R);
  2797. Inc(R2.B.Y);
  2798. R2.A.Y:=R2.B.Y-1;
  2799. New(HSB, Init(R2));
  2800. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  2801. HSB^.SetStep(R.B.X-R.A.X,1);
  2802. Insert(HSB);
  2803. R2.Copy(R);
  2804. Inc(R2.B.X);
  2805. R2.A.X:=R2.B.X-1;
  2806. New(VSB, Init(R2));
  2807. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  2808. Insert(VSB);
  2809. New(WLB,Init(R,HSB,VSB));
  2810. WLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  2811. WLB^.Transparent:=true;
  2812. Insert(WLB);
  2813. If assigned(WatchesWindow) then
  2814. dispose(WatchesWindow,done);
  2815. WatchesWindow:=@Self;
  2816. Update;
  2817. end;
  2818. procedure TWatchesWindow.Update;
  2819. begin
  2820. WatchesCollection^.Update;
  2821. Draw;
  2822. end;
  2823. constructor TWatchesWindow.Load(var S: TStream);
  2824. begin
  2825. inherited Load(S);
  2826. GetSubViewPtr(S,WLB);
  2827. If assigned(WatchesWindow) then
  2828. dispose(WatchesWindow,done);
  2829. WatchesWindow:=@Self;
  2830. end;
  2831. procedure TWatchesWindow.Store(var S: TStream);
  2832. begin
  2833. inherited Store(S);
  2834. PutSubViewPtr(S,WLB);
  2835. end;
  2836. Destructor TWatchesWindow.Done;
  2837. begin
  2838. WatchesWindow:=nil;
  2839. Dispose(WLB,done);
  2840. inherited done;
  2841. end;
  2842. {****************************************************************************
  2843. TWatchItemDialog
  2844. ****************************************************************************}
  2845. constructor TWatchItemDialog.Init(AWatch: PWatch);
  2846. var R,R2: TRect;
  2847. begin
  2848. R.Assign(0,0,50,10);
  2849. inherited Init(R,'Edit Watch');
  2850. Watch:=AWatch;
  2851. GetExtent(R); R.Grow(-3,-2);
  2852. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+36;
  2853. New(NameIL, Init(R, 255)); Insert(NameIL);
  2854. R2.Copy(R); R2.A.X:=R2.B.X; R2.B.X:=R2.A.X+3;
  2855. Insert(New(PHistory, Init(R2, NameIL, hidWatchDialog)));
  2856. R2.Copy(R); R2.Move(-1,-1);
  2857. Insert(New(PLabel, Init(R2, label_watch_expressiontowatch, NameIL)));
  2858. GetExtent(R);
  2859. R.Grow(-3,-1);
  2860. R.A.Y:=R.A.Y+3;
  2861. TextST:=New(PAdvancedStaticText, Init(R, label_watch_values));
  2862. Insert(TextST);
  2863. InsertButtons(@Self);
  2864. NameIL^.Select;
  2865. end;
  2866. function TWatchItemDialog.Execute: Word;
  2867. var R: word;
  2868. S1,S2: string;
  2869. begin
  2870. S1:=GetStr(Watch^.expr);
  2871. NameIL^.SetData(S1);
  2872. S1:=GetPChar(Watch^.Current_value);
  2873. S2:=GetPChar(Watch^.Last_value);
  2874. ClearFormatParams;
  2875. AddFormatParamStr(S1);
  2876. AddFormatParamStr(S2);
  2877. if assigned(Watch^.Last_value) and
  2878. assigned(Watch^.Current_value) and
  2879. (strcomp(Watch^.Last_value,Watch^.Current_value)=0) then
  2880. S1:=FormatStrF(msg_watch_currentvalue,FormatParams)
  2881. else
  2882. S1:=FormatStrF(msg_watch_currentandpreviousvalue,FormatParams);
  2883. TextST^.SetText(S1);
  2884. if assigned(FirstEditorWindow) then
  2885. FindReplaceEditor:=FirstEditorWindow^.Editor;
  2886. R:=inherited Execute;
  2887. FindReplaceEditor:=nil;
  2888. if R=cmOK then
  2889. begin
  2890. NameIL^.GetData(S1);
  2891. Watch^.Rename(S1);
  2892. If assigned(Debugger) then
  2893. Debugger^.ReadWatches;
  2894. end;
  2895. Execute:=R;
  2896. end;
  2897. {****************************************************************************
  2898. TStackWindow
  2899. ****************************************************************************}
  2900. constructor TFramesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  2901. begin
  2902. Inherited Init(Bounds,AHScrollBar,AVScrollBar);
  2903. end;
  2904. procedure TFramesListBox.Update;
  2905. var i : longint;
  2906. W : PSourceWindow;
  2907. begin
  2908. { call backtrace command }
  2909. If not assigned(Debugger) then
  2910. exit;
  2911. {$ifndef NODEBUG}
  2912. DeskTop^.Lock;
  2913. Clear;
  2914. { forget all old frames }
  2915. Debugger^.clear_frames;
  2916. if Debugger^.WindowWidth<>-1 then
  2917. Debugger^.Command('set width 0xffffffff');
  2918. Debugger^.Command('backtrace');
  2919. { generate list }
  2920. { all is in tframeentry }
  2921. for i:=0 to Debugger^.frame_count-1 do
  2922. begin
  2923. with Debugger^.frames[i]^ do
  2924. begin
  2925. if assigned(file_name) then
  2926. AddItem(new(PMessageItem,init(0,GetPChar(function_name)+GetPChar(args),
  2927. AddModuleName(GetPChar(file_name)),line_number,1)))
  2928. else
  2929. AddItem(new(PMessageItem,init(0,HexStr(address,8)+' '+GetPChar(function_name)+GetPChar(args),
  2930. AddModuleName(''),line_number,1)));
  2931. W:=SearchOnDesktop(GetPChar(file_name),false);
  2932. { First reset all Debugger rows }
  2933. If assigned(W) then
  2934. begin
  2935. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,-1);
  2936. W^.Editor^.DebuggerRow:=-1;
  2937. end;
  2938. end;
  2939. end;
  2940. { Now set all Debugger rows }
  2941. for i:=0 to Debugger^.frame_count-1 do
  2942. begin
  2943. with Debugger^.frames[i]^ do
  2944. begin
  2945. W:=SearchOnDesktop(GetPChar(file_name),false);
  2946. If assigned(W) then
  2947. begin
  2948. If W^.Editor^.DebuggerRow=-1 then
  2949. begin
  2950. W^.Editor^.SetLineFlagState(line_number-1,lfDebuggerRow,true);
  2951. W^.Editor^.DebuggerRow:=line_number-1;
  2952. end;
  2953. end;
  2954. end;
  2955. end;
  2956. if Assigned(list) and (List^.Count > 0) then
  2957. FocusItem(0);
  2958. if Debugger^.WindowWidth<>-1 then
  2959. Debugger^.Command('set width '+IntToStr(Debugger^.WindowWidth));
  2960. DeskTop^.Unlock;
  2961. {$endif}
  2962. end;
  2963. function TFramesListBox.GetLocalMenu: PMenu;
  2964. begin
  2965. GetLocalMenu:=Inherited GetLocalMenu;
  2966. end;
  2967. procedure TFramesListBox.GotoSource;
  2968. begin
  2969. { select frame for watches }
  2970. If not assigned(Debugger) then
  2971. exit;
  2972. {$ifndef NODEBUG}
  2973. Debugger^.Command('f '+IntToStr(Focused));
  2974. { for local vars }
  2975. Debugger^.RereadWatches;
  2976. {$endif}
  2977. { goto source }
  2978. inherited GotoSource;
  2979. end;
  2980. procedure TFramesListBox.GotoAssembly;
  2981. begin
  2982. { select frame for watches }
  2983. If not assigned(Debugger) then
  2984. exit;
  2985. {$ifndef NODEBUG}
  2986. Debugger^.Command('f '+IntToStr(Focused));
  2987. { for local vars }
  2988. Debugger^.RereadWatches;
  2989. {$endif}
  2990. { goto source/assembly mixture }
  2991. InitDisassemblyWindow;
  2992. DisassemblyWindow^.LoadFunction('');
  2993. DisassemblyWindow^.SetCurAddress(Debugger^.frames[Focused]^.address);
  2994. DisassemblyWindow^.SelectInDebugSession;
  2995. end;
  2996. procedure TFramesListBox.HandleEvent(var Event: TEvent);
  2997. begin
  2998. if ((Event.What=EvKeyDown) and (Event.CharCode='i')) or
  2999. ((Event.What=EvCommand) and (Event.Command=cmDisassemble)) then
  3000. GotoAssembly;
  3001. inherited HandleEvent(Event);
  3002. end;
  3003. destructor TFramesListBox.Done;
  3004. begin
  3005. Inherited Done;
  3006. end;
  3007. Constructor TStackWindow.Init;
  3008. var
  3009. HSB,VSB: PScrollBar;
  3010. R,R2 : trect;
  3011. begin
  3012. Desktop^.GetExtent(R);
  3013. R.A.Y:=R.B.Y-5;
  3014. inherited Init(R, dialog_callstack, wnNoNumber);
  3015. Palette:=wpCyanWindow;
  3016. GetExtent(R);
  3017. HelpCtx:=hcStackWindow;
  3018. R.Grow(-1,-1);
  3019. R2.Copy(R);
  3020. Inc(R2.B.Y);
  3021. R2.A.Y:=R2.B.Y-1;
  3022. New(HSB, Init(R2));
  3023. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  3024. Insert(HSB);
  3025. R2.Copy(R);
  3026. Inc(R2.B.X);
  3027. R2.A.X:=R2.B.X-1;
  3028. New(VSB, Init(R2));
  3029. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  3030. Insert(VSB);
  3031. New(FLB,Init(R,HSB,VSB));
  3032. FLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  3033. Insert(FLB);
  3034. If assigned(StackWindow) then
  3035. dispose(StackWindow,done);
  3036. StackWindow:=@Self;
  3037. Update;
  3038. end;
  3039. procedure TStackWindow.Update;
  3040. begin
  3041. FLB^.Update;
  3042. DrawView;
  3043. end;
  3044. constructor TStackWindow.Load(var S: TStream);
  3045. begin
  3046. inherited Load(S);
  3047. GetSubViewPtr(S,FLB);
  3048. If assigned(StackWindow) then
  3049. dispose(StackWindow,done);
  3050. StackWindow:=@Self;
  3051. end;
  3052. procedure TStackWindow.Store(var S: TStream);
  3053. begin
  3054. inherited Store(S);
  3055. PutSubViewPtr(S,FLB);
  3056. end;
  3057. Destructor TStackWindow.Done;
  3058. begin
  3059. StackWindow:=nil;
  3060. Dispose(FLB,done);
  3061. inherited done;
  3062. end;
  3063. {****************************************************************************
  3064. Init/Final
  3065. ****************************************************************************}
  3066. function GetGDBTargetShortName : string;
  3067. begin
  3068. {$ifdef SUPPORT_REMOTE}
  3069. GetGDBTargetShortName:='linux';
  3070. {$else not SUPPORT_REMOTE}
  3071. {$ifdef COMPILER_1_0}
  3072. GetGDBTargetShortName:=source_os.shortname
  3073. {$else}
  3074. GetGDBTargetShortName:=source_info.shortname
  3075. {$endif}
  3076. {$endif not SUPPORT_REMOTE}
  3077. end;
  3078. procedure InitDebugger;
  3079. {$ifdef DEBUG}
  3080. var s : string;
  3081. i,p : longint;
  3082. {$endif DEBUG}
  3083. var
  3084. NeedRecompileExe : boolean;
  3085. cm : longint;
  3086. begin
  3087. {$ifdef DEBUG}
  3088. if not use_gdb_file then
  3089. begin
  3090. Assign(gdb_file,GDBOutFileName);
  3091. {$I-}
  3092. Rewrite(gdb_file);
  3093. if InOutRes<>0 then
  3094. begin
  3095. s:=GDBOutFileName;
  3096. p:=pos('.',s);
  3097. if p>1 then
  3098. for i:=0 to 9 do
  3099. begin
  3100. s:=copy(s,1,p-2)+chr(i+ord('0'))+copy(s,p,length(s));
  3101. InOutRes:=0;
  3102. Assign(gdb_file,s);
  3103. rewrite(gdb_file);
  3104. if InOutRes=0 then
  3105. break;
  3106. end;
  3107. end;
  3108. if IOResult=0 then
  3109. Use_gdb_file:=true;
  3110. end;
  3111. {$I+}
  3112. {$endif}
  3113. NeedRecompileExe:=false;
  3114. if TargetSwitches^.GetCurrSelParam<>GetGDBTargetShortName then
  3115. begin
  3116. ClearFormatParams;
  3117. AddFormatParamStr(TargetSwitches^.GetCurrSelParam);
  3118. AddFormatParamStr(GetGDBTargetShortName);
  3119. cm:=ConfirmBox(msg_cantdebugchangetargetto,@FormatParams,true);
  3120. if cm=cmCancel then
  3121. Exit;
  3122. if cm=cmYes then
  3123. begin
  3124. { force recompilation }
  3125. PrevMainFile:='';
  3126. NeedRecompileExe:=true;
  3127. TargetSwitches^.SetCurrSelParam(GetGDBTargetShortName);
  3128. If DebugInfoSwitches^.GetCurrSelParam='-' then
  3129. DebugInfoSwitches^.SetCurrSelParam('l');
  3130. IDEApp.UpdateTarget;
  3131. end;
  3132. end;
  3133. if not NeedRecompileExe then
  3134. NeedRecompileExe:=(not ExistsFile(ExeFile)) or (CompilationPhase<>cpDone) or
  3135. (PrevMainFile<>MainFile) or NeedRecompile(cRun,false);
  3136. if Not NeedRecompileExe and Not MainHasDebugInfo then
  3137. begin
  3138. ClearFormatParams;
  3139. cm:=ConfirmBox(msg_compiledwithoutdebuginforecompile,nil,true);
  3140. if cm=cmCancel then
  3141. Exit;
  3142. if cm=cmYes then
  3143. begin
  3144. { force recompilation }
  3145. PrevMainFile:='';
  3146. NeedRecompileExe:=true;
  3147. DebugInfoSwitches^.SetCurrSelParam('l');
  3148. end;
  3149. end;
  3150. if NeedRecompileExe then
  3151. DoCompile(cRun);
  3152. if CompilationPhase<>cpDone then
  3153. Exit;
  3154. if (EXEFile='') then
  3155. begin
  3156. ErrorBox(msg_nothingtodebug,nil);
  3157. Exit;
  3158. end;
  3159. { init debugcontroller }
  3160. if not assigned(Debugger) then
  3161. begin
  3162. PushStatus(msg_startingdebugger);
  3163. new(Debugger,Init);
  3164. PopStatus;
  3165. end;
  3166. Debugger^.SetExe(ExeFile);
  3167. {$ifdef GDBWINDOW}
  3168. InitGDBWindow;
  3169. {$endif def GDBWINDOW}
  3170. end;
  3171. procedure DoneDebugger;
  3172. begin
  3173. {$ifdef DEBUG}
  3174. If IDEApp.IsRunning then
  3175. PushStatus('Closing debugger');
  3176. {$endif}
  3177. if assigned(Debugger) then
  3178. dispose(Debugger,Done);
  3179. Debugger:=nil;
  3180. {$ifdef DOS}
  3181. If assigned(UserScreen) then
  3182. PDosScreen(UserScreen)^.FreeGraphBuffer;
  3183. {$endif DOS}
  3184. {$ifdef DEBUG}
  3185. If Use_gdb_file then
  3186. begin
  3187. Use_gdb_file:=false;
  3188. Close(GDB_file);
  3189. end;
  3190. If IDEApp.IsRunning then
  3191. PopStatus;
  3192. {$endif DEBUG}
  3193. end;
  3194. procedure InitGDBWindow;
  3195. var
  3196. R : TRect;
  3197. begin
  3198. if GDBWindow=nil then
  3199. begin
  3200. DeskTop^.GetExtent(R);
  3201. new(GDBWindow,init(R));
  3202. DeskTop^.Insert(GDBWindow);
  3203. end;
  3204. end;
  3205. procedure DoneGDBWindow;
  3206. begin
  3207. If IDEApp.IsRunning and
  3208. assigned(GDBWindow) then
  3209. begin
  3210. DeskTop^.Delete(GDBWindow);
  3211. end;
  3212. GDBWindow:=nil;
  3213. end;
  3214. procedure InitDisassemblyWindow;
  3215. var
  3216. R : TRect;
  3217. begin
  3218. if DisassemblyWindow=nil then
  3219. begin
  3220. DeskTop^.GetExtent(R);
  3221. new(DisassemblyWindow,init(R));
  3222. DeskTop^.Insert(DisassemblyWindow);
  3223. end;
  3224. end;
  3225. procedure DoneDisassemblyWindow;
  3226. begin
  3227. if assigned(DisassemblyWindow) then
  3228. begin
  3229. DeskTop^.Delete(DisassemblyWindow);
  3230. Dispose(DisassemblyWindow,Done);
  3231. DisassemblyWindow:=nil;
  3232. end;
  3233. end;
  3234. procedure InitStackWindow;
  3235. begin
  3236. if StackWindow=nil then
  3237. begin
  3238. new(StackWindow,init);
  3239. DeskTop^.Insert(StackWindow);
  3240. end;
  3241. end;
  3242. procedure DoneStackWindow;
  3243. begin
  3244. if assigned(StackWindow) then
  3245. begin
  3246. DeskTop^.Delete(StackWindow);
  3247. StackWindow:=nil;
  3248. end;
  3249. end;
  3250. procedure InitBreakpoints;
  3251. begin
  3252. New(BreakpointsCollection,init(10,10));
  3253. end;
  3254. procedure DoneBreakpoints;
  3255. begin
  3256. Dispose(BreakpointsCollection,Done);
  3257. BreakpointsCollection:=nil;
  3258. end;
  3259. procedure InitWatches;
  3260. begin
  3261. New(WatchesCollection,init);
  3262. end;
  3263. procedure DoneWatches;
  3264. begin
  3265. Dispose(WatchesCollection,Done);
  3266. WatchesCollection:=nil;
  3267. end;
  3268. procedure RegisterFPDebugViews;
  3269. begin
  3270. RegisterType(RWatchesWindow);
  3271. RegisterType(RBreakpointsWindow);
  3272. RegisterType(RWatchesListBox);
  3273. RegisterType(RBreakpointsListBox);
  3274. RegisterType(RStackWindow);
  3275. RegisterType(RFramesListBox);
  3276. RegisterType(RBreakpoint);
  3277. RegisterType(RWatch);
  3278. RegisterType(RBreakpointCollection);
  3279. RegisterType(RWatchesCollection);
  3280. end;
  3281. end.
  3282. {
  3283. $Log$
  3284. Revision 1.43 2002-12-18 01:20:12 pierre
  3285. + Use TEditorInputLine instead of TInputLine
  3286. Revision 1.42 2002/12/16 15:15:40 pierre
  3287. * Added TBreakpointCollection.FindBreakpointAt method
  3288. Revision 1.41 2002/12/16 09:05:28 pierre
  3289. * sanity ceck in ToggleFileLine method
  3290. Revision 1.40 2002/02/09 02:04:46 pierre
  3291. * fix problem with disable all invalid breakpoints
  3292. Revision 1.39 2002/12/12 00:05:57 pierre
  3293. * add code for breakpoint moves + registers in fprags.pas unit
  3294. Revision 1.38 2002/11/30 01:56:52 pierre
  3295. + powerpc cpu support started
  3296. Revision 1.37 2002/11/28 13:00:25 pierre
  3297. + remote support
  3298. Revision 1.36 2002/11/21 17:52:28 pierre
  3299. * some crossgdb infos added
  3300. Revision 1.35 2002/11/21 15:48:39 pierre
  3301. * fix several problems related to remote cross debugging
  3302. Revision 1.34 2002/11/21 00:37:56 pierre
  3303. + some cross gdb enhancements
  3304. Revision 1.33 2002/09/21 22:23:49 pierre
  3305. * restore text mode on reset for Dos apps
  3306. Revision 1.32 2002/09/17 21:58:45 pierre
  3307. * correct last fpu patch so 'info all' is called only once
  3308. Revision 1.31 2002/09/17 21:48:41 pierre
  3309. * allow fpu window to be resized
  3310. Revision 1.30 2002/09/17 21:20:07 pierre
  3311. * fix infinite recursion if GDB window and register window open
  3312. Revision 1.29 2002/09/13 22:30:50 pierre
  3313. * only fpc uses video unit
  3314. Revision 1.28 2002/09/13 08:13:07 pierre
  3315. * avoid RTE 201 in hexstr calls
  3316. Revision 1.27 2002/09/07 21:04:41 carl
  3317. * fix range check errors for version 1.1 compilation
  3318. Revision 1.26 2002/09/07 15:40:42 peter
  3319. * old logs removed and tabs fixed
  3320. Revision 1.25 2002/09/03 13:59:47 pierre
  3321. + added history for watches and breakpoints
  3322. Revision 1.24 2002/09/02 10:18:09 pierre
  3323. * fix problems with breakpoint lists
  3324. Revision 1.23 2002/08/13 08:59:12 pierre
  3325. + Run menu changes depending on wether the debuggee is running or not
  3326. Revision 1.22 2002/08/13 07:15:02 pierre
  3327. + Disable all invalid breakpoints feature added
  3328. Revision 1.21 2002/06/10 19:26:48 pierre
  3329. * check if DebuggeTTY is a valid terminal
  3330. Revision 1.20 2002/06/06 14:11:25 pierre
  3331. * handle win32 Ctrl-C change for graphic version
  3332. Revision 1.19 2002/06/06 08:16:18 pierre
  3333. * avoid crashes if quitting while debuggee is running
  3334. Revision 1.18 2002/04/25 13:33:31 pierre
  3335. * fix the problem with dirs containing asterisks
  3336. Revision 1.17 2002/04/17 11:11:54 pierre
  3337. * avoid problems for ClassVariable in Watches window
  3338. Revision 1.16 2002/04/11 06:41:13 pierre
  3339. * fix problem of TWatchesListBox with fvision
  3340. Revision 1.15 2002/04/03 06:18:30 pierre
  3341. * fix some win32 GDB filename problems
  3342. Revision 1.14 2002/04/02 15:09:38 pierre
  3343. * fixed wrong exit without unlock
  3344. Revision 1.13 2002/04/02 13:23:54 pierre
  3345. * Use StrToCard and HexToCard functions to avoid signed/unsigned overflows
  3346. Revision 1.12 2002/04/02 12:20:58 pierre
  3347. * fix problem with breakpoints in subdirs
  3348. Revision 1.11 2002/04/02 11:10:29 pierre
  3349. * fix FPC_BREAK_ERROR problem and avoid blinking J
  3350. Revision 1.10 2002/03/27 11:24:09 pierre
  3351. * fix several problems related to long file nmze support for win32 exes
  3352. Revision 1.9 2002/02/06 14:45:00 pierre
  3353. + handle signals
  3354. }