mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-14 18:59:28 +02:00

* support for case aware filesystems (Windows), they do now only one lookup if a file exists * add -WI option to generate import section for DLL imports or let the linker handle it. Default is still import section until the Makefiles are fixed, then the generation can be left to the linker git-svn-id: trunk@2274 -
2153 lines
62 KiB
ObjectPascal
2153 lines
62 KiB
ObjectPascal
{
|
|
Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
|
|
|
|
Reads command line options and config files
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
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. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************
|
|
}
|
|
unit options;
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
globtype,globals,verbose,systems,cpuinfo;
|
|
|
|
type
|
|
TOption=class
|
|
FirstPass,
|
|
ParaLogo,
|
|
NoPressEnter,
|
|
LogoWritten : boolean;
|
|
FileLevel : longint;
|
|
QuickInfo : string;
|
|
ParaIncludePath,
|
|
ParaUnitPath,
|
|
ParaObjectPath,
|
|
ParaLibraryPath : TSearchPathList;
|
|
ParaAlignment : TAlignmentInfo;
|
|
Constructor Create;
|
|
Destructor Destroy;override;
|
|
procedure WriteLogo;
|
|
procedure WriteInfo;
|
|
procedure WriteHelpPages;
|
|
procedure WriteQuickInfo;
|
|
procedure IllegalPara(const opt:string);
|
|
function Unsetbool(var Opts:string; Pos: Longint):boolean;
|
|
procedure interpret_proc_specific_options(const opt:string);virtual;
|
|
procedure interpret_option(const opt :string;ispara:boolean);
|
|
procedure Interpret_envvar(const envname : string);
|
|
procedure Interpret_file(const filename : string);
|
|
procedure Read_Parameters;
|
|
procedure parsecmd(cmd:string);
|
|
procedure TargetDefines(def:boolean);
|
|
end;
|
|
|
|
TOptionClass=class of toption;
|
|
|
|
var
|
|
coption : TOptionClass;
|
|
|
|
procedure read_arguments(cmd:string);
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
widestr,
|
|
{$IFDEF USE_SYSUTILS}
|
|
SysUtils,
|
|
{$ELSE USE_SYSUTILS}
|
|
dos,
|
|
{$ENDIF USE_SYSUTILS}
|
|
version,
|
|
cutils,cmsgs,
|
|
comphook,
|
|
symtable,scanner
|
|
{$ifdef BrowserLog}
|
|
,browlog
|
|
{$endif BrowserLog}
|
|
;
|
|
|
|
const
|
|
page_size = 24;
|
|
|
|
var
|
|
option : toption;
|
|
read_configfile, { read config file, set when a cfgfile is found }
|
|
disable_configfile : boolean;
|
|
fpcdir,
|
|
ppccfg,
|
|
ppcaltcfg,
|
|
param_file : string; { file to compile specified on the commandline }
|
|
|
|
{****************************************************************************
|
|
Defines
|
|
****************************************************************************}
|
|
|
|
procedure set_default_link_type;
|
|
begin
|
|
{ win32 and wdosx need smartlinking by default to prevent including too much
|
|
dll dependencies }
|
|
if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
|
|
begin
|
|
def_system_macro('FPC_LINK_SMART');
|
|
undef_system_macro('FPC_LINK_STATIC');
|
|
undef_system_macro('FPC_LINK_DYNAMIC');
|
|
initglobalswitches:=initglobalswitches+[cs_link_smart];
|
|
initglobalswitches:=initglobalswitches-[cs_link_shared,cs_link_static];
|
|
end
|
|
else
|
|
begin
|
|
undef_system_macro('FPC_LINK_SMART');
|
|
def_system_macro('FPC_LINK_STATIC');
|
|
undef_system_macro('FPC_LINK_DYNAMIC');
|
|
initglobalswitches:=initglobalswitches+[cs_link_static];
|
|
initglobalswitches:=initglobalswitches-[cs_link_shared,cs_link_smart];
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
{****************************************************************************
|
|
Toption
|
|
****************************************************************************}
|
|
|
|
procedure StopOptions(err:longint);
|
|
begin
|
|
if assigned(Option) then
|
|
begin
|
|
Option.free;
|
|
Option:=nil;
|
|
end;
|
|
raise ECompilerAbortSilent.Create;
|
|
end;
|
|
|
|
|
|
procedure Toption.WriteLogo;
|
|
var
|
|
p : pchar;
|
|
begin
|
|
if not LogoWritten then
|
|
begin
|
|
p:=MessagePchar(option_logo);
|
|
while assigned(p) do
|
|
Comment(V_Normal,GetMsgLine(p));
|
|
LogoWritten:= true;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure Toption.WriteInfo;
|
|
var
|
|
p : pchar;
|
|
hs,hs1,s : TCmdStr;
|
|
target : tsystem;
|
|
cpu : tprocessors;
|
|
fpu : tfputype;
|
|
begin
|
|
p:=MessagePchar(option_info);
|
|
while assigned(p) do
|
|
begin
|
|
s:=GetMsgLine(p);
|
|
{ list OS Targets }
|
|
if pos('$OSTARGETS',s)>0 then
|
|
begin
|
|
for target:=low(tsystem) to high(tsystem) do
|
|
if assigned(targetinfos[target]) then
|
|
begin
|
|
hs:=s;
|
|
hs1:=targetinfos[target]^.name;
|
|
if tf_under_development in targetinfos[target]^.flags then
|
|
hs1:=hs1+' (under development)';
|
|
Replace(hs,'$OSTARGETS',hs1);
|
|
Comment(V_Normal,hs);
|
|
end;
|
|
end
|
|
else if pos('$INSTRUCTIONSETS',s)>0 then
|
|
begin
|
|
for cpu:=low(tprocessors) to high(tprocessors) do
|
|
begin
|
|
hs:=s;
|
|
hs1:=processorsstr[cpu];
|
|
if hs1<>'' then
|
|
begin
|
|
Replace(hs,'$INSTRUCTIONSETS',hs1);
|
|
Comment(V_Normal,hs);
|
|
end;
|
|
end;
|
|
end
|
|
else if pos('$FPUINSTRUCTIONSETS',s)>0 then
|
|
begin
|
|
for fpu:=low(tfputype) to high(tfputype) do
|
|
begin
|
|
hs:=s;
|
|
hs1:=fputypestr[fpu];
|
|
if hs1<>'' then
|
|
begin
|
|
Replace(hs,'$FPUINSTRUCTIONSETS',hs1);
|
|
Comment(V_Normal,hs);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
Comment(V_Normal,s);
|
|
end;
|
|
StopOptions(0);
|
|
end;
|
|
|
|
|
|
procedure Toption.WriteHelpPages;
|
|
|
|
function PadEnd(s:string;i:longint):string;
|
|
begin
|
|
while (length(s)<i) do
|
|
s:=s+' ';
|
|
PadEnd:=s;
|
|
end;
|
|
|
|
var
|
|
lastident,
|
|
j,outline,
|
|
ident,
|
|
lines : longint;
|
|
show : boolean;
|
|
opt : string[32];
|
|
input,
|
|
s : string;
|
|
p : pchar;
|
|
begin
|
|
WriteLogo;
|
|
Lines:=4;
|
|
Message1(option_usage,FixFileName(system.paramstr(0)));
|
|
lastident:=0;
|
|
p:=MessagePChar(option_help_pages);
|
|
while assigned(p) do
|
|
begin
|
|
{ get a line and reset }
|
|
s:=GetMsgLine(p);
|
|
ident:=0;
|
|
show:=false;
|
|
{ parse options }
|
|
case s[1] of
|
|
{$ifdef UNITALIASES}
|
|
'a',
|
|
{$endif}
|
|
{$ifdef EXTDEBUG}
|
|
'e',
|
|
{$endif EXTDEBUG}
|
|
{$ifdef i386}
|
|
'3',
|
|
{$endif}
|
|
{$ifdef x86_64}
|
|
'4',
|
|
{$endif}
|
|
{$ifdef m68k}
|
|
'6',
|
|
{$endif}
|
|
{$ifdef arm}
|
|
'A',
|
|
{$endif}
|
|
{$ifdef powerpc}
|
|
'P',
|
|
{$endif}
|
|
{$ifdef sparc}
|
|
'S',
|
|
{$endif}
|
|
{$ifdef vis}
|
|
'V',
|
|
{$endif}
|
|
'*' : show:=true;
|
|
end;
|
|
if show then
|
|
begin
|
|
case s[2] of
|
|
'g',
|
|
{$ifdef Unix}
|
|
'L',
|
|
{$endif}
|
|
{$ifdef os2}
|
|
'O',
|
|
{$endif}
|
|
'*' : show:=true;
|
|
else
|
|
show:=false;
|
|
end;
|
|
end;
|
|
{ now we may show the message or not }
|
|
if show then
|
|
begin
|
|
case s[3] of
|
|
'0' : begin
|
|
ident:=0;
|
|
outline:=0;
|
|
end;
|
|
'1' : begin
|
|
ident:=2;
|
|
outline:=7;
|
|
end;
|
|
'2' : begin
|
|
ident:=6;
|
|
outline:=11;
|
|
end;
|
|
'3' : begin
|
|
ident:=9;
|
|
outline:=11;
|
|
end;
|
|
end;
|
|
j:=pos('_',s);
|
|
opt:=Copy(s,4,j-4);
|
|
if opt='*' then
|
|
opt:=''
|
|
else
|
|
if opt=' ' then
|
|
opt:=PadEnd(opt,outline)
|
|
else
|
|
opt:=PadEnd('-'+opt,outline);
|
|
if (ident=0) and (lastident<>0) then
|
|
begin
|
|
Comment(V_Normal,'');
|
|
inc(Lines);
|
|
end;
|
|
{ page full ? }
|
|
if (lines >= page_size - 1) then
|
|
begin
|
|
if not NoPressEnter then
|
|
begin
|
|
Message(option_help_press_enter);
|
|
readln(input);
|
|
if upper(input)='Q' then
|
|
StopOptions(0);
|
|
end;
|
|
lines:=0;
|
|
end;
|
|
Comment(V_Normal,PadEnd('',ident)+opt+Copy(s,j+1,255));
|
|
LastIdent:=Ident;
|
|
inc(Lines);
|
|
end;
|
|
end;
|
|
StopOptions(0);
|
|
end;
|
|
|
|
|
|
procedure Toption.IllegalPara(const opt:string);
|
|
begin
|
|
Message1(option_illegal_para,opt);
|
|
Message(option_help_pages_para);
|
|
StopOptions(1);
|
|
end;
|
|
|
|
|
|
function Toption.Unsetbool(var Opts:string; Pos: Longint):boolean;
|
|
{ checks if the character after pos in Opts is a + or a - and returns resp.
|
|
false or true. If it is another character (or none), it also returns false }
|
|
begin
|
|
UnsetBool := false;
|
|
if Length(Opts)>Pos then
|
|
begin
|
|
inc(Pos);
|
|
UnsetBool := Opts[Pos] = '-';
|
|
if Opts[Pos] in ['-','+']then
|
|
delete(Opts,Pos,1);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOption.interpret_proc_specific_options(const opt:string);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TOption.interpret_option(const opt:string;ispara:boolean);
|
|
var
|
|
code : integer;
|
|
c : char;
|
|
more : string;
|
|
major,minor : longint;
|
|
error : integer;
|
|
j,l : longint;
|
|
d : DirStr;
|
|
e : ExtStr;
|
|
s : string;
|
|
begin
|
|
if opt='' then
|
|
exit;
|
|
|
|
{ only parse define,undef,target,verbosity,link etc options the firsttime }
|
|
if firstpass and
|
|
not(
|
|
(opt[1]='-') and
|
|
(
|
|
((length(opt)>1) and (opt[2] in ['i','d','v','T','u','n','X','l'])) or
|
|
((length(opt)>3) and (opt[2]='F') and (opt[3]='e'))
|
|
)
|
|
) then
|
|
exit;
|
|
|
|
Message1(option_handling_option,opt);
|
|
case opt[1] of
|
|
'-' :
|
|
begin
|
|
more:=Copy(opt,3,255);
|
|
if firstpass then
|
|
Message1(option_interpreting_firstpass_option,opt)
|
|
else
|
|
Message1(option_interpreting_option,opt);
|
|
case opt[2] of
|
|
'?' :
|
|
WriteHelpPages;
|
|
|
|
'a' :
|
|
begin
|
|
include(initglobalswitches,cs_asm_leave);
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
'l' :
|
|
include(initglobalswitches,cs_asm_source);
|
|
'r' :
|
|
include(initglobalswitches,cs_asm_regalloc);
|
|
't' :
|
|
include(initglobalswitches,cs_asm_tempalloc);
|
|
'n' :
|
|
include(initglobalswitches,cs_asm_nodes);
|
|
'p' :
|
|
begin
|
|
exclude(initglobalswitches,cs_asm_leave);
|
|
if UnsetBool(More, 0) then
|
|
exclude(initglobalswitches,cs_asm_pipe)
|
|
else
|
|
include(initglobalswitches,cs_asm_pipe);
|
|
end;
|
|
'-' :
|
|
initglobalswitches:=initglobalswitches -
|
|
[cs_asm_leave, cs_asm_source,cs_asm_regalloc, cs_asm_tempalloc,
|
|
cs_asm_nodes, cs_asm_pipe];
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'A' :
|
|
begin
|
|
paratargetasm:=find_asm_by_string(More);
|
|
if paratargetasm=as_none then
|
|
IllegalPara(opt);
|
|
end;
|
|
|
|
'b' :
|
|
begin
|
|
{$ifdef supportbrowser}
|
|
if UnsetBool(More,0) then
|
|
begin
|
|
exclude(initmoduleswitches,cs_browser);
|
|
exclude(initmoduleswitches,cs_local_browser);
|
|
{$ifdef BrowserLog}
|
|
exclude(initglobalswitches,cs_browser_log);
|
|
{$endif}
|
|
end
|
|
else
|
|
begin
|
|
include(initmoduleswitches,cs_browser);
|
|
{$ifdef BrowserLog}
|
|
include(initglobalswitches,cs_browser_log);
|
|
{$endif}
|
|
end;
|
|
if More<>'' then
|
|
if (More='l') or (More='l+') then
|
|
include(initmoduleswitches,cs_local_browser)
|
|
else
|
|
if More='l-' then
|
|
exclude(initmoduleswitches,cs_local_browser)
|
|
else
|
|
{$ifdef BrowserLog}
|
|
browserlog.elements_to_list.insert(more);
|
|
{$else}
|
|
IllegalPara(opt);
|
|
{$endif}
|
|
{$endif supportbrowser}
|
|
end;
|
|
|
|
'B' :
|
|
do_build:=not UnSetBool(more,0);
|
|
|
|
'C' :
|
|
begin
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
'a' :
|
|
Message2(option_obsolete_switch_use_new,'-Ca','-Or');
|
|
'c' :
|
|
begin
|
|
if not SetAktProcCall(upper(copy(more,j+1,length(more)-j)),true) then
|
|
IllegalPara(opt);
|
|
break;
|
|
end;
|
|
{$ifdef cpufpemu}
|
|
'e' :
|
|
begin
|
|
If UnsetBool(More, j) then
|
|
exclude(initmoduleswitches,cs_fp_emulation)
|
|
Else
|
|
include(initmoduleswitches,cs_fp_emulation);
|
|
end;
|
|
{$endif cpufpemu}
|
|
'f' :
|
|
begin
|
|
s:=upper(copy(more,j+1,length(more)-j));
|
|
if not(SetFpuType(s,true)) then
|
|
IllegalPara(opt);
|
|
break;
|
|
end;
|
|
'g' :
|
|
include(initmoduleswitches,cs_create_pic);
|
|
'h' :
|
|
begin
|
|
val(copy(more,j+1,length(more)-j),heapsize,code);
|
|
if (code<>0) or (heapsize<1024) then
|
|
IllegalPara(opt);
|
|
break;
|
|
end;
|
|
'i' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initlocalswitches,cs_check_io)
|
|
else
|
|
include(initlocalswitches,cs_check_io);
|
|
'n' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initglobalswitches,cs_link_extern)
|
|
Else
|
|
include(initglobalswitches,cs_link_extern);
|
|
'o' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initlocalswitches,cs_check_overflow)
|
|
Else
|
|
include(initlocalswitches,cs_check_overflow);
|
|
'p' :
|
|
begin
|
|
s:=upper(copy(more,j+1,length(more)-j));
|
|
if not(SetProcessor(s,true)) then
|
|
IllegalPara(opt);
|
|
break;
|
|
end;
|
|
'r' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initlocalswitches,cs_check_range)
|
|
Else
|
|
include(initlocalswitches,cs_check_range);
|
|
'R' :
|
|
If UnsetBool(More, j) then
|
|
begin
|
|
exclude(initlocalswitches,cs_check_range);
|
|
exclude(initlocalswitches,cs_check_object);
|
|
end
|
|
Else
|
|
begin
|
|
include(initlocalswitches,cs_check_range);
|
|
include(initlocalswitches,cs_check_object);
|
|
end;
|
|
's' :
|
|
begin
|
|
val(copy(more,j+1,length(more)-j),stacksize,code);
|
|
if (code<>0) or (stacksize>=67107840) or (stacksize<1024) then
|
|
IllegalPara(opt);
|
|
break;
|
|
end;
|
|
't' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initlocalswitches,cs_check_stack)
|
|
Else
|
|
include(initlocalswitches,cs_check_stack);
|
|
'D' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initmoduleswitches,cs_create_dynamic)
|
|
Else
|
|
include(initmoduleswitches,cs_create_dynamic);
|
|
'X' :
|
|
If UnsetBool(More, j) then
|
|
exclude(initmoduleswitches,cs_create_smart)
|
|
Else
|
|
include(initmoduleswitches,cs_create_smart);
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'd' :
|
|
if more <> '' then
|
|
begin
|
|
l:=Pos(':=',more);
|
|
if l>0 then
|
|
set_system_compvar(Copy(more,1,l-1),Copy(more,l+2,255))
|
|
else
|
|
def_system_macro(more);
|
|
end;
|
|
'D' :
|
|
begin
|
|
include(initglobalswitches,cs_link_deffile);
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
'd' :
|
|
begin
|
|
description:=Copy(more,j+1,255);
|
|
break;
|
|
end;
|
|
'v' :
|
|
begin
|
|
dllversion:=Copy(more,j+1,255);
|
|
l:=pos('.',dllversion);
|
|
dllminor:=0;
|
|
error:=0;
|
|
if l>0 then
|
|
begin
|
|
val(copy(dllversion,l+1,255),minor,error);
|
|
if (error=0) and
|
|
(minor>=0) and (minor<=$ffff) then
|
|
dllminor:=minor
|
|
else
|
|
if error=0 then
|
|
error:=1;
|
|
end;
|
|
if l=0 then
|
|
l:=256;
|
|
dllmajor:=1;
|
|
if error=0 then
|
|
val(copy(dllversion,1,l-1),major,error);
|
|
if (error=0) and (major>=0) and (major<=$ffff) then
|
|
dllmajor:=major
|
|
else
|
|
if error=0 then
|
|
error:=1;
|
|
if error<>0 then
|
|
Message1(scan_w_wrong_version_ignored,dllversion);
|
|
break;
|
|
end;
|
|
'w' :
|
|
usewindowapi:=true;
|
|
'-' :
|
|
begin
|
|
exclude(initglobalswitches,cs_link_deffile);
|
|
usewindowapi:=false;
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'e' :
|
|
exepath:=FixPath(More,true);
|
|
|
|
'E' :
|
|
begin
|
|
if UnsetBool(More, 0) then
|
|
exclude(initglobalswitches,cs_link_extern)
|
|
else
|
|
include(initglobalswitches,cs_link_extern);
|
|
end;
|
|
|
|
'F' :
|
|
begin
|
|
c:=more[1];
|
|
Delete(more,1,1);
|
|
DefaultReplacements(More);
|
|
case c of
|
|
'a' :
|
|
autoloadunits:=more;
|
|
'c' :
|
|
begin
|
|
if (upper(more)='UTF8') or (upper(more)='UTF-8') then
|
|
initsourcecodepage:='utf8'
|
|
else if not(cpavailable(more)) then
|
|
Message1(option_code_page_not_available,more)
|
|
else
|
|
initsourcecodepage:=more;
|
|
end;
|
|
'D' :
|
|
utilsdirectory:=FixPath(More,true);
|
|
'e' :
|
|
SetRedirectFile(More);
|
|
'E' :
|
|
OutputExeDir:=FixPath(More,true);
|
|
'i' :
|
|
begin
|
|
if ispara then
|
|
ParaIncludePath.AddPath(More,false)
|
|
else
|
|
includesearchpath.AddPath(More,true);
|
|
end;
|
|
'g' :
|
|
Message2(option_obsolete_switch_use_new,'-Fg','-Fl');
|
|
'l' :
|
|
begin
|
|
if ispara then
|
|
ParaLibraryPath.AddPath(More,false)
|
|
else
|
|
LibrarySearchPath.AddPath(More,true);
|
|
end;
|
|
'L' :
|
|
begin
|
|
if More<>'' then
|
|
ParaDynamicLinker:=More
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
'o' :
|
|
begin
|
|
if ispara then
|
|
ParaObjectPath.AddPath(More,false)
|
|
else
|
|
ObjectSearchPath.AddPath(More,true);
|
|
end;
|
|
'r' :
|
|
Msgfilename:=More;
|
|
'u' :
|
|
begin
|
|
if ispara then
|
|
ParaUnitPath.AddPath(More,false)
|
|
else
|
|
unitsearchpath.AddPath(More,true);
|
|
end;
|
|
'U' :
|
|
OutputUnitDir:=FixPath(More,true);
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
end;
|
|
'g' : begin
|
|
if UnsetBool(More, 0) then
|
|
begin
|
|
exclude(initmoduleswitches,cs_debuginfo);
|
|
exclude(initglobalswitches,cs_use_heaptrc);
|
|
exclude(initglobalswitches,cs_use_lineinfo);
|
|
exclude(initlocalswitches,cs_checkpointer);
|
|
end
|
|
else
|
|
begin
|
|
include(initmoduleswitches,cs_debuginfo);
|
|
end;
|
|
if not RelocSectionSetExplicitly then
|
|
RelocSection:=false;
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
'c' :
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
exclude(initlocalswitches,cs_checkpointer)
|
|
else
|
|
include(initlocalswitches,cs_checkpointer);
|
|
end;
|
|
'd' :
|
|
begin
|
|
paratargetdbg:=dbg_dwarf;
|
|
end;
|
|
'h' :
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
exclude(initglobalswitches,cs_use_heaptrc)
|
|
else
|
|
include(initglobalswitches,cs_use_heaptrc);
|
|
end;
|
|
'l' :
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
exclude(initglobalswitches,cs_use_lineinfo)
|
|
else
|
|
include(initglobalswitches,cs_use_lineinfo);
|
|
end;
|
|
's' :
|
|
begin
|
|
paratargetdbg:=dbg_stabs;
|
|
end;
|
|
'v' :
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
exclude(initglobalswitches,cs_gdb_valgrind)
|
|
else
|
|
include(initglobalswitches,cs_gdb_valgrind);
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'h' :
|
|
begin
|
|
NoPressEnter:=true;
|
|
WriteHelpPages;
|
|
end;
|
|
|
|
'i' :
|
|
begin
|
|
if More='' then
|
|
WriteInfo
|
|
else
|
|
QuickInfo:=QuickInfo+More;
|
|
end;
|
|
|
|
'I' :
|
|
begin
|
|
if ispara then
|
|
ParaIncludePath.AddPath(More,false)
|
|
else
|
|
includesearchpath.AddPath(More,false);
|
|
end;
|
|
|
|
'k' :
|
|
begin
|
|
if more<>'' then
|
|
ParaLinkOptions:=ParaLinkOptions+' '+More
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
|
|
'l' :
|
|
if not UnSetBool(more,0) then
|
|
ParaLogo:=true;
|
|
|
|
'm' :
|
|
parapreprocess:=not UnSetBool(more,0);
|
|
|
|
'M' :
|
|
begin
|
|
more:=Upper(more);
|
|
if not SetCompileMode(more, true) then
|
|
IllegalPara(opt);
|
|
end;
|
|
|
|
'n' :
|
|
begin
|
|
if More='' then
|
|
disable_configfile:=true
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
|
|
'N' :
|
|
begin
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
'u' :
|
|
initglobalswitches:=initglobalswitches+[cs_loopunroll];
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'o' :
|
|
begin
|
|
if More<>'' then
|
|
begin
|
|
{$IFDEF USE_SYSUTILS}
|
|
D:=SplitPath(More);
|
|
OutputFile:=SplitFileName(More);
|
|
OutputExtension:=SplitExtension(More);
|
|
{$ELSE USE_SYSUTILS}
|
|
FSplit(More,D,OutputFile,OutputExtension);
|
|
{$ENDIF USE_SYSUTILS}
|
|
if (D<>'') then
|
|
OutputExeDir:=FixPath(D,True);
|
|
end
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
|
|
'p' :
|
|
begin
|
|
if UnsetBool(More, 0) then
|
|
begin
|
|
initmoduleswitches:=initmoduleswitches-[cs_profile];
|
|
undef_system_macro('FPC_PROFILE');
|
|
end
|
|
else
|
|
if Length(More)=0 then
|
|
IllegalPara(opt)
|
|
else
|
|
case more[1] of
|
|
'g' : if UnsetBool(more, 1) then
|
|
begin
|
|
exclude(initmoduleswitches,cs_profile);
|
|
undef_system_macro('FPC_PROFILE');
|
|
end
|
|
else
|
|
begin
|
|
include(initmoduleswitches,cs_profile);
|
|
def_system_macro('FPC_PROFILE');
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
end;
|
|
|
|
'P' : ; { Ignore used by fpc.pp }
|
|
|
|
's' :
|
|
begin
|
|
if UnsetBool(More, 0) then
|
|
begin
|
|
initglobalswitches:=initglobalswitches-[cs_asm_extern,cs_link_extern];
|
|
if more<>'' then
|
|
IllegalPara(opt);
|
|
end
|
|
else
|
|
begin
|
|
initglobalswitches:=initglobalswitches+[cs_asm_extern,cs_link_extern];
|
|
if more='h' then
|
|
initglobalswitches:=initglobalswitches-[cs_link_on_target]
|
|
else if more='t' then
|
|
initglobalswitches:=initglobalswitches+[cs_link_on_target]
|
|
else if more='r' then
|
|
initglobalswitches:=initglobalswitches+[cs_asm_leave,cs_no_regalloc]
|
|
else if more<>'' then
|
|
IllegalPara(opt);
|
|
end;
|
|
end;
|
|
|
|
'S' :
|
|
begin
|
|
if more[1]='I' then
|
|
begin
|
|
if upper(more)='ICOM' then
|
|
initinterfacetype:=it_interfacecom
|
|
else if upper(more)='ICORBA' then
|
|
initinterfacetype:=it_interfacecorba
|
|
else
|
|
IllegalPara(opt);
|
|
end
|
|
else
|
|
begin
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
'2' : //an alternative to -Mobjfpc
|
|
SetCompileMode('OBJFPC',true);
|
|
'a' :
|
|
include(initlocalswitches,cs_do_assertion);
|
|
'c' :
|
|
include(initmoduleswitches,cs_support_c_operators);
|
|
'd' : //an alternative to -Mdelphi
|
|
SetCompileMode('DELPHI',true);
|
|
'e' :
|
|
begin
|
|
SetErrorFlags(copy(more,j+1,length(more)));
|
|
break;
|
|
end;
|
|
'g' :
|
|
include(initmoduleswitches,cs_support_goto);
|
|
'h' :
|
|
include(initlocalswitches,cs_ansistrings);
|
|
'i' :
|
|
include(initmoduleswitches,cs_support_inline);
|
|
'k' :
|
|
include(initglobalswitches,cs_load_fpcylix_unit);
|
|
'm' :
|
|
include(initmoduleswitches,cs_support_macro);
|
|
'o' : //an alternative to -Mtp
|
|
SetCompileMode('TP',true);
|
|
'p' : //an alternative to -Mgpc
|
|
SetCompileMode('GPC',true);
|
|
's' :
|
|
include(initglobalswitches,cs_constructor_name);
|
|
't' :
|
|
include(initmoduleswitches,cs_static_keyword);
|
|
'-' :
|
|
begin
|
|
exclude(initglobalswitches,cs_constructor_name);
|
|
initlocalswitches:=InitLocalswitches - [cs_do_assertion, cs_ansistrings];
|
|
initmoduleswitches:=initmoduleswitches - [cs_support_c_operators, cs_support_goto,
|
|
cs_support_inline, cs_support_macro,
|
|
cs_static_keyword];
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
'T' :
|
|
begin
|
|
more:=Upper(More);
|
|
if paratarget=system_none then
|
|
begin
|
|
{ remove old target define }
|
|
TargetDefines(false);
|
|
{ load new target }
|
|
paratarget:=find_system_by_string(More);
|
|
if paratarget<>system_none then
|
|
set_target(paratarget)
|
|
else
|
|
IllegalPara(opt);
|
|
{ set new define }
|
|
TargetDefines(true);
|
|
end
|
|
else
|
|
if More<>upper(target_info.shortname) then
|
|
Message1(option_target_is_already_set,target_info.shortname);
|
|
end;
|
|
|
|
'u' :
|
|
if more <> '' then
|
|
undef_system_macro(more);
|
|
'U' :
|
|
begin
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case more[j] of
|
|
{$ifdef UNITALIASES}
|
|
'a' :
|
|
begin
|
|
AddUnitAlias(Copy(More,j+1,255));
|
|
break;
|
|
end;
|
|
{$endif UNITALIASES}
|
|
'n' :
|
|
exclude(initglobalswitches,cs_check_unit_name);
|
|
'p' :
|
|
begin
|
|
Message2(option_obsolete_switch_use_new,'-Up','-Fu');
|
|
break;
|
|
end;
|
|
'r' :
|
|
do_release:=true;
|
|
's' :
|
|
include(initmoduleswitches,cs_compilesystem);
|
|
'-' :
|
|
begin
|
|
exclude(initmoduleswitches,cs_compilesystem);
|
|
exclude(initglobalswitches,cs_check_unit_name);
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'v' :
|
|
begin
|
|
if not setverbosity(More) then
|
|
IllegalPara(opt);
|
|
end;
|
|
|
|
'V' : ; { Ignore used by fpc }
|
|
|
|
'W' :
|
|
begin
|
|
j:=1;
|
|
while j<=length(More) do
|
|
begin
|
|
case More[j] of
|
|
'A':
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
apptype:=app_native
|
|
else
|
|
apptype:=app_cui;
|
|
end;
|
|
'B':
|
|
begin
|
|
{ -WB200000 means set trefered base address
|
|
to $200000, but does not change relocsection boolean
|
|
this way we can create both relocatble and
|
|
non relocatable DLL at a specific base address PM }
|
|
if (length(More)>j) then
|
|
begin
|
|
if DLLImageBase=nil then
|
|
DLLImageBase:=StringDup(Copy(More,j+1,255));
|
|
end
|
|
else
|
|
begin
|
|
RelocSection:=true;
|
|
RelocSectionSetExplicitly:=true;
|
|
end;
|
|
break;
|
|
end;
|
|
'C':
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
apptype:=app_gui
|
|
else
|
|
apptype:=app_cui;
|
|
end;
|
|
'D':
|
|
begin
|
|
UseDeffileForExports:=not UnsetBool(More, j);
|
|
UseDeffileForExportsSetExplicitly:=true;
|
|
end;
|
|
'F':
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
apptype:=app_cui
|
|
else
|
|
apptype:=app_fs;
|
|
end;
|
|
'G':
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
apptype:=app_cui
|
|
else
|
|
apptype:=app_gui;
|
|
end;
|
|
'I':
|
|
begin
|
|
GenerateImportSection:=UnsetBool(More,j);
|
|
end;
|
|
'N':
|
|
begin
|
|
RelocSection:=UnsetBool(More,j);
|
|
RelocSectionSetExplicitly:=true;
|
|
end;
|
|
'R':
|
|
begin
|
|
{ support -WR+ / -WR- as synonyms to -WR / -WN }
|
|
RelocSection:=not UnsetBool(More,j);
|
|
RelocSectionSetExplicitly:=true;
|
|
end;
|
|
'T':
|
|
begin
|
|
if UnsetBool(More, j) then
|
|
apptype:=app_cui
|
|
else
|
|
apptype:=app_tool;
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
'X' :
|
|
begin
|
|
j:=1;
|
|
while j<=length(more) do
|
|
begin
|
|
case More[j] of
|
|
'i' :
|
|
include(initglobalswitches,cs_link_internal);
|
|
'm' :
|
|
include(initglobalswitches,cs_link_map);
|
|
'f' :
|
|
include(initglobalswitches,cs_link_pthread);
|
|
's' :
|
|
include(initglobalswitches,cs_link_strip);
|
|
'c' : Cshared:=TRUE;
|
|
't' :
|
|
include(initglobalswitches,cs_link_staticflag);
|
|
'D' :
|
|
begin
|
|
def_system_macro('FPC_LINK_DYNAMIC');
|
|
undef_system_macro('FPC_LINK_SMART');
|
|
undef_system_macro('FPC_LINK_STATIC');
|
|
exclude(initglobalswitches,cs_link_static);
|
|
exclude(initglobalswitches,cs_link_smart);
|
|
include(initglobalswitches,cs_link_shared);
|
|
LinkTypeSetExplicitly:=true;
|
|
end;
|
|
'd' : Dontlinkstdlibpath:=TRUE;
|
|
'P' : Begin
|
|
utilsprefix:=Copy(more,2,length(More)-1);
|
|
DefaultReplacements(utilsprefix);
|
|
More:='';
|
|
End;
|
|
'r' : Begin
|
|
rlinkpath:=Copy(more,2,length(More)-1);
|
|
DefaultReplacements(rlinkpath);
|
|
More:='';
|
|
end;
|
|
'S' :
|
|
begin
|
|
def_system_macro('FPC_LINK_STATIC');
|
|
undef_system_macro('FPC_LINK_SMART');
|
|
undef_system_macro('FPC_LINK_DYNAMIC');
|
|
include(initglobalswitches,cs_link_static);
|
|
exclude(initglobalswitches,cs_link_smart);
|
|
exclude(initglobalswitches,cs_link_shared);
|
|
LinkTypeSetExplicitly:=true;
|
|
end;
|
|
'X' :
|
|
begin
|
|
def_system_macro('FPC_LINK_SMART');
|
|
undef_system_macro('FPC_LINK_STATIC');
|
|
undef_system_macro('FPC_LINK_DYNAMIC');
|
|
exclude(initglobalswitches,cs_link_static);
|
|
include(initglobalswitches,cs_link_smart);
|
|
exclude(initglobalswitches,cs_link_shared);
|
|
LinkTypeSetExplicitly:=true;
|
|
end;
|
|
'M' :
|
|
begin
|
|
mainaliasname:=Copy(more,2,length(More)-1);
|
|
More:='';
|
|
end;
|
|
'-' :
|
|
begin
|
|
exclude(initglobalswitches,cs_link_staticflag);
|
|
exclude(initglobalswitches,cs_link_strip);
|
|
exclude(initglobalswitches,cs_link_map);
|
|
set_default_link_type;
|
|
end;
|
|
else
|
|
IllegalPara(opt);
|
|
end;
|
|
inc(j);
|
|
end;
|
|
end;
|
|
|
|
{ give processor specific options a chance }
|
|
else
|
|
interpret_proc_specific_options(opt);
|
|
end;
|
|
end;
|
|
|
|
'@' :
|
|
begin
|
|
Message(option_no_nested_response_file);
|
|
StopOptions(1);
|
|
end;
|
|
|
|
else
|
|
begin
|
|
if (length(param_file)<>0) then
|
|
Message(option_only_one_source_support);
|
|
param_file:=opt;
|
|
Message1(option_found_file,opt);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure Toption.Interpret_file(const filename : string);
|
|
|
|
procedure RemoveSep(var fn:string);
|
|
var
|
|
i : longint;
|
|
begin
|
|
i:=0;
|
|
while (i<length(fn)) and (fn[i+1] in [',',' ',#9]) do
|
|
inc(i);
|
|
Delete(fn,1,i);
|
|
i:=length(fn);
|
|
while (i>0) and (fn[i] in [',',' ',#9]) do
|
|
dec(i);
|
|
fn:=copy(fn,1,i);
|
|
end;
|
|
|
|
function GetName(var fn:string):string;
|
|
var
|
|
i : longint;
|
|
begin
|
|
i:=0;
|
|
while (i<length(fn)) and (fn[i+1] in ['a'..'z','A'..'Z','0'..'9','_','-']) do
|
|
inc(i);
|
|
GetName:=Copy(fn,1,i);
|
|
Delete(fn,1,i);
|
|
end;
|
|
|
|
const
|
|
maxlevel=16;
|
|
var
|
|
f : text;
|
|
s, tmp,
|
|
opts : string;
|
|
skip : array[0..maxlevel-1] of boolean;
|
|
level : longint;
|
|
option_read : boolean;
|
|
begin
|
|
{ avoid infinite loop }
|
|
Inc(FileLevel);
|
|
Option_read:=false;
|
|
If FileLevel>MaxLevel then
|
|
Message(option_too_many_cfg_files);
|
|
{ Maybe It's Directory ?} //Jaro Change:
|
|
if DirectoryExists(filename) then
|
|
begin
|
|
Message1(option_config_is_dir,filename);
|
|
exit;
|
|
end;
|
|
{ open file }
|
|
Message1(option_using_file,filename);
|
|
{$ifdef USE_SYSUTILS}
|
|
assign(f,ExpandFileName(filename));
|
|
{$else USE_SYSUTILS}
|
|
assign(f,FExpand(filename));
|
|
{$endif USE_SYsUTILS}
|
|
{$I-}
|
|
reset(f);
|
|
{$I+}
|
|
if ioresult<>0 then
|
|
begin
|
|
Message1(option_unable_open_file,filename);
|
|
exit;
|
|
end;
|
|
Message1(option_start_reading_configfile,filename);
|
|
fillchar(skip,sizeof(skip),0);
|
|
level:=0;
|
|
while not eof(f) do
|
|
begin
|
|
readln(f,opts);
|
|
RemoveSep(opts);
|
|
if (opts<>'') and (opts[1]<>';') then
|
|
begin
|
|
if opts[1]='#' then
|
|
begin
|
|
Message1(option_interpreting_file_option,opts);
|
|
Delete(opts,1,1);
|
|
s:=upper(GetName(opts));
|
|
if (s='SECTION') then
|
|
begin
|
|
RemoveSep(opts);
|
|
s:=upper(GetName(opts));
|
|
if level=0 then
|
|
skip[level]:=not (assigned(search_macro(s)) or (s='COMMON'));
|
|
end
|
|
else
|
|
if (s='IFDEF') then
|
|
begin
|
|
RemoveSep(opts);
|
|
if Level>=maxlevel then
|
|
begin
|
|
Message(option_too_many_ifdef);
|
|
stopOptions(1);
|
|
end;
|
|
inc(Level);
|
|
skip[level]:=(skip[level-1] or not assigned(search_macro(upper(GetName(opts)))));
|
|
end
|
|
else
|
|
if (s='IFNDEF') then
|
|
begin
|
|
RemoveSep(opts);
|
|
if Level>=maxlevel then
|
|
begin
|
|
Message(option_too_many_ifdef);
|
|
stopOptions(1);
|
|
end;
|
|
inc(Level);
|
|
skip[level]:=(skip[level-1] or assigned(search_macro(upper(GetName(opts)))));
|
|
end
|
|
else
|
|
if (s='ELSE') then
|
|
skip[level]:=skip[level-1] or (not skip[level])
|
|
else
|
|
if (s='ENDIF') then
|
|
begin
|
|
skip[level]:=false;
|
|
if Level=0 then
|
|
begin
|
|
Message(option_too_many_endif);
|
|
stopOptions(1);
|
|
end;
|
|
dec(level);
|
|
end
|
|
else
|
|
if (not skip[level]) then
|
|
begin
|
|
if (s='DEFINE') then
|
|
begin
|
|
RemoveSep(opts);
|
|
tmp:= GetName(opts);
|
|
if tmp <> '' then
|
|
def_system_macro(tmp);
|
|
end
|
|
else
|
|
if (s='UNDEF') then
|
|
begin
|
|
RemoveSep(opts);
|
|
tmp:= GetName(opts);
|
|
if tmp <> '' then
|
|
undef_system_macro(tmp);
|
|
end
|
|
else
|
|
if (s='WRITE') then
|
|
begin
|
|
Delete(opts,1,1);
|
|
WriteLn(opts);
|
|
end
|
|
else
|
|
if (s='INCLUDE') then
|
|
begin
|
|
Delete(opts,1,1);
|
|
Interpret_file(opts);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (opts[1]='-') or (opts[1]='@') then
|
|
begin
|
|
if (not skip[level]) then
|
|
interpret_option(opts,false);
|
|
Option_read:=true;
|
|
end
|
|
else
|
|
Message1(option_illegal_para,opts);
|
|
end;
|
|
end;
|
|
end;
|
|
if Level>0 then
|
|
Message(option_too_less_endif);
|
|
if Not Option_read then
|
|
Message1(option_no_option_found,filename)
|
|
else
|
|
Message1(option_end_reading_configfile,filename);
|
|
Close(f);
|
|
Dec(FileLevel);
|
|
end;
|
|
|
|
|
|
procedure Toption.Interpret_envvar(const envname : string);
|
|
var
|
|
argstart,
|
|
env,
|
|
pc : pchar;
|
|
arglen : longint;
|
|
quote : set of char;
|
|
hs : string;
|
|
begin
|
|
Message1(option_using_env,envname);
|
|
env:=GetEnvPChar(envname);
|
|
pc:=env;
|
|
if assigned(pc) then
|
|
begin
|
|
repeat
|
|
{ skip leading spaces }
|
|
while pc^ in [' ',#9,#13] do
|
|
inc(pc);
|
|
case pc^ of
|
|
#0 :
|
|
break;
|
|
'"' :
|
|
begin
|
|
quote:=['"'];
|
|
inc(pc);
|
|
end;
|
|
'''' :
|
|
begin
|
|
quote:=[''''];
|
|
inc(pc);
|
|
end;
|
|
else
|
|
quote:=[' ',#9,#13];
|
|
end;
|
|
{ scan until the end of the argument }
|
|
argstart:=pc;
|
|
while (pc^<>#0) and not(pc^ in quote) do
|
|
inc(pc);
|
|
{ create argument }
|
|
arglen:=pc-argstart;
|
|
hs[0]:=chr(arglen);
|
|
move(argstart^,hs[1],arglen);
|
|
interpret_option(hs,true);
|
|
{ skip quote }
|
|
if pc^ in quote then
|
|
inc(pc);
|
|
until false;
|
|
end
|
|
else
|
|
Message1(option_no_option_found,'(env) '+envname);
|
|
FreeEnvPChar(env);
|
|
end;
|
|
|
|
|
|
procedure toption.read_parameters;
|
|
var
|
|
opts : string;
|
|
paramindex : longint;
|
|
begin
|
|
paramindex:=0;
|
|
while paramindex<paramcount do
|
|
begin
|
|
inc(paramindex);
|
|
opts:=system.paramstr(paramindex);
|
|
case opts[1] of
|
|
'@' :
|
|
if not firstpass then
|
|
begin
|
|
Delete(opts,1,1);
|
|
Message1(option_reading_further_from,opts);
|
|
interpret_file(opts);
|
|
end;
|
|
'!' :
|
|
if not firstpass then
|
|
begin
|
|
Delete(opts,1,1);
|
|
Message1(option_reading_further_from,'(env) '+opts);
|
|
interpret_envvar(opts);
|
|
end;
|
|
else
|
|
interpret_option(opts,true);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure toption.parsecmd(cmd:string);
|
|
var
|
|
i,ps : longint;
|
|
opts : string;
|
|
begin
|
|
while (cmd<>'') do
|
|
begin
|
|
while cmd[1]=' ' do
|
|
delete(cmd,1,1);
|
|
i:=pos(' ',cmd);
|
|
if i=0 then
|
|
i:=256;
|
|
opts:=Copy(cmd,1,i-1);
|
|
Delete(cmd,1,i);
|
|
case opts[1] of
|
|
'@' :
|
|
if not firstpass then
|
|
begin
|
|
Delete(opts,1,1);
|
|
Message1(option_reading_further_from,opts);
|
|
interpret_file(opts);
|
|
end;
|
|
'!' :
|
|
if not firstpass then
|
|
begin
|
|
Delete(opts,1,1);
|
|
Message1(option_reading_further_from,'(env) '+opts);
|
|
interpret_envvar(opts);
|
|
end;
|
|
'"' :
|
|
begin
|
|
Delete(opts,1,1);
|
|
ps:=pos('"',cmd);
|
|
if (i<>256) and (ps>0) then
|
|
begin
|
|
opts:=opts + ' '+ copy(cmd,1,ps-1);
|
|
cmd:=copy(cmd,ps+1,255);
|
|
end;
|
|
interpret_option(opts,true);
|
|
end;
|
|
else
|
|
interpret_option(opts,true);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure toption.writequickinfo;
|
|
var
|
|
s : string;
|
|
i : longint;
|
|
|
|
procedure addinfo(const hs:string);
|
|
begin
|
|
if s<>'' then
|
|
s:=s+' '+hs
|
|
else
|
|
s:=hs;
|
|
end;
|
|
|
|
begin
|
|
s:='';
|
|
i:=0;
|
|
while (i<length(quickinfo)) do
|
|
begin
|
|
inc(i);
|
|
case quickinfo[i] of
|
|
'S' :
|
|
begin
|
|
inc(i);
|
|
case quickinfo[i] of
|
|
'O' :
|
|
addinfo(lower(source_info.shortname));
|
|
'P' :
|
|
addinfo(source_cpu_string);
|
|
else
|
|
IllegalPara('-i'+QuickInfo);
|
|
end;
|
|
end;
|
|
'T' :
|
|
begin
|
|
inc(i);
|
|
case quickinfo[i] of
|
|
'O' :
|
|
addinfo(lower(target_info.shortname));
|
|
'P' :
|
|
AddInfo(target_cpu_string);
|
|
else
|
|
IllegalPara('-i'+QuickInfo);
|
|
end;
|
|
end;
|
|
'V' :
|
|
AddInfo(version_string);
|
|
'D' :
|
|
AddInfo(date_string);
|
|
'_' :
|
|
;
|
|
else
|
|
IllegalPara('-i'+QuickInfo);
|
|
end;
|
|
end;
|
|
if s<>'' then
|
|
begin
|
|
writeln(s);
|
|
stopoptions(0);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOption.TargetDefines(def:boolean);
|
|
var
|
|
s : string;
|
|
i : integer;
|
|
begin
|
|
if def then
|
|
def_system_macro(target_info.shortname)
|
|
else
|
|
undef_system_macro(target_info.shortname);
|
|
s:=target_info.extradefines;
|
|
while (s<>'') do
|
|
begin
|
|
i:=pos(';',s);
|
|
if i=0 then
|
|
i:=length(s)+1;
|
|
if def then
|
|
def_system_macro(Copy(s,1,i-1))
|
|
else
|
|
undef_system_macro(Copy(s,1,i-1));
|
|
delete(s,1,i);
|
|
end;
|
|
end;
|
|
|
|
|
|
constructor TOption.create;
|
|
begin
|
|
LogoWritten:=false;
|
|
NoPressEnter:=false;
|
|
FirstPass:=false;
|
|
FileLevel:=0;
|
|
Quickinfo:='';
|
|
ParaIncludePath:=TSearchPathList.Create;
|
|
ParaObjectPath:=TSearchPathList.Create;
|
|
ParaUnitPath:=TSearchPathList.Create;
|
|
ParaLibraryPath:=TSearchPathList.Create;
|
|
FillChar(ParaAlignment,sizeof(ParaAlignment),0);
|
|
end;
|
|
|
|
|
|
destructor TOption.destroy;
|
|
begin
|
|
ParaIncludePath.Free;
|
|
ParaObjectPath.Free;
|
|
ParaUnitPath.Free;
|
|
ParaLibraryPath.Free;
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
Callable Routines
|
|
****************************************************************************}
|
|
|
|
function check_configfile(const fn:string;var foundfn:string):boolean;
|
|
|
|
function CfgFileExists(const fn:string):boolean;
|
|
begin
|
|
Comment(V_Tried,'Configfile search: '+fn);
|
|
CfgFileExists:=FileExists(fn);
|
|
end;
|
|
|
|
var
|
|
configpath : pathstr;
|
|
begin
|
|
foundfn:=fn;
|
|
check_configfile:=true;
|
|
{ retrieve configpath }
|
|
{$IFDEF USE_SYSUTILS}
|
|
configpath:=FixPath(GetEnvironmentVariable('PPC_CONFIG_PATH'),false);
|
|
{$ELSE USE_SYSUTILS}
|
|
configpath:=FixPath(dos.getenv('PPC_CONFIG_PATH'),false);
|
|
{$ENDIF USE_SYSUTILS}
|
|
{$ifdef Unix}
|
|
if configpath='' then
|
|
configpath:=CleanPath(FixPath(exepath+'../etc/',false));
|
|
{$endif}
|
|
{
|
|
Order to read configuration file :
|
|
try reading fpc.cfg in :
|
|
1 - current dir
|
|
2 - configpath
|
|
3 - compiler path
|
|
}
|
|
if not FileExists(fn) then
|
|
begin
|
|
{$ifdef Unix}
|
|
{$IFDEF USE_SYSUTILS}
|
|
if (GetEnvironmentVariable('HOME')<>'') and CfgFileExists(FixPath(GetEnvironmentVariable('HOME'),false)+'.'+fn) then
|
|
foundfn:=FixPath(GetEnvironmentVariable('HOME'),false)+'.'+fn
|
|
{$ELSE USE_SYSUTILS}
|
|
if (dos.getenv('HOME')<>'') and CfgFileExists(FixPath(dos.getenv('HOME'),false)+'.'+fn) then
|
|
foundfn:=FixPath(dos.getenv('HOME'),false)+'.'+fn
|
|
{$ENDIF USE_SYSUTILS}
|
|
else
|
|
{$endif}
|
|
if CfgFileExists(configpath+fn) then
|
|
foundfn:=configpath+fn
|
|
else
|
|
{$ifndef Unix}
|
|
if CfgFileExists(exepath+fn) then
|
|
foundfn:=exepath+fn
|
|
else
|
|
{$else}
|
|
if CfgFileExists('/etc/'+fn) then
|
|
foundfn:='/etc/'+fn
|
|
else
|
|
{$endif}
|
|
check_configfile:=false;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure read_arguments(cmd:string);
|
|
begin
|
|
option:=coption.create;
|
|
disable_configfile:=false;
|
|
|
|
{ get default messagefile }
|
|
{$IFDEF USE_SYSUTILS}
|
|
msgfilename:=GetEnvironmentVariable('PPC_ERROR_FILE');
|
|
{$ELSE USE_SYSUTILS}
|
|
msgfilename:=dos.getenv('PPC_ERROR_FILE');
|
|
{$ENDIF USE_SYSUTILS}
|
|
|
|
{ default configfile can be specified on the commandline,
|
|
remove it first }
|
|
if (cmd<>'') and (cmd[1]='[') then
|
|
begin
|
|
ppccfg:=Copy(cmd,2,pos(']',cmd)-2);
|
|
Delete(cmd,1,pos(']',cmd));
|
|
end
|
|
else
|
|
begin
|
|
ppccfg:='fpc.cfg';
|
|
ppcaltcfg:='ppc386.cfg';
|
|
end;
|
|
|
|
{ first pass reading of parameters, only -i -v -T etc.}
|
|
option.firstpass:=true;
|
|
if cmd<>'' then
|
|
option.parsecmd(cmd)
|
|
else
|
|
begin
|
|
option.read_parameters;
|
|
{ Write only quickinfo }
|
|
if option.quickinfo<>'' then
|
|
option.writequickinfo;
|
|
end;
|
|
option.firstpass:=false;
|
|
|
|
{ target is set here, for wince the default app type is gui }
|
|
if target_info.system in system_wince then
|
|
apptype:=app_gui;
|
|
|
|
{ default defines }
|
|
def_system_macro(target_info.shortname);
|
|
def_system_macro('FPC');
|
|
def_system_macro('VER'+version_nr);
|
|
def_system_macro('VER'+version_nr+'_'+release_nr);
|
|
def_system_macro('VER'+version_nr+'_'+release_nr+'_'+patch_nr);
|
|
|
|
{ Temporary defines, until things settle down }
|
|
{ "main" symbol is generated in the main program, and left out of the system unit }
|
|
def_system_macro('FPC_DARWIN_PASCALMAIN');
|
|
def_system_macro('COMPPROCINLINEFIXED');
|
|
|
|
if pocall_default = pocall_register then
|
|
def_system_macro('REGCALL');
|
|
|
|
{ using a case is pretty useless here (FK) }
|
|
{ some stuff for TP compatibility }
|
|
{$ifdef i386}
|
|
def_system_macro('CPU86');
|
|
def_system_macro('CPU87');
|
|
{$endif}
|
|
{$ifdef m68k}
|
|
def_system_macro('CPU68');
|
|
{$endif}
|
|
|
|
{ new processor stuff }
|
|
{$ifdef i386}
|
|
def_system_macro('CPUI386');
|
|
def_system_macro('CPU32');
|
|
def_system_macro('FPC_HAS_TYPE_EXTENDED');
|
|
def_system_macro('FPC_HAS_TYPE_DOUBLE');
|
|
def_system_macro('FPC_HAS_TYPE_SINGLE');
|
|
def_system_macro('FPC_HAS_RESOURCES');
|
|
{$endif}
|
|
{$ifdef m68k}
|
|
def_system_macro('CPU68K');
|
|
def_system_macro('CPUM68K');
|
|
def_system_macro('CPU32');
|
|
def_system_macro('FPC_CURRENCY_IS_INT64');
|
|
def_system_macro('FPC_COMP_IS_INT64');
|
|
{$endif}
|
|
{$ifdef ALPHA}
|
|
def_system_macro('CPUALPHA');
|
|
def_system_macro('CPU64');
|
|
{$endif}
|
|
{$ifdef powerpc}
|
|
def_system_macro('CPUPOWERPC');
|
|
def_system_macro('CPUPOWERPC32');
|
|
def_system_macro('CPU32');
|
|
def_system_macro('FPC_HAS_TYPE_DOUBLE');
|
|
def_system_macro('FPC_HAS_TYPE_SINGLE');
|
|
def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
|
|
def_system_macro('FPC_CURRENCY_IS_INT64');
|
|
def_system_macro('FPC_COMP_IS_INT64');
|
|
{$endif}
|
|
{$ifdef POWERPC64}
|
|
def_system_macro('CPUPOWERPC');
|
|
def_system_macro('CPUPOWERPC64');
|
|
def_system_macro('CPU64');
|
|
def_system_macro('FPC_HAS_TYPE_DOUBLE');
|
|
def_system_macro('FPC_HAS_TYPE_SINGLE');
|
|
def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
|
|
def_system_macro('FPC_CURRENCY_IS_INT64');
|
|
def_system_macro('FPC_COMP_IS_INT64');
|
|
def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
|
|
{$endif}
|
|
{$ifdef iA64}
|
|
def_system_macro('CPUIA64');
|
|
def_system_macro('CPU64');
|
|
{$endif}
|
|
{$ifdef x86_64}
|
|
def_system_macro('CPUX86_64');
|
|
def_system_macro('CPUAMD64');
|
|
def_system_macro('CPU64');
|
|
{ not supported for now, afaik (FK)
|
|
def_system_macro('FPC_HAS_TYPE_FLOAT128'); }
|
|
|
|
{ win64 doesn't support the legacy fpu }
|
|
if target_info.system<>system_x86_64_win64 then
|
|
def_system_macro('FPC_HAS_TYPE_EXTENDED')
|
|
else
|
|
begin
|
|
def_system_macro('FPC_CURRENCY_IS_INT64');
|
|
def_system_macro('FPC_COMP_IS_INT64');
|
|
undef_system_macro('FPC_HAS_TYPE_EXTENDED');
|
|
end;
|
|
|
|
def_system_macro('FPC_HAS_TYPE_DOUBLE');
|
|
def_system_macro('FPC_HAS_TYPE_SINGLE');
|
|
{$endif}
|
|
{$ifdef sparc}
|
|
def_system_macro('CPUSPARC');
|
|
def_system_macro('CPUSPARC32');
|
|
def_system_macro('CPU32');
|
|
def_system_macro('FPC_HAS_TYPE_DOUBLE');
|
|
def_system_macro('FPC_HAS_TYPE_SINGLE');
|
|
def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
|
|
def_system_macro('FPC_CURRENCY_IS_INT64');
|
|
def_system_macro('FPC_COMP_IS_INT64');
|
|
def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
|
|
{$endif}
|
|
{$ifdef vis}
|
|
def_system_macro('CPUVIS');
|
|
def_system_macro('CPU32');
|
|
{$endif}
|
|
{$ifdef arm}
|
|
def_system_macro('CPUARM');
|
|
def_system_macro('FPUFPA');
|
|
def_system_macro('CPU32');
|
|
def_system_macro('FPC_HAS_TYPE_DOUBLE');
|
|
def_system_macro('FPC_HAS_TYPE_SINGLE');
|
|
def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
|
|
def_system_macro('FPC_CURRENCY_IS_INT64');
|
|
def_system_macro('FPC_COMP_IS_INT64');
|
|
def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
|
|
{$endif arm}
|
|
|
|
if source_info.system<>target_info.system then
|
|
def_system_macro('FPC_CROSSCOMPILING');
|
|
|
|
if source_info.cpu<>target_info.cpu then
|
|
def_system_macro('FPC_CPUCROSSCOMPILING');
|
|
|
|
{ read configuration file }
|
|
if (not disable_configfile) and
|
|
(ppccfg<>'') then
|
|
begin
|
|
read_configfile:=check_configfile(ppccfg,ppccfg);
|
|
{ Maybe alternative configfile ? }
|
|
if (not read_configfile) and
|
|
(ppcaltcfg<>'') then
|
|
read_configfile:=check_configfile(ppcaltcfg,ppccfg);
|
|
end
|
|
else
|
|
read_configfile := false;
|
|
|
|
{ Read commandline and configfile }
|
|
param_file:='';
|
|
|
|
{ read configfile }
|
|
if read_configfile then
|
|
option.interpret_file(ppccfg);
|
|
|
|
{ read parameters again to override config file }
|
|
if cmd<>'' then
|
|
option.parsecmd(cmd)
|
|
else
|
|
begin
|
|
{ Write help pages if no parameters are passed }
|
|
if (paramcount=0) then
|
|
Option.WriteHelpPages;
|
|
option.read_parameters;
|
|
{ Write only quickinfo }
|
|
if option.quickinfo<>'' then
|
|
option.writequickinfo;
|
|
end;
|
|
|
|
{ Stop if errors in options }
|
|
if ErrorCount>0 then
|
|
StopOptions(1);
|
|
|
|
{ Write logo }
|
|
if option.ParaLogo then
|
|
option.writelogo;
|
|
|
|
{ Non-core target defines }
|
|
Option.TargetDefines(true);
|
|
|
|
{ endian define }
|
|
case target_info.endian of
|
|
endian_little :
|
|
begin
|
|
def_system_macro('ENDIAN_LITTLE');
|
|
def_system_macro('FPC_LITTLE_ENDIAN');
|
|
end;
|
|
endian_big :
|
|
begin
|
|
def_system_macro('ENDIAN_BIG');
|
|
def_system_macro('FPC_BIG_ENDIAN');
|
|
end;
|
|
end;
|
|
|
|
{ abi define }
|
|
case target_info.abi of
|
|
abi_powerpc_sysv :
|
|
def_system_macro('FPC_ABI_SYSV');
|
|
abi_powerpc_aix :
|
|
def_system_macro('FPC_ABI_AIX');
|
|
end;
|
|
|
|
{$ifdef m68k}
|
|
if initoptprocessor=MC68020 then
|
|
def_system_macro('CPUM68020');
|
|
{$endif m68k}
|
|
|
|
{ Check file to compile }
|
|
if param_file='' then
|
|
begin
|
|
Message(option_no_source_found);
|
|
StopOptions(1);
|
|
end;
|
|
{$ifndef Unix}
|
|
param_file:=FixFileName(param_file);
|
|
{$endif}
|
|
{$IFDEF USE_SYSUTILS}
|
|
inputdir := SplitPath(param_file);
|
|
inputfile := SplitName(param_file);
|
|
inputextension := SplitExtension(param_file);
|
|
{$ELSE USE_SYSUTILS}
|
|
fsplit(param_file,inputdir,inputfile,inputextension);
|
|
{$ENDIF USE_SYSUTILS}
|
|
if inputextension='' then
|
|
begin
|
|
if FileExists(inputdir+inputfile+sourceext) then
|
|
inputextension:=sourceext
|
|
else if FileExists(inputdir+inputfile+pasext) then
|
|
inputextension:=pasext
|
|
else if ((m_mac in aktmodeswitches) or
|
|
(tf_p_ext_support in target_info.flags))
|
|
and FileExists(inputdir+inputfile+pext) then
|
|
inputextension:=pext;
|
|
end;
|
|
|
|
{ Check output dir }
|
|
if (OutputExeDir<>'') and
|
|
not PathExists(OutputExeDir) then
|
|
begin
|
|
Message1(general_e_path_does_not_exist,OutputExeDir);
|
|
StopOptions(1);
|
|
end;
|
|
|
|
{ Add paths specified with parameters to the searchpaths }
|
|
UnitSearchPath.AddList(option.ParaUnitPath,true);
|
|
ObjectSearchPath.AddList(option.ParaObjectPath,true);
|
|
IncludeSearchPath.AddList(option.ParaIncludePath,true);
|
|
LibrarySearchPath.AddList(option.ParaLibraryPath,true);
|
|
|
|
{ add unit environment and exepath to the unit search path }
|
|
if inputdir<>'' then
|
|
Unitsearchpath.AddPath(inputdir,true);
|
|
if not disable_configfile then
|
|
begin
|
|
{$IFDEF USE_SYSUTILS}
|
|
UnitSearchPath.AddPath(GetEnvironmentVariable(target_info.unit_env),false);
|
|
{$ELSE USE_SYSUTILS}
|
|
UnitSearchPath.AddPath(dos.getenv(target_info.unit_env),false);
|
|
{$ENDIF USE_SYSUTILS}
|
|
end;
|
|
|
|
{$ifdef Unix}
|
|
{$IFDEF USE_SYSUTILS}
|
|
fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'),false);
|
|
{$ELSE USE_SYSUTILS}
|
|
fpcdir:=FixPath(getenv('FPCDIR'),false);
|
|
{$ENDIF USE_SYSUTILS}
|
|
if fpcdir='' then
|
|
begin
|
|
if PathExists('/usr/local/lib/fpc/'+version_string) then
|
|
fpcdir:='/usr/local/lib/fpc/'+version_string+'/'
|
|
else
|
|
fpcdir:='/usr/lib/fpc/'+version_string+'/';
|
|
end;
|
|
{$else}
|
|
{$IFDEF USE_SYSUTILS}
|
|
fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'),false);
|
|
{$ELSE USE_SYSUTILS}
|
|
fpcdir:=FixPath(getenv('FPCDIR'),false);
|
|
{$ENDIF USE_SYSUTILS}
|
|
if fpcdir='' then
|
|
begin
|
|
fpcdir:=ExePath+'../';
|
|
if not(PathExists(fpcdir+'/units')) and
|
|
not(PathExists(fpcdir+'/rtl')) then
|
|
fpcdir:=fpcdir+'../';
|
|
end;
|
|
{$endif}
|
|
{ first try development RTL, else use the default installation path }
|
|
if not disable_configfile then
|
|
begin
|
|
if PathExists(FpcDir+'rtl') then
|
|
if tf_use_8_3 in Source_Info.Flags then
|
|
UnitSearchPath.AddPath(FpcDir+'rtl/'+target_os_string,false)
|
|
else
|
|
UnitSearchPath.AddPath(FpcDir+'rtl/'+target_full_string,false)
|
|
else
|
|
if tf_use_8_3 in Source_Info.Flags then
|
|
UnitSearchPath.AddPath(FpcDir+'units/'+target_os_string+'/rtl',false)
|
|
else
|
|
UnitSearchPath.AddPath(FpcDir+'units/'+target_full_string+'/rtl',false);
|
|
end;
|
|
{ Add exepath if the exe is not in the current dir, because that is always searched already.
|
|
Do not add it when linking on the target because then we can maybe already find
|
|
.o files that are not for the target }
|
|
if (ExePath<>GetCurrentDir) and
|
|
not(cs_link_on_target in initglobalswitches) then
|
|
UnitSearchPath.AddPath(ExePath,false);
|
|
{ Add unit dir to the object and library path }
|
|
objectsearchpath.AddList(unitsearchpath,false);
|
|
librarysearchpath.AddList(unitsearchpath,false);
|
|
|
|
{ maybe override debug info format }
|
|
if (paratargetdbg<>dbg_none) then
|
|
set_target_dbg(paratargetdbg);
|
|
|
|
{ maybe override assembler }
|
|
if (paratargetasm<>as_none) then
|
|
set_target_asm(paratargetasm);
|
|
|
|
{ switch assembler if it's binary and we got -a on the cmdline }
|
|
if (cs_asm_leave in initglobalswitches) and
|
|
(af_outputbinary in target_asm.flags) then
|
|
begin
|
|
Message(option_switch_bin_to_src_assembler);
|
|
set_target_asm(target_info.assemextern);
|
|
end;
|
|
|
|
if (target_asm.supported_target <> system_any) and
|
|
(target_asm.supported_target <> target_info.system) then
|
|
begin
|
|
Message2(option_incompatible_asm,target_asm.idtxt,target_info.name);
|
|
set_target_asm(target_info.assemextern);
|
|
Message1(option_asm_forced,target_asm.idtxt);
|
|
end;
|
|
|
|
{ turn off stripping if compiling with debuginfo or profile }
|
|
if (cs_debuginfo in initmoduleswitches) or
|
|
(cs_profile in initmoduleswitches) then
|
|
exclude(initglobalswitches,cs_link_strip);
|
|
|
|
{ force fpu emulation on arm/wince }
|
|
if target_info.system=system_arm_wince then
|
|
include(initmoduleswitches,cs_fp_emulation);
|
|
|
|
{$ifdef x86_64}
|
|
{$warning HACK: turn off smartlinking}
|
|
exclude(initmoduleswitches,cs_create_smart);
|
|
{$endif}
|
|
|
|
if not LinkTypeSetExplicitly then
|
|
set_default_link_type;
|
|
|
|
{ Default alignment settings,
|
|
1. load the defaults for the target
|
|
2. override with generic optimizer setting (little size)
|
|
3. override with the user specified -Oa }
|
|
UpdateAlignment(initalignment,target_info.alignment);
|
|
if (cs_littlesize in aktglobalswitches) then
|
|
begin
|
|
initalignment.procalign:=1;
|
|
initalignment.jumpalign:=1;
|
|
initalignment.loopalign:=1;
|
|
end;
|
|
|
|
UpdateAlignment(initalignment,option.paraalignment);
|
|
|
|
set_system_macro('FPC_VERSION',version_nr);
|
|
set_system_macro('FPC_RELEASE',release_nr);
|
|
set_system_macro('FPC_PATCH',patch_nr);
|
|
|
|
option.free;
|
|
Option:=nil;
|
|
end;
|
|
|
|
|
|
initialization
|
|
coption:=toption;
|
|
finalization
|
|
if assigned(option) then
|
|
option.free;
|
|
end.
|