mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 08:38:14 +02:00
1652 lines
48 KiB
ObjectPascal
1652 lines
48 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal Integrated Development Environment
|
|
Copyright (c) 1998-2000 by Berczi Gabor
|
|
|
|
Compiler switches routines for the IDE
|
|
|
|
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.
|
|
|
|
**********************************************************************}
|
|
unit FPSwitch;
|
|
|
|
{$ifdef cpullvm}
|
|
{$modeswitch nestedprocvars}
|
|
{$endif}
|
|
{$H-}
|
|
|
|
interface
|
|
|
|
uses
|
|
Objects,
|
|
Systems,
|
|
WUtils,
|
|
FPConst;
|
|
|
|
const
|
|
MinMemSize = 1024; { min. local heap and stack size }
|
|
MaxMemSize = 67107840; { max. local heap and stack size }
|
|
|
|
type
|
|
TParamID =
|
|
(idNone,idAlign,idRangeChecks,idStackChecks,idIOChecks,
|
|
idOverflowChecks,idObjMethCallChecks,
|
|
idAsmDirect,idAsmATT,idAsmIntel,idAsmMot,idAsmStandard,
|
|
idSymInfNone,idSymInfGlobalOnly,idSymInfGlobalLocal,
|
|
idStackSize,idHeapSize,idStrictVarStrings,idExtendedSyntax,
|
|
idMMXOps,idTypedAddress,idPackRecords,idPackEnum,idStackFrames,
|
|
idReferenceInfo,idDebugInfo,idBoolEval,
|
|
idAnsiString,idTypeInfo);
|
|
|
|
TSwitchMode = (om_Normal,om_Debug,om_Release);
|
|
|
|
TCompilerMode = (moNone,moFpc,moObjFpc,moTp,moDelphi,moDelphiUnicode,
|
|
moMacPas,moIso,moExtendedPascal,moGnu);
|
|
|
|
TSwitchItemTyp = (ot_Select,ot_Boolean,ot_String,ot_MultiString,ot_Longint);
|
|
|
|
PSwitchItem = ^TSwitchItem;
|
|
TSwitchItem = object(TObject)
|
|
Typ : TSwitchItemTyp;
|
|
Name : string[50];
|
|
Param : string[30];
|
|
ParamID : TParamID;
|
|
constructor Init(const n,p:string; AID: TParamID);
|
|
function NeedParam:boolean;virtual;
|
|
function ParamValue(nr:sw_integer):string;virtual;
|
|
function ParamValueBool(SM: TSwitchMode):boolean;virtual;
|
|
function ParamCount:sw_integer;virtual;
|
|
function GetSwitchStr(SM: TSwitchMode): string; virtual;
|
|
function GetNumberStr(SM: TSwitchMode): string; virtual;
|
|
function GetOptionStr(SM: TSwitchMode): string; virtual;
|
|
procedure Reset;virtual;
|
|
end;
|
|
|
|
PSelectItem = ^TSelectItem;
|
|
TSelectItem = object(TSwitchItem)
|
|
IsDefault : boolean;
|
|
constructor Init(const n,p:string; AID: TParamID);
|
|
{ Select to avoid anything in config file }
|
|
constructor InitDefault(const n:string);
|
|
end;
|
|
|
|
PBooleanItem = ^TBooleanItem;
|
|
TBooleanItem = object(TSwitchItem)
|
|
IsSet : array[TSwitchMode] of boolean;
|
|
constructor Init(const n,p:string; AID: TParamID);
|
|
function NeedParam:boolean;virtual;
|
|
procedure Reset;virtual;
|
|
function GetSwitchStr(SM: TSwitchMode): string; virtual;
|
|
function ParamValueBool(SM: TSwitchMode):boolean;virtual;
|
|
end;
|
|
|
|
PStringItem = ^TStringItem;
|
|
TStringItem = object(TSwitchItem)
|
|
Str : array[TSwitchMode] of string;
|
|
multiple : boolean;
|
|
SeparateSpaces : boolean;
|
|
constructor Init(const n,p:string;AID: TParamID; mult,allowspaces:boolean);
|
|
function NeedParam:boolean;virtual;
|
|
function ParamValue(nr:sw_integer):string;virtual;
|
|
procedure Reset;virtual;
|
|
end;
|
|
|
|
PMultiStringItem = ^TMultiStringItem;
|
|
TMultiStringItem = object(TSwitchItem)
|
|
MultiStr : array[TSwitchMode] of PunsortedStringCollection;
|
|
constructor Init(const n,p:string;AID: TParamID);
|
|
function NeedParam:boolean;virtual;
|
|
function ParamValue(nr:sw_integer):string;virtual;
|
|
function ParamCount:sw_integer;virtual;
|
|
procedure Reset;virtual;
|
|
destructor done;virtual;
|
|
end;
|
|
|
|
|
|
PLongintItem = ^TLongintItem;
|
|
TLongintItem = object(TSwitchItem)
|
|
Val : array[TSwitchMode] of longint;
|
|
constructor Init(const n,p:string; AID: TParamID);
|
|
function NeedParam:boolean;virtual;
|
|
function ParamValue(nr:sw_integer):string;virtual;
|
|
function GetNumberStr(SM: TSwitchMode): string; virtual;
|
|
procedure Reset;virtual;
|
|
end;
|
|
|
|
PSwitches = ^TSwitches;
|
|
TSwitches = object
|
|
constructor Init(ch:AnsiChar);
|
|
constructor InitSelect(ch:AnsiChar);
|
|
destructor Done;
|
|
{ general items }
|
|
function ItemCount:integer;
|
|
function ItemName(index:integer):string;
|
|
function ItemParam(index:integer):string;
|
|
{ type specific }
|
|
procedure AddSelectItem(const name,param:string; AID: TParamID);
|
|
procedure AddDefaultSelect(const name:string);
|
|
procedure AddBooleanItem(const name,param:string; AID: TParamID);
|
|
procedure AddLongintItem(const name,param:string; AID: TParamID);
|
|
procedure AddStringItem(const name,param:string;AID: TParamID;mult,allowspaces:boolean);
|
|
procedure AddMultiStringItem(const name,param:string;AID: TParamID);
|
|
function GetCurrSel:integer;
|
|
function GetCurrSelParam : String;
|
|
function GetCurrSelParamID : TParamID;
|
|
function GetBooleanItem(index:integer):boolean;
|
|
function GetLongintItem(index:integer):longint;
|
|
function GetStringItem(index:integer):string;
|
|
function GetMultiStringItem(index:integer):PunsortedStringCollection;
|
|
function GetItemTyp(index:integer):TSwitchItemTyp;
|
|
procedure SetCurrSel(index:integer);
|
|
function SetCurrSelParam(const s:string) : boolean;
|
|
procedure SetBooleanItem(index:integer;b:boolean);
|
|
procedure SetLongintItem(index:integer;l:longint);
|
|
procedure SetStringItem(index:integer;const s:string);
|
|
{ read / write to cfgfile which must be open }
|
|
procedure WriteItemsCfg;
|
|
function ReadItemsCfg(const s:string):boolean;
|
|
private
|
|
IsSel : boolean;
|
|
Prefix : AnsiChar;
|
|
SelNr : array[TSwitchMode] of integer;
|
|
Items : PCollection;
|
|
end;
|
|
|
|
const
|
|
SwitchesMode : TSwitchMode = om_Normal;
|
|
|
|
SwitchesModeName : array[TSwitchMode] of string[10]=
|
|
('~N~ormal','~D~ebug','~R~elease');
|
|
SwitchesModeStr : array[TSwitchMode] of string[8]=
|
|
('NORMAL','DEBUG','RELEASE');
|
|
CustomArg : array[TSwitchMode] of string{$ifndef FPC}[128]{$endif}=
|
|
('','','');
|
|
|
|
var
|
|
LibLinkerSwitches,
|
|
OtherLinkerSwitches,
|
|
DebugInfoSwitches,
|
|
LinkAfterSwitches,
|
|
ProfileInfoSwitches,
|
|
{MemorySizeSwitches, doubled !! }
|
|
SyntaxSwitches,
|
|
CompilerModeSwitches,
|
|
VerboseSwitches,
|
|
CodegenSwitches,
|
|
OptimizationSwitches,
|
|
ProcessorCodeGenerationSwitches,
|
|
ProcessorOptimizationSwitches,
|
|
AsmReaderSwitches,
|
|
AsmInfoSwitches,
|
|
TargetSwitches,
|
|
ConditionalSwitches,
|
|
MemorySwitches,
|
|
BrowserSwitches,
|
|
DirectorySwitches : PSwitches;
|
|
|
|
{Every mode can have different target, thus have its own AsmOutput}
|
|
AsmOutputSwitches: array [TSwitchMode] of PSwitches;
|
|
|
|
{ write/read the Switches to fpc.cfg file }
|
|
procedure WriteSwitches(const fn:string);
|
|
procedure ReadSwitches(const fn:string);
|
|
|
|
procedure UpdateAsmOutputSwitches;
|
|
|
|
{ initialize }
|
|
procedure InitSwitches;
|
|
procedure SetDefaultSwitches;
|
|
procedure DoneSwitches;
|
|
function GetSourceDirectories : string;
|
|
|
|
procedure GetCompilerOptionLines(C: PUnsortedStringCollection);
|
|
|
|
implementation
|
|
|
|
uses
|
|
Dos,
|
|
GlobType,
|
|
CpuInfo,
|
|
FPVars,FPUtils;
|
|
|
|
var
|
|
CfgFile : text;
|
|
|
|
{$ifdef useresstrings}
|
|
resourcestring
|
|
{$else}
|
|
const
|
|
{$endif}
|
|
msg_automaticallycreateddontedit = 'Automatically created file, don''t edit.';
|
|
|
|
{ Compiler options }
|
|
opt_objectpascal = 'Object pascal support';
|
|
opt_clikeoperators = 'C-like operators';
|
|
opt_stopafterfirsterror = 'Stop after first error';
|
|
opt_allowlabelandgoto = 'Allow LABEL and GOTO';
|
|
opt_cplusplusstyledinline = 'Allow inline';
|
|
opt_globalcmacros = 'Enable macros';
|
|
opt_allowstaticinobjects = 'Allow STATIC in objects';
|
|
opt_assertions = 'Include assertion code';
|
|
opt_kylix = 'Load Kylix compat. unit';
|
|
opt_ansistring = 'Use Ansi Strings';
|
|
opt_strictvarstrings = 'Strict var-strings';
|
|
opt_extendedsyntax = 'Extended syntax';
|
|
opt_allowmmxoperations = 'Allow MMX operations';
|
|
|
|
opt_mode_freepascal = 'Free Pascal dialect';
|
|
opt_mode_objectpascal = 'Object Pascal extension on';
|
|
opt_mode_turbopascal = 'Turbo Pascal compatible';
|
|
opt_mode_delphi = 'Delphi compatible';
|
|
opt_mode_delphiunicode = 'Delphi Unicode';
|
|
opt_mode_macpascal = 'Macintosh Pascal dialect';
|
|
opt_mode_iso = 'Standard Pascal, ISO 7185';
|
|
opt_mode_extendedpascal = 'Extended Pascal, ISO 10206';
|
|
opt_mode_gnupascal = 'GNU Pascal';
|
|
{ Verbose options }
|
|
opt_warnings = '~W~arnings';
|
|
opt_notes = 'N~o~tes';
|
|
opt_hints = '~H~ints';
|
|
opt_generalinfo = 'General ~I~nfo';
|
|
opt_usedtriedinfo = '~U~sed,tried info';
|
|
opt_all = '~A~ll';
|
|
opt_showallprocsonerror = 'Show all ~P~rocedures if error';
|
|
{ Checking options }
|
|
opt_rangechecking = '~R~ange checking';
|
|
opt_stackchecking = '~S~tack checking';
|
|
opt_iochecking = '~I~/O checking';
|
|
opt_overflowchecking = 'Integer ~o~verflow checking';
|
|
opt_objmethcallvalid = 'Object ~m~ethod call checking';
|
|
{ Code generation }
|
|
opt_pic = '~P~osition independent code';
|
|
opt_smart = 'Create smart~l~inkable units';
|
|
{ Code options }
|
|
//opt_generatefastercode = 'Generate ~f~aster code';
|
|
opt_generatesmallercode = 'G~e~nerate smaller code';
|
|
opt_useregistervariables = 'Use regis~t~er-variables';
|
|
opt_uncertainoptimizations = '~U~ncertain optimizations';
|
|
opt_level1optimizations = 'Level ~1~ optimizations';
|
|
opt_level2optimizations = 'Level ~2~ optimizations';
|
|
opt_level3optimizations = 'Level ~3~ optimizations';
|
|
{ optimization processor target }
|
|
opt_i386486 = 'i~3~86/i486';
|
|
opt_pentium = 'P~e~ntium (tm)';
|
|
opt_pentiummmx = 'PentiumMM~X~ (tm)';
|
|
opt_pentiumpro = '~P~entium2/PentiumM/AMD';
|
|
opt_pentiumiv = 'Pentium~4~';
|
|
opt_pentiumm = 'Pentium~M~';
|
|
opt_m68000 = 'm~6~8000';
|
|
opt_m68020 = 'm680~2~0';
|
|
{ Assembler options }
|
|
opt_directassembler = '~D~irect assembler';
|
|
opt_defaultassembler = '~D~efault style assembler';
|
|
opt_attassembler = '~A~T&T style assembler';
|
|
opt_intelassembler = '~I~ntel style assembler';
|
|
opt_motassembler = '~M~otorola style assembler';
|
|
opt_standardassembler = '~S~tandard style assembler';
|
|
opt_listsource = '~L~ist source';
|
|
opt_listregisterallocation = 'list ~r~egister allocation';
|
|
opt_listtempallocation = 'list ~t~emp allocation';
|
|
opt_listnodeallocation = 'list ~n~ode allocation';
|
|
opt_useasmpipe = 'use ~p~ipe with assembler';
|
|
{ Assembler output selection }
|
|
opt_usedefaultas = 'Use ~d~efault output';
|
|
opt_usegnuas = 'Use ~G~NU as';
|
|
{ I386 assembler output selection }
|
|
opt_usenasmcoff = 'Use ~N~ASM coff';
|
|
opt_usenasmwin32 = 'Use NASM ~w~in32';
|
|
opt_usenasmwdosx= 'Use ~N~ASM w~d~osx';
|
|
opt_usenasmelf = 'Use NASM el~f~';
|
|
opt_usenasmbeos = 'Use NASM ~b~eos';
|
|
opt_usenasmobj = 'Use NASM ~o~bj';
|
|
opt_usemasm = 'Use ~M~ASM';
|
|
opt_usetasm = 'Use ~T~ASM';
|
|
opt_usewasm = 'Use ~W~ASM';
|
|
opt_usecoff = 'Use internal ~c~off';
|
|
opt_usepecoff = 'Use internal ~p~ecoff';
|
|
opt_usepecoffwdosx = 'Use internal pewdos~x~';
|
|
opt_useelf= 'Use internal ~e~lf';
|
|
|
|
{ Browser options }
|
|
opt_nobrowser = 'N~o~ browser';
|
|
opt_globalonlybrowser = 'Only Glob~a~l browser';
|
|
opt_localglobalbrowser = '~L~ocal and global browser';
|
|
{ Conditional defines }
|
|
opt_conditionaldefines = 'Conditio~n~al defines';
|
|
{ Memory sizes }
|
|
opt_stacksize = '~S~tack size';
|
|
opt_heapsize = '~H~eap size';
|
|
{ Directory options }
|
|
opt_unitdirectories = '~U~nit directories';
|
|
opt_includedirectories = '~I~nclude directories';
|
|
opt_librarydirectories = '~L~ibrary directories';
|
|
opt_objectdirectories = '~O~bject directories';
|
|
opt_exeppudirectories = '~E~XE output directory';
|
|
opt_ppuoutputdirectory = '~P~PU output directory';
|
|
opt_cross_tools_directory = '~C~ross tools directory';
|
|
opt_dynamic_linker = '~D~ynamic linker path';
|
|
{ Library options }
|
|
opt_librariesdefault = '~T~arget default';
|
|
opt_dynamiclibraries = 'Link to ~D~ynamic libraries';
|
|
opt_staticlibraries = 'Link to ~S~tatic libraries';
|
|
opt_smartlibraries = 'Link to S~m~art libraries';
|
|
opt_forcestaticlibs = 'Only link to st~a~tic libraries';
|
|
{ Symbol info options }
|
|
opt_stripalldebugsymbols = '~S~trip all debug symbols from executable';
|
|
opt_nogendebugsymbolinfo = 'Skip ~d~ebug information generation';
|
|
opt_gendebugsymbolinfo = 'Generate ~d~ebug symbol information';
|
|
opt_gensymbolandbacktraceinfo = 'Generate also backtrace ~l~ine information';
|
|
opt_valgrindinfo = 'Generate ~v~algrind compatible debug info';
|
|
{ Link after options }
|
|
opt_linkafter = 'Call ~l~inker after';
|
|
{ Profiling options }
|
|
opt_noprofileinfo = '~N~o profile information';
|
|
opt_gprofinfo = 'Generate profile code for g~p~rof';
|
|
|
|
{*****************************************************************************
|
|
TSwitchItem
|
|
*****************************************************************************}
|
|
|
|
constructor TSwitchItem.Init(const n,p:string; AID: TParamID);
|
|
begin
|
|
Inherited Init;
|
|
Name:=n;
|
|
Param:=p;
|
|
ParamID:=AID;
|
|
end;
|
|
|
|
|
|
function TSwitchItem.NeedParam:boolean;
|
|
begin
|
|
NeedParam:=false;
|
|
end;
|
|
|
|
|
|
function TSwitchItem.ParamValue(nr:sw_integer):string;
|
|
begin
|
|
ParamValue:='';
|
|
end;
|
|
|
|
function TSwitchItem.ParamValueBool(SM: TSwitchMode):boolean;
|
|
begin
|
|
Abstract;
|
|
ParamValueBool:=false;
|
|
end;
|
|
|
|
function TSwitchItem.ParamCount:sw_integer;
|
|
|
|
begin
|
|
ParamCount:=1;
|
|
end;
|
|
|
|
function TSwitchItem.GetSwitchStr(SM: TSwitchMode): string;
|
|
begin
|
|
Abstract;
|
|
GetSwitchStr:='';
|
|
end;
|
|
|
|
function TSwitchItem.GetNumberStr(SM: TSwitchMode): string;
|
|
begin
|
|
Abstract;
|
|
GetNumberStr:='';
|
|
end;
|
|
|
|
function TSwitchItem.GetOptionStr(SM: TSwitchMode): string;
|
|
begin
|
|
Abstract;
|
|
GetOptionStr:='';
|
|
end;
|
|
|
|
procedure TSwitchItem.Reset;
|
|
begin
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
TSelectItem
|
|
*****************************************************************************}
|
|
|
|
constructor TSelectItem.Init(const n,p:string; AID: TParamID);
|
|
begin
|
|
Inherited Init(n,p,AID);
|
|
Typ:=ot_Select;
|
|
IsDefault:=false;
|
|
end;
|
|
|
|
constructor TSelectItem.InitDefault(const n:string);
|
|
begin
|
|
Inherited Init(n,'',idNone);
|
|
Typ:=ot_Select;
|
|
IsDefault:=true;
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
TBooleanItem
|
|
*****************************************************************************}
|
|
|
|
constructor TBooleanItem.Init(const n,p:string; AID: TParamID);
|
|
begin
|
|
Inherited Init(n,p,AID);
|
|
Typ:=ot_Boolean;
|
|
Reset;
|
|
end;
|
|
|
|
|
|
function TBooleanItem.NeedParam:boolean;
|
|
begin
|
|
NeedParam:=IsSet[SwitchesMode];
|
|
end;
|
|
|
|
|
|
procedure TBooleanItem.Reset;
|
|
begin
|
|
FillChar(IsSet,sizeof(IsSet),0);
|
|
end;
|
|
|
|
function TBooleanItem.ParamValueBool(SM: TSwitchMode):boolean;
|
|
begin
|
|
ParamValueBool:=IsSet[SM];
|
|
end;
|
|
|
|
function TBooleanItem.GetSwitchStr(SM: TSwitchMode): string;
|
|
begin
|
|
GetSwitchStr:=BoolToStr(IsSet[SM],'+','-');
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
TStringItem
|
|
*****************************************************************************}
|
|
|
|
constructor TStringItem.Init(const n,p:string; AID: TParamID; mult,allowspaces:boolean);
|
|
begin
|
|
Inherited Init(n,p,AID);
|
|
Typ:=ot_String;
|
|
Multiple:=mult;
|
|
SeparateSpaces:=not allowspaces;
|
|
Reset;
|
|
end;
|
|
|
|
|
|
function TStringItem.NeedParam:boolean;
|
|
begin
|
|
NeedParam:=(Str[SwitchesMode]<>'');
|
|
end;
|
|
|
|
|
|
function TStringItem.ParamValue(nr:sw_integer):string;
|
|
begin
|
|
ParamValue:=Str[SwitchesMode];
|
|
end;
|
|
|
|
|
|
procedure TStringItem.Reset;
|
|
begin
|
|
FillChar(Str,sizeof(Str),0);
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
TMultiStringItem
|
|
*****************************************************************************}
|
|
|
|
constructor TMultiStringItem.Init(const n,p:string;AID:TParamID);
|
|
|
|
var i:TSwitchMode;
|
|
|
|
begin
|
|
inherited Init(n,p,AID);
|
|
typ:=ot_MultiString;
|
|
for i:=low(MultiStr) to high(MultiStr) do
|
|
new(MultiStr[i],init(5,5));
|
|
{ Reset;}
|
|
end;
|
|
|
|
function TMultiStringItem.NeedParam:boolean;
|
|
|
|
begin
|
|
NeedParam:=(multistr[SwitchesMode]^.count<>0);
|
|
end;
|
|
|
|
function TMultiStringItem.ParamValue(nr:sw_integer):string;
|
|
|
|
begin
|
|
ParamValue:=MultiStr[SwitchesMode]^.at(nr)^;
|
|
end;
|
|
|
|
function TMultiStringItem.ParamCount:sw_integer;
|
|
|
|
begin
|
|
ParamCount:=Multistr[SwitchesMode]^.count;
|
|
end;
|
|
|
|
procedure TMultiStringItem.Reset;
|
|
|
|
var i:TSwitchMode;
|
|
|
|
begin
|
|
for i:=low(multiStr) to high(multiStr) do
|
|
MultiStr[i]^.freeall;
|
|
end;
|
|
|
|
destructor TmultiStringItem.done;
|
|
|
|
var i:TSwitchMode;
|
|
|
|
begin
|
|
for i:=low(MultiStr) to high(MultiStr) do
|
|
dispose(MultiStr[i],done);
|
|
inherited done;
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
TLongintItem
|
|
*****************************************************************************}
|
|
|
|
constructor TLongintItem.Init(const n,p:string; AID: TParamID);
|
|
begin
|
|
Inherited Init(n,p,AID);
|
|
Typ:=ot_Longint;
|
|
Reset;
|
|
end;
|
|
|
|
|
|
function TLongintItem.NeedParam:boolean;
|
|
begin
|
|
NeedParam:=(Val[SwitchesMode]<>0);
|
|
end;
|
|
|
|
|
|
function TLongintItem.ParamValue(nr:sw_integer):string;
|
|
var
|
|
s : string;
|
|
begin
|
|
Str(Val[SwitchesMode],s);
|
|
ParamValue:=s;
|
|
end;
|
|
|
|
procedure TLongintItem.Reset;
|
|
begin
|
|
FillChar(Val,sizeof(Val),0);
|
|
end;
|
|
|
|
function TLongintItem.GetNumberStr(SM: TSwitchMode): string;
|
|
begin
|
|
GetNumberStr:=IntToStr(Val[SM]);
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
TSwitch
|
|
*****************************************************************************}
|
|
|
|
constructor TSwitches.Init(ch:AnsiChar);
|
|
begin
|
|
new(Items,Init(10,5));
|
|
Prefix:=ch;
|
|
FillChar(SelNr,SizeOf(SelNr),#0);
|
|
IsSel:=false;
|
|
end;
|
|
|
|
|
|
constructor TSwitches.InitSelect(ch:AnsiChar);
|
|
begin
|
|
new(Items,Init(10,5));
|
|
Prefix:=ch;
|
|
FillChar(SelNr,SizeOf(SelNr),#0);
|
|
IsSel:=true;
|
|
end;
|
|
|
|
|
|
destructor TSwitches.Done;
|
|
begin
|
|
dispose(Items,Done);
|
|
end;
|
|
|
|
|
|
procedure TSwitches.AddSelectItem(const name,param:string; AID: TParamID);
|
|
begin
|
|
Items^.Insert(New(PSelectItem,Init(name,Param,AID)));
|
|
end;
|
|
|
|
|
|
procedure TSwitches.AddDefaultSelect(const name:string);
|
|
begin
|
|
Items^.Insert(New(PSelectItem,InitDefault(name)));
|
|
end;
|
|
|
|
|
|
procedure TSwitches.AddBooleanItem(const name,param:string; AID: TParamID);
|
|
begin
|
|
Items^.Insert(New(PBooleanItem,Init(name,Param,AID)));
|
|
end;
|
|
|
|
|
|
procedure TSwitches.AddLongintItem(const name,param:string; AID: TParamID);
|
|
begin
|
|
Items^.Insert(New(PLongintItem,Init(name,Param,AID)));
|
|
end;
|
|
|
|
|
|
procedure TSwitches.AddStringItem(const name,param:string;AID:TParamID;mult,allowspaces:boolean);
|
|
begin
|
|
Items^.Insert(New(PStringItem,Init(name,Param,AID,mult,allowspaces)));
|
|
end;
|
|
|
|
procedure TSwitches.AddMultiStringItem(const name,param:string;AID:TParamID);
|
|
begin
|
|
Items^.Insert(New(PMultiStringItem,Init(name,Param,AID)));
|
|
end;
|
|
|
|
function TSwitches.ItemCount:integer;
|
|
begin
|
|
ItemCount:=Items^.Count;
|
|
end;
|
|
|
|
|
|
function TSwitches.ItemName(index:integer):string;
|
|
var
|
|
P : PSwitchItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) then
|
|
ItemName:=P^.Name
|
|
else
|
|
ItemName:='';
|
|
end;
|
|
|
|
|
|
function TSwitches.ItemParam(index:integer):string;
|
|
var
|
|
P : PSwitchItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) then
|
|
ItemParam:='-'+Prefix+P^.Param
|
|
else
|
|
ItemParam:='';
|
|
end;
|
|
|
|
|
|
function TSwitches.GetBooleanItem(index:integer):boolean;
|
|
var
|
|
P : PBooleanItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) and (P^.Typ=ot_boolean) then
|
|
GetBooleanItem:=P^.IsSet[SwitchesMode]
|
|
else
|
|
GetBooleanItem:=false;
|
|
end;
|
|
|
|
|
|
function TSwitches.GetLongintItem(index:integer):longint;
|
|
var
|
|
P : PLongintItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) and (P^.Typ=ot_longint) then
|
|
GetLongintItem:=P^.Val[SwitchesMode]
|
|
else
|
|
GetLongintItem:=0;
|
|
end;
|
|
|
|
|
|
function TSwitches.GetStringItem(index:integer):string;
|
|
var
|
|
P : PStringItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) and (P^.Typ=ot_string) then
|
|
GetStringItem:=P^.Str[SwitchesMode]
|
|
else
|
|
GetStringItem:='';
|
|
end;
|
|
|
|
function TSwitches.GetMultiStringItem(index:integer):PUnsortedStringCollection;
|
|
|
|
var p:PMultiStringItem;
|
|
|
|
begin
|
|
if index<ItemCount then
|
|
p:=Items^.at(Index)
|
|
else
|
|
p:=nil;
|
|
if (p<>nil) and (p^.typ=ot_multistring) then
|
|
GetMultiStringItem:=p^.MultiStr[SwitchesMode]
|
|
else
|
|
GetMultiStringItem:=nil;
|
|
end;
|
|
|
|
function TSwitches.GetItemTyp(index:integer):TSwitchItemTyp;
|
|
|
|
var p:PSwitchItem;
|
|
|
|
begin
|
|
assert(index<itemcount);
|
|
GetItemTyp:=PSwitchItem(items^.at(index))^.typ;
|
|
end;
|
|
|
|
procedure TSwitches.SetBooleanItem(index:integer;b:boolean);
|
|
var
|
|
P : PBooleanItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) and (P^.Typ=ot_boolean) then
|
|
P^.IsSet[SwitchesMode]:=b;
|
|
end;
|
|
|
|
|
|
procedure TSwitches.SetLongintItem(index:integer;l:longint);
|
|
var
|
|
P : PLongintItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) and (P^.Typ=ot_longint) then
|
|
P^.Val[SwitchesMode]:=l;
|
|
end;
|
|
|
|
|
|
procedure TSwitches.SetStringItem(index:integer;const s:string);
|
|
var
|
|
P : PStringItem;
|
|
begin
|
|
if index<ItemCount then
|
|
P:=Items^.At(Index)
|
|
else
|
|
P:=nil;
|
|
if assigned(P) and (P^.Typ=ot_string) then
|
|
P^.Str[SwitchesMode]:=s;
|
|
end;
|
|
|
|
|
|
function TSwitches.GetCurrSel:integer;
|
|
begin
|
|
if IsSel then
|
|
GetCurrSel:=SelNr[SwitchesMode]
|
|
else
|
|
GetCurrSel:=-1;
|
|
end;
|
|
|
|
|
|
function TSwitches.GetCurrSelParam : String;
|
|
begin
|
|
if IsSel then
|
|
GetCurrSelParam:=PSwitchItem(Items^.At(SelNr[SwitchesMode]))^.Param
|
|
else
|
|
GetCurrSelParam:='';
|
|
end;
|
|
|
|
function TSwitches.GetCurrSelParamID : TParamID;
|
|
begin
|
|
if IsSel then
|
|
GetCurrSelParamID:=PSwitchItem(Items^.At(SelNr[SwitchesMode]))^.ParamID
|
|
else
|
|
GetCurrSelParamID:=idNone;
|
|
end;
|
|
|
|
procedure TSwitches.SetCurrSel(index:integer);
|
|
begin
|
|
if index<ItemCount then
|
|
SelNr[SwitchesMode]:=index;
|
|
end;
|
|
|
|
function TSwitches.SetCurrSelParam(const s : String) : boolean;
|
|
function checkitem(P:PSwitchItem):boolean;
|
|
begin
|
|
{ empty items are not equivalent to others !! }
|
|
CheckItem:=((S='') and (P^.Param='')) or
|
|
((Length(S)>0) and (P^.Param=s));
|
|
end;
|
|
|
|
var
|
|
FoundP : PSwitchItem;
|
|
begin
|
|
FoundP:=Items^.FirstThat(TCallbackFunBoolParam(@CheckItem));
|
|
if Assigned(FoundP) then
|
|
begin
|
|
SetCurrSelParam:=true;
|
|
SelNr[SwitchesMode]:=Items^.IndexOf(FoundP);
|
|
end
|
|
else
|
|
SetCurrSelParam:=false;
|
|
end;
|
|
|
|
|
|
procedure TSwitches.WriteItemsCfg;
|
|
var
|
|
Pref : AnsiChar;
|
|
|
|
procedure writeitem(P:PSwitchItem);
|
|
var
|
|
s,s1 : string;
|
|
i,j : integer;
|
|
begin
|
|
if P^.NeedParam then
|
|
begin
|
|
if (P^.Typ=ot_string) and (PStringItem(P)^.Multiple) then
|
|
begin
|
|
s:=PStringItem(P)^.Str[SwitchesMode];
|
|
repeat
|
|
i:=pos(';',s);
|
|
if PStringItem(P)^.SeparateSpaces then
|
|
j:=pos(' ',s)
|
|
else
|
|
j:=0;
|
|
if i=0 then
|
|
i:=256;
|
|
if (j>0) and (j<i) then
|
|
i:=j;
|
|
s1:=Copy(s,1,i-1);
|
|
if s1<>'' then
|
|
writeln(CfgFile,' -'+Pref+P^.Param+s1);
|
|
Delete(s,1,i);
|
|
until s='';
|
|
end
|
|
else
|
|
if P^.Param<>'/' then
|
|
for i:=0 to p^.ParamCount-1 do
|
|
Writeln(CfgFile,' -'+Pref+P^.Param+P^.ParamValue(i));
|
|
end;
|
|
end;
|
|
|
|
var
|
|
P : PSelectItem;
|
|
begin
|
|
Pref:=Prefix;
|
|
if IsSel then
|
|
begin
|
|
{ can be empty for some targets }
|
|
If Items^.count>0 then
|
|
begin
|
|
P:=Items^.At(SelNr[SwitchesMode]);
|
|
if not P^.IsDefault then
|
|
writeln(CfgFile,' '+ItemParam(SelNr[SwitchesMode]));
|
|
end;
|
|
end
|
|
else
|
|
Items^.ForEach(TCallbackProcParam(@writeitem));
|
|
end;
|
|
|
|
procedure WriteCustom;
|
|
var
|
|
s : string;
|
|
i : longint;
|
|
begin
|
|
s:=CustomArg[SwitchesMode];
|
|
While s<>'' do
|
|
begin
|
|
i:=pos(' ',s);
|
|
if i=0 then i:=256;
|
|
writeln(CfgFile,' '+Copy(s,1,i-1));
|
|
if i=256 then
|
|
s:=''
|
|
else
|
|
s:=copy(s,i+1,255);
|
|
end;
|
|
end;
|
|
|
|
|
|
function TSwitches.ReadItemsCfg(const s:string):boolean;
|
|
|
|
function checkitem(P:PSwitchItem):boolean;
|
|
begin
|
|
{ empty items are not equivalent to others !! }
|
|
{ but -dGDB didn't work because of this PM }
|
|
CheckItem:=((P^.Param='') and ((S='') or (P^.typ in [ot_Boolean,ot_String]))) or
|
|
((Length(P^.Param)>0) and (upcase(P^.Param)=upcase(S)) and
|
|
not (P^.typ in [ot_Boolean,ot_String])) or
|
|
((Length(P^.Param)>0) and (P^.typ<>ot_Select) and
|
|
(P^.Param=Copy(s,1,length(P^.Param))));
|
|
end;
|
|
|
|
var
|
|
FoundP : PSwitchItem;
|
|
code : integer;
|
|
begin
|
|
FoundP:=Items^.FirstThat(TCallbackFunBoolParam(@checkitem));
|
|
if assigned(FoundP) then
|
|
begin
|
|
case FoundP^.Typ of
|
|
ot_Select : SelNr[SwitchesMode]:=Items^.IndexOf(FoundP);
|
|
ot_Boolean : PBooleanItem(FoundP)^.IsSet[SwitchesMode]:=true;
|
|
ot_String : begin
|
|
if (PStringItem(FoundP)^.Multiple) and (PStringItem(FoundP)^.Str[SwitchesMode]<>'') then
|
|
PStringItem(FoundP)^.Str[SwitchesMode]:=PStringItem(FoundP)^.Str[SwitchesMode]+';'+
|
|
Copy(s,length(FoundP^.Param)+1,255)
|
|
else
|
|
PStringItem(FoundP)^.Str[SwitchesMode]:=Copy(s,length(FoundP^.Param)+1,255);
|
|
end;
|
|
ot_MultiString :
|
|
PMultiStringItem(foundP)^.MultiStr[SwitchesMode]^.insert(newstr(copy(s,length(foundP^.param)+1,255)));
|
|
ot_Longint : Val(Copy(s,length(FoundP^.Param)+1,255),PLongintItem(FoundP)^.Val[SwitchesMode],code);
|
|
end;
|
|
ReadItemsCfg:=true;
|
|
end
|
|
else
|
|
ReadItemsCfg:=false;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
Read / Write
|
|
*****************************************************************************}
|
|
|
|
procedure WriteSwitches(const fn:string);
|
|
var
|
|
OldSwitchesMode, SWM: TSwitchMode;
|
|
begin
|
|
{ create the switches }
|
|
assign(CfgFile,fn);
|
|
{$I-}
|
|
rewrite(CfgFile);
|
|
{$I+}
|
|
if ioresult<>0 then
|
|
exit;
|
|
writeln(CfgFile,'# '+msg_automaticallycreateddontedit);
|
|
OldSwitchesMode:=SwitchesMode;
|
|
for SWM:=low(TSwitchMode) to high(TSwitchMode) do
|
|
begin
|
|
SwitchesMode := SWM;
|
|
Writeln(CfgFile,'#IFDEF '+SwitchesModeStr[SwitchesMode]);
|
|
TargetSwitches^.WriteItemsCfg;
|
|
CompilerModeSwitches^.WriteItemsCfg;
|
|
VerboseSwitches^.WriteItemsCfg;
|
|
SyntaxSwitches^.WriteItemsCfg;
|
|
CodegenSwitches^.WriteItemsCfg;
|
|
OptimizationSwitches^.WriteItemsCfg;
|
|
ProcessorCodeGenerationSwitches^.WriteItemsCfg;
|
|
ProcessorOptimizationSwitches^.WriteItemsCfg;
|
|
AsmReaderSwitches^.WriteItemsCfg;
|
|
AsmInfoSwitches^.WriteItemsCfg;
|
|
if assigned(AsmOutputSwitches[SwitchesMode]) then
|
|
AsmOutputSwitches[SwitchesMode]^.WriteItemsCfg;
|
|
DirectorySwitches^.WriteItemsCfg;
|
|
MemorySwitches^.WriteItemsCfg;
|
|
ConditionalSwitches^.WriteItemsCfg;
|
|
LibLinkerSwitches^.WriteItemsCfg;
|
|
OtherLinkerSwitches^.WriteItemsCfg;
|
|
DebugInfoSwitches^.WriteItemsCfg;
|
|
ProfileInfoSwitches^.WriteItemsCfg;
|
|
LinkAfterSwitches^.WriteItemsCfg;
|
|
BrowserSwitches^.WriteItemsCfg;
|
|
{MemorySizeSwitches^.WriteItemsCfg;}
|
|
WriteCustom;
|
|
Writeln(CfgFile,'#ENDIF');
|
|
Writeln(CfgFile,'');
|
|
end;
|
|
close(CfgFile);
|
|
SwitchesMode:=OldSwitchesMode;
|
|
end;
|
|
|
|
|
|
procedure ReadSwitches(const fn:string);
|
|
var
|
|
c : AnsiChar;
|
|
s : string;
|
|
res : boolean;
|
|
OldSwitchesMode,i : TSwitchMode;
|
|
begin
|
|
assign(CfgFile,fn);
|
|
{$I-}
|
|
reset(CfgFile);
|
|
{$I+}
|
|
if ioresult<>0 then
|
|
begin
|
|
SetDefaultSwitches;
|
|
exit;
|
|
end;
|
|
OldSwitchesMode:=SwitchesMode;
|
|
SwitchesMode:=om_Normal;
|
|
while not eof(CfgFile) do
|
|
begin
|
|
readln(CfgFile,s);
|
|
s:=LTrim(s);
|
|
if (length(s)>=2) and (s[1]='-') then
|
|
begin
|
|
c:=s[2];
|
|
res:=false;
|
|
Delete(s,1,2);
|
|
case c of
|
|
'a' : res:=AsmInfoSwitches^.ReadItemsCfg(s);
|
|
'A' : begin
|
|
UpdateAsmOutputSwitches;
|
|
res:=AsmOutputSwitches[SwitchesMode]^.ReadItemsCfg(s);
|
|
end;
|
|
'b' : res:=BrowserSwitches^.ReadItemsCfg(s);
|
|
'C' : begin
|
|
res:=CodegenSwitches^.ReadItemsCfg(s);
|
|
if not res then
|
|
res:=MemorySwitches^.ReadItemsCfg(s);
|
|
if not res then
|
|
res:=ProcessorCodeGenerationSwitches^.ReadItemsCfg(s);
|
|
end;
|
|
'd' : res:=ConditionalSwitches^.ReadItemsCfg(s);
|
|
'F' : res:=DirectorySwitches^.ReadItemsCfg(s);
|
|
'g' : res:=DebugInfoSwitches^.ReadItemsCfg(s);
|
|
'O' : begin
|
|
res:=OptimizationSwitches^.ReadItemsCfg(s);
|
|
if not res then
|
|
res:=ProcessorOptimizationSwitches^.ReadItemsCfg(s);
|
|
end;
|
|
'M' : res:=CompilerModeSwitches^.ReadItemsCfg(s);
|
|
'p' : res:=ProfileInfoSwitches^.ReadItemsCfg(s);
|
|
's' : res:=LinkAfterSwitches^.ReadItemsCfg(s);
|
|
'R' : res:=AsmReaderSwitches^.ReadItemsCfg(s);
|
|
'S' : res:=SyntaxSwitches^.ReadItemsCfg(s);
|
|
'T' : res:=TargetSwitches^.ReadItemsCfg(s);
|
|
'v' : res:=VerboseSwitches^.ReadItemsCfg(s);
|
|
'X' : begin
|
|
res:=LibLinkerSwitches^.ReadItemsCfg(s);
|
|
if not res then
|
|
res:=OtherLinkerSwitches^.ReadItemsCfg(s);
|
|
end;
|
|
end;
|
|
{ keep all others as a string }
|
|
if not res then
|
|
CustomArg[SwitchesMode]:=CustomArg[SwitchesMode]+' -'+c+s;
|
|
end
|
|
else
|
|
if (Copy(s,1,7)='#IFDEF ') then
|
|
begin
|
|
Delete(s,1,7);
|
|
for i:=low(TSwitchMode) to high(TSwitchMode) do
|
|
if s=SwitchesModeStr[i] then
|
|
begin
|
|
SwitchesMode:=i;
|
|
break;
|
|
end;
|
|
end
|
|
else;
|
|
end;
|
|
close(CfgFile);
|
|
SwitchesMode:=OldSwitchesMode;
|
|
end;
|
|
|
|
|
|
function GetSourceDirectories : string;
|
|
var
|
|
P : PStringItem;
|
|
S : String;
|
|
c : AnsiChar;
|
|
function checkitem(P:PSwitchItem):boolean;
|
|
begin
|
|
CheckItem:=(P^.Typ=ot_string) and (P^.Param=c);
|
|
end;
|
|
begin
|
|
GetSourceDirectories:='';
|
|
c:='u';
|
|
P:=DirectorySwitches^.Items^.FirstThat(TCallbackFunBoolParam(@CheckItem));
|
|
S:='';
|
|
if assigned(P) then
|
|
S:=P^.Str[SwitchesMode];
|
|
c:='i';
|
|
P:=DirectorySwitches^.Items^.FirstThat(TCallbackFunBoolParam(@CheckItem));
|
|
if assigned(P) then
|
|
S:=P^.Str[SwitchesMode]+';'+S;
|
|
if S='' then
|
|
GetSourceDirectories:=SourceDirs+';'
|
|
else
|
|
GetSourceDirectories:=SourceDirs+';'+S+';';
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
AsmOutputInitialize
|
|
*****************************************************************************}
|
|
|
|
procedure UpdateAsmOutputSwitches;
|
|
var
|
|
ta : tasm;
|
|
zt : tsystem;
|
|
sy : tsystem;
|
|
sw : TSwitchMode;
|
|
st : string;
|
|
L : String;
|
|
t : string;
|
|
begin
|
|
sw:=SwitchesMode;
|
|
t:='';
|
|
if assigned(TargetSwitches) then
|
|
t:=TargetSwitches^.ItemName(TargetSwitches^.GetCurrSel);
|
|
sy:=target_info.system;
|
|
for zt:=low(tsystem) to high(tsystem) do
|
|
if assigned(targetinfos[zt]) then
|
|
begin
|
|
if targetinfos[zt]^.name = t then
|
|
begin
|
|
sy:=zt;
|
|
break;
|
|
end;
|
|
end;
|
|
L:='';
|
|
if assigned(AsmOutputSwitches[sw]) then
|
|
begin
|
|
L:=AsmOutputSwitches[sw]^.GetCurrSelParam;
|
|
dispose(AsmOutputSwitches[sw],Done);
|
|
end;
|
|
New(AsmOutputSwitches[sw],InitSelect('A'));
|
|
with AsmOutputSwitches[sw]^ do
|
|
begin
|
|
AddDefaultSelect(opt_usedefaultas);
|
|
for ta:=low(tasm) to high(tasm) do
|
|
if assigned(asminfos[ta]) and
|
|
((sy in asminfos[ta]^.supported_targets) or
|
|
(system_any in asminfos[ta]^.supported_targets)) then
|
|
begin
|
|
st:='Asm '+asminfos[ta]^.idtxt;
|
|
if asminfos[ta]^.idtxt='AS' then
|
|
st:=opt_usegnuas;
|
|
{$if defined(I386) or defined(x86_64)}
|
|
if asminfos[ta]^.idtxt='NASMCOFF' then
|
|
st:=opt_usenasmcoff;
|
|
if asminfos[ta]^.idtxt='NASMOBJ' then
|
|
st:=opt_usenasmobj;
|
|
if asminfos[ta]^.idtxt='NASMWIN32' then
|
|
st:=opt_usenasmwin32;
|
|
if asminfos[ta]^.idtxt='NASMWDOSX' then
|
|
st:=opt_usenasmwdosx;
|
|
if asminfos[ta]^.idtxt='NASMELF' then
|
|
st:=opt_usenasmelf;
|
|
if asminfos[ta]^.idtxt='NASMBEOS' then
|
|
st:=opt_usenasmbeos;
|
|
if asminfos[ta]^.idtxt='MASM' then
|
|
st:=opt_usemasm;
|
|
if asminfos[ta]^.idtxt='TASM' then
|
|
st:=opt_usetasm;
|
|
if asminfos[ta]^.idtxt='WASM' then
|
|
st:=opt_usewasm;
|
|
if asminfos[ta]^.idtxt='COFF' then
|
|
st:=opt_usecoff;
|
|
if asminfos[ta]^.idtxt='PECOFF' then
|
|
st:=opt_usepecoff;
|
|
if asminfos[ta]^.idtxt='PEWDOSX' then
|
|
st:=opt_usepecoffwdosx;
|
|
if asminfos[ta]^.idtxt='ELF' then
|
|
st:=opt_useelf;
|
|
{$endif I386}
|
|
AddSelectItem(st,asminfos[ta]^.idtxt,idNone);
|
|
end;
|
|
end;
|
|
AsmOutputSwitches[sw]^.SetCurrSelParam(L);
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
Initialize
|
|
*****************************************************************************}
|
|
|
|
procedure InitSwitches;
|
|
var
|
|
t : tsystem;
|
|
cpu : tcputype;
|
|
st : string;
|
|
begin
|
|
New(SyntaxSwitches,Init('S'));
|
|
with SyntaxSwitches^ do
|
|
begin
|
|
// AddBooleanItem(opt_objectpascal,'2',idNone);
|
|
AddBooleanItem(opt_stopafterfirsterror,'e',idNone);
|
|
AddBooleanItem(opt_allowlabelandgoto,'g',idNone);
|
|
AddBooleanItem(opt_globalcmacros,'m',idNone);
|
|
AddBooleanItem(opt_cplusplusstyledinline,'i',idNone);
|
|
// AddBooleanItem(opt_tp7compatibility,'o',idNone);
|
|
// AddBooleanItem(opt_delphicompatibility,'d',idNone);
|
|
AddBooleanItem(opt_assertions,'a',idNone);
|
|
AddBooleanItem(opt_ansistring,'h',idAnsiString);
|
|
AddBooleanItem(opt_kylix,'k',idNone);
|
|
AddBooleanItem(opt_allowstaticinobjects,'s',idNone);
|
|
AddBooleanItem(opt_clikeoperators,'c',idNone);
|
|
{ Useless as they are not passed to the compiler PM
|
|
AddBooleanItem(opt_strictvarstrings,'/',idStrictVarStrings);
|
|
AddBooleanItem(opt_extendedsyntax,'/',idExtendedSyntax);
|
|
AddBooleanItem(opt_allowmmxoperations,'/',idMMXOps); }
|
|
end;
|
|
New(CompilerModeSwitches,InitSelect('M'));
|
|
with CompilerModeSwitches^ do
|
|
begin
|
|
AddSelectItem(opt_mode_freepascal,'fpc',TParamID(moFpc));
|
|
AddSelectItem(opt_mode_objectpascal,'objfpc',TParamID(moObjFpc));
|
|
AddSelectItem(opt_mode_turbopascal,'tp',TParamID(moTp));
|
|
AddSelectItem(opt_mode_delphi,'delphi',TParamID(moDelphi));
|
|
AddSelectItem(opt_mode_delphiunicode,'delphiunicode',TParamID(moDelphiUnicode));
|
|
AddSelectItem(opt_mode_macpascal,'macpas',TParamID(moMacPas));
|
|
AddSelectItem(opt_mode_iso,'iso',TParamID(moIso));
|
|
AddSelectItem(opt_mode_extendedpascal,'extendedpascal',TParamID(moExtendedPascal));
|
|
{ GNU Pascal mode doesn't do much, better disable it
|
|
AddSelectItem(opt_mode_gnupascal,'gpc',idNone);}
|
|
end;
|
|
New(VerboseSwitches,Init('v'));
|
|
with VerboseSwitches^ do
|
|
begin
|
|
AddBooleanItem(opt_warnings,'w',idNone);
|
|
AddBooleanItem(opt_notes,'n',idNone);
|
|
AddBooleanItem(opt_hints,'h',idNone);
|
|
AddBooleanItem(opt_generalinfo,'i',idNone);
|
|
AddBooleanItem(opt_usedtriedinfo,'ut',idNone);
|
|
AddBooleanItem(opt_all,'a',idNone);
|
|
AddBooleanItem(opt_showallprocsonerror,'b',idNone);
|
|
end;
|
|
New(CodegenSwitches,Init('C'));
|
|
with CodegenSwitches^ do
|
|
begin
|
|
AddBooleanItem(opt_rangechecking,'r',idRangeChecks);
|
|
AddBooleanItem(opt_stackchecking,'t',idStackChecks);
|
|
AddBooleanItem(opt_iochecking,'i',idIOChecks);
|
|
AddBooleanItem(opt_overflowchecking,'o',idOverflowChecks);
|
|
AddBooleanItem(opt_objmethcallvalid,'R',idObjMethCallChecks);
|
|
AddBooleanItem(opt_pic,'g',idNone);
|
|
AddBooleanItem(opt_smart,'X',idNone);
|
|
end;
|
|
New(OptimizationSwitches,Init('O'));
|
|
with OptimizationSwitches^ do
|
|
begin
|
|
AddBooleanItem(opt_generatesmallercode,'s',idNone);
|
|
{$ifdef I386}
|
|
AddBooleanItem(opt_useregistervariables,'oregvar',idNone);
|
|
AddBooleanItem(opt_uncertainoptimizations,'ouncertain',idNone);
|
|
AddBooleanItem(opt_level1optimizations,'1',idNone);
|
|
AddBooleanItem(opt_level2optimizations,'2',idNone);
|
|
AddBooleanItem(opt_level3optimizations,'3',idNone);
|
|
{$else not I386}
|
|
{$ifdef m68k}
|
|
AddBooleanItem(opt_level1optimizations,'a',idNone);
|
|
AddBooleanItem(opt_useregistervariables,'x',idNone);
|
|
{$endif m68k}
|
|
{$endif I386}
|
|
end;
|
|
New(ProcessorOptimizationSwitches,InitSelect('O'));
|
|
with ProcessorOptimizationSwitches^ do
|
|
begin
|
|
for cpu:=low(tcputype) to high(tcputype) do
|
|
begin
|
|
st:=cputypestr[cpu];
|
|
{$ifdef I386}
|
|
if st='386' then
|
|
st:=opt_i386486;
|
|
if st='PENTIUM' then
|
|
st:=opt_pentium;
|
|
if st='PENTIUM2' then
|
|
st:=opt_pentiummmx;
|
|
if st='PENTIUM3' then
|
|
st:=opt_pentiumpro;
|
|
if st='PENTIUM4' then
|
|
st:=opt_pentiumiv;
|
|
if st='PENTIUMM' then
|
|
st:=opt_pentiumM;
|
|
{$endif not I386}
|
|
{$ifdef m68k}
|
|
if st='68000' then
|
|
st:=opt_m68000;
|
|
if st='68020' then
|
|
st:=opt_m68020;
|
|
{$endif m68k}
|
|
if st<>'' then
|
|
AddSelectItem(st,'p'+cputypestr[cpu],idNone);
|
|
end;
|
|
end;
|
|
New(ProcessorCodeGenerationSwitches,InitSelect('C'));
|
|
with ProcessorCodeGenerationSwitches^ do
|
|
begin
|
|
for cpu:=low(tcputype) to high(tcputype) do
|
|
begin
|
|
st:=cputypestr[cpu];
|
|
{$ifdef I386}
|
|
if st='386' then
|
|
st:=opt_i386486;
|
|
if st='PENTIUM' then
|
|
st:=opt_pentium;
|
|
if st='PENTIUM2' then
|
|
st:=opt_pentiummmx;
|
|
if st='PENTIUM3' then
|
|
st:=opt_pentiumpro;
|
|
if st='PENTIUM4' then
|
|
st:=opt_pentiumiv;
|
|
if st='PENTIUMM' then
|
|
st:=opt_pentiumM;
|
|
{$endif not I386}
|
|
{$ifdef m68k}
|
|
if st='68000' then
|
|
st:=opt_m68000;
|
|
if st='68020' then
|
|
st:=opt_m68020;
|
|
{$endif m68k}
|
|
{ we use the string twice so kill duplicate highlights }
|
|
while pos('~',st)<>0 do
|
|
delete(st,pos('~',st),1);
|
|
|
|
if st<>'' then
|
|
AddSelectItem(st,'p'+cputypestr[cpu],idNone);
|
|
end;
|
|
end;
|
|
New(TargetSwitches,InitSelect('T'));
|
|
with TargetSwitches^ do
|
|
begin
|
|
{ better, we've a correct target list without "tilded" names instead a wrong one }
|
|
for t:=low(tsystem) to high(tsystem) do
|
|
if assigned(targetinfos[t]) then
|
|
AddSelectItem(targetinfos[t]^.name,targetinfos[t]^.shortname,idNone);
|
|
end;
|
|
New(AsmReaderSwitches,InitSelect('R'));
|
|
with AsmReaderSwitches^ do
|
|
begin
|
|
AddSelectItem(opt_defaultassembler,'default',idNone);
|
|
{$if defined(I386) or defined(x86_64)}
|
|
AddSelectItem(opt_attassembler,'att',idAsmATT);
|
|
AddSelectItem(opt_intelassembler,'intel',idAsmIntel);
|
|
{$endif I386}
|
|
{$ifdef M68K}
|
|
//AddSelectItem(opt_standardassembler,'standard',idAsmStandard);
|
|
AddSelectItem(opt_motassembler,'motorola',idAsmMot);
|
|
{$endif M68K}
|
|
end;
|
|
New(AsmInfoSwitches,Init('a'));
|
|
with AsmInfoSwitches^ do
|
|
begin
|
|
AddBooleanItem(opt_listsource,'l',idNone);
|
|
AddBooleanItem(opt_listregisterallocation,'r',idNone);
|
|
AddBooleanItem(opt_listtempallocation,'t',idNone);
|
|
AddBooleanItem(opt_listnodeallocation,'n',idNone);
|
|
AddBooleanItem(opt_useasmpipe,'p',idNone);
|
|
end;
|
|
UpdateAsmOutputSwitches;
|
|
New(BrowserSwitches,InitSelect('b'));
|
|
with BrowserSwitches^ do
|
|
begin
|
|
AddSelectItem(opt_nobrowser,'-',idSymInfNone);
|
|
AddSelectItem(opt_globalonlybrowser,'+',idSymInfGlobalOnly);
|
|
AddSelectItem(opt_localglobalbrowser,'l',idSymInfGlobalLocal);
|
|
end;
|
|
New(ConditionalSwitches,Init('d'));
|
|
with ConditionalSwitches^ do
|
|
begin
|
|
AddStringItem(opt_conditionaldefines,'',idNone,true,false);
|
|
end;
|
|
New(MemorySwitches,Init('C'));
|
|
with MemorySwitches^ do
|
|
begin
|
|
AddLongintItem(opt_stacksize,'s',idStackSize);
|
|
AddLongintItem(opt_heapsize,'h',idHeapSize);
|
|
end;
|
|
New(DirectorySwitches,Init('F'));
|
|
with DirectorySwitches^ do
|
|
begin
|
|
AddMultiStringItem(opt_unitdirectories,'u',idNone);
|
|
AddMultiStringItem(opt_includedirectories,'i',idNone);
|
|
AddMultiStringItem(opt_librarydirectories,'l',idNone);
|
|
AddMultiStringItem(opt_objectdirectories,'o',idNone);
|
|
AddStringItem(opt_exeppudirectories,'E',idNone,true,true);
|
|
AddStringItem(opt_ppuoutputdirectory,'U',idNone,true,true);
|
|
AddStringItem(opt_cross_tools_directory,'D',idNone,true,true);
|
|
AddStringItem(opt_dynamic_linker,'L',idNone,false,false);
|
|
end;
|
|
|
|
New(LibLinkerSwitches,InitSelect('X'));
|
|
with LibLinkerSwitches^ do
|
|
begin
|
|
AddDefaultSelect(opt_librariesdefault);
|
|
AddSelectItem(opt_dynamiclibraries,'D',idNone);
|
|
AddSelectItem(opt_staticlibraries,'S',idNone);
|
|
AddSelectItem(opt_smartlibraries,'X',idNone);
|
|
end;
|
|
New(OtherLinkerSwitches,Init('X'));
|
|
with OtherLinkerSwitches^ do
|
|
begin
|
|
AddBooleanItem(opt_stripalldebugsymbols,'s',idNone);
|
|
AddBooleanItem(opt_forcestaticlibs,'t',idNone);
|
|
end;
|
|
New(DebugInfoSwitches,InitSelect('g'));
|
|
with DebugInfoSwitches^ do
|
|
begin
|
|
AddSelectItem(opt_nogendebugsymbolinfo,'-',idNone);
|
|
AddSelectItem(opt_gendebugsymbolinfo,'',idNone);
|
|
AddSelectItem(opt_gensymbolandbacktraceinfo,'l',idNone);
|
|
AddSelectItem(opt_valgrindinfo,'v',idNone);
|
|
{ AddSelectItem('Generate ~d~bx symbol information','d');
|
|
does not work anyhow (PM) }
|
|
end;
|
|
New(LinkAfterSwitches,Init('s'));
|
|
LinkAfterSwitches^.AddBooleanItem(opt_linkafter,'',idNone);
|
|
New(ProfileInfoSwitches,InitSelect('p'));
|
|
with ProfileInfoSwitches^ do
|
|
begin
|
|
AddSelectItem(opt_noprofileinfo,'-',idNone);
|
|
AddSelectItem(opt_gprofinfo,'g',idNone);
|
|
end;
|
|
{New(MemorySizeSwitches,Init('C'));
|
|
with MemorySizeSwitches^ do
|
|
begin
|
|
AddLongIntItem('~S~tack size','s');
|
|
AddLongIntItem('Local ~h~eap size','h');
|
|
end;}
|
|
SwitchesPath:=LocateFile(SwitchesFileName);
|
|
if SwitchesPath='' then
|
|
SwitchesPath:=SwitchesFileName;
|
|
SwitchesPath:=FExpand(SwitchesPath);
|
|
end;
|
|
|
|
procedure SetDefaultSwitches;
|
|
var
|
|
i,OldSwitchesMode : TSwitchMode;
|
|
|
|
begin
|
|
{ setup some useful defaults }
|
|
OldSwitchesMode:=SwitchesMode;
|
|
for i:=low(TSwitchMode) to high(TSwitchMode) do
|
|
begin
|
|
SwitchesMode:=i;
|
|
|
|
{ default is Pentium }
|
|
ProcessorOptimizationSwitches^.SetCurrSel(1);
|
|
{ AT&T reader }
|
|
AsmReaderSwitches^.SetCurrSel(1);
|
|
|
|
{ FPC mode}
|
|
CompilerModeSwitches^.SetCurrSel(0);
|
|
(* Use platform defaults for memory switches. *)
|
|
{ 128k stack }
|
|
{ MemorySwitches^.SetLongintItem(0,65536*2);}
|
|
MemorySwitches^.SetLongintItem(0,0);
|
|
{ 2 MB heap }
|
|
{ MemorySwitches^.SetLongintItem(1,1024*1024*2);}
|
|
MemorySwitches^.SetLongintItem(1,0);
|
|
{ goto/lable allowed }
|
|
SyntaxSwitches^.SetBooleanItem(1,true);
|
|
{ inline allowed }
|
|
SyntaxSwitches^.SetBooleanItem(3,true);
|
|
{ Exe size complaints are louder than speed complaints: Optimize for size by default. }
|
|
OptimizationSwitches^.SetBooleanItem(0,true);
|
|
case i of
|
|
om_debug:
|
|
begin
|
|
{ debugging info on }
|
|
DebugInfoSwitches^.SetCurrSel(1);
|
|
{ range checking }
|
|
CodegenSwitches^.SetBooleanItem(0,true);
|
|
{ io checking }
|
|
CodegenSwitches^.SetBooleanItem(2,true);
|
|
{ overflow checking }
|
|
CodegenSwitches^.SetBooleanItem(3,true);
|
|
{ method call checking }
|
|
CodegenSwitches^.SetBooleanItem(4,true);
|
|
{ assertions on }
|
|
SyntaxSwitches^.SetBooleanItem(4,true);
|
|
end;
|
|
om_normal:
|
|
begin
|
|
{Register variables.}
|
|
OptimizationSwitches^.SetBooleanItem(1,true);
|
|
{Level 1 optimizations.}
|
|
OptimizationSwitches^.SetBooleanItem(3,true);
|
|
end;
|
|
om_release:
|
|
begin
|
|
{Register variables.}
|
|
OptimizationSwitches^.SetBooleanItem(1,true);
|
|
{Level 2 optimizations.}
|
|
OptimizationSwitches^.SetBooleanItem(4,true);
|
|
{Smart linking.}
|
|
LibLinkerSwitches^.SetCurrSel(3);
|
|
CodegenSwitches^.SetBooleanItem(6,true);
|
|
{Strip debug info}
|
|
OtherLinkerSwitches^.SetBooleanItem(0,true);
|
|
end;
|
|
end;
|
|
{ set appriopriate default target }
|
|
TargetSwitches^.SetCurrSelParam(target_info.shortname);
|
|
end;
|
|
SwitchesMode:=OldSwitchesMode;
|
|
end;
|
|
|
|
procedure DoneSwitches;
|
|
var sw : TSwitchMode;
|
|
begin
|
|
dispose(SyntaxSwitches,Done);
|
|
dispose(CompilerModeSwitches,Done);
|
|
dispose(VerboseSwitches,Done);
|
|
dispose(CodegenSwitches,Done);
|
|
dispose(OptimizationSwitches,Done);
|
|
dispose(ProcessorOptimizationSwitches,Done);
|
|
dispose(ProcessorCodeGenerationSwitches,Done);
|
|
dispose(BrowserSwitches,Done);
|
|
dispose(TargetSwitches,Done);
|
|
dispose(AsmReaderSwitches,Done);
|
|
dispose(AsmInfoSwitches,Done);
|
|
dispose(ConditionalSwitches,Done);
|
|
dispose(MemorySwitches,Done);
|
|
{dispose(MemorySizeSwitches,Done);}
|
|
dispose(DirectorySwitches,Done);
|
|
dispose(DebugInfoSwitches,Done);
|
|
dispose(LibLinkerSwitches,Done);
|
|
dispose(LinkAfterSwitches,Done);
|
|
dispose(OtherLinkerSwitches,Done);
|
|
dispose(ProfileInfoSwitches,Done);
|
|
for sw:=low(TSwitchMode) to high(TSwitchMode) do
|
|
if assigned(AsmOutputSwitches[sw]) then
|
|
dispose(AsmOutputSwitches[sw],Done);
|
|
end;
|
|
|
|
procedure GetCompilerOptionLines(C: PUnsortedStringCollection);
|
|
procedure AddLine(const S: string);
|
|
begin
|
|
C^.Insert(NewStr(S));
|
|
end;
|
|
procedure ConstructSwitchModeDirectives(SM: TSwitchMode; const IfDefSym: string);
|
|
var SwitchParams: PStringCollection;
|
|
MiscParams : PStringCollection;
|
|
procedure AddSwitch(const S: string);
|
|
begin
|
|
SwitchParams^.Insert(NewStr(S));
|
|
end;
|
|
procedure AddParam(const S: string);
|
|
begin
|
|
MiscParams^.Insert(NewStr(S));
|
|
end;
|
|
|
|
procedure EnumSwitches(P: PSwitches);
|
|
|
|
procedure HandleSwitch(P: PSwitchItem);
|
|
begin
|
|
case P^.ParamID of
|
|
{ idAlign :}
|
|
idRangeChecks : AddSwitch('R'+P^.GetSwitchStr(SM));
|
|
idStackChecks : AddSwitch('S'+P^.GetSwitchStr(SM));
|
|
idIOChecks : AddSwitch('I'+P^.GetSwitchStr(SM));
|
|
idOverflowChecks : AddSwitch('Q'+P^.GetSwitchStr(SM));
|
|
idObjMethCallChecks: AddSwitch('OBJECTCHECKS'+P^.GetSwitchStr(SM));
|
|
{ idAsmDirect : if P^.GetParamValueBool[SM] then AddParam('ASMMODE DIRECT');
|
|
idAsmATT : if P^.GetParamValueBool[SM] then AddParam('ASMMODE ATT');
|
|
idAsmIntel : if P^.GetParamValueBool[SM] then AddParam('ASMMODE INTEL');
|
|
idAsmMot : if P^.GetParamValueBool[SM] then AddParam('ASMMODE MOTOROLA');
|
|
idAsmStandard : if P^.GetParamValueBool[SM] then AddParam('ASMMODE STANDARD');}
|
|
{ idSymInfNone : ;
|
|
idSymInfGlobalOnly:;
|
|
idSymInfGlobalLocal:if P^.ParamValueBool(SM) then AddSwitch('L+');}
|
|
{ idStackSize
|
|
idHeapSize}
|
|
idStrictVarStrings: AddSwitch('V'+P^.GetSwitchStr(SM));
|
|
idExtendedSyntax : AddSwitch('X'+P^.GetSwitchStr(SM));
|
|
idMMXOps : if P^.ParamValueBool(SM) then AddParam('MMX');
|
|
idTypedAddress : AddSwitch('T'+P^.GetSwitchStr(SM));
|
|
{ idPackRecords
|
|
idPackEnum}
|
|
idStackFrames : AddSwitch('W'+P^.GetSwitchStr(SM));
|
|
idReferenceInfo : AddSwitch('Y'+P^.GetSwitchStr(SM));
|
|
idDebugInfo : AddSwitch('D'+P^.GetSwitchStr(SM));
|
|
idBoolEval : AddSwitch('B'+P^.GetSwitchStr(SM));
|
|
idAnsiString : AddSwitch('H'+P^.GetSwitchStr(SM));
|
|
idTypeInfo : AddSwitch('M'+P^.GetSwitchStr(SM));
|
|
end;
|
|
end;
|
|
begin
|
|
P^.Items^.ForEach(TCallbackProcParam(@HandleSwitch));
|
|
end;
|
|
var I: integer;
|
|
S: string;
|
|
begin
|
|
AddLine('{$IFDEF '+IfDefSym+'}');
|
|
New(SwitchParams, Init(10,10));
|
|
New(MiscParams, Init(10,10));
|
|
EnumSwitches(LibLinkerSwitches);
|
|
EnumSwitches(OtherLinkerSwitches);
|
|
EnumSwitches(DebugInfoSwitches);
|
|
EnumSwitches(ProfileInfoSwitches);
|
|
EnumSwitches(SyntaxSwitches);
|
|
EnumSwitches(CompilerModeSwitches);
|
|
EnumSwitches(VerboseSwitches);
|
|
EnumSwitches(CodegenSwitches);
|
|
EnumSwitches(OptimizationSwitches);
|
|
EnumSwitches(ProcessorOptimizationSwitches);
|
|
EnumSwitches(ProcessorCodeGenerationSwitches);
|
|
EnumSwitches(AsmReaderSwitches);
|
|
EnumSwitches(AsmInfoSwitches);
|
|
EnumSwitches(AsmOutputSwitches[SM]);
|
|
EnumSwitches(TargetSwitches);
|
|
EnumSwitches(ConditionalSwitches);
|
|
EnumSwitches(MemorySwitches);
|
|
EnumSwitches(BrowserSwitches);
|
|
EnumSwitches(DirectorySwitches);
|
|
S:='';
|
|
for I:=0 to SwitchParams^.Count-1 do
|
|
begin
|
|
if I=0 then S:='{$' else S:=S+',';
|
|
S:=S+PString(SwitchParams^.At(I))^;
|
|
end;
|
|
if S<>'' then S:=S+'}';
|
|
if S<>'' then AddLine(' '+S);
|
|
for I:=0 to MiscParams^.Count-1 do
|
|
AddLine(' {$'+PString(MiscParams^.At(I))^+'}');
|
|
Dispose(SwitchParams, Done); Dispose(MiscParams, Done);
|
|
AddLine('{$ENDIF '+IfDefSym+'}');
|
|
end;
|
|
var SM: TSwitchMode;
|
|
begin
|
|
for SM:=Low(TSwitchMode) to High(TSwitchMode) do
|
|
ConstructSwitchModeDirectives(SM,SwitchesModeStr[SM]);
|
|
end;
|
|
|
|
|
|
end.
|