sourcepawn/batchtool/uFunc.pas
author Michael McKoy <ferret99gt@gmail.com>
Sat Nov 24 03:28:33 2007 +0000 (2007-11-24)
changeset 1719 c9d5e55f0899
parent 1303 93201b8bd474
permissions -rw-r--r--
The current map played shouldn't appear in MapChooser votes or RTV votes now. It can still be nominated in RTV though.
dvander@1248
     1
(* AMX Mod X
dvander@1248
     2
*    compile.exe
dvander@1248
     3
*
dvander@1248
     4
* by the AMX Mod X Development Team
dvander@1248
     5
*
dvander@1248
     6
*
dvander@1248
     7
*  This program is free software; you can redistribute it and/or modify it
dvander@1248
     8
*  under the terms of the GNU General Public License as published by the
dvander@1248
     9
*  Free Software Foundation; either version 2 of the License, or (at
dvander@1248
    10
*  your option) any later version.
dvander@1248
    11
*
dvander@1248
    12
*  This program is distributed in the hope that it will be useful, but
dvander@1248
    13
*  WITHOUT ANY WARRANTY; without even the implied warranty of
dvander@1248
    14
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dvander@1248
    15
*  General Public License for more details.
dvander@1248
    16
*
dvander@1248
    17
*  You should have received a copy of the GNU General Public License
dvander@1248
    18
*  along with this program; if not, write to the Free Software Foundation,
dvander@1248
    19
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
dvander@1248
    20
*
dvander@1248
    21
*  In addition, as a special exception, the author gives permission to
dvander@1248
    22
*  link the code of this program with the Half-Life Game Engine ("HL
dvander@1248
    23
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
dvander@1248
    24
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
dvander@1248
    25
*  respects for all of the code used other than the HL Engine and MODs
dvander@1248
    26
*  from Valve. If you modify this file, you may extend this exception
dvander@1248
    27
*  to your version of the file, but you are not obligated to do so. If
dvander@1248
    28
*  you do not wish to do so, delete this exception statement from your
dvander@1248
    29
*  version.
dvander@1248
    30
*)
dvander@1248
    31
dvander@1248
    32
unit uFunc;
dvander@1248
    33
dvander@1248
    34
interface
dvander@1248
    35
dvander@1248
    36
uses
dvander@1248
    37
  Windows, SysUtils, Classes, Math, IniFiles;
dvander@1248
    38
dvander@1248
    39
resourcestring
dvander@1248
    40
  COMPILER_EXE = 'spcomp.exe';
dvander@1248
    41
dvander@1248
    42
procedure AppExit;
bmasterc@1302
    43
procedure CompilePlugin(const Name, OutputDir: String);
dvander@1248
    44
function GetAgeFromDat(const FileName: String): Integer;
dvander@1248
    45
procedure SetAgeToDat(const FileName: String; const Age: Integer);
dvander@1248
    46
function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
dvander@1248
    47
dvander@1248
    48
implementation
dvander@1248
    49
dvander@1248
    50
procedure AppExit;
dvander@1248
    51
begin
dvander@1248
    52
  WriteLn;
dvander@1248
    53
  Write('Press enter to exit ...');
dvander@1248
    54
  ReadLn;
dvander@1248
    55
  Halt;
dvander@1248
    56
end;
dvander@1248
    57
bmasterc@1302
    58
procedure CompilePlugin(const Name, OutputDir: String);
dvander@1248
    59
var
dvander@1248
    60
  Output: TStringList;
dvander@1248
    61
  i: Word;
dvander@1248
    62
  cStart,cEnd: Longword;
dvander@1248
    63
  FileName, FilePath, Compiled: String;
dvander@1248
    64
begin
dvander@1248
    65
  FileName := ExtractFileName(Name);
dvander@1248
    66
  FilePath := ExtractFilePath(Name);
bmasterc@1302
    67
  if (OutputDir = '') then
bmasterc@1302
    68
    Compiled := FilePath+'compiled\'+ChangeFileExt(Filename,'.smx')
bmasterc@1302
    69
  else
bmasterc@1302
    70
    Compiled := OutputDir+ChangeFileExt(Filename,'.smx');
bmasterc@1302
    71
dvander@1248
    72
  if (FilePath='') then
dvander@1248
    73
    FilePath := ExtractFilePath(ParamStr(0));
dvander@1248
    74
dvander@1248
    75
  WriteLn;
dvander@1248
    76
  WriteLn('//// '+ExtractFileName(FileName));
dvander@1248
    77
bmasterc@1302
    78
  if FileExists(Compiled) and ( GetAgeFromDat(Name)=FileAge(Name) ) then
dvander@1248
    79
  begin
dvander@1248
    80
    WriteLn('// Already compiled.');
dvander@1248
    81
    WriteLn('// ----------------------------------------');
dvander@1248
    82
    Exit;
dvander@1248
    83
  end;
dvander@1248
    84
dvander@1248
    85
  Output := TStringList.Create;
dvander@1248
    86
dvander@1248
    87
  try
dvander@1248
    88
    cStart := GetTickCount;
bmasterc@1303
    89
    if not GetConsoleOutput(ExtractFilePath(ParamStr(0))+COMPILER_EXE+' "'+Name+'" "-o'+Compiled+'"',Output) then
dvander@1248
    90
    begin
dvander@1248
    91
      WriteLn('// Internal error.');
dvander@1248
    92
      AppExit;
dvander@1248
    93
    end;
dvander@1248
    94
    cEnd := GetTickCount;
dvander@1248
    95
dvander@1248
    96
    for i := 3 to (Output.Count-1) do
dvander@1248
    97
    begin
dvander@1248
    98
      WriteLn('// '+Output.Strings[i]);
dvander@1248
    99
    end;
dvander@1248
   100
dvander@1248
   101
    WriteLn('//');
dvander@1248
   102
    WriteLn('// Compilation Time: '+FloatToStr(SimpleRoundTo((cEnd-cStart) / 1000,-2))+' sec');
dvander@1248
   103
    WriteLn('// ----------------------------------------');
dvander@1248
   104
    Output.Free;
dvander@1248
   105
  except
dvander@1248
   106
    WriteLn('// Internal error.');
dvander@1248
   107
    AppExit;
dvander@1248
   108
  end;
dvander@1248
   109
bmasterc@1302
   110
  SetAgeToDat(Name,FileAge(Name));
dvander@1248
   111
end;
dvander@1248
   112
dvander@1248
   113
function GetAgeFromDat(const FileName: String): Integer;
dvander@1248
   114
var
dvander@1248
   115
  Ini: TIniFile;
dvander@1248
   116
begin
dvander@1248
   117
  Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
dvander@1248
   118
  Result := Ini.ReadInteger(FileName,'Age',-1);
dvander@1248
   119
  Ini.Free;
dvander@1248
   120
end;
dvander@1248
   121
dvander@1248
   122
procedure SetAgeToDat(const FileName: String; const Age: Integer);
dvander@1248
   123
var
dvander@1248
   124
  Ini: TIniFile;
dvander@1248
   125
begin
dvander@1248
   126
  Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
dvander@1248
   127
  Ini.WriteInteger(FileName,'Age',Age);
dvander@1248
   128
  Ini.UpdateFile;
dvander@1248
   129
  Ini.Free;
bmasterc@1302
   130
  SetFileAttributes(PChar(ExtractFilePath(ParamStr(0))+'compile.dat'), faHidden);
dvander@1248
   131
end;
dvander@1248
   132
dvander@1248
   133
function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
dvander@1248
   134
var
dvander@1248
   135
  StartupInfo: TStartupInfo;
dvander@1248
   136
  ProcessInfo: TProcessInformation;
dvander@1248
   137
  SecurityAttr: TSecurityAttributes;
dvander@1248
   138
  PipeOutputRead: THandle;
dvander@1248
   139
  PipeOutputWrite: THandle;
dvander@1248
   140
  PipeErrorsRead: THandle;
dvander@1248
   141
  PipeErrorsWrite: THandle;
dvander@1248
   142
  Succeed: Boolean;
dvander@1248
   143
  Buffer: array [0..255] of Char;
dvander@1248
   144
  NumberOfBytesRead: DWORD;
dvander@1248
   145
  Stream: TMemoryStream;
bmasterc@1302
   146
  Errors: String;
dvander@1248
   147
begin
dvander@1248
   148
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
bmasterc@1302
   149
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
dvander@1248
   150
dvander@1248
   151
  SecurityAttr.nLength := SizeOf(SecurityAttr);
dvander@1248
   152
  SecurityAttr.bInheritHandle := True;
dvander@1248
   153
  SecurityAttr.lpSecurityDescriptor := nil;
dvander@1248
   154
dvander@1248
   155
  CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
dvander@1248
   156
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
dvander@1248
   157
dvander@1248
   158
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
dvander@1248
   159
  StartupInfo.cb:=SizeOf(StartupInfo);
dvander@1248
   160
  StartupInfo.hStdInput := 0;
dvander@1248
   161
  StartupInfo.hStdOutput := PipeOutputWrite;
dvander@1248
   162
  StartupInfo.hStdError := PipeErrorsWrite;
dvander@1248
   163
  StartupInfo.wShowWindow := SW_HIDE;
dvander@1248
   164
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
dvander@1248
   165
bmasterc@1302
   166
  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
dvander@1248
   167
    Result := True;
dvander@1248
   168
    CloseHandle(PipeOutputWrite);
dvander@1248
   169
    CloseHandle(PipeErrorsWrite);
dvander@1248
   170
dvander@1248
   171
    Stream := TMemoryStream.Create;
dvander@1248
   172
    try
dvander@1248
   173
      while True do begin
dvander@1248
   174
        Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
dvander@1248
   175
        if not Succeed then Break;
dvander@1248
   176
        Stream.Write(Buffer, NumberOfBytesRead);
dvander@1248
   177
      end;
dvander@1248
   178
    finally
bmasterc@1302
   179
      // nothing
dvander@1248
   180
    end;
bmasterc@1302
   181
    Stream.Position := 0;
bmasterc@1302
   182
    Output.LoadFromStream(Stream);
bmasterc@1302
   183
    Stream.Free;
dvander@1248
   184
    CloseHandle(PipeOutputRead);
dvander@1248
   185
bmasterc@1302
   186
    Errors := '';
dvander@1248
   187
    try
dvander@1248
   188
      while True do
dvander@1248
   189
      begin
dvander@1248
   190
        Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
dvander@1248
   191
        if not Succeed then Break;
bmasterc@1302
   192
        Errors := Errors + Copy(Buffer, 1, NumberOfBytesRead);
dvander@1248
   193
      end;
dvander@1248
   194
    finally
bmasterc@1302
   195
      // nothing
dvander@1248
   196
    end;
dvander@1248
   197
    CloseHandle(PipeErrorsRead);
dvander@1248
   198
dvander@1248
   199
    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
dvander@1248
   200
    CloseHandle(ProcessInfo.hProcess);
dvander@1248
   201
  end
dvander@1248
   202
  else
dvander@1248
   203
  begin
dvander@1248
   204
    Result := False;
dvander@1248
   205
    CloseHandle(PipeOutputRead);
dvander@1248
   206
    CloseHandle(PipeOutputWrite);
dvander@1248
   207
    CloseHandle(PipeErrorsRead);
dvander@1248
   208
    CloseHandle(PipeErrorsWrite);
dvander@1248
   209
  end;
bmasterc@1302
   210
  // error management
bmasterc@1302
   211
  if (Errors <> '') then begin
bmasterc@1302
   212
    if (Output.Count > 1) then begin
bmasterc@1302
   213
      if (Trim(Output[Output.Count -2]) = '') then
bmasterc@1302
   214
        Output.Strings[Output.Count -2] := TrimRight(Errors)
bmasterc@1302
   215
      else
bmasterc@1302
   216
        Output.Insert(Output.Count -1, TrimRight(Errors));
bmasterc@1302
   217
    end
bmasterc@1302
   218
    else
bmasterc@1302
   219
      Output.Add(Errors);
bmasterc@1302
   220
    Output.Text := Output.Text; // pseudo-rearrangement
bmasterc@1302
   221
  end;
bmasterc@1302
   222
end;
dvander@1248
   223
dvander@1248
   224
end.