mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 18:39:25 +01:00
258 lines
5.4 KiB
ObjectPascal
258 lines
5.4 KiB
ObjectPascal
{$mode objfpc}
|
|
{$h+}
|
|
unit pkgglobals;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils,
|
|
Classes;
|
|
|
|
Const
|
|
{$ifdef unix}
|
|
ExeExt = '';
|
|
AllFiles='*';
|
|
{$else unix}
|
|
ExeExt = '.exe';
|
|
AllFiles='*.*';
|
|
{$endif unix}
|
|
|
|
Type
|
|
TVerbosity = (vError,vWarning,vInfo,vCommands,vDebug);
|
|
TVerbosities = Set of TVerbosity;
|
|
|
|
EPackagerError = class(Exception);
|
|
|
|
// Logging
|
|
Function StringToVerbosity (S : String) : TVerbosity;
|
|
Function VerbosityToString (V : TVerbosity): String;
|
|
Procedure Log(Level: TVerbosity;Msg : String);
|
|
Procedure Log(Level: TVerbosity;Fmt : String; const Args : array of const);
|
|
Procedure Error(Msg : String);
|
|
Procedure Error(Fmt : String; const Args : array of const);
|
|
|
|
// Utils
|
|
function maybequoted(const s:string):string;
|
|
Function FixPath(const S : String) : string;
|
|
Procedure DeleteDir(const ADir:string);
|
|
Procedure SearchFiles(SL:TStringList;const APattern:string);
|
|
Function GetCompilerInfo(const ACompiler,AOptions:string):string;
|
|
|
|
var
|
|
Verbosity : TVerbosities;
|
|
|
|
|
|
Implementation
|
|
|
|
// define use_shell to use sysutils.executeprocess
|
|
// as alternate to using 'process' in getcompilerinfo
|
|
{$IFDEF GO32v2}
|
|
{$DEFINE USE_SHELL}
|
|
{$ENDIF GO32v2}
|
|
|
|
{$IFDEF WATCOM}
|
|
{$DEFINE USE_SHELL}
|
|
{$ENDIF WATCOM}
|
|
|
|
{$IFDEF OS2}
|
|
{$DEFINE USE_SHELL}
|
|
{$ENDIF OS2}
|
|
|
|
uses
|
|
typinfo,
|
|
{$IFNDEF USE_SHELL}
|
|
process,
|
|
{$ENDIF USE_SHELL}
|
|
contnrs,
|
|
uriparser,
|
|
pkgmessages;
|
|
|
|
function StringToVerbosity(S: String): TVerbosity;
|
|
Var
|
|
I : integer;
|
|
begin
|
|
I:=GetEnumValue(TypeInfo(TVerbosity),'v'+S);
|
|
If (I<>-1) then
|
|
Result:=TVerbosity(I)
|
|
else
|
|
Raise EPackagerError.CreateFmt(SErrInvalidVerbosity,[S]);
|
|
end;
|
|
|
|
Function VerbosityToString (V : TVerbosity): String;
|
|
begin
|
|
Result:=GetEnumName(TypeInfo(TVerbosity),Integer(V));
|
|
Delete(Result,1,1);// Delete 'v'
|
|
end;
|
|
|
|
|
|
procedure Log(Level:TVerbosity;Msg: String);
|
|
var
|
|
Prefix : string;
|
|
begin
|
|
if not(Level in Verbosity) then
|
|
exit;
|
|
Prefix:='';
|
|
if Level=vWarning then
|
|
Prefix:=SWarning;
|
|
Writeln(stdErr,Prefix,Msg);
|
|
end;
|
|
|
|
|
|
Procedure Log(Level:TVerbosity; Fmt:String; const Args:array of const);
|
|
begin
|
|
Log(Level,Format(Fmt,Args));
|
|
end;
|
|
|
|
|
|
procedure Error(Msg: String);
|
|
begin
|
|
Raise EPackagerError.Create(Msg);
|
|
end;
|
|
|
|
|
|
procedure Error(Fmt: String; const Args: array of const);
|
|
begin
|
|
Raise EPackagerError.CreateFmt(Fmt,Args);
|
|
end;
|
|
|
|
|
|
function maybequoted(const s:string):string;
|
|
const
|
|
{$IFDEF MSWINDOWS}
|
|
FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
|
|
'{', '}', '''', '`', '~'];
|
|
{$ELSE}
|
|
FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
|
|
'{', '}', '''', ':', '\', '`', '~'];
|
|
{$ENDIF}
|
|
var
|
|
s1 : string;
|
|
i : integer;
|
|
quoted : boolean;
|
|
begin
|
|
quoted:=false;
|
|
s1:='"';
|
|
for i:=1 to length(s) do
|
|
begin
|
|
case s[i] of
|
|
'"' :
|
|
begin
|
|
quoted:=true;
|
|
s1:=s1+'\"';
|
|
end;
|
|
' ',
|
|
#128..#255 :
|
|
begin
|
|
quoted:=true;
|
|
s1:=s1+s[i];
|
|
end;
|
|
else begin
|
|
if s[i] in FORBIDDEN_CHARS then
|
|
quoted:=True;
|
|
s1:=s1+s[i];
|
|
end;
|
|
end;
|
|
end;
|
|
if quoted then
|
|
maybequoted:=s1+'"'
|
|
else
|
|
maybequoted:=s;
|
|
end;
|
|
|
|
|
|
Function FixPath(const S : String) : string;
|
|
begin
|
|
If (S<>'') then
|
|
Result:=IncludeTrailingPathDelimiter(S)
|
|
else
|
|
Result:='';
|
|
end;
|
|
|
|
|
|
Procedure DeleteDir(const ADir:string);
|
|
var
|
|
Info : TSearchRec;
|
|
begin
|
|
if FindFirst(ADir+PathDelim+AllFiles,faAnyFile, Info)=0 then
|
|
try
|
|
repeat
|
|
if (Info.Attr and faDirectory)=faDirectory then
|
|
begin
|
|
if (Info.Name<>'.') and (Info.Name<>'..') then
|
|
DeleteDir(ADir+PathDelim+Info.Name)
|
|
end
|
|
else
|
|
DeleteFile(ADir+PathDelim+Info.Name);
|
|
until FindNext(Info)<>0;
|
|
finally
|
|
FindClose(Info);
|
|
end;
|
|
end;
|
|
|
|
|
|
Procedure SearchFiles(SL:TStringList;const APattern:string);
|
|
var
|
|
Info : TSearchRec;
|
|
ADir : string;
|
|
begin
|
|
ADir:=ExtractFilePath(APattern);
|
|
if FindFirst(APattern,faAnyFile, Info)=0 then
|
|
try
|
|
repeat
|
|
if (Info.Attr and faDirectory)=faDirectory then
|
|
begin
|
|
if (Info.Name<>'.') and (Info.Name<>'..') then
|
|
SearchFiles(SL,ADir+Info.Name+PathDelim+ExtractFileName(APattern))
|
|
end;
|
|
SL.Add(ADir+Info.Name);
|
|
until FindNext(Info)<>0;
|
|
finally
|
|
FindClose(Info);
|
|
end;
|
|
end;
|
|
|
|
|
|
//
|
|
// if use_shell defined uses sysutils.executeprocess else uses 'process'
|
|
//
|
|
function GetCompilerInfo(const ACompiler,AOptions:string):string;
|
|
const
|
|
BufSize = 1024;
|
|
var
|
|
{$IFDEF USE_SHELL}
|
|
TmpFileName, ProcIDStr: shortstring;
|
|
TmpFile: file;
|
|
CmdLine2: string;
|
|
{$ELSE USE_SHELL}
|
|
S: TProcess;
|
|
{$ENDIF USE_SHELL}
|
|
Buf: array [0..BufSize - 1] of char;
|
|
Count: longint;
|
|
begin
|
|
{$IFDEF USE_SHELL}
|
|
Str (GetProcessID, ProcIDStr);
|
|
TmpFileName := GetEnvironmentVariable ('TEMP');
|
|
if TmpFileName <> '' then
|
|
TmpFileName := TmpFileName + DirectorySeparator + 'fppkgout.' + ProcIDStr
|
|
else
|
|
TmpfileName := 'fppkgout.' + ProcIDStr;
|
|
CmdLine2 := '/C ' + ACompiler + ' ' + AOptions + ' > ' + TmpFileName;
|
|
SysUtils.ExecuteProcess (GetEnvironmentVariable ('COMSPEC'), CmdLine2);
|
|
Assign (TmpFile, TmpFileName);
|
|
Reset (TmpFile, 1);
|
|
BlockRead (TmpFile, Buf, BufSize, Count);
|
|
Close (TmpFile);
|
|
{$ELSE USE_SHELL}
|
|
S:=TProcess.Create(Nil);
|
|
S.Commandline:=ACompiler+' '+AOptions;
|
|
S.Options:=[poUsePipes];
|
|
S.execute;
|
|
Count:=s.output.read(buf,BufSize);
|
|
S.Free;
|
|
{$ENDIF USE_SHELL}
|
|
SetLength(Result,Count);
|
|
Move(Buf,Result[1],Count);
|
|
end;
|
|
|
|
end.
|