unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, process, FileUtil, Forms, Controls, Graphics, Dialogs,
  StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Memo1: TMemo;
    memoError: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure memoErrorChange(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
const
  READ_BYTES = 2048;
var
  S: TStringList;
  M: TMemoryStream;
  P: TProcess;
  n: LongInt;
  BytesRead: LongInt;
begin

  Memo1.Clear;
  memoError.Clear;

  // Wir können poWaitOnExit hier nicht nutzen, weil wir die
  // Größe des Outputs nicht kennen. In Linux ist die Größe der
  // Pipe 2kB. Wenn die Ausgabe größer ist, müssen die Daten
  // zwischenzeitlich ausgelesen werden. Dies ist nicht möglich,
  // wenn auf das Ende gewartet wird - ein Deadlock tritt auf.
  //
  // Ein temporärer Memorystream wird verwendet, um den output zu puffern.

  M := TMemoryStream.Create;
  BytesRead := 0;

  P := TProcess.Create(nil);
//  P.CommandLine := 'ppc386 -va bogus.pp';
  if (ComboBox1.Text[1] = '[') and (ComboBox1.Text[5] = ']') then
    P.CommandLine := RightStr(ComboBox1.Text,Length(ComboBox1.Text)-6)
  else
    P.CommandLine := ComboBox1.Text;
  P.Options := [poUsePipes];
//  WriteLn('-- executing --');
  P.Execute;
  while P.Running do
  begin
    // stellt sicher, dass wir Platz haben
    M.SetSize(BytesRead + READ_BYTES);

    // versuche, es zu lesen
    n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
    if n > 0
    then begin
      Inc(BytesRead, n);
//      Write('.')
    end
    else begin
      // keine Daten, warte 100 ms
      Sleep(100);
    end;
  end;
  // lese den letzten Teil
  repeat
    // stellt sicher, dass wir Platz haben
    M.SetSize(BytesRead + READ_BYTES);
    // versuche es zu lesen
    n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
    if n > 0
    then begin
      Inc(BytesRead, n);
//      Write('.');
    end;
  until n <= 0;
//  if BytesRead > 0 then WriteLn;
  M.SetSize(BytesRead);
//  WriteLn('-- executed --');

  S := TStringList.Create;
//  S.LoadFromStream(M);
  Memo1.Lines.LoadFromStream(M);
  memoError.Lines.LoadFromStream(P.Stderr);
//  WriteLn('-- linecount = ', S.Count, ' --');
  for n := 0 to S.Count - 1 do
  begin
//    WriteLn('| ', S[n]);
  end;
//  WriteLn('-- end --');
  S.Free;
  P.Free;
  M.Free;


end;

procedure TForm1.memoErrorChange(Sender: TObject);
begin

end;

end.

