sourcepawn/batchtool/uFunc.pas
author Borja Ferrer <faluco@alliedmods.net>
Sat Aug 04 00:09:10 2007 +0000 (2007-08-04)
changeset 1262 843e9ed0ff29
parent 1248 ee9f7860e9db
child 1302 63cab5e08c56
permissions -rw-r--r--
fixed amb728, precache slap sounds
     1 (* AMX Mod X
     2 *    compile.exe
     3 *
     4 * by the AMX Mod X Development Team
     5 *
     6 *
     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.
    11 *
    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.
    16 *
    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
    20 *
    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
    29 *  version.
    30 *)
    31 
    32 unit uFunc;
    33 
    34 interface
    35 
    36 uses
    37   Windows, SysUtils, Classes, Math, IniFiles;
    38 
    39 resourcestring
    40   COMPILER_EXE = 'spcomp.exe';
    41 
    42 procedure AppExit;
    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;
    47 
    48 implementation
    49 
    50 procedure AppExit;
    51 begin
    52   WriteLn;
    53   Write('Press enter to exit ...');
    54   ReadLn;
    55   Halt;
    56 end;
    57 
    58 procedure CompilePlugin(const Name: String);
    59 var
    60   Output: TStringList;
    61   i: Word;
    62   cStart,cEnd: Longword;
    63   FileName, FilePath, Compiled: String;
    64 begin
    65   FileName := ExtractFileName(Name);
    66   FilePath := ExtractFilePath(Name);
    67   Compiled := FilePath+'compiled\'+ChangeFileExt(Filename,'.smx');
    68   if (FilePath='') then
    69     FilePath := ExtractFilePath(ParamStr(0));
    70 
    71   WriteLn;
    72   WriteLn('//// '+ExtractFileName(FileName));
    73 
    74   if FileExists(Compiled) and ( GetAgeFromDat(FileName)=FileAge(Name) ) then
    75   begin
    76     WriteLn('// Already compiled.');
    77     WriteLn('// ----------------------------------------');
    78     Exit;
    79   end;
    80 
    81   Output := TStringList.Create;
    82 
    83   try
    84     cStart := GetTickCount;
    85     if not GetConsoleOutput(ExtractFilePath(ParamStr(0))+COMPILER_EXE+' "'+FilePath+FileName+'" "-o'+Compiled+'"',Output) then
    86     begin
    87       WriteLn('// Internal error.');
    88       AppExit;
    89     end;
    90     cEnd := GetTickCount;
    91 
    92     for i := 3 to (Output.Count-1) do
    93     begin
    94       WriteLn('// '+Output.Strings[i]);
    95     end;
    96 
    97     WriteLn('//');
    98     WriteLn('// Compilation Time: '+FloatToStr(SimpleRoundTo((cEnd-cStart) / 1000,-2))+' sec');
    99     WriteLn('// ----------------------------------------');
   100     Output.Free;
   101   except
   102     WriteLn('// Internal error.');
   103     AppExit;
   104   end;
   105 
   106   SetAgeToDat(FileName,FileAge(Name));
   107 end;
   108 
   109 function GetAgeFromDat(const FileName: String): Integer;
   110 var
   111   Ini: TIniFile;
   112 begin
   113   Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
   114   Result := Ini.ReadInteger(FileName,'Age',-1);
   115   Ini.Free;
   116 end;
   117 
   118 procedure SetAgeToDat(const FileName: String; const Age: Integer);
   119 var
   120   Ini: TIniFile;
   121 begin
   122   Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
   123   Ini.WriteInteger(FileName,'Age',Age);
   124   Ini.UpdateFile;
   125   Ini.Free;
   126 end;
   127 
   128 function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
   129 var
   130   StartupInfo: TStartupInfo;
   131   ProcessInfo: TProcessInformation;
   132   SecurityAttr: TSecurityAttributes;
   133   PipeOutputRead: THandle;
   134   PipeOutputWrite: THandle;
   135   PipeErrorsRead: THandle;
   136   PipeErrorsWrite: THandle;
   137   Succeed: Boolean;
   138   Buffer: array [0..255] of Char;
   139   NumberOfBytesRead: DWORD;
   140   Stream: TMemoryStream;
   141 begin
   142   FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
   143 
   144   FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
   145   SecurityAttr.nLength := SizeOf(SecurityAttr);
   146   SecurityAttr.bInheritHandle := True;
   147   SecurityAttr.lpSecurityDescriptor := nil;
   148 
   149   CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
   150   CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
   151 
   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;
   159 
   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
   163     Result := True;
   164     CloseHandle(PipeOutputWrite);
   165     CloseHandle(PipeErrorsWrite);
   166 
   167     Stream := TMemoryStream.Create;
   168     try
   169       while True do begin
   170         Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
   171         if not Succeed then Break;
   172         Stream.Write(Buffer, NumberOfBytesRead);
   173       end;
   174       Stream.Position := 0;
   175       Output.LoadFromStream(Stream);
   176     finally
   177       Stream.Free;
   178     end;
   179     CloseHandle(PipeOutputRead);
   180 
   181     try
   182       while True do
   183       begin
   184         Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
   185         if not Succeed then Break;
   186       end;
   187     finally
   188     end;
   189     CloseHandle(PipeErrorsRead);
   190 
   191     WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
   192     CloseHandle(ProcessInfo.hProcess);
   193   end
   194   else
   195   begin
   196     Result := False;
   197     CloseHandle(PipeOutputRead);
   198     CloseHandle(PipeOutputWrite);
   199     CloseHandle(PipeErrorsRead);
   200     CloseHandle(PipeErrorsWrite);
   201   end;
   202 end;
   203 
   204 end.