unit dmsh;

(*
  DMonkey Script Host

  History:
  2005/06/24
    ・ダイアログのフィルタを増やした

  2003/10/21
    ・経過時間出力オプション(-t)

  2003/04/09
    ・AllocConsole(オプション -c)

  2002/12/26
    ・エンジンバージョンを0.2.0.1に
    ・help起動オプション
    ・カレントディレクトリを変更
    ・ファイルが存在しない時はダイアログを開くようにした
    ・標準出力に、コンパイル、実行時間情報を追加
    ・引数の仕様をdm.exeに合わせて変更。
    ・バージョンをエンジンと同じに
    ・argumentsにはパラメータのみ格納

  2002/11/23
    ・DMonkey0.1.7で作り直し。
    ・標準出力をファイルに吐くようにした。
    ・ecma_guiobjectを参照しないようにした。
*)


interface


uses
  Windows, Classes, SysUtils, Forms, Dialogs, ShellAPI,
  dmonkey, ecma_type, ecma_misc;

type
  TDMSH = class(TObject)
  private
    FDM: TDMonkey;
    FStdout: string;
    FLogout: Boolean;
    procedure DMStdout(Sender: TObject; S: string);
    procedure DMStderr(Sender: TObject; S: string);
    function OpenFile: string;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Run;
  end;


implementation


{ TDMSH }

constructor TDMSH.Create;
begin
  inherited Create;
  FDM := TDMonkey.Create(nil);
  FDM.CompiledBinary := True;
  FDM.OnStdout := DMStdout;
  FDM.OnStderr := DMStderr;
end;

destructor TDMSH.Destroy;
begin
  FDM.Free;
  inherited;
end;

procedure TDMSH.DMStdout(Sender: TObject; S: string);
begin
  FLogout := True;
  FStdout := FStdout + S;
end;

procedure TDMSH.DMStderr(Sender: TObject; S: string);
begin
  ShowDMonkeyException(Sender as TDMonkey);
end;

function TDMSH.OpenFile: string;
var
  dlg: TOpenDialog;
begin
  Result := '';
  dlg := TOpenDialog.Create(nil);
  try
    dlg.Filter := 'DMonkey File (*' + DMS_EXT + ';*' + DMS_COMPILED_EXT + ')|*' + DMS_EXT + ';*' + DMS_COMPILED_EXT +
                  '|DMonkey Script File (*' + DMS_EXT + ')|*' + DMS_EXT +
                  '|DMonkey Compiled Script File (*' + DMS_COMPILED_EXT + ')|*' + DMS_COMPILED_EXT +
                  '|すべてのファイル (*.*)|*.*';
    if dlg.Execute then
      Result := dlg.FileName;
  finally
    dlg.Free;
  end;
end;

procedure TDMSH.Run;
var
  prm: TJValueList;
  src,hlp,opt: string;
  sl: TStringList;
  i,opcount: Integer;
  cout,tout: Boolean;
begin
  cout := False;
  tout := False;
  opcount := 0; //起動オプションの数

  for i := 1 to ParamCount do
  begin
    opt := ParamStr(i);
    if (Length(opt) > 0) and (opt[1] in ['-','/']) then
    begin
      Inc(opcount);
      opt := Copy(opt,2,MaxInt);
      //help起動
      if (opt = 'help') or (opt = 'h') or (opt = '?') then
      begin
        hlp := ExtractFilePath(ParamStr(0)) + 'dmsref.hlp';
        ShellExecute(0,nil,PChar(hlp),nil,nil,SW_SHOW);
        Exit;
      end
      //console出力
      else if opt = 'c' then
        cout := True
      //経過時間出力
      else if opt = 't' then
        tout := True;
    end
    else
      Break;
  end;

  //起動オプションの次がソースファイル
  src := ParamStr(opcount + 1);

  if ExtractFileExt(src) = '' then
    src := src + DMS_EXT;

  if not FileExists(src) then
  begin
    src := OpenFile;
    if not FileExists(src) then Exit;
  end;

  //カレントdir変更
  SetCurrentDir(ExtractFileDir(src));

  prm := TJValueList.Create;
  try
    for i := (opcount + 2) to ParamCount do
      prm.Add(BuildString(ParamStr(i)));

    if FDM.CompileFile(src) then
      FDM.Run(prm);
  finally
    prm.Free;
  end;

  if FLogout or tout then
  begin
    if not cout then
    begin
      sl := TStringList.Create;
      try try
        sl.Text := FStdout;
        if tout then
        begin
          sl.Add('---------------------');
          sl.Add('compile: ' + MSecToStr2(FDM.TookTimeToCompile));
          sl.Add('run    : ' + MSecToStr2(FDM.TookTimeToRun));
        end;
        sl.SaveToFile(ChangeFileExt(src, '.log'));
      except
        MsgBox('ログファイルを作成できません',
            PChar(Application.Title), MB_OK or MB_ICONHAND);
      end;
      finally
        sl.Free;
      end;
    end
    else begin
      Win32Check(AllocConsole);
      try
        Write(FStdout);
        if tout then
        begin
          Writeln('---------------------');
          Writeln('compile: ' + MSecToStr2(FDM.TookTimeToCompile));
          Writeln('run    : ' + MSecToStr2(FDM.TookTimeToRun));
        end;
        Readln;
      finally
        FreeConsole;
      end;
    end;
  end;
end;

end.
