123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- {
- FPCRes - Free Pascal Resource Converter
- Part of the Free Pascal distribution
- Copyright (C) 2008 by Giulio Bernardi
-
- Handles the parsing of parameters
- See the file COPYING, 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.
- }
- unit paramparser;
- {$MODE OBJFPC} {$H+}
- interface
- uses
- Classes, SysUtils, target;
- type
- EParametersException = class(Exception);
- EOutputFileAlreadySetException = class(EParametersException);
- EUnknownParameterException = class(EParametersException);
- EArgumentMissingException = class(EParametersException);
- EUnknownObjFormatException = class(EParametersException);
- EUnknownMachineException = class(EParametersException);
- EUnknownSubMachineException = class(EParametersException);
- ECannotReadConfFile = class(EParametersException);
- type
- { TParameters }
- TParameters = class
- private
- fHelp : boolean;
- fVersion : boolean;
- fVerbose : boolean;
- fInputFiles : TStringList;
- fOutputFile : string;
- fTarget : TResTarget;
- fRCIncludeDirs: TStringList;
- fRCDefines: TStringList;
- procedure ParseInputFiles(aList : TStringList; var index : integer; const parname : string);
- procedure ParseRCInclude(aList: TStringList; var index: integer; const parname: string);
- procedure ParseRCUnDefine(aList: TStringList; var index: integer; const parname: string);
- procedure ParseOutputFile(aList : TStringList; var index : integer; const parname : string);
- procedure ParseOutputFormat(aList : TStringList; var index : integer; const parname : string);virtual;
- procedure ParseArchitecture(aList : TStringList; var index : integer; const parname : string);virtual;
- procedure ParseSubArchitecture(aList : TStringList; var index : integer; const parname : string);virtual;
- procedure ParseConfigFile(aList : TStringList; var index : integer; const parname : string);
- function DoOptionalArgument(aList : TStringList; const i : integer) : string;
- function DoMandatoryArgument(aList : TStringList; const i : integer) : string;
- function IsParameter(const s : string) : boolean;
- function ParamsToStrList : TStringList;
- protected
- public
- constructor Create;
- destructor Destroy; override;
- procedure Parse;
- property Help : boolean read fHelp;
- property Version : boolean read fVersion;
- property Verbose : boolean read fVerbose;
- property InputFiles : TStringList read fInputFiles;
- property RCIncludeDirs: TStringList read fRCIncludeDirs;
- property RCDefines: TStringList read fRCDefines;
- property OutputFile : string read fOutputFile write fOutputFile;
- property Target : TResTarget read fTarget;
- end;
- implementation
- uses
- msghandler;
- type
- { TConfFileParser }
- TConfFileParser = class
- private
- fConfFile : TStringList;
- fParList : TStringList;
- fInsPos : integer;
- procedure ParseLine(idx : integer);
- function GetParameter(pc : pchar; var i : integer) : string;
- function GetString(pc : pchar; var i : integer) : string;
- protected
- public
- constructor Create(aFileName : string; aParList : TStringList; aInsPos : integer);
- procedure Parse;
- destructor Destroy; override;
- end;
- { TConfFileParser }
- procedure TConfFileParser.ParseLine(idx: integer);
- var pc : pchar;
- tmp : string;
- i : integer;
- begin
- pc:=pchar(fConfFile[idx]);
- i:=0;
- while pc[i]<>#0 do
- begin
- case pc[i] of
- ' ',#9,#13,#10 : inc(i);
- '#' : break
- else
- begin
- tmp:=GetParameter(pc,i);
- if tmp<>'' then
- begin
- fParList.Insert(fInsPos,tmp);
- inc(fInsPos);
- end;
- end;
- end;
- end;
- end;
- function TConfFileParser.GetParameter(pc : pchar; var i : integer): string;
- begin
- Result:='';
- while pc[i]<>#0 do
- begin
- case pc[i] of
- ' ',#9,#13,#10 : exit;
- '#' : exit;
- '"' : Result:=Result+GetString(pc,i);
- else
- Result:=Result+pc[i];
- end;
- inc(i);
- end;
- end;
- function TConfFileParser.GetString(pc: pchar; var i: integer): string;
- begin
- Result:='';
- inc(i);
- while pc[i]<>#0 do
- begin
- if pc[i] = '"' then
- exit
- else
- Result:=Result+pc[i];
- inc(i);
- end;
- dec(i);
- end;
- constructor TConfFileParser.Create(aFileName: string; aParList: TStringList; aInsPos : integer);
- begin
- fInsPos:=aInsPos+1;
- fConfFile:=TStringList.Create;
- fParList:=aParList;
- try
- fConfFile.LoadFromFile(aFileName);
- except
- raise ECannotReadConfFile.Create(aFileName);
- end;
- end;
- procedure TConfFileParser.Parse;
- var i : integer;
- begin
- for i:=0 to fConfFile.Count-1 do
- ParseLine(i);
- end;
- destructor TConfFileParser.Destroy;
- begin
- fConfFile.Free;
- end;
- { TParameters }
- //for compatibility allow -i <inputfiles>
- procedure TParameters.ParseInputFiles(aList: TStringList; var index: integer;
- const parname : string);
- var tmp : string;
- begin
- tmp:=DoMandatoryArgument(aList,index+1);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- while tmp<>'' do
- begin
- inc(index);
- fInputFiles.Add(tmp);
- tmp:=DoOptionalArgument(aList,index+1);
- end;
- end;
- procedure TParameters.ParseRCInclude(aList: TStringList; var index: integer;
- const parname : string);
- var
- tmp: String;
- begin
- inc(index);
- tmp:=DoMandatoryArgument(aList,index);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- fRCIncludeDirs.Add(tmp);
- end;
- procedure TParameters.ParseRCUnDefine(aList: TStringList; var index: integer;
- const parname : string);
- var
- tmp: String;
- i: integer;
- begin
- inc(index);
- tmp:=DoMandatoryArgument(aList,index);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- if (parname='-D') or (parname='--define') then begin
- i:= pos('=', tmp);
- if i<1 then
- fRCDefines.Values[tmp]:= ''
- else
- fRCDefines.Values[Copy(tmp, 1, i-1)]:= Copy(tmp, i+1);
- end else begin
- i:= fRCDefines.IndexOfName(tmp);
- if i >= 0 then
- fRCDefines.Delete(i);
- end;
- fRCIncludeDirs.Add(tmp);
- end;
- procedure TParameters.ParseOutputFile(aList: TStringList; var index: integer;
- const parname : string);
- begin
- if fOutputFile<>'' then
- raise EOutputFileAlreadySetException.Create('');
- inc(index);
- fOutputFile:=DoMandatoryArgument(aList,index);
- if fOutputFile='' then
- raise EArgumentMissingException.Create(parname);
- end;
- procedure TParameters.ParseOutputFormat(aList: TStringList; var index: integer;
- const parname: string);
- var tmp : string;
- aFormat : TObjFormat;
- begin
- inc(index);
- tmp:=DoMandatoryArgument(aList,index);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- for aFormat:=low(TObjFormat) to high(TObjFormat) do
- begin
- if ObjFormats[aFormat].name=tmp then
- begin
- fTarget.objformat:=aFormat;
- exit;
- end;
- end;
-
- raise EUnknownObjFormatException.Create(tmp);
- end;
- procedure TParameters.ParseArchitecture(aList: TStringList; var index: integer;
- const parname: string);
- var tmp : string;
- aMachine : TMachineType;
- begin
- inc(index);
- tmp:=DoMandatoryArgument(aList,index);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- for aMachine:=low(TMachineType) to high(TMachineType) do
- begin
- if (Machines[aMachine].name=tmp) or (Machines[aMachine].alias = tmp) then
- begin
- fTarget.machine:=aMachine;
- fTarget.submachine:=GetDefaultSubMachineForMachine(fTarget.machine);
- exit;
- end;
- end;
- raise EUnknownMachineException.Create(tmp);
- end;
- procedure TParameters.ParseSubArchitecture(aList: TStringList; var index: integer; const parname: string);
- var tmp : string;
- aSubMachineArm : TSubMachineTypeArm;
- aSubMachineGeneric : TSubMachineTypeGeneric;
- begin
- inc(index);
- tmp:=DoMandatoryArgument(aList,index);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- case fTarget.machine of
- mtarm,mtarmeb:
- for aSubMachineArm:=low(TSubMachineTypeArm) to high(TSubMachineTypeArm) do
- if SubMachinesArm[aSubMachineArm]=tmp then
- begin
- ftarget.submachine.subarm:=aSubMachineArm;
- exit;
- end;
- else
- for aSubMachineGeneric:=low(TSubMachineTypeGeneric) to high(TSubMachineTypeGeneric) do
- if SubMachinesGen[aSubMachineGeneric]=tmp then
- begin
- ftarget.submachine.subgen:=aSubMachineGeneric;
- exit;
- end;
- end;
- raise EUnknownSubMachineException.Create(tmp);
- end;
- procedure TParameters.ParseConfigFile(aList: TStringList; var index: integer;
- const parname : string);
- var tmp : string;
- cp : TConfFileParser;
- begin
- tmp:=copy(parname,2,length(parname)-1);
- if tmp='' then
- raise EArgumentMissingException.Create(parname);
- cp:=TConfFileParser.Create(tmp,aList,index);
- try
- cp.Parse;
- finally
- cp.Free;
- end;
- end;
- function TParameters.DoOptionalArgument(aList: TStringList; const i: integer
- ): string;
- begin
- Result:='';
- if aList.Count>i then
- begin
- if not IsParameter(aList[i]) then
- Result:=aList[i];
- end;
- end;
- function TParameters.DoMandatoryArgument(aList: TStringList; const i: integer
- ): string;
- begin
- Result:='';
- if aList.count>i then
- Result:=aList[i];
- end;
- function TParameters.IsParameter(const s: string): boolean;
- begin
- Result:=false;
- if length(s)<=1 then exit;
- if copy(s,1,1)='-' then Result:=true;
- end;
- function TParameters.ParamsToStrList: TStringList;
- var i : integer;
- begin
- Result:=TStringList.Create;
- try
- for i:=1 to ParamCount do
- Result.Add(ParamStr(i));
- except
- Result.Free;
- raise;
- end;
- end;
- procedure TParameters.Parse;
- var fList : TStringList;
- tmp : string;
- i : integer;
- begin
- fList:=ParamsToStrList;
- try
- i:=0;
- while i<fList.Count do
- begin
- tmp:=fList[i];
- Messages.DoVerbose(Format('parsing parameter ''%s''',[tmp]));
- if IsParameter(tmp) then
- begin
- if ((tmp='--help') or (tmp='-h') or (tmp='-?')) then
- fHelp:=true
- else if ((tmp='--version') or (tmp='-V')) then
- fVersion:=true
- else if ((tmp='--verbose') or (tmp='-v')) then
- fVerbose:=true
- else if ((tmp='-i') or (tmp='--input')) then
- ParseInputFiles(fList,i,tmp)
- else if ((tmp='-I') or (tmp='--include')) then
- ParseRCInclude(fList,i,tmp)
- else if ((tmp='-D') or (tmp='--define'))
- or ((tmp='-U') or (tmp='--undefine')) then
- ParseRCUnDefine(fList,i,tmp)
- else if ((tmp='-o') or (tmp='--output')) then
- ParseOutputFile(fList,i,tmp)
- else if (tmp='-of') then
- ParseOutputFormat(fList,i,tmp)
- else if ((tmp='-a') or (tmp='--arch')) then
- ParseArchitecture(fList,i,tmp)
- else if ((tmp='-s') or (tmp='--subarch')) then
- ParseSubArchitecture(fList,i,tmp)
- else
- raise EUnknownParameterException.Create(tmp);
- end
- else
- if copy(tmp,1,1)='@' then
- ParseConfigFile(fList,i,tmp)
- else
- fInputFiles.Add(tmp); //assume it is an input file
- inc(i);
- end;
- finally
- fList.Free;
- end;
- end;
- constructor TParameters.Create;
- begin
- inherited Create;
- fHelp:=false;
- fVersion:=false;
- fVerbose:=false;
- fInputFiles:=TStringList.Create;
- fRCIncludeDirs:= TStringList.Create;
- fRCIncludeDirs.Duplicates:= dupIgnore;
- fRCDefines:= TStringList.Create;
- fOutputFile:='';
- fTarget.machine:=mtnone;
- GetDefaultSubMachineForMachine(fTarget.machine);
- fTarget.objformat:=ofnone;
- end;
- destructor TParameters.Destroy;
- begin
- fRCDefines.Free;
- fRCIncludeDirs.Free;
- fInputFiles.Free;
- inherited;
- end;
- end.
|