gdbcon.pp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Peter Vreman
  4. Lowlevel GDB interface which communicates directly with libgdb
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit GDBCon;
  12. interface
  13. uses
  14. GDBInt;
  15. type
  16. PGDBController=^TGDBController;
  17. TGDBController=object(TGDBInterface)
  18. progname,
  19. progdir,
  20. progargs : pchar;
  21. in_command,
  22. init_count : longint;
  23. constructor Init;
  24. destructor Done;
  25. procedure CommandBegin(const s:string);virtual;
  26. procedure Command(const s:string);
  27. procedure CommandEnd(const s:string);virtual;
  28. procedure Reset;virtual;
  29. { tracing }
  30. procedure StartTrace;
  31. procedure Run;virtual;
  32. procedure TraceStep;virtual;
  33. procedure TraceNext;virtual;
  34. procedure TraceStepI;virtual;
  35. procedure TraceNextI;virtual;
  36. procedure Continue;virtual;
  37. { needed for dos because newlines are only #10 (PM) }
  38. procedure WriteErrorBuf;
  39. procedure WriteOutputBuf;
  40. function GetOutput : Pchar;
  41. function GetError : Pchar;
  42. function LoadFile(var fn:string):boolean;
  43. procedure SetDir(const s : string);
  44. procedure SetArgs(const s : string);
  45. procedure ClearSymbols;
  46. end;
  47. procedure UnixDir(var s : string);
  48. implementation
  49. uses
  50. {$ifdef win32}
  51. windows,
  52. {$endif win32}
  53. strings;
  54. {$ifdef win32}
  55. const
  56. CygDrivePrefixKey1 = 'Software';
  57. CygDrivePrefixKey2 = 'Cygnus Solutions';
  58. CygDrivePrefixKey3 = 'Cygwin';
  59. CygDrivePrefixKey4 = 'mounts v2';
  60. CygDrivePrefixKey = 'cygdrive prefix';
  61. function CygDrivePrefix : string;
  62. var
  63. i : longint;
  64. length : dword;
  65. Value : pchar;
  66. _type : dword;
  67. Key,NKey : HKey;
  68. begin
  69. Length:=0;
  70. Key:=HKEY_CURRENT_USER;
  71. i := RegOpenKeyEx(Key, CygDrivePrefixKey1, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  72. if i=ERROR_SUCCESS then
  73. begin
  74. Key:=NKey;
  75. i := RegOpenKeyEx(Key, CygDrivePrefixKey2, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  76. end;
  77. if i=ERROR_SUCCESS then
  78. begin
  79. RegCloseKey(Key);
  80. Key:=NKey;
  81. i := RegOpenKeyEx(Key, CygDrivePrefixKey3, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  82. end;
  83. if i=ERROR_SUCCESS then
  84. begin
  85. RegCloseKey(Key);
  86. Key:=NKey;
  87. i := RegOpenKeyEx(Key, CygDrivePrefixKey4, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  88. end;
  89. if i=ERROR_SUCCESS then
  90. begin
  91. RegCloseKey(Key);
  92. Key:=NKey;
  93. i := RegQueryValueEx( Key, CygDrivePrefixKey, nil, @_type, nil, @length);
  94. end;
  95. if i<>ERROR_SUCCESS then
  96. CygDrivePrefix:='/cygdrive'
  97. else
  98. Begin
  99. GetMem(Value,Length);
  100. i := RegQueryValueEx( Key, CygDrivePrefixKey, nil, @_type, LPByte(Value), @length);
  101. if i<>ERROR_SUCCESS then
  102. CygDrivePrefix:='/cygdrive'
  103. else
  104. CygDrivePrefix:=StrPas(Value);
  105. FreeMem(Value,Length);
  106. End;
  107. if Key<>HKEY_CURRENT_USER then
  108. RegCloseKey(Key);
  109. end;
  110. {$endif win32}
  111. procedure UnixDir(var s : string);
  112. var i : longint;
  113. begin
  114. for i:=1 to length(s) do
  115. if s[i]='\' then
  116. {$ifdef win32}
  117. { Don't touch at '\ ' used to escapes spaces in windows file names PM }
  118. if (i=length(s)) or (s[i+1]<>' ') then
  119. {$endif win32}
  120. s[i]:='/';
  121. {$ifdef win32}
  122. { for win32 we should convert e:\ into //e/ PM }
  123. if (length(s)>2) and (s[2]=':') and (s[3]='/') then
  124. s:=CygDrivePrefix+'/'+s[1]+copy(s,3,length(s));
  125. {$endif win32}
  126. end;
  127. constructor TGDBController.Init;
  128. begin
  129. inherited init;
  130. end;
  131. destructor TGDBController.Done;
  132. begin
  133. if assigned(progname) then
  134. strdispose(progname);
  135. if assigned(progdir) then
  136. strdispose(progdir);
  137. if assigned(progargs) then
  138. strdispose(progargs);
  139. inherited done;
  140. end;
  141. procedure TGDBController.Command(const s:string);
  142. begin
  143. inc(in_command);
  144. CommandBegin(s);
  145. gdboutputbuf.reset;
  146. gdberrorbuf.reset;
  147. gdb_command(s);
  148. {
  149. What is that for ?? PM
  150. I had to comment it because
  151. it resets the debuggere after each command !!
  152. Maybe it can happen on errors ??
  153. if in_command<0 then
  154. begin
  155. in_command:=0;
  156. inc(in_command);
  157. Reset;
  158. dec(in_command);
  159. end; }
  160. CommandEnd(s);
  161. dec(in_command);
  162. end;
  163. procedure TGDBController.CommandBegin(const s:string);
  164. begin
  165. end;
  166. procedure TGDBController.CommandEnd(const s:string);
  167. begin
  168. end;
  169. function TGDBController.LoadFile(var fn:string):boolean;
  170. var
  171. cmd : string;
  172. begin
  173. getdir(0,cmd);
  174. UnixDir(cmd);
  175. cmd:='cd '+cmd;
  176. Command(cmd);
  177. GDB__Init;
  178. UnixDir(fn);
  179. if assigned(progname) then
  180. strdispose(progname);
  181. getmem(progname,length(fn)+1);
  182. strpcopy(progname,fn);
  183. if fn<>'' then
  184. Command('file '+fn);
  185. LoadFile:=true;
  186. end;
  187. procedure TGDBController.SetDir(const s : string);
  188. var
  189. hs : string;
  190. begin
  191. hs:=s;
  192. UnixDir(hs);
  193. if assigned(progdir) then
  194. strdispose(progdir);
  195. getmem(progdir,length(hs)+1);
  196. strpcopy(progdir,hs);
  197. command('cd '+hs);
  198. end;
  199. procedure TGDBController.SetArgs(const s : string);
  200. begin
  201. if assigned(progargs) then
  202. strdispose(progargs);
  203. getmem(progargs,length(s)+1);
  204. strpcopy(progargs,s);
  205. command('set args '+s);
  206. end;
  207. procedure TGDBController.Reset;
  208. begin
  209. call_reset:=false;
  210. { DeleteBreakPoints(); }
  211. if debuggee_started then
  212. begin
  213. reset_command:=true;
  214. BreakSession;
  215. Command('kill');
  216. reset_command:=false;
  217. debuggee_started:=false;
  218. end;
  219. end;
  220. procedure TGDBController.StartTrace;
  221. begin
  222. Command('tbreak PASCALMAIN');
  223. Run;
  224. end;
  225. procedure TGDBController.Run;
  226. begin
  227. Command('run');
  228. inc(init_count);
  229. end;
  230. procedure TGDBController.TraceStep;
  231. begin
  232. Command('step');
  233. end;
  234. procedure TGDBController.TraceNext;
  235. begin
  236. Command('next');
  237. end;
  238. procedure TGDBController.TraceStepI;
  239. begin
  240. Command('stepi');
  241. end;
  242. procedure TGDBController.TraceNextI;
  243. begin
  244. Command('nexti');
  245. end;
  246. procedure TGDBController.Continue;
  247. begin
  248. Command('continue');
  249. end;
  250. procedure TGDBController.ClearSymbols;
  251. begin
  252. if debuggee_started then
  253. Reset;
  254. if init_count>0 then
  255. Command('file');
  256. end;
  257. procedure BufWrite(Buf : pchar);
  258. var p,pe : pchar;
  259. begin
  260. p:=buf;
  261. While assigned(p) do
  262. begin
  263. pe:=strscan(p,#10);
  264. if pe<>nil then
  265. pe^:=#0;
  266. Writeln(p);
  267. { restore for dispose }
  268. if pe<>nil then
  269. pe^:=#10;
  270. if pe=nil then
  271. p:=nil
  272. else
  273. begin
  274. p:=pe;
  275. inc(p);
  276. end;
  277. end;
  278. end;
  279. function TGDBController.GetOutput : Pchar;
  280. begin
  281. GetOutput:=gdboutputbuf.buf;
  282. end;
  283. function TGDBController.GetError : Pchar;
  284. var p : pchar;
  285. begin
  286. p:=gdberrorbuf.buf;
  287. if (p^=#0) and got_error then
  288. GetError:=pchar(longint(gdboutputbuf.buf)+gdboutputbuf.idx)
  289. else
  290. GetError:=p;
  291. end;
  292. procedure TGDBController.WriteErrorBuf;
  293. begin
  294. BufWrite(gdberrorbuf.buf);
  295. end;
  296. procedure TGDBController.WriteOutputBuf;
  297. begin
  298. BufWrite(gdboutputbuf.buf);
  299. end;
  300. end.
  301. {
  302. $Log$
  303. Revision 1.6 2004-11-08 21:55:09 peter
  304. * fixed run directory
  305. * Open dialog starts in dir of last editted file
  306. Revision 1.5 2002/09/17 20:57:04 pierre
  307. * increment in_command before calling CommandBegin
  308. and after calling CommandEnd to be able to count
  309. command levels inside these methods.
  310. Revision 1.4 2002/09/07 15:42:51 peter
  311. * old logs removed and tabs fixed
  312. Revision 1.3 2002/04/03 09:09:22 pierre
  313. * fix UniwDir for win32 gdbcon.pp
  314. Revision 1.2 2002/03/26 16:23:14 pierre
  315. * get IDE to work with dirs containing spaces for win32
  316. Revision 1.1 2002/01/29 17:54:49 peter
  317. * splitted to base and extra
  318. }