mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-13 05:03:59 +02:00
210 lines
4.9 KiB
ObjectPascal
210 lines
4.9 KiB
ObjectPascal
{ ----------------------------------------------------
|
|
DbgIntfPsuedoTerminal.pp - Debugger helper class
|
|
----------------------------------------------------
|
|
|
|
This unit contains a helper class for a console containing a program being debugged.
|
|
|
|
|
|
***************************************************************************
|
|
* *
|
|
* This source is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This code is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* General Public License for more details. *
|
|
* *
|
|
* A copy of the GNU General Public License is available on the World *
|
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
|
* obtain it by writing to the Free Software Foundation, *
|
|
* Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
|
|
* *
|
|
***************************************************************************
|
|
}
|
|
|
|
unit DbgIntfPseudoTerminal;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$IFDEF linux} {$DEFINE DBG_ENABLE_TERMINAL} {$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils
|
|
{$IFDEF DBG_ENABLE_TERMINAL}
|
|
, IDEMiniLibC, BaseUnix
|
|
{$ENDIF}
|
|
;
|
|
|
|
type
|
|
|
|
{ TPseudoTerminal }
|
|
|
|
TPseudoTerminal = class
|
|
{$IFDEF DBG_ENABLE_TERMINAL}
|
|
private
|
|
FDeviceName: string;
|
|
FOnCanRead: TNotifyEvent;
|
|
FPTy: Integer;
|
|
FReadBuf: String;
|
|
procedure CloseInp;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Open;
|
|
procedure Close;
|
|
function Write(s: string): Integer;
|
|
function Read: String;
|
|
procedure CheckCanRead;
|
|
property OnCanRead: TNotifyEvent read FOnCanRead write FOnCanRead;
|
|
property DevicePtyMaster: integer read FPty;
|
|
property Devicename: string read FDeviceName;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
{$IFDEF DBG_ENABLE_TERMINAL}
|
|
|
|
{ TPseudoTerminal }
|
|
|
|
procedure TPseudoTerminal.CloseInp;
|
|
var
|
|
ios: termios;
|
|
begin
|
|
// Based on MSEGui
|
|
if FPTy = InvalHandle then exit;
|
|
tcgetattr(FPty, @ios);
|
|
ios.c_lflag:= (ios.c_lflag and not (icanon)) or echo;
|
|
ios.c_cc[vmin]:= 0;
|
|
ios.c_cc[vtime]:= 0;
|
|
tcsetattr(FPty, tcsanow, @ios);
|
|
//foutput.writeln('');
|
|
end;
|
|
|
|
constructor TPseudoTerminal.Create;
|
|
begin
|
|
FPTy := InvalHandle;
|
|
end;
|
|
|
|
destructor TPseudoTerminal.Destroy;
|
|
begin
|
|
Close;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TPseudoTerminal.Close;
|
|
begin
|
|
CloseInp;
|
|
if FPTy <> InvalHandle
|
|
then __Close(FPTy);
|
|
FPTy := InvalHandle;
|
|
end;
|
|
|
|
procedure TPseudoTerminal.Open;
|
|
const
|
|
BufLen = 100;
|
|
var
|
|
ios: termios;
|
|
int1: integer;
|
|
|
|
procedure Error;
|
|
begin
|
|
if FPTy <> InvalHandle
|
|
then __Close(FPTy);
|
|
FPTy := InvalHandle;
|
|
FDeviceName := '';
|
|
end;
|
|
|
|
begin
|
|
Close;
|
|
FPTy := getpt;
|
|
if FPTy < 0 then Error;
|
|
if (grantpt(FPTy) < 0) or (unlockpt(FPTy) < 0) then begin
|
|
Error;
|
|
exit;
|
|
end;
|
|
setlength(FDeviceName, BufLen);
|
|
if ptsname_r(FPTy, @FDeviceName[1], BufLen) < 0 then begin
|
|
Error;
|
|
exit;
|
|
end;
|
|
setlength(FDeviceName,length(pchar(FDeviceName)));
|
|
if tcgetattr(FPTy, @ios) <> 0 then begin
|
|
Error;
|
|
exit;
|
|
end;
|
|
ios.c_lflag:= ios.c_lflag and not (icanon); // or echo);
|
|
ios.c_cc[vmin]:= 1;
|
|
ios.c_cc[vtime]:= 0;
|
|
if tcsetattr(FPTy, tcsanow, @ios) <> 0 then begin
|
|
Error;
|
|
exit;
|
|
end;
|
|
|
|
int1 := fcntl(FPTy, f_getfl, 0);
|
|
if int1 = InvalHandle then begin
|
|
Error;
|
|
exit;
|
|
end;
|
|
if fcntl(FPTy, f_setfl, int1 or o_nonblock) = InvalHandle then Error;
|
|
end;
|
|
|
|
function TPseudoTerminal.Write(s: string): Integer;
|
|
var
|
|
int1, nbytes: Integer;
|
|
p: PChar;
|
|
begin
|
|
nbytes := length(s);
|
|
if (FPTy = InvalHandle) or (nbytes = 0) then exit(0);
|
|
Result:= nbytes;
|
|
p := @s[1];
|
|
repeat
|
|
int1 := __write(FPTy, p^, nbytes);
|
|
if int1 = -1 then begin
|
|
if errno <> eintr then begin
|
|
Result:= int1;
|
|
break;
|
|
end;
|
|
continue;
|
|
end;
|
|
inc(p, int1);
|
|
dec(nbytes, int1);
|
|
until integer(nbytes) <= 0;
|
|
end;
|
|
|
|
function TPseudoTerminal.Read: String;
|
|
const
|
|
BufLen = 1024;
|
|
var
|
|
buf: String;
|
|
i: Integer;
|
|
begin
|
|
if (FPTy = InvalHandle) then exit('');
|
|
|
|
SetLength(buf, BufLen + 1);
|
|
Result := FReadBuf;
|
|
FReadBuf := '';
|
|
repeat
|
|
i := __read(FPTy, buf[1], BufLen);
|
|
if i > 0 then Result := Result + copy(buf, 1, i);
|
|
until i <= 0;
|
|
end;
|
|
|
|
procedure TPseudoTerminal.CheckCanRead;
|
|
begin
|
|
FReadBuf := Read;
|
|
if (FReadBuf <> '') and assigned(FOnCanRead)
|
|
then FOnCanRead(self);
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
end.
|
|
|