1.1 --- a/sourcepawn/batchtool/uFunc.pas Fri Mar 28 06:21:34 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,224 +0,0 @@
1.4 -(* AMX Mod X
1.5 -* compile.exe
1.6 -*
1.7 -* by the AMX Mod X Development Team
1.8 -*
1.9 -*
1.10 -* This program is free software; you can redistribute it and/or modify it
1.11 -* under the terms of the GNU General Public License as published by the
1.12 -* Free Software Foundation; either version 2 of the License, or (at
1.13 -* your option) any later version.
1.14 -*
1.15 -* This program is distributed in the hope that it will be useful, but
1.16 -* WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.18 -* General Public License for more details.
1.19 -*
1.20 -* You should have received a copy of the GNU General Public License
1.21 -* along with this program; if not, write to the Free Software Foundation,
1.22 -* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.23 -*
1.24 -* In addition, as a special exception, the author gives permission to
1.25 -* link the code of this program with the Half-Life Game Engine ("HL
1.26 -* Engine") and Modified Game Libraries ("MODs") developed by Valve,
1.27 -* L.L.C ("Valve"). You must obey the GNU General Public License in all
1.28 -* respects for all of the code used other than the HL Engine and MODs
1.29 -* from Valve. If you modify this file, you may extend this exception
1.30 -* to your version of the file, but you are not obligated to do so. If
1.31 -* you do not wish to do so, delete this exception statement from your
1.32 -* version.
1.33 -*)
1.34 -
1.35 -unit uFunc;
1.36 -
1.37 -interface
1.38 -
1.39 -uses
1.40 - Windows, SysUtils, Classes, Math, IniFiles;
1.41 -
1.42 -resourcestring
1.43 - COMPILER_EXE = 'spcomp.exe';
1.44 -
1.45 -procedure AppExit;
1.46 -procedure CompilePlugin(const Name, OutputDir: String);
1.47 -function GetAgeFromDat(const FileName: String): Integer;
1.48 -procedure SetAgeToDat(const FileName: String; const Age: Integer);
1.49 -function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
1.50 -
1.51 -implementation
1.52 -
1.53 -procedure AppExit;
1.54 -begin
1.55 - WriteLn;
1.56 - Write('Press enter to exit ...');
1.57 - ReadLn;
1.58 - Halt;
1.59 -end;
1.60 -
1.61 -procedure CompilePlugin(const Name, OutputDir: String);
1.62 -var
1.63 - Output: TStringList;
1.64 - i: Word;
1.65 - cStart,cEnd: Longword;
1.66 - FileName, FilePath, Compiled: String;
1.67 -begin
1.68 - FileName := ExtractFileName(Name);
1.69 - FilePath := ExtractFilePath(Name);
1.70 - if (OutputDir = '') then
1.71 - Compiled := FilePath+'compiled\'+ChangeFileExt(Filename,'.smx')
1.72 - else
1.73 - Compiled := OutputDir+ChangeFileExt(Filename,'.smx');
1.74 -
1.75 - if (FilePath='') then
1.76 - FilePath := ExtractFilePath(ParamStr(0));
1.77 -
1.78 - WriteLn;
1.79 - WriteLn('//// '+ExtractFileName(FileName));
1.80 -
1.81 - if FileExists(Compiled) and ( GetAgeFromDat(Name)=FileAge(Name) ) then
1.82 - begin
1.83 - WriteLn('// Already compiled.');
1.84 - WriteLn('// ----------------------------------------');
1.85 - Exit;
1.86 - end;
1.87 -
1.88 - Output := TStringList.Create;
1.89 -
1.90 - try
1.91 - cStart := GetTickCount;
1.92 - if not GetConsoleOutput(ExtractFilePath(ParamStr(0))+COMPILER_EXE+' "'+Name+'" "-o'+Compiled+'"',Output) then
1.93 - begin
1.94 - WriteLn('// Internal error.');
1.95 - AppExit;
1.96 - end;
1.97 - cEnd := GetTickCount;
1.98 -
1.99 - for i := 3 to (Output.Count-1) do
1.100 - begin
1.101 - WriteLn('// '+Output.Strings[i]);
1.102 - end;
1.103 -
1.104 - WriteLn('//');
1.105 - WriteLn('// Compilation Time: '+FloatToStr(SimpleRoundTo((cEnd-cStart) / 1000,-2))+' sec');
1.106 - WriteLn('// ----------------------------------------');
1.107 - Output.Free;
1.108 - except
1.109 - WriteLn('// Internal error.');
1.110 - AppExit;
1.111 - end;
1.112 -
1.113 - SetAgeToDat(Name,FileAge(Name));
1.114 -end;
1.115 -
1.116 -function GetAgeFromDat(const FileName: String): Integer;
1.117 -var
1.118 - Ini: TIniFile;
1.119 -begin
1.120 - Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
1.121 - Result := Ini.ReadInteger(FileName,'Age',-1);
1.122 - Ini.Free;
1.123 -end;
1.124 -
1.125 -procedure SetAgeToDat(const FileName: String; const Age: Integer);
1.126 -var
1.127 - Ini: TIniFile;
1.128 -begin
1.129 - Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
1.130 - Ini.WriteInteger(FileName,'Age',Age);
1.131 - Ini.UpdateFile;
1.132 - Ini.Free;
1.133 - SetFileAttributes(PChar(ExtractFilePath(ParamStr(0))+'compile.dat'), faHidden);
1.134 -end;
1.135 -
1.136 -function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
1.137 -var
1.138 - StartupInfo: TStartupInfo;
1.139 - ProcessInfo: TProcessInformation;
1.140 - SecurityAttr: TSecurityAttributes;
1.141 - PipeOutputRead: THandle;
1.142 - PipeOutputWrite: THandle;
1.143 - PipeErrorsRead: THandle;
1.144 - PipeErrorsWrite: THandle;
1.145 - Succeed: Boolean;
1.146 - Buffer: array [0..255] of Char;
1.147 - NumberOfBytesRead: DWORD;
1.148 - Stream: TMemoryStream;
1.149 - Errors: String;
1.150 -begin
1.151 - FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
1.152 - FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
1.153 -
1.154 - SecurityAttr.nLength := SizeOf(SecurityAttr);
1.155 - SecurityAttr.bInheritHandle := True;
1.156 - SecurityAttr.lpSecurityDescriptor := nil;
1.157 -
1.158 - CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
1.159 - CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
1.160 -
1.161 - FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
1.162 - StartupInfo.cb:=SizeOf(StartupInfo);
1.163 - StartupInfo.hStdInput := 0;
1.164 - StartupInfo.hStdOutput := PipeOutputWrite;
1.165 - StartupInfo.hStdError := PipeErrorsWrite;
1.166 - StartupInfo.wShowWindow := SW_HIDE;
1.167 - StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
1.168 -
1.169 - if CreateProcess(nil, PChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin
1.170 - Result := True;
1.171 - CloseHandle(PipeOutputWrite);
1.172 - CloseHandle(PipeErrorsWrite);
1.173 -
1.174 - Stream := TMemoryStream.Create;
1.175 - try
1.176 - while True do begin
1.177 - Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
1.178 - if not Succeed then Break;
1.179 - Stream.Write(Buffer, NumberOfBytesRead);
1.180 - end;
1.181 - finally
1.182 - // nothing
1.183 - end;
1.184 - Stream.Position := 0;
1.185 - Output.LoadFromStream(Stream);
1.186 - Stream.Free;
1.187 - CloseHandle(PipeOutputRead);
1.188 -
1.189 - Errors := '';
1.190 - try
1.191 - while True do
1.192 - begin
1.193 - Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
1.194 - if not Succeed then Break;
1.195 - Errors := Errors + Copy(Buffer, 1, NumberOfBytesRead);
1.196 - end;
1.197 - finally
1.198 - // nothing
1.199 - end;
1.200 - CloseHandle(PipeErrorsRead);
1.201 -
1.202 - WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
1.203 - CloseHandle(ProcessInfo.hProcess);
1.204 - end
1.205 - else
1.206 - begin
1.207 - Result := False;
1.208 - CloseHandle(PipeOutputRead);
1.209 - CloseHandle(PipeOutputWrite);
1.210 - CloseHandle(PipeErrorsRead);
1.211 - CloseHandle(PipeErrorsWrite);
1.212 - end;
1.213 - // error management
1.214 - if (Errors <> '') then begin
1.215 - if (Output.Count > 1) then begin
1.216 - if (Trim(Output[Output.Count -2]) = '') then
1.217 - Output.Strings[Output.Count -2] := TrimRight(Errors)
1.218 - else
1.219 - Output.Insert(Output.Count -1, TrimRight(Errors));
1.220 - end
1.221 - else
1.222 - Output.Add(Errors);
1.223 - Output.Text := Output.Text; // pseudo-rearrangement
1.224 - end;
1.225 -end;
1.226 -
1.227 -end.