123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 2003 by the Free Pascal development team
- CustomApplication class.
-
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$mode objfpc}
- {$h+}
- unit CustApp;
- Interface
- uses SysUtils,Classes;
- Type
- TExceptionEvent = Procedure (Sender : TObject; E : Exception) Of Object;
-
- TCustomApplication = Class(TComponent)
- Private
- FOnException: TExceptionEvent;
- FTerminated : Boolean;
- FHelpFile,
- FTitle : String;
- FOptionChar : Char;
- FCaseSensitiveOptions : Boolean;
- FStopOnException : Boolean;
- function GetEnvironmentVar(VarName : String): String;
- function GetExeName: string;
- Function GetLocation : String;
- function GetTitle: string;
- Protected
- procedure SetTitle(const AValue: string); Virtual;
- Function GetConsoleApplication : boolean; Virtual;
- Procedure DoRun; Virtual;
- Function GetParams(Index : Integer) : String;virtual;
- function GetParamCount: Integer;Virtual;
- Public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- // Some Delphi methods.
- procedure HandleException(Sender: TObject); virtual;
- procedure Initialize; virtual;
- procedure Run;
- procedure ShowException(E: Exception);virtual;
- procedure Terminate; virtual;
- // Extra methods.
- function FindOptionIndex(Const S : String; Var Longopt : Boolean) : Integer;
- Function GetOptionValue(Const S : String) : String;
- Function GetOptionValue(Const C: Char; Const S : String) : String;
- Function HasOption(Const S : String) : Boolean;
- Function HasOption(Const C : Char; Const S : String) : Boolean;
- Function CheckOptions(Const ShortOptions : String; Const Longopts : TStrings; Opts,NonOpts : TStrings) : String;
- Function CheckOptions(Const ShortOptions : String; Const Longopts : TStrings) : String;
- Function CheckOptions(Const ShortOptions : String; Const LongOpts : Array of string) : String;
- Function CheckOptions(Const ShortOptions : String; Const LongOpts : String) : String;
- Procedure GetEnvironmentList(List : TStrings;NamesOnly : Boolean);
- Procedure GetEnvironmentList(List : TStrings);
- // Delphi properties
- property ExeName: string read GetExeName;
- property HelpFile: string read FHelpFile write FHelpFile;
- property Terminated: Boolean read FTerminated;
- property Title: string read FTitle write SetTitle;
- property OnException: TExceptionEvent read FOnException write FOnException;
- // Extra properties
- Property ConsoleApplication : Boolean Read GetConsoleApplication;
- Property Location : String Read GetLocation;
- Property Params [Index : integer] : String Read GetParams;
- Property ParamCount : Integer Read GetParamCount;
- Property EnvironmentVariable[envName : String] : String Read GetEnvironmentVar;
- Property OptionChar : Char Read FoptionChar Write FOptionChar;
- Property CaseSensitiveOptions : Boolean Read FCaseSensitiveOptions Write FCaseSensitiveOptions;
- Property StopOnException : Boolean Read FStopOnException Write FStopOnException;
- end;
-
- Implementation
- {$i custapp.inc}
- { TCustomApplication }
- function TCustomApplication.GetExeName: string;
- begin
- Result:=Paramstr(0);
- end;
- function TCustomApplication.GetEnvironmentVar(VarName : String): String;
- begin
- Result:=GetEnvironmentVariable(VarName);
- end;
- Procedure TCustomApplication.GetEnvironmentList(List : TStrings;NamesOnly : Boolean);
- begin
- // Routine must be in custapp.inc
- SysGetEnvironmentList(List,NamesOnly);
- end;
- Procedure TCustomApplication.GetEnvironmentList(List : TStrings);
- begin
- GetEnvironmentList(List,False);
- end;
- function TCustomApplication.GetLocation: String;
- begin
- Result:=ExtractFilePath(GetExeName);
- end;
- function TCustomApplication.GetParamCount: Integer;
- begin
- Result:=System.ParamCount;
- end;
- function TCustomApplication.GetTitle: string;
- begin
- Result:=FTitle;
- end;
- function TCustomApplication.GetParams(Index: Integer): String;
- begin
- Result:=ParamStr(Index);
- end;
- procedure TCustomApplication.SetTitle(const AValue: string);
- begin
- FTitle:=AValue;
- end;
- function TCustomApplication.GetConsoleApplication: boolean;
- begin
- Result:=IsConsole;
- end;
- procedure TCustomApplication.DoRun;
- begin
- // Do nothing. Override in descendent classes.
- end;
- constructor TCustomApplication.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FOptionChar:='-';
- FCaseSensitiveOptions:=True;
- FStopOnException:=False;
- end;
- destructor TCustomApplication.Destroy;
- begin
- inherited Destroy;
- end;
- procedure TCustomApplication.HandleException(Sender: TObject);
- begin
- If Not (ExceptObject is Exception) then
- SysUtils.showexception(ExceptObject,ExceptAddr)
- else
- begin
- If Not Assigned(FOnexception) then
- ShowException(Exception(ExceptObject))
- else
- FOnException(Sender,Exception(ExceptObject));
- end;
- If FStopOnException then
- FTerminated:=True;
- end;
- procedure TCustomApplication.Initialize;
- begin
- FTerminated:=False;
- end;
- procedure TCustomApplication.Run;
- begin
- Repeat
- Try
- DoRun;
- except
- HandleException(Self);
- end;
- Until FTerminated;
- end;
- procedure TCustomApplication.ShowException(E: Exception);
- begin
- Sysutils.ShowException(E,ExceptAddr)
- end;
- procedure TCustomApplication.Terminate;
- begin
- FTerminated:=True;
- end;
- function TCustomApplication.GetOptionValue(Const S: String): String;
- begin
- Result:=GetoptionValue(#255,S);
- end;
- function TCustomApplication.GetOptionValue(Const C: Char; Const S: String): String;
- Var
- B : Boolean;
- I,P : integer;
- O : String;
-
- begin
- Result:='';
- I:=FindOptionIndex(C,B);
- If (I=-1) then
- I:=FindoptionIndex(S,B);
- If (I<>-1) then
- begin
- If B then
- begin // Long options have form --option=value
- O:=Params[I];
- P:=Pos('=',O);
- If (P=0) then
- P:=Length(O);
- Delete(O,1,P);
- Result:=O;
- end
- else
- begin // short options have form '-o value'
- If (I<ParamCount) then
- Result:=Params[I+1];
- end;
- end;
- end;
- function TCustomApplication.HasOption(Const S: String): Boolean;
- Var
- B : Boolean;
- begin
- Result:=FindOptionIndex(S,B)<>-1;
- end;
- function TCustomApplication.FindOptionIndex(Const S : String; Var Longopt : Boolean) : Integer;
- Var
- SO,O : String;
- I,P : Integer;
-
- begin
- If Not CaseSensitiveOptions then
- SO:=UpperCase(S)
- else
- SO:=S;
- Result:=-1;
- I:=ParamCount;
- While (Result=-1) and (I>0) do
- begin
- O:=Params[i];
- If (Length(O)>0) and (O[1]=FOptionChar) then
- begin
- Delete(O,1,1);
- LongOpt:=(Length(O)>0) and (O[1]=FOptionChar);
- If LongOpt then
- begin
- Delete(O,1,1);
- P:=Pos('=',O);
- If (P<>0) then
- O:=Copy(O,1,P-1);
- end;
- If Not CaseSensitiveOptions then
- O:=UpperCase(O);
- If (O=SO) then
- Result:=i;
- end;
- Dec(i);
- end;
- end;
- function TCustomApplication.HasOption(Const C: Char; Const S: String): Boolean;
- Var
- B : Boolean;
- begin
- Result:=(FindOptionIndex(C,B)<>-1) or (FindOptionIndex(S,B)<>-1);
- end;
- Function TCustomApplication.CheckOptions(Const ShortOptions : String; Const Longopts : TStrings) : String;
- begin
- Result:=CheckOptions(ShortOptions,LongOpts,Nil,Nil);
- end;
- ResourceString
- SErrInvalidOption = 'Invalid option at position %d: "%s"';
- SErrNoOptionAllowed = 'Option at position %d does not allow an argument: %s';
- SErrOptionNeeded = 'Option at position %d needs an argument : %s';
-
- Function TCustomApplication.CheckOptions(Const ShortOptions : String; Const Longopts : TStrings; Opts,NonOpts : TStrings) : String;
- Var
- I,J,L,P : Integer;
- O,OV,SO : String;
- HaveArg : Boolean;
-
- Function FindLongOpt(S : String) : boolean;
-
- Var
- I : integer;
-
- begin
- If CaseSensitiveOptions then
- begin
- I:=LongOpts.Count-1;
- While (I>=0) and (LongOpts[i]<>S) do
- Dec(i);
- end
- else
- begin
- S:=UpperCase(S);
- I:=LongOpts.Count-1;
- While (I>=0) and (UpperCase(LongOpts[i])<>S) do
- Dec(i);
- end;
- Result:=(I<>-1);
- end;
-
- begin
- If CaseSensitiveOptions then
- SO:=Shortoptions
- else
- SO:=LowerCase(Shortoptions);
- Result:='';
- I:=1;
- While (I<=ParamCount) and (Result='') do
- begin
- O:=Paramstr(I);
- If (Length(O)=0) or (O[1]<>FOptionChar) then
- begin
- If Assigned(NonOpts) then
- NonOpts.Add(O)
- end
- else
- begin
- If (Length(O)<2) then
- Result:=Format(SErrInvalidOption,[i,O])
- else
- begin
- HaveArg:=False;
- OV:='';
- // Long option ?
- If (O[2]=FOptionChar) then
- begin
- Delete(O,1,2);
- J:=Pos('=',O);
- If J<>0 then
- begin
- HaveArg:=true;
- OV:=O;
- Delete(OV,1,J);
- O:=Copy(O,1,J-1);
- end;
- // Switch Option
- If FindLongopt(O) then
- begin
- If HaveArg then
- Result:=Format(SErrNoOptionAllowed,[I,O])
- end
- else
- begin // Required argument
- If FindLongOpt(O+':') then
- begin
- If Not HaveArg then
- Result:=Format(SErrOptionNeeded,[I,O]);
- end
- else
- begin // Optional Argument.
- If not FindLongOpt(O+'::') then
- Result:=Format(SErrInvalidOption,[I,O]);
- end;
- end;
- end
- else // Short Option.
- begin
- HaveArg:=(I<ParamCount) and (Length(ParamStr(I+1))>0) and (ParamStr(I+1)[i]<>FOptionChar);
- If HaveArg then
- OV:=Paramstr(I+1);
- If Not CaseSensitiveOptions then
- O:=LowerCase(O);
- L:=Length(O);
- J:=2;
- While (result='') and (J<=L) do
- begin
- P:=Pos(O[J],ShortOptions);
- If (P=0) or (O[j]=':') then
- Result:=Format(SErrInvalidOption,[I,O[J]])
- else
- begin
- If (P<Length(ShortOptions)) and (Shortoptions[P+1]=':') then
- begin
- // Required argument
- Writeln('P ',P,' J ',J,' ',O[J],' ',l,' Havearg ',HaveArg);
- If ((P+1)=Length(ShortOptions)) or (Shortoptions[P+2]<>':') Then
- If (J<L) or not haveArg then // Must be last in multi-opt !!
- Result:=Format(SErrOptionNeeded,[I,O[J]]);
- O:=O[j]; // O is added to arguments.
- end;
- end;
- Inc(J);
- end;
- If HaveArg then
- begin
- Inc(I); // Skip argument.
- O:=O[Length(O)]; // O is added to arguments !
- end;
- end;
- If HaveArg and (Result='') then
- If Assigned(Opts) then
- Opts.Add(O+'='+OV);
- end;
- end;
- Inc(I);
- end;
- end;
- Function TCustomApplication.CheckOptions(Const ShortOptions : String; Const LongOpts : Array of string) : String;
- Var
- L : TStringList;
- I : Integer;
-
- begin
- L:=TStringList.Create;
- Try
- For I:=0 to High(LongOpts) do
- L.Add(LongOpts[i]);
- Result:=CheckOptions(ShortOptions,L);
- Finally
- L.Free;
- end;
- end;
- Function TCustomApplication.CheckOptions(Const ShortOptions : String; Const LongOpts : String) : String;
- Const
- SepChars = ' '#10#13#9;
- Var
- L : TStringList;
- Len,I,J : Integer;
-
- begin
- L:=TStringList.Create;
- Try
- I:=1;
- Len:=Length(LongOpts);
- While I<=Len do
- begin
- While Isdelimiter(SepChars,LongOpts,I) do
- Inc(I);
- J:=I;
- While (J<=Len) and Not IsDelimiter(SepChars,LongOpts,J) do
- Inc(J);
- If (I<=J) then
- L.Add(Copy(LongOpts,I,(J-I)));
- I:=J+1;
- end;
- Result:=CheckOptions(Shortoptions,L);
- Finally
- L.Free;
- end;
- end;
- end.
- {
- $Log$
- Revision 1.6 2003-06-01 14:40:05 marco
- * Fix to get it to build "name" was considered dup ident. Changed to
- envname and added logs
- }
|