4 * by the AMX Mod X Development Team
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * In addition, as a special exception, the author gives permission to
22 * link the code of this program with the Half-Life Game Engine ("HL
23 * Engine") and Modified Game Libraries ("MODs") developed by Valve,
24 * L.L.C ("Valve"). You must obey the GNU General Public License in all
25 * respects for all of the code used other than the HL Engine and MODs
26 * from Valve. If you modify this file, you may extend this exception
27 * to your version of the file, but you are not obligated to do so. If
28 * you do not wish to do so, delete this exception statement from your
37 Windows, SysUtils, Classes, Math, IniFiles;
40 COMPILER_EXE = 'spcomp.exe';
43 procedure CompilePlugin(const Name: String);
44 function GetAgeFromDat(const FileName: String): Integer;
45 procedure SetAgeToDat(const FileName: String; const Age: Integer);
46 function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
53 Write('Press enter to exit ...');
58 procedure CompilePlugin(const Name: String);
62 cStart,cEnd: Longword;
63 FileName, FilePath, Compiled: String;
65 FileName := ExtractFileName(Name);
66 FilePath := ExtractFilePath(Name);
67 Compiled := FilePath+'compiled\'+ChangeFileExt(Filename,'.smx');
69 FilePath := ExtractFilePath(ParamStr(0));
72 WriteLn('//// '+ExtractFileName(FileName));
74 if FileExists(Compiled) and ( GetAgeFromDat(FileName)=FileAge(Name) ) then
76 WriteLn('// Already compiled.');
77 WriteLn('// ----------------------------------------');
81 Output := TStringList.Create;
84 cStart := GetTickCount;
85 if not GetConsoleOutput(ExtractFilePath(ParamStr(0))+COMPILER_EXE+' "'+FilePath+FileName+'" "-o'+Compiled+'"',Output) then
87 WriteLn('// Internal error.');
92 for i := 3 to (Output.Count-1) do
94 WriteLn('// '+Output.Strings[i]);
98 WriteLn('// Compilation Time: '+FloatToStr(SimpleRoundTo((cEnd-cStart) / 1000,-2))+' sec');
99 WriteLn('// ----------------------------------------');
102 WriteLn('// Internal error.');
106 SetAgeToDat(FileName,FileAge(Name));
109 function GetAgeFromDat(const FileName: String): Integer;
113 Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
114 Result := Ini.ReadInteger(FileName,'Age',-1);
118 procedure SetAgeToDat(const FileName: String; const Age: Integer);
122 Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
123 Ini.WriteInteger(FileName,'Age',Age);
128 function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
130 StartupInfo: TStartupInfo;
131 ProcessInfo: TProcessInformation;
132 SecurityAttr: TSecurityAttributes;
133 PipeOutputRead: THandle;
134 PipeOutputWrite: THandle;
135 PipeErrorsRead: THandle;
136 PipeErrorsWrite: THandle;
138 Buffer: array [0..255] of Char;
139 NumberOfBytesRead: DWORD;
140 Stream: TMemoryStream;
142 FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
144 FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
145 SecurityAttr.nLength := SizeOf(SecurityAttr);
146 SecurityAttr.bInheritHandle := True;
147 SecurityAttr.lpSecurityDescriptor := nil;
149 CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
150 CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
152 FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
153 StartupInfo.cb:=SizeOf(StartupInfo);
154 StartupInfo.hStdInput := 0;
155 StartupInfo.hStdOutput := PipeOutputWrite;
156 StartupInfo.hStdError := PipeErrorsWrite;
157 StartupInfo.wShowWindow := SW_HIDE;
158 StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
160 if CreateProcess(nil, PChar(command), nil, nil, true,
161 CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil,
162 StartupInfo, ProcessInfo) then begin
164 CloseHandle(PipeOutputWrite);
165 CloseHandle(PipeErrorsWrite);
167 Stream := TMemoryStream.Create;
170 Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
171 if not Succeed then Break;
172 Stream.Write(Buffer, NumberOfBytesRead);
174 Stream.Position := 0;
175 Output.LoadFromStream(Stream);
179 CloseHandle(PipeOutputRead);
184 Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
185 if not Succeed then Break;
189 CloseHandle(PipeErrorsRead);
191 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
192 CloseHandle(ProcessInfo.hProcess);
197 CloseHandle(PipeOutputRead);
198 CloseHandle(PipeOutputWrite);
199 CloseHandle(PipeErrorsRead);
200 CloseHandle(PipeErrorsWrite);