gdbmiproc.pas 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. if C = #10 then
  49. begin
  50. DebugLn(Result);
  51. exit;
  52. end;
  53. Result := Result + C;
  54. end;
  55. end;
  56. constructor TGDBProcess.Create;
  57. begin
  58. if DebugLogEnabled then
  59. begin
  60. AssignFile(FDebugLog, 'gdblog.txt');
  61. Rewrite(FDebugLog);
  62. CloseFile(FDebugLog);
  63. end;
  64. FProcess := TProcess.Create(nil);
  65. FProcess.Options := [poUsePipes, poStdErrToOutput];
  66. FProcess.Executable := GdbProgramName;
  67. FProcess.Parameters.Add('--interpreter=mi');
  68. try
  69. FProcess.Execute;
  70. except
  71. on e: Exception do
  72. begin
  73. DebugErrorLn('Could not start GDB: ' + e.Message);
  74. FreeAndNil(FProcess);
  75. end;
  76. end;
  77. end;
  78. destructor TGDBProcess.Destroy;
  79. begin
  80. FProcess.Free;
  81. inherited Destroy;
  82. end;
  83. procedure TGDBProcess.DebugLn(const S: string);
  84. begin
  85. if DebugLogEnabled then
  86. begin
  87. Append(FDebugLog);
  88. Writeln(FDebugLog, S);
  89. CloseFile(FDebugLog);
  90. end;
  91. end;
  92. procedure TGDBProcess.DebugErrorLn(const S: string);
  93. begin
  94. DebugLn('ERROR: ' + S);
  95. end;
  96. procedure TGDBProcess.GDBWrite(const S: string);
  97. begin
  98. FProcess.Input.Write(S[1], Length(S));
  99. end;
  100. procedure TGDBProcess.GDBWriteln(const S: string);
  101. begin
  102. if not IsAlive then
  103. begin
  104. DebugErrorLn('Trying to send command to a dead GDB: ' + S);
  105. exit;
  106. end;
  107. DebugLn(S);
  108. GDBWrite(S + #10);
  109. end;
  110. begin
  111. if GetEnvironmentVariable('FPIDE_GDBLOG') = '1' then
  112. DebugLogEnabled := True;
  113. if GetEnvironmentVariable('FPIDE_GDBPROG') <> '' then
  114. GdbProgramName := GetEnvironmentVariable('FPIDE_GDBPROG');
  115. end.