tstppuutils.pas 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. unit tstppuutils;
  2. {$mode ObjFPC}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Process;
  6. function FileIsExecutable(const AFilename: string): boolean;
  7. function RunTool(const Filename: string; Params: TStrings;
  8. WorkingDirectory: string; Quiet, WriteOnError: boolean; out Lines: TStringList): boolean;
  9. implementation
  10. {$IFDEF Unix}
  11. uses BaseUnix;
  12. {$ENDIF}
  13. function FileIsExecutable(const AFilename: string): boolean;
  14. {$IFDEF Unix}
  15. var
  16. Info : Stat;
  17. begin
  18. // first check AFilename is not a directory and then check if executable
  19. Result:= (FpStat(AFilename,info{%H-})<>-1) and FPS_ISREG(info.st_mode)
  20. and (BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0);
  21. end;
  22. {$ELSE}
  23. begin
  24. Result:=FileExists(AFilename);
  25. end;
  26. {$ENDIF}
  27. function RunTool(const Filename: string; Params: TStrings;
  28. WorkingDirectory: string; Quiet, WriteOnError: boolean; out Lines: TStringList): boolean;
  29. var
  30. buf: string;
  31. TheProcess: TProcess;
  32. OutputLine: String;
  33. OutLen: Integer;
  34. LineStart, i: Integer;
  35. begin
  36. Result:=false;
  37. Lines:=nil;
  38. if not FileIsExecutable(Filename) then
  39. raise Exception.Create('Compiler not executable: "'+Filename+'"');
  40. if (WorkingDirectory<>'') and not DirectoryExists(WorkingDirectory) then
  41. raise Exception.Create('WorkingDirectory not found "'+WorkingDirectory+'"');
  42. Lines:=TStringList.Create;
  43. buf:='';
  44. if (MainThreadID=GetCurrentThreadId) and not Quiet then begin
  45. write('Hint: RunTool: "',Filename,'"');
  46. for i:=0 to Params.Count-1 do
  47. write(' "',Params[i],'"');
  48. if WorkingDirectory<>'' then
  49. write(', WorkDir="',WorkingDirectory,'"');
  50. writeln;
  51. end;
  52. TheProcess := TProcess.Create(nil);
  53. try
  54. TheProcess.Executable := Filename;
  55. TheProcess.Parameters:=Params;
  56. TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
  57. TheProcess.ShowWindow := swoHide;
  58. TheProcess.CurrentDirectory:=WorkingDirectory;
  59. TheProcess.Execute;
  60. OutputLine:='';
  61. SetLength(buf,4096);
  62. repeat
  63. if (TheProcess.Output<>nil) then begin
  64. OutLen:=TheProcess.Output.Read(Buf[1],length(Buf));
  65. end else
  66. OutLen:=0;
  67. LineStart:=1;
  68. i:=1;
  69. while i<=OutLen do begin
  70. if Buf[i] in [#10,#13] then begin
  71. OutputLine:=OutputLine+copy(Buf,LineStart,i-LineStart);
  72. Lines.Add(OutputLine);
  73. OutputLine:='';
  74. if (i<OutLen) and (Buf[i+1] in [#10,#13]) and (Buf[i]<>Buf[i+1])
  75. then
  76. inc(i);
  77. LineStart:=i+1;
  78. end;
  79. inc(i);
  80. end;
  81. OutputLine:=OutputLine+copy(Buf,LineStart,OutLen-LineStart+1);
  82. until OutLen=0;
  83. if OutputLine<>'' then
  84. Lines.Add(OutputLine);
  85. TheProcess.WaitOnExit;
  86. Result:=(TheProcess.ExitCode=0) and (TheProcess.ExitStatus=0);
  87. finally
  88. if not Result and WriteOnError then
  89. begin
  90. for i:=0 to Lines.Count-1 do
  91. writeln(Lines[i]);
  92. end;
  93. TheProcess.Free;
  94. end;
  95. end;
  96. end.