program CompUtil;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils, Registry, Classes;

type
  TWhichOption = (woHppModify,
    woSetupD02,woSetupD03,woSetupD04,woSetupD05,woSetupD06,woSetupD07,woSetupD08,woSetupD09,woSetupD10,woSetupD11,woSetupD12,
    woSetupC01,woSetupC03,woSetupC04,woSetupC05,woSetupC06,woSetupC07,woSetupC08,woSetupC09,woSetupC10,woSetupC11,woSetupC12,
    woInvalid);

var
  Options: array[TWhichOption] of String = ('HppModify',
    'SetupD02','SetupD03','SetupD04','SetupD05','SetupD06','SetupD07','SetupD08','SetupD09','SetupD10','SetupD11','SetupD12',
    'SetupC01','SetupC03','SetupC04','SetupC05','SetupC06','SetupC07','SetupC08','SetupC09','SetupC10','SetupC11','SetupC12',
    'Invalid');
  WhichOption: TWhichOption;
  CmdParam: string;

  procedure HPPModify;

  var
    InFile: file;
    OutFile: text;
    Line: string;
    Buffer: pointer;
    BufPtr: PChar;
    BufSize: longint;
    EOL: boolean;

  begin { HPPModify }
  // Fix C++Builder HPP conversion bug:
  //   - Input line in RVDefine.pas is
  //       TRaveUnits = {$IFDEF WIN32}type{$ENDIF} TRaveFloat;
  //
  //   - Invalid output line in RVDefine.hpp is
  //       typedef TRaveUnits TRaveUnits;
  //
  //   - Valid output line in RVDefine.hpp should be
  //       typedef double TRaveUnits;

  { Read in RVDefine.hpp as binary }
    AssignFile(InFile,ParamStr(2) + 'RVDefine.hpp');
    Reset(InFile,1);
    BufSize := FileSize(InFile);
    GetMem(Buffer,BufSize);
    BlockRead(InFile,Buffer^,BufSize);
    CloseFile(InFile);
    BufPtr := Buffer;

  { Write out modified RVDefine.hpp as text }
    AssignFile(OutFile,ParamStr(2) + 'RVDefine.hpp');
    Rewrite(OutFile);
    While BufSize > 0 do begin
      Line := '';
      EOL := false;
      Repeat { Get a line of text }
        If BufPtr^ = #13 then begin
          Inc(BufPtr);
          Dec(BufSize);
          Inc(BufPtr);
          Dec(BufSize);
          EOL := true;
        end else begin
          Line := Line + BufPtr^;
          Inc(BufPtr);
          Dec(BufSize);
        end; { else }
      until EOL or (BufSize = 0);
      If Line = 'typedef TRaveUnits TRaveUnits;' then begin
        Line := 'typedef double TRaveUnits;';
      end; { if }
      Writeln(OutFile,Line);
    end; { while }
    CloseFile(OutFile);
  end; { HPPModify }

  procedure SetPath(EnvName: string;
                    RegRoot: string);

  const
    MaxPathLen = 67;

  var
    CompilerFound: boolean;
    SysDirFound: boolean;
    VarName: string;
    EnvList: TStringList;
    SysDir: string;
    ShortPath: string;
    LongPath: string;

  begin { SetPath }
    VarName := EnvName;
    CompilerFound := GetEnvironmentVariable(@VarName[1],nil,0) <> 0;
    VarName := 'NDWINSYS';
    SysDirFound := GetEnvironmentVariable(@VarName[1],nil,0) <> 0;

    If not CompilerFound or not SysDirFound then begin
      EnvList := TStringList.Create;
      try
        If FileExists('SetEnv.bat') then begin { Read in existing file }
          EnvList.LoadFromFile('SetEnv.bat');
        end; { if }

        If not CompilerFound then begin { Get compiler path and add to string list }
          With TRegistry.Create do try
            RootKey := HKEY_LOCAL_MACHINE;
            If OpenKey(RegRoot,false) and ValueExists('RootDir') then begin
              LongPath := ReadString('RootDir');
              SetLength(ShortPath, MaxPathLen);	// when casting to a PChar, be sure the string is not empty
              SetLength(ShortPath, GetShortPathName(PChar(LongPath), PChar(ShortPath), MaxPathLen) );
              If (ShortPath[1] = #0) or (Length(ShortPath) = Length(LongPath)) then begin
                ShortPath := LongPath;
              end;
              EnvList.Add('SET ' + EnvName + '=' + ShortPath);
              EnvList.SaveToFile('SetEnv.bat');
            end else begin
              Writeln('Compiler not installed!');
              Halt(1);
            end; { else }
          finally
            Free;
          end; { with }
        end; { if }

        If not SysDirFound then begin { Get System Directory and add to string list }
          VarName := 'NDWINSYS';
          If GetEnvironmentVariable(@VarName[1],nil,0) = 0 then begin { Not found }
            SetLength(SysDir,255);
            SetLength(SysDir,GetSystemDirectory(@SysDir[1],255));
            EnvList.Add('SET NDWINSYS=' + SysDir);
            EnvList.SaveToFile('SetEnv.bat');
          end; { if }
        end; { if }
      finally
        EnvList.Free;
      end; { tryf }
    end; { if }
  end;  { SetPath }

begin
{ Figure out which feature to run }
  CmdParam := ParamStr(1);
  WhichOption := Low(WhichOption);
  While WhichOption < High(WhichOption) do begin
    If UpperCase(CmdParam) = UpperCase(Options[WhichOption]) then begin
      Break;
    end; { if }
    Inc(WhichOption);
  end; { while }

  Case WhichOption of
    woHppModify: begin
      HPPModify;
    end;
    woSetupD02: begin
      SetPath('NDD02','Software\Borland\Delphi\2.0');
    end;
    woSetupD03: begin
      SetPath('NDD03','Software\Borland\Delphi\3.0');
    end;
    woSetupD04: begin
      SetPath('NDD04','Software\Borland\Delphi\4.0');
    end;
    woSetupD05: begin
      SetPath('NDD05','Software\Borland\Delphi\5.0');
    end;
    woSetupD06: begin
      SetPath('NDD06','Software\Borland\Delphi\6.0');
    end;
    woSetupD07: begin
      SetPath('NDD07','Software\Borland\Delphi\7.0');
    end;
    woSetupD08: begin
      SetPath('NDD08','Software\Borland\BDS\2.0');
    end;
    woSetupD09: begin
      SetPath('NDD09','Software\Borland\BDS\3.0');
    end;
    woSetupD10: begin
      SetPath('NDD10','Software\Borland\BDS\4.0');
    end;
    woSetupD11: begin
      SetPath('NDD11','Software\Borland\BDS\5.0');
    end;
    woSetupD12: begin
      SetPath('NDD12','Software\Borland\BDS\6.0');
    end;
    woSetupC01: begin
      SetPath('NDC01','Software\Borland\C++Builder\1.0');
    end;
    woSetupC03: begin
      SetPath('NDC03','Software\Borland\C++Builder\3.0');
    end;
    woSetupC04: begin
      SetPath('NDC04','Software\Borland\C++Builder\4.0');
    end;
    woSetupC05: begin
      SetPath('NDC05','Software\Borland\C++Builder\5.0');
    end;
    woSetupC06: begin
      SetPath('NDC06','Software\Borland\C++Builder\6.0');
    end;
    woSetupC07: begin
      SetPath('NDC07','Software\Borland\C++Builder\7.0');
    end;
    woSetupC08: begin
      SetPath('NDC08','Software\Borland\BDS\2.0');
    end;
    woSetupC09: begin
      SetPath('NDC09','Software\Borland\BDS\3.0');
    end;
    woSetupC10: begin
      SetPath('NDC10','Software\Borland\BDS\4.0');
    end;
    woSetupC11: begin
      SetPath('NDC11','Software\Borland\BDS\5.0');
    end;
    woSetupC12: begin
      SetPath('NDC12','Software\Borland\BDS\6.0');
    end;
    woInvalid: begin
      Writeln('Invalid Parameter');
    end;
  end; { case }
end.
