gdbmiproc.pas 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. {
  2. Copyright (c) 2015 by Nikolay Nikolov
  3. This unit implements a class, which launches gdb in GDB/MI mode
  4. and allows sending textual commands to it and receiving the response
  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 GDBMIProc;
  12. {$MODE objfpc}{$H+}
  13. interface
  14. uses
  15. SysUtils, Classes, Process;
  16. type
  17. TGDBProcess = class
  18. private
  19. FProcess: TProcess;
  20. FDebugLog: TextFile;
  21. function IsAlive: Boolean;
  22. procedure GDBWrite(const S: string);
  23. procedure DebugLn(const S: string);
  24. procedure DebugErrorLn(const S: string);
  25. public
  26. constructor Create;
  27. destructor Destroy; override;
  28. function GDBReadLn: string;
  29. procedure GDBWriteLn(const S: string);
  30. property Alive: Boolean read IsAlive;
  31. end;
  32. implementation
  33. var
  34. DebugLogEnabled: Boolean = False;
  35. GdbProgramName: string = 'gdb';
  36. function TGDBProcess.IsAlive: Boolean;
  37. begin
  38. Result := Assigned(FProcess) and FProcess.Running;
  39. end;
  40. function TGDBProcess.GDBReadLn: string;
  41. var
  42. C: Char;
  43. begin
  44. Result := '';
  45. while FProcess.Running do
  46. begin
  47. FProcess.Output.Read(C, 1);
  48. {$ifdef windows}
  49. { On windows we expect both #13 and #10 }
  50. if C = #13 then
  51. begin
  52. FPRocess.Output.Read(C,1);
  53. {$endif windows}
  54. if C = #10 then
  55. begin
  56. DebugLn(Result);
  57. exit;
  58. end;
  59. {$ifdef windows}
  60. end;
  61. {$endif windows}
  62. Result := Result + C;
  63. end;
  64. end;
  65. constructor TGDBProcess.Create;
  66. begin
  67. if DebugLogEnabled then
  68. begin
  69. AssignFile(FDebugLog, 'gdblog.txt');
  70. Rewrite(FDebugLog);
  71. CloseFile(FDebugLog);
  72. end;
  73. FProcess := TProcess.Create(nil);
  74. FProcess.Options := [poUsePipes, poStdErrToOutput];
  75. FProcess.Executable := GdbProgramName;
  76. FProcess.Parameters.Add('--interpreter=mi');
  77. try
  78. FProcess.Execute;
  79. except
  80. on e: Exception do
  81. begin
  82. DebugErrorLn('Could not start GDB: ' + e.Message);
  83. FreeAndNil(FProcess);
  84. end;
  85. end;
  86. end;
  87. destructor TGDBProcess.Destroy;
  88. begin
  89. FProcess.Free;
  90. inherited Destroy;
  91. end;
  92. procedure TGDBProcess.DebugLn(const S: string);
  93. begin
  94. if DebugLogEnabled then
  95. begin
  96. Append(FDebugLog);
  97. Writeln(FDebugLog, S);
  98. CloseFile(FDebugLog);
  99. end;
  100. end;
  101. procedure TGDBProcess.DebugErrorLn(const S: string);
  102. begin
  103. DebugLn('ERROR: ' + S);
  104. end;
  105. procedure TGDBProcess.GDBWrite(const S: string);
  106. begin
  107. FProcess.Input.Write(S[1], Length(S));
  108. end;
  109. procedure TGDBProcess.GDBWriteln(const S: string);
  110. begin
  111. if not IsAlive then
  112. begin
  113. DebugErrorLn('Trying to send command to a dead GDB: ' + S);
  114. exit;
  115. end;
  116. DebugLn(S);
  117. GDBWrite(S + #10);
  118. end;
  119. begin
  120. if GetEnvironmentVariable('FPIDE_GDBLOG') = '1' then
  121. DebugLogEnabled := True;
  122. if GetEnvironmentVariable('FPIDE_GDBPROG') <> '' then
  123. GdbProgramName := GetEnvironmentVariable('FPIDE_GDBPROG');
  124. end.