mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 04:22:07 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1540 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1540 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2002 by Florian Klaempfl
 | 
						|
 | 
						|
    This unit implements some support functions and global variables
 | 
						|
 | 
						|
    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 globals;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
{$ifdef windows}
 | 
						|
      windows,
 | 
						|
{$endif}
 | 
						|
{$ifdef os2}
 | 
						|
      dos,
 | 
						|
{$endif os2}
 | 
						|
{$ifdef hasunix}
 | 
						|
      Baseunix,unix,
 | 
						|
{$endif}
 | 
						|
 | 
						|
{$IFNDEF USE_FAKE_SYSUTILS}
 | 
						|
      sysutils,
 | 
						|
{$ELSE}
 | 
						|
      fksysutl,
 | 
						|
{$ENDIF}
 | 
						|
 | 
						|
      { comphook pulls in sysutils anyways }
 | 
						|
      cutils,cclasses,cfileutl,
 | 
						|
      cpuinfo,
 | 
						|
      globtype,version,systems;
 | 
						|
 | 
						|
    const
 | 
						|
       delphimodeswitches =
 | 
						|
         [m_delphi,m_all,m_class,m_objpas,m_result,m_string_pchar,
 | 
						|
          m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
 | 
						|
          m_out,m_default_para,m_duplicate_names,m_hintdirective,
 | 
						|
          m_property,m_default_inline,m_except,m_advanced_records];
 | 
						|
       fpcmodeswitches =
 | 
						|
         [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward,
 | 
						|
          m_cvar_support,m_initfinal,m_hintdirective,
 | 
						|
          m_property,m_default_inline];
 | 
						|
       objfpcmodeswitches =
 | 
						|
         [m_objfpc,m_fpc,m_all,m_class,m_objpas,m_result,m_string_pchar,m_nested_comment,
 | 
						|
          m_repeat_forward,m_cvar_support,m_initfinal,m_out,m_default_para,m_hintdirective,
 | 
						|
          m_property,m_default_inline,m_except];
 | 
						|
       tpmodeswitches =
 | 
						|
         [m_tp7,m_all,m_tp_procvar,m_duplicate_names];
 | 
						|
{$ifdef gpc_mode}
 | 
						|
       gpcmodeswitches =
 | 
						|
         [m_gpc,m_all,m_tp_procvar];
 | 
						|
{$endif}
 | 
						|
       macmodeswitches =
 | 
						|
         [m_mac,m_all,m_cvar_support,m_mac_procvar,m_nested_procvars,m_non_local_goto,m_isolike_unary_minus];
 | 
						|
       isomodeswitches =
 | 
						|
         [m_iso,m_all,m_tp_procvar,m_duplicate_names,m_nested_procvars,m_non_local_goto,m_isolike_unary_minus];
 | 
						|
 | 
						|
       { maximum nesting of routines }
 | 
						|
       maxnesting = 32;
 | 
						|
 | 
						|
       { Filenames and extensions }
 | 
						|
       sourceext  = '.pp';
 | 
						|
       pasext     = '.pas';
 | 
						|
       pext       = '.p';
 | 
						|
 | 
						|
       treelogfilename = 'tree.log';
 | 
						|
 | 
						|
{$if defined(CPUARM) and defined(FPUFPA)}
 | 
						|
       MathQNaN : tdoublerec = (bytes : (0,0,252,255,0,0,0,0));
 | 
						|
       MathInf : tdoublerec = (bytes : (0,0,240,127,0,0,0,0));
 | 
						|
       MathNegInf : tdoublerec = (bytes : (0,0,240,255,0,0,0,0));
 | 
						|
       MathPi : tdoublerec =  (bytes : (251,33,9,64,24,45,68,84));
 | 
						|
{$else}
 | 
						|
{$ifdef FPC_LITTLE_ENDIAN}
 | 
						|
       MathQNaN : tdoublerec = (bytes : (0,0,0,0,0,0,252,255));
 | 
						|
       MathInf : tdoublerec = (bytes : (0,0,0,0,0,0,240,127));
 | 
						|
       MathNegInf : tdoublerec = (bytes : (0,0,0,0,0,0,240,255));
 | 
						|
       MathPi : tdoublerec = (bytes : (24,45,68,84,251,33,9,64));
 | 
						|
       MathPiExtended : textendedrec = (bytes : (53,194,104,33,162,218,15,201,0,64));
 | 
						|
{$else FPC_LITTLE_ENDIAN}
 | 
						|
       MathQNaN : tdoublerec = (bytes : (255,252,0,0,0,0,0,0));
 | 
						|
       MathInf : tdoublerec = (bytes : (127,240,0,0,0,0,0,0));
 | 
						|
       MathNegInf : tdoublerec = (bytes : (255,240,0,0,0,0,0,0));
 | 
						|
       MathPi : tdoublerec =  (bytes : (64,9,33,251,84,68,45,24));
 | 
						|
       MathPiExtended : textendedrec = (bytes : (64,0,201,15,218,162,33,104,194,53));
 | 
						|
{$endif FPC_LITTLE_ENDIAN}
 | 
						|
{$endif}
 | 
						|
 | 
						|
    type
 | 
						|
       tcodepagestring = string[20];
 | 
						|
 | 
						|
       { this is written to ppus during token recording for generics so it must be packed }
 | 
						|
       tsettings = packed record
 | 
						|
         alignment       : talignmentinfo;
 | 
						|
         globalswitches  : tglobalswitches;
 | 
						|
         moduleswitches  : tmoduleswitches;
 | 
						|
         localswitches   : tlocalswitches;
 | 
						|
         modeswitches    : tmodeswitches;
 | 
						|
         optimizerswitches : toptimizerswitches;
 | 
						|
         { generate information necessary to perform these wpo's during a subsequent compilation }
 | 
						|
         genwpoptimizerswitches: twpoptimizerswitches;
 | 
						|
         { perform these wpo's using information generated during a previous compilation }
 | 
						|
         dowpoptimizerswitches: twpoptimizerswitches;
 | 
						|
         debugswitches   : tdebugswitches;
 | 
						|
         { 0: old behaviour for sets <=256 elements
 | 
						|
           >0: round to this size }
 | 
						|
         pmessage : pmessagestaterecord;
 | 
						|
         setalloc,
 | 
						|
         packenum        : shortint;
 | 
						|
 | 
						|
         packrecords     : shortint;
 | 
						|
         maxfpuregisters : shortint;
 | 
						|
 | 
						|
         cputype,
 | 
						|
         optimizecputype : tcputype;
 | 
						|
         fputype         : tfputype;
 | 
						|
         asmmode         : tasmmode;
 | 
						|
         interfacetype   : tinterfacetypes;
 | 
						|
         defproccall     : tproccalloption;
 | 
						|
         sourcecodepage  : tcodepagestring;
 | 
						|
 | 
						|
         minfpconstprec  : tfloattype;
 | 
						|
 | 
						|
         disabledircache : boolean;
 | 
						|
 | 
						|
        { CPU targets with microcontroller support can add a controller specific unit }
 | 
						|
{$if defined(ARM) or defined(AVR)}
 | 
						|
        controllertype   : tcontrollertype;
 | 
						|
{$endif defined(ARM) or defined(AVR)}
 | 
						|
       end;
 | 
						|
 | 
						|
    const
 | 
						|
      LinkMapWeightDefault = 1000;
 | 
						|
 | 
						|
    type
 | 
						|
      TLinkRec = record
 | 
						|
        Key   : AnsiString;
 | 
						|
        Value : AnsiString; // key expands to valuelist "value"
 | 
						|
        Weight: longint;
 | 
						|
      end;
 | 
						|
 | 
						|
      TLinkStrMap  = class
 | 
						|
      private
 | 
						|
        itemcnt : longint;
 | 
						|
        fmap : Array Of TLinkRec;
 | 
						|
        function  Lookup(key:Ansistring):longint;
 | 
						|
        function getlinkrec(i:longint):TLinkRec;
 | 
						|
      public
 | 
						|
        procedure Add(key:ansistring;value:AnsiString='';weight:longint=LinkMapWeightDefault);
 | 
						|
        procedure addseries(keys:AnsiString;weight:longint=LinkMapWeightDefault);
 | 
						|
        function  AddDep(keyvalue:String):boolean;
 | 
						|
        function  AddWeight(keyvalue:String):boolean;
 | 
						|
        procedure SetValue(key:AnsiString;Weight:Integer);
 | 
						|
        procedure SortonWeight;
 | 
						|
        function Find(key:AnsiString):AnsiString;
 | 
						|
        procedure Expand(src:TCmdStrList;dest: TLinkStrMap);
 | 
						|
        procedure UpdateWeights(Weightmap:TLinkStrMap);
 | 
						|
        constructor Create;
 | 
						|
        property count : longint read itemcnt;
 | 
						|
        property items[I:longint]:TLinkRec read getlinkrec; default;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
      tpendingstate = record
 | 
						|
        nextverbositystr : shortstring;
 | 
						|
        nextlocalswitches : tlocalswitches;
 | 
						|
        nextverbosityfullswitch: longint;
 | 
						|
        nextcallingstr : shortstring;
 | 
						|
        nextmessagerecord : pmessagestaterecord;
 | 
						|
        verbosityfullswitched,
 | 
						|
        localswitcheschanged : boolean;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    var
 | 
						|
       { specified inputfile }
 | 
						|
       inputfilepath     : string;
 | 
						|
       inputfilename     : string;
 | 
						|
       { specified outputfile with -o parameter }
 | 
						|
       outputfilename    : string;
 | 
						|
       outputprefix      : pshortstring;
 | 
						|
       outputsuffix      : pshortstring;
 | 
						|
       { specified with -FE or -FU }
 | 
						|
       outputexedir      : TPathStr;
 | 
						|
       outputunitdir     : TPathStr;
 | 
						|
       { specified with -FW and -Fw }
 | 
						|
       wpofeedbackinput,
 | 
						|
       wpofeedbackoutput : TPathStr;
 | 
						|
 | 
						|
       { things specified with parameters }
 | 
						|
       paratarget        : tsystem;
 | 
						|
       paratargetdbg     : tdbg;
 | 
						|
       paratargetasm     : tasm;
 | 
						|
       paralinkoptions   : TCmdStr;
 | 
						|
       paradynamiclinker : string;
 | 
						|
       paraprintnodetree : byte;
 | 
						|
       parapreprocess    : boolean;
 | 
						|
       printnodefile     : text;
 | 
						|
 | 
						|
       {  typical cross compiling params}
 | 
						|
 | 
						|
       { directory where the utils can be found (options -FD) }
 | 
						|
       utilsdirectory : TPathStr;
 | 
						|
       { targetname specific prefix used by these utils (options -XP<path>) }
 | 
						|
       utilsprefix    : TCmdStr;
 | 
						|
       cshared        : boolean;        { pass --shared to ld to link C libs shared}
 | 
						|
       Dontlinkstdlibpath: Boolean;     { Don't add std paths to linkpath}
 | 
						|
       rlinkpath      : TCmdStr;        { rpath-link linkdir override}
 | 
						|
       sysrootpath    : TCmdStr;        { target system root to search dyn linker }
 | 
						|
 | 
						|
       { some flags for global compiler switches }
 | 
						|
       do_build,
 | 
						|
       do_release,
 | 
						|
       do_make       : boolean;
 | 
						|
       { path for searching units, different paths can be seperated by ; }
 | 
						|
       exepath            : TPathStr;  { Path to ppc }
 | 
						|
       librarysearchpath,
 | 
						|
       unitsearchpath,
 | 
						|
       objectsearchpath,
 | 
						|
       includesearchpath,
 | 
						|
       frameworksearchpath  : TSearchPathList;
 | 
						|
       autoloadunits      : string;
 | 
						|
 | 
						|
       { linking }
 | 
						|
       usegnubinutils : boolean;
 | 
						|
       forceforwardslash : boolean;
 | 
						|
       usewindowapi  : boolean;
 | 
						|
       description   : string;
 | 
						|
       SetPEFlagsSetExplicity,
 | 
						|
       ImageBaseSetExplicity,
 | 
						|
       MinStackSizeSetExplicity,
 | 
						|
       MaxStackSizeSetExplicity,
 | 
						|
       DescriptionSetExplicity : boolean;
 | 
						|
       dllversion    : string;
 | 
						|
       dllmajor,
 | 
						|
       dllminor,
 | 
						|
       dllrevision   : word;  { revision only for netware }
 | 
						|
       { win pe  }
 | 
						|
       peflags : longint;
 | 
						|
       minstacksize,
 | 
						|
       maxstacksize,
 | 
						|
       imagebase     : puint;
 | 
						|
       UseDeffileForExports    : boolean;
 | 
						|
       UseDeffileForExportsSetExplicitly : boolean;
 | 
						|
       GenerateImportSection,
 | 
						|
       GenerateImportSectionSetExplicitly,
 | 
						|
       RelocSection : boolean;
 | 
						|
       RelocSectionSetExplicitly : boolean;
 | 
						|
       LinkTypeSetExplicitly : boolean;
 | 
						|
 | 
						|
       current_tokenpos,                  { position of the last token }
 | 
						|
       current_filepos : tfileposinfo;    { current position }
 | 
						|
 | 
						|
       nwscreenname : string;
 | 
						|
       nwthreadname : string;
 | 
						|
       nwcopyright  : string;
 | 
						|
 | 
						|
       codegenerror : boolean;           { true if there is an error reported }
 | 
						|
 | 
						|
       block_type : tblock_type;         { type of currently parsed block }
 | 
						|
 | 
						|
       compile_level : word;
 | 
						|
       exceptblockcounter    : integer;  { each except block gets a unique number check gotos      }
 | 
						|
       current_exceptblock        : integer;  { the exceptblock number of the current block (0 if none) }
 | 
						|
       LinkLibraryAliases : TLinkStrMap;
 | 
						|
       LinkLibraryOrder   : TLinkStrMap;
 | 
						|
 | 
						|
       init_settings,
 | 
						|
       current_settings   : tsettings;
 | 
						|
 | 
						|
       pendingstate       : tpendingstate;
 | 
						|
     { Memory sizes }
 | 
						|
       heapsize,
 | 
						|
       stacksize,
 | 
						|
       jmp_buf_size,
 | 
						|
       jmp_buf_align : longint;
 | 
						|
 | 
						|
{$Ifdef EXTDEBUG}
 | 
						|
     { parameter switches }
 | 
						|
       debugstop : boolean;
 | 
						|
{$EndIf EXTDEBUG}
 | 
						|
       { windows / OS/2 application type }
 | 
						|
       apptype : tapptype;
 | 
						|
 | 
						|
       features : tfeatures;
 | 
						|
 | 
						|
    const
 | 
						|
       DLLsource : boolean = false;
 | 
						|
 | 
						|
       { used to set all registers used for each global function
 | 
						|
         this should dramatically decrease the number of
 | 
						|
         recompilations needed PM }
 | 
						|
       simplify_ppu : boolean = true;
 | 
						|
 | 
						|
       Inside_asm_statement : boolean = false;
 | 
						|
 | 
						|
       global_unit_count : word = 0;
 | 
						|
 | 
						|
       { for error info in pp.pas }
 | 
						|
       parser_current_file : string = '';
 | 
						|
 | 
						|
{$if defined(m68k) or defined(arm)}
 | 
						|
       { PalmOS resources }
 | 
						|
       palmos_applicationname : string = 'FPC Application';
 | 
						|
       palmos_applicationid : string[4] = 'FPCA';
 | 
						|
{$endif defined(m68k) or defined(arm)}
 | 
						|
 | 
						|
{$ifdef powerpc}
 | 
						|
       { default calling convention used on MorphOS }
 | 
						|
       syscall_convention : string = 'LEGACY';
 | 
						|
{$endif powerpc}
 | 
						|
 | 
						|
       { default name of the C-style "main" procedure of the library/program }
 | 
						|
       { (this will be prefixed with the target_info.cprefix)                }
 | 
						|
       defaultmainaliasname = 'main';
 | 
						|
       mainaliasname : string = defaultmainaliasname;
 | 
						|
 | 
						|
       { by default no local variable trashing }
 | 
						|
       localvartrashing: longint = -1;
 | 
						|
       { actual values are defined in ncgutil.pas }
 | 
						|
       nroftrashvalues = 4;
 | 
						|
 | 
						|
    const
 | 
						|
      default_settings : TSettings = (
 | 
						|
        alignment : (
 | 
						|
          procalign : 0;
 | 
						|
          loopalign : 0;
 | 
						|
          jumpalign : 0;
 | 
						|
          constalignmin : 0;
 | 
						|
          constalignmax : 0;
 | 
						|
          varalignmin : 0;
 | 
						|
          varalignmax : 0;
 | 
						|
          localalignmin : 0;
 | 
						|
          localalignmax : 0;
 | 
						|
          recordalignmin : 0;
 | 
						|
          recordalignmax : 0;
 | 
						|
          maxCrecordalign : 0;
 | 
						|
        );
 | 
						|
        globalswitches : [cs_check_unit_name,cs_link_static];
 | 
						|
        moduleswitches : [cs_extsyntax,cs_implicit_exceptions];
 | 
						|
        localswitches : [cs_check_io,cs_typed_const_writable,cs_pointermath];
 | 
						|
        modeswitches : fpcmodeswitches;
 | 
						|
        optimizerswitches : [];
 | 
						|
        genwpoptimizerswitches : [];
 | 
						|
        dowpoptimizerswitches : [];
 | 
						|
        debugswitches : [];
 | 
						|
        pmessage : nil;
 | 
						|
 | 
						|
        setalloc : 0;
 | 
						|
        packenum : 4;
 | 
						|
 | 
						|
        packrecords     : 0;
 | 
						|
        maxfpuregisters : 0;
 | 
						|
 | 
						|
{ Note: GENERIC_CPU is sued together with generic subdirectory to
 | 
						|
  be able to compile some of the units without any real CPU.
 | 
						|
  This is used to generate a CPU independant PPUDUMP utility. PM }
 | 
						|
{$ifdef GENERIC_CPU}
 | 
						|
        cputype : cpu_none;
 | 
						|
        optimizecputype : cpu_none;
 | 
						|
        fputype : fpu_none;
 | 
						|
{$else not GENERIC_CPU}
 | 
						|
  {$ifdef i386}
 | 
						|
        cputype : cpu_Pentium;
 | 
						|
        optimizecputype : cpu_Pentium3;
 | 
						|
        fputype : fpu_x87;
 | 
						|
  {$endif i386}
 | 
						|
  {$ifdef m68k}
 | 
						|
        cputype : cpu_MC68020;
 | 
						|
        optimizecputype : cpu_MC68020;
 | 
						|
        fputype : fpu_soft;
 | 
						|
  {$endif m68k}
 | 
						|
  {$ifdef powerpc}
 | 
						|
        cputype : cpu_PPC604;
 | 
						|
        optimizecputype : cpu_ppc7400;
 | 
						|
        fputype : fpu_standard;
 | 
						|
  {$endif powerpc}
 | 
						|
  {$ifdef POWERPC64}
 | 
						|
        cputype : cpu_PPC970;
 | 
						|
        optimizecputype : cpu_ppc970;
 | 
						|
        fputype : fpu_standard;
 | 
						|
  {$endif POWERPC64}
 | 
						|
  {$ifdef sparc}
 | 
						|
        cputype : cpu_SPARC_V8;
 | 
						|
        optimizecputype : cpu_SPARC_V8;
 | 
						|
        fputype : fpu_hard;
 | 
						|
  {$endif sparc}
 | 
						|
  {$ifdef arm}
 | 
						|
        cputype : cpu_armv3;
 | 
						|
        optimizecputype : cpu_armv3;
 | 
						|
        fputype : fpu_fpa;
 | 
						|
  {$endif arm}
 | 
						|
  {$ifdef x86_64}
 | 
						|
        cputype : cpu_athlon64;
 | 
						|
        optimizecputype : cpu_athlon64;
 | 
						|
        fputype : fpu_sse64;
 | 
						|
  {$endif x86_64}
 | 
						|
  {$ifdef avr}
 | 
						|
        cputype : cpuinfo.cpu_avr5;
 | 
						|
        optimizecputype : cpuinfo.cpu_avr5;
 | 
						|
        fputype : fpu_none;
 | 
						|
  {$endif avr}
 | 
						|
  {$ifdef mips}
 | 
						|
        cputype : cpu_mips32;
 | 
						|
        optimizecputype : cpu_mips32;
 | 
						|
        fputype : fpu_mips2;
 | 
						|
  {$endif mips}
 | 
						|
{$endif not GENERIC_CPU}
 | 
						|
        asmmode : asmmode_standard;
 | 
						|
        interfacetype : it_interfacecom;
 | 
						|
        defproccall : pocall_default;
 | 
						|
        sourcecodepage : '8859-1';
 | 
						|
        minfpconstprec : s32real;
 | 
						|
 | 
						|
        disabledircache : false;
 | 
						|
{$if defined(ARM) or defined(AVR)}
 | 
						|
        controllertype : ct_none;
 | 
						|
{$endif defined(ARM) or defined(AVR)}
 | 
						|
      );
 | 
						|
 | 
						|
    var
 | 
						|
      starttime  : real;
 | 
						|
 | 
						|
    function getdatestr:string;
 | 
						|
    function gettimestr:string;
 | 
						|
    function filetimestring( t : longint) : string;
 | 
						|
    function getrealtime : real;
 | 
						|
 | 
						|
    procedure DefaultReplacements(var s:ansistring);
 | 
						|
 | 
						|
    function Shell(const command:ansistring): longint;
 | 
						|
    function  GetEnvPChar(const envname:string):pchar;
 | 
						|
    procedure FreeEnvPChar(p:pchar);
 | 
						|
 | 
						|
    function is_number_float(d : double) : boolean;
 | 
						|
    { discern +0.0 and -0.0 }
 | 
						|
    function get_real_sign(r: bestreal): longint;
 | 
						|
 | 
						|
    procedure InitGlobals;
 | 
						|
    procedure DoneGlobals;
 | 
						|
 | 
						|
    function  string2guid(const s: string; var GUID: TGUID): boolean;
 | 
						|
    function  guid2string(const GUID: TGUID): string;
 | 
						|
 | 
						|
    function SetAktProcCall(const s:string; var a:tproccalloption):boolean;
 | 
						|
    function Setabitype(const s:string;var a:tabi):boolean;
 | 
						|
    function Setcputype(const s:string;var a:tcputype):boolean;
 | 
						|
    function SetFpuType(const s:string;var a:tfputype):boolean;
 | 
						|
{$if defined(arm) or defined(avr)}
 | 
						|
    function SetControllerType(const s:string;var a:tcontrollertype):boolean;
 | 
						|
{$endif defined(arm) or defined(avr)}
 | 
						|
    function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
 | 
						|
    function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
 | 
						|
    function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
 | 
						|
    function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
 | 
						|
    function IncludeFeature(const s : string) : boolean;
 | 
						|
    function SetMinFPConstPrec(const s: string; var a: tfloattype) : boolean;
 | 
						|
 | 
						|
    {# Routine to get the required alignment for size of data, which will
 | 
						|
       be placed in bss segment, according to the current alignment requirements }
 | 
						|
    function var_align(want_align: longint): shortint;
 | 
						|
    function var_align_size(siz: longint): shortint;
 | 
						|
    {# Routine to get the required alignment for size of data, which will
 | 
						|
       be placed in data/const segment, according to the current alignment requirements }
 | 
						|
    function const_align(want_align: longint): shortint;
 | 
						|
    function const_align_size(siz: longint): shortint;
 | 
						|
{$ifdef ARM}
 | 
						|
    function is_double_hilo_swapped: boolean;{$ifdef USEINLINE}inline;{$endif}
 | 
						|
{$endif ARM}
 | 
						|
    function floating_point_range_check_error : boolean;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
{$ifdef macos}
 | 
						|
      macutils,
 | 
						|
{$endif}
 | 
						|
{$ifdef mswindows}
 | 
						|
{$ifdef VER2_4}
 | 
						|
      cwindirs,
 | 
						|
{$else VER2_4}
 | 
						|
      windirs,
 | 
						|
{$endif VER2_4}
 | 
						|
{$endif}
 | 
						|
      comphook;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                 TLinkStrMap
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    Constructor TLinkStrMap.create;
 | 
						|
      begin
 | 
						|
        inherited;
 | 
						|
        itemcnt:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TLinkStrMap.Add(key:ansistring;value:AnsiString='';weight:longint=LinkMapWeightDefault);
 | 
						|
      begin
 | 
						|
        if lookup(key)<>-1 Then
 | 
						|
          exit;
 | 
						|
        if itemcnt<=length(fmap) Then
 | 
						|
          setlength(fmap,itemcnt+10);
 | 
						|
        fmap[itemcnt].key:=key;
 | 
						|
        fmap[itemcnt].value:=value;
 | 
						|
        fmap[itemcnt].weight:=weight;
 | 
						|
        inc(itemcnt);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function  TLinkStrMap.AddDep(keyvalue:String):boolean;
 | 
						|
      var
 | 
						|
        i : Longint;
 | 
						|
      begin
 | 
						|
        AddDep:=false;
 | 
						|
        i:=pos('=',keyvalue);
 | 
						|
        if i=0 then
 | 
						|
          exit;
 | 
						|
        Add(Copy(KeyValue,1,i-1),Copy(KeyValue,i+1,length(KeyValue)-i));
 | 
						|
        AddDep:=True;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function  TLinkStrMap.AddWeight(keyvalue:String):boolean;
 | 
						|
      var
 | 
						|
        i,j    : Longint;
 | 
						|
        Code : Word;
 | 
						|
        s    : AnsiString;
 | 
						|
      begin
 | 
						|
        AddWeight:=false;
 | 
						|
        i:=pos('=',keyvalue);
 | 
						|
        if i=0 then
 | 
						|
          exit;
 | 
						|
        s:=Copy(KeyValue,i+1,length(KeyValue)-i);
 | 
						|
        val(s,j,code);
 | 
						|
        if code=0 Then
 | 
						|
          begin
 | 
						|
            Add(Copy(KeyValue,1,i-1),'',j);
 | 
						|
            AddWeight:=True;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TLinkStrMap.addseries(keys:AnsiString;weight:longint);
 | 
						|
      var
 | 
						|
        i,j,k : longint;
 | 
						|
      begin
 | 
						|
       k:=length(keys);
 | 
						|
       i:=1;
 | 
						|
       while i<=k do
 | 
						|
         begin
 | 
						|
           j:=i;
 | 
						|
           while (i<=k) and (keys[i]<>',') do
 | 
						|
             inc(i);
 | 
						|
           add(copy(keys,j,i-j),'',weight);
 | 
						|
           inc(i);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TLinkStrMap.SetValue(Key:Ansistring;weight:Integer);
 | 
						|
      var
 | 
						|
        j : longint;
 | 
						|
      begin
 | 
						|
         j:=lookup(key);
 | 
						|
         if j<>-1 then
 | 
						|
          fmap[j].weight:=weight;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TLinkStrMap.find(key:Ansistring):Ansistring;
 | 
						|
      var
 | 
						|
        j : longint;
 | 
						|
      begin
 | 
						|
         find:='';
 | 
						|
         j:=lookup(key);
 | 
						|
         if j<>-1 then
 | 
						|
          find:=fmap[j].value;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TLinkStrMap.lookup(key:Ansistring):longint;
 | 
						|
      var
 | 
						|
        i : longint;
 | 
						|
      begin
 | 
						|
         lookup:=-1;
 | 
						|
         i:=0;
 | 
						|
         while (i<itemcnt) and (fmap[i].key<>key) do
 | 
						|
           inc(i);
 | 
						|
         if i<>itemcnt then
 | 
						|
            lookup:=i;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TLinkStrMap.SortOnWeight;
 | 
						|
      var
 | 
						|
        i, j : longint;
 | 
						|
        m    : TLinkRec;
 | 
						|
      begin
 | 
						|
        if itemcnt <2 then exit;
 | 
						|
        for i:=0 to itemcnt-1 do
 | 
						|
          for j:=i+1 to itemcnt-1 do
 | 
						|
            begin
 | 
						|
            if fmap[i].weight>fmap[j].weight Then
 | 
						|
              begin
 | 
						|
                m:=fmap[i];
 | 
						|
                fmap[i]:=fmap[j];
 | 
						|
                fmap[j]:=m;
 | 
						|
              end;
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TLinkStrMap.getlinkrec(i:longint):TLinkRec;
 | 
						|
      begin
 | 
						|
        result:=fmap[i];
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TLinkStrMap.Expand(Src:TCmdStrList;Dest:TLinkStrMap);
 | 
						|
      // expands every thing in Src to Dest for linkorder purposes.
 | 
						|
      var
 | 
						|
        r  : longint;
 | 
						|
        LibN    : TCmdStr;
 | 
						|
      begin
 | 
						|
        while not src.empty do
 | 
						|
          begin
 | 
						|
            LibN:=src.getfirst;
 | 
						|
            r:=lookup (LibN);
 | 
						|
            if r=-1 then
 | 
						|
              dest.add(LibN)
 | 
						|
            else
 | 
						|
              dest.addseries(fmap[r].value);
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TLinkStrMap.UpdateWeights(Weightmap:TLinkStrMap);
 | 
						|
      var
 | 
						|
        l,r : longint;
 | 
						|
      begin
 | 
						|
        for l := 0 to itemcnt-1 do
 | 
						|
          begin
 | 
						|
            r:=weightmap.lookup (fmap[l].key);
 | 
						|
            if r<>-1 then
 | 
						|
              fmap[l].weight:=weightmap[r].weight;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                               Time Handling
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    Function L0(l:longint):string;
 | 
						|
    {
 | 
						|
      return the string of value l, if l<10 then insert a zero, so
 | 
						|
      the string is always at least 2 chars '01','02',etc
 | 
						|
    }
 | 
						|
      var
 | 
						|
        s : string;
 | 
						|
      begin
 | 
						|
        Str(l,s);
 | 
						|
        if l<10 then
 | 
						|
         s:='0'+s;
 | 
						|
        L0:=s;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
   function gettimestr:string;
 | 
						|
   {
 | 
						|
     get the current time in a string HH:MM:SS
 | 
						|
   }
 | 
						|
      var
 | 
						|
        hour,min,sec,hsec : word;
 | 
						|
      begin
 | 
						|
        DecodeTime(Time,hour,min,sec,hsec);
 | 
						|
        gettimestr:=L0(Hour)+':'+L0(min)+':'+L0(sec);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
   function getdatestr:string;
 | 
						|
   {
 | 
						|
     get the current date in a string YY/MM/DD
 | 
						|
   }
 | 
						|
      var
 | 
						|
        Year,Month,Day: Word;
 | 
						|
      begin
 | 
						|
        DecodeDate(Date,year,month,day);
 | 
						|
        getdatestr:=L0(Year)+'/'+L0(Month)+'/'+L0(Day);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
   function  filetimestring( t : longint) : string;
 | 
						|
   {
 | 
						|
     convert dos datetime t to a string YY/MM/DD HH:MM:SS
 | 
						|
   }
 | 
						|
     var
 | 
						|
       DT : TDateTime;
 | 
						|
       hsec : word;
 | 
						|
       Year,Month,Day: Word;
 | 
						|
       hour,min,sec : word;
 | 
						|
     begin
 | 
						|
       if t=-1 then
 | 
						|
        begin
 | 
						|
          Result := 'Not Found';
 | 
						|
          exit;
 | 
						|
        end;
 | 
						|
       DT := FileDateToDateTime(t);
 | 
						|
       DecodeTime(DT,hour,min,sec,hsec);
 | 
						|
       DecodeDate(DT,year,month,day);
 | 
						|
       Result := L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
 | 
						|
     end;
 | 
						|
 | 
						|
 | 
						|
   function getrealtime : real;
 | 
						|
     var
 | 
						|
       h,m,s,s1000 : word;
 | 
						|
     begin
 | 
						|
       DecodeTime(Time,h,m,s,s1000);
 | 
						|
       result:=h*3600.0+m*60.0+s+s1000/1000.0;
 | 
						|
     end;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                          Default Macro Handling
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
 | 
						|
     procedure DefaultReplacements(var s:ansistring);
 | 
						|
{$ifdef mswindows}
 | 
						|
       procedure ReplaceSpecialFolder(const MacroName: string; const ID: integer);
 | 
						|
         begin
 | 
						|
           // Only try to receive the special folders (and thus dynamically
 | 
						|
           // load shfolder.dll) when that's needed.
 | 
						|
           if pos(MacroName,s)>0 then
 | 
						|
             Replace(s,MacroName,GetWindowsSpecialDir(ID));
 | 
						|
         end;
 | 
						|
 | 
						|
{$endif mswindows}
 | 
						|
       var
 | 
						|
         envstr: string;
 | 
						|
         envvalue: pchar;
 | 
						|
         i: integer;
 | 
						|
       begin
 | 
						|
         { Replace some macros }
 | 
						|
         Replace(s,'$FPCVERSION',version_string);
 | 
						|
         Replace(s,'$FPCFULLVERSION',full_version_string);
 | 
						|
         Replace(s,'$FPCDATE',date_string);
 | 
						|
         Replace(s,'$FPCCPU',target_cpu_string);
 | 
						|
         Replace(s,'$FPCOS',target_os_string);
 | 
						|
         if tf_use_8_3 in Source_Info.Flags then
 | 
						|
           Replace(s,'$FPCTARGET',target_os_string)
 | 
						|
         else
 | 
						|
           Replace(s,'$FPCTARGET',target_full_string);
 | 
						|
{$ifdef mswindows}
 | 
						|
         ReplaceSpecialFolder('$LOCAL_APPDATA',CSIDL_LOCAL_APPDATA);
 | 
						|
         ReplaceSpecialFolder('$APPDATA',CSIDL_APPDATA);
 | 
						|
         ReplaceSpecialFolder('$COMMON_APPDATA',CSIDL_COMMON_APPDATA);
 | 
						|
         ReplaceSpecialFolder('$PERSONAL',CSIDL_PERSONAL);
 | 
						|
         ReplaceSpecialFolder('$PROGRAM_FILES',CSIDL_PROGRAM_FILES);
 | 
						|
         ReplaceSpecialFolder('$PROGRAM_FILES_COMMON',CSIDL_PROGRAM_FILES_COMMON);
 | 
						|
         ReplaceSpecialFolder('$PROFILE',CSIDL_PROFILE);
 | 
						|
{$endif mswindows}
 | 
						|
         { Replace environment variables between dollar signs }
 | 
						|
         i := pos('$',s);
 | 
						|
         while i>0 do
 | 
						|
          begin
 | 
						|
            envstr:=copy(s,i+1,length(s)-i);
 | 
						|
            i:=pos('$',envstr);
 | 
						|
            if i>0 then
 | 
						|
             begin
 | 
						|
               envstr := copy(envstr,1,i-1);
 | 
						|
               envvalue := GetEnvPChar(envstr);
 | 
						|
               if assigned(envvalue) then
 | 
						|
                 begin
 | 
						|
                 Replace(s,'$'+envstr+'$',envvalue);
 | 
						|
                 // Look if there is another env.var in the string
 | 
						|
                 i:=pos('$',s);
 | 
						|
                 end
 | 
						|
               else
 | 
						|
                 // if the env.var is not set, do not replace the env.variable
 | 
						|
                 // and stop looking for more env.var within the string
 | 
						|
                 i := 0;
 | 
						|
              FreeEnvPChar(envvalue);
 | 
						|
             end;
 | 
						|
          end;
 | 
						|
       end;
 | 
						|
 | 
						|
 | 
						|
 {****************************************************************************
 | 
						|
                               OS Dependent things
 | 
						|
 ****************************************************************************}
 | 
						|
 | 
						|
    function GetEnvPChar(const envname:string):pchar;
 | 
						|
      {$ifdef win32}
 | 
						|
      var
 | 
						|
        s     : string;
 | 
						|
        i,len : longint;
 | 
						|
        hp,p,p2 : pchar;
 | 
						|
      {$endif}
 | 
						|
      begin
 | 
						|
      {$ifdef hasunix}
 | 
						|
        GetEnvPchar:=BaseUnix.fpGetEnv(envname);
 | 
						|
        {$define GETENVOK}
 | 
						|
      {$endif}
 | 
						|
      {$ifdef win32}
 | 
						|
        GetEnvPchar:=nil;
 | 
						|
        p:=GetEnvironmentStrings;
 | 
						|
        hp:=p;
 | 
						|
        while hp^<>#0 do
 | 
						|
         begin
 | 
						|
           s:=strpas(hp);
 | 
						|
           i:=pos('=',s);
 | 
						|
           len:=strlen(hp);
 | 
						|
           if upper(copy(s,1,i-1))=upper(envname) then
 | 
						|
            begin
 | 
						|
              GetMem(p2,len-length(envname));
 | 
						|
              Move(hp[i],p2^,len-length(envname));
 | 
						|
              GetEnvPchar:=p2;
 | 
						|
              break;
 | 
						|
            end;
 | 
						|
           { next string entry}
 | 
						|
           hp:=hp+len+1;
 | 
						|
         end;
 | 
						|
        FreeEnvironmentStrings(p);
 | 
						|
        {$define GETENVOK}
 | 
						|
      {$endif}
 | 
						|
      {$ifdef os2}
 | 
						|
        GetEnvPChar := Dos.GetEnvPChar (EnvName);
 | 
						|
        {$define GETENVOK}
 | 
						|
      {$endif}
 | 
						|
      {$ifdef GETENVOK}
 | 
						|
        {$undef GETENVOK}
 | 
						|
      {$else}
 | 
						|
        GetEnvPchar:=StrPNew(GetEnvironmentVariable(envname));
 | 
						|
      {$endif}
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure FreeEnvPChar(p:pchar);
 | 
						|
      begin
 | 
						|
      {$ifndef hasunix}
 | 
						|
       {$ifndef os2}
 | 
						|
        freemem(p);
 | 
						|
       {$endif}
 | 
						|
      {$endif}
 | 
						|
      end;
 | 
						|
 | 
						|
{$if defined(MORPHOS) or defined(AMIGA)}
 | 
						|
  {$define AMIGASHELL}
 | 
						|
{$endif}
 | 
						|
 | 
						|
    function Shell(const command:ansistring): longint;
 | 
						|
      { This is already defined in the linux.ppu for linux, need for the *
 | 
						|
        expansion under linux }
 | 
						|
{$ifdef hasunix}
 | 
						|
      begin
 | 
						|
        result := Unix.fpsystem(command);
 | 
						|
      end;
 | 
						|
{$else hasunix}
 | 
						|
  {$ifdef amigashell}
 | 
						|
      begin
 | 
						|
        result := ExecuteProcess('',command);
 | 
						|
      end;
 | 
						|
  {$else amigashell}
 | 
						|
      var
 | 
						|
        comspec : string;
 | 
						|
      begin
 | 
						|
        comspec:=GetEnvironmentVariable('COMSPEC');
 | 
						|
        result := ExecuteProcess(comspec,' /C '+command);
 | 
						|
      end;
 | 
						|
   {$endif amigashell}
 | 
						|
{$endif hasunix}
 | 
						|
 | 
						|
{$UNDEF AMIGASHELL}
 | 
						|
      function is_number_float(d : double) : boolean;
 | 
						|
        var
 | 
						|
           bytearray : array[0..7] of byte;
 | 
						|
        begin
 | 
						|
          move(d,bytearray,8);
 | 
						|
          { only 1.1 save, 1.0.x will use always little endian }
 | 
						|
{$ifdef FPC_BIG_ENDIAN}
 | 
						|
          result:=((bytearray[0] and $7f)<>$7f) or ((bytearray[1] and $f0)<>$f0);
 | 
						|
{$else FPC_BIG_ENDIAN}
 | 
						|
          result:=((bytearray[7] and $7f)<>$7f) or ((bytearray[6] and $f0)<>$f0);
 | 
						|
{$endif FPC_BIG_ENDIAN}
 | 
						|
        end;
 | 
						|
 | 
						|
    function get_real_sign(r: bestreal): longint;
 | 
						|
      var
 | 
						|
        p: pbyte;
 | 
						|
      begin
 | 
						|
        p := pbyte(@r);
 | 
						|
{$ifdef CPU_ARM}
 | 
						|
        inc(p,4);
 | 
						|
{$else}
 | 
						|
{$ifdef FPC_LITTLE_ENDIAN}
 | 
						|
        inc(p,sizeof(r)-1);
 | 
						|
{$endif}
 | 
						|
{$endif}
 | 
						|
        if (p^ and $80) = 0 then
 | 
						|
          result := 1
 | 
						|
        else
 | 
						|
          result := -1;
 | 
						|
      end;
 | 
						|
 | 
						|
    function convertdoublerec(d : tdoublerec) : tdoublerec;{$ifdef USEINLINE}inline;{$endif}
 | 
						|
{$ifdef CPUARM}
 | 
						|
      var
 | 
						|
        i : longint;
 | 
						|
      begin
 | 
						|
        for i:=0 to 3 do
 | 
						|
          begin
 | 
						|
            result.bytes[i+4]:=d.bytes[i];
 | 
						|
            result.bytes[i]:=d.bytes[i+4];
 | 
						|
          end;
 | 
						|
{$else CPUARM}
 | 
						|
      begin
 | 
						|
        result:=d;
 | 
						|
{$endif CPUARM}
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    { '('D1:'00000000-'D2:'0000-'D3:'0000-'D4:'0000-000000000000)' }
 | 
						|
    function string2guid(const s: string; var GUID: TGUID): boolean;
 | 
						|
        function ishexstr(const hs: string): boolean;
 | 
						|
          var
 | 
						|
            i: integer;
 | 
						|
          begin
 | 
						|
            ishexstr:=false;
 | 
						|
            for i:=1 to Length(hs) do begin
 | 
						|
              if not (hs[i] in ['0'..'9','A'..'F','a'..'f']) then
 | 
						|
                exit;
 | 
						|
            end;
 | 
						|
            ishexstr:=true;
 | 
						|
          end;
 | 
						|
        function hexstr2longint(const hexs: string): longint;
 | 
						|
          var
 | 
						|
            i: integer;
 | 
						|
            rl: longint;
 | 
						|
          begin
 | 
						|
            rl:=0;
 | 
						|
            for i:=1 to length(hexs) do begin
 | 
						|
              rl:=rl shl 4;
 | 
						|
              case hexs[i] of
 | 
						|
                '0'..'9' : inc(rl,ord(hexs[i])-ord('0'));
 | 
						|
                'A'..'F' : inc(rl,ord(hexs[i])-ord('A')+10);
 | 
						|
                'a'..'f' : inc(rl,ord(hexs[i])-ord('a')+10);
 | 
						|
              end
 | 
						|
            end;
 | 
						|
            hexstr2longint:=rl;
 | 
						|
          end;
 | 
						|
      var
 | 
						|
        i: integer;
 | 
						|
      begin
 | 
						|
        if (Length(s)=38) and (s[1]='{') and (s[38]='}') and
 | 
						|
           (s[10]='-') and (s[15]='-') and (s[20]='-') and (s[25]='-') and
 | 
						|
           ishexstr(copy(s,2,8)) and ishexstr(copy(s,11,4)) and
 | 
						|
           ishexstr(copy(s,16,4)) and ishexstr(copy(s,21,4)) and
 | 
						|
           ishexstr(copy(s,26,12)) then begin
 | 
						|
          GUID.D1:=dword(hexstr2longint(copy(s,2,8)));
 | 
						|
          { these values are arealdy in the correct range (4 chars = word) }
 | 
						|
          GUID.D2:=word(hexstr2longint(copy(s,11,4)));
 | 
						|
          GUID.D3:=word(hexstr2longint(copy(s,16,4)));
 | 
						|
          for i:=0 to 1 do
 | 
						|
            GUID.D4[i]:=byte(hexstr2longint(copy(s,21+i*2,2)));
 | 
						|
          for i:=2 to 7 do
 | 
						|
            GUID.D4[i]:=byte(hexstr2longint(copy(s,22+i*2,2)));
 | 
						|
          string2guid:=true;
 | 
						|
        end
 | 
						|
        else if (length(s)=0) then
 | 
						|
          begin
 | 
						|
          FillChar(GUID,SizeOf(GUID),0);
 | 
						|
          string2guid:=true;
 | 
						|
          end
 | 
						|
        else
 | 
						|
          string2guid:=false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function guid2string(const GUID: TGUID): string;
 | 
						|
 | 
						|
      begin
 | 
						|
        guid2string:=
 | 
						|
          '{'+hexstr(GUID.D1,8)+
 | 
						|
          '-'+hexstr(GUID.D2,4)+
 | 
						|
          '-'+hexstr(GUID.D3,4)+
 | 
						|
          '-'+hexstr(GUID.D4[0],2)+hexstr(GUID.D4[1],2)+
 | 
						|
          '-'+hexstr(GUID.D4[2],2)+hexstr(GUID.D4[3],2)+
 | 
						|
              hexstr(GUID.D4[4],2)+hexstr(GUID.D4[5],2)+
 | 
						|
              hexstr(GUID.D4[6],2)+hexstr(GUID.D4[7],2)+
 | 
						|
          '}';
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function SetAktProcCall(const s:string; var a:tproccalloption):boolean;
 | 
						|
      const
 | 
						|
        DefProcCallName : array[tproccalloption] of string[12] = ('',
 | 
						|
         'CDECL',
 | 
						|
         'CPPDECL',
 | 
						|
         'FAR16',
 | 
						|
         'OLDFPCCALL',
 | 
						|
         '', { internproc }
 | 
						|
         '', { syscall }
 | 
						|
         'PASCAL',
 | 
						|
         'REGISTER',
 | 
						|
         'SAFECALL',
 | 
						|
         'STDCALL',
 | 
						|
         'SOFTFLOAT',
 | 
						|
         'MWPASCAL',
 | 
						|
         'INTERRUPT'
 | 
						|
        );
 | 
						|
      var
 | 
						|
        t  : tproccalloption;
 | 
						|
        hs : string;
 | 
						|
      begin
 | 
						|
        result:=false;
 | 
						|
        if (s = '') then
 | 
						|
          exit;
 | 
						|
        hs:=upper(s);
 | 
						|
        if (hs = 'DEFAULT') then
 | 
						|
          begin
 | 
						|
            a := pocall_default;
 | 
						|
            result := true;
 | 
						|
            exit;
 | 
						|
          end;
 | 
						|
        for t:=low(tproccalloption) to high(tproccalloption) do
 | 
						|
         if DefProcCallName[t]=hs then
 | 
						|
          begin
 | 
						|
            a:=t;
 | 
						|
            result:=true;
 | 
						|
            break;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function Setabitype(const s:string;var a:tabi):boolean;
 | 
						|
      var
 | 
						|
        t  : tabi;
 | 
						|
        hs : string;
 | 
						|
      begin
 | 
						|
        result:=false;
 | 
						|
        hs:=Upper(s);
 | 
						|
        for t:=low(t) to high(t) do
 | 
						|
          if abi2str[t]=hs then
 | 
						|
            begin
 | 
						|
              a:=t;
 | 
						|
              result:=true;
 | 
						|
              break;
 | 
						|
            end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function Setcputype(const s:string;var a:tcputype):boolean;
 | 
						|
      var
 | 
						|
        t  : tcputype;
 | 
						|
        hs : string;
 | 
						|
      begin
 | 
						|
        result:=false;
 | 
						|
        hs:=Upper(s);
 | 
						|
        for t:=low(tcputype) to high(tcputype) do
 | 
						|
          if cputypestr[t]=hs then
 | 
						|
            begin
 | 
						|
              a:=t;
 | 
						|
              result:=true;
 | 
						|
              break;
 | 
						|
            end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function SetFpuType(const s:string;var a:tfputype):boolean;
 | 
						|
      var
 | 
						|
        t : tfputype;
 | 
						|
      begin
 | 
						|
        result:=false;
 | 
						|
        for t:=low(tfputype) to high(tfputype) do
 | 
						|
          if fputypestr[t]=s then
 | 
						|
            begin
 | 
						|
              a:=t;
 | 
						|
              result:=true;
 | 
						|
              break;
 | 
						|
            end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{$if defined(arm) or defined(avr)}
 | 
						|
    function SetControllerType(const s:string;var a:tcontrollertype):boolean;
 | 
						|
      var
 | 
						|
        t  : tcontrollertype;
 | 
						|
        hs : string;
 | 
						|
      begin
 | 
						|
        result:=false;
 | 
						|
        hs:=Upper(s);
 | 
						|
        for t:=low(tcontrollertype) to high(tcontrollertype) do
 | 
						|
          if controllertypestr[t]=hs then
 | 
						|
            begin
 | 
						|
              a:=t;
 | 
						|
              result:=true;
 | 
						|
              break;
 | 
						|
            end;
 | 
						|
      end;
 | 
						|
{$endif defined(arm) or defined(avr)}
 | 
						|
 | 
						|
 | 
						|
    function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
 | 
						|
      var
 | 
						|
        tok  : string;
 | 
						|
        vstr : string;
 | 
						|
        l    : longint;
 | 
						|
        code : integer;
 | 
						|
        b    : talignmentinfo;
 | 
						|
      begin
 | 
						|
        UpdateAlignmentStr:=true;
 | 
						|
        uppervar(s);
 | 
						|
        fillchar(b,sizeof(b),0);
 | 
						|
        repeat
 | 
						|
          tok:=GetToken(s,'=');
 | 
						|
          if tok='' then
 | 
						|
           break;
 | 
						|
          vstr:=GetToken(s,',');
 | 
						|
          val(vstr,l,code);
 | 
						|
          if tok='PROC' then
 | 
						|
           b.procalign:=l
 | 
						|
          else if tok='JUMP' then
 | 
						|
           b.jumpalign:=l
 | 
						|
          else if tok='LOOP' then
 | 
						|
           b.loopalign:=l
 | 
						|
          else if tok='CONSTMIN' then
 | 
						|
           begin
 | 
						|
             b.constalignmin:=l;
 | 
						|
             if l>b.constalignmax then
 | 
						|
               b.constalignmax:=l;
 | 
						|
           end
 | 
						|
          else if tok='CONSTMAX' then
 | 
						|
           b.constalignmax:=l
 | 
						|
          else if tok='VARMIN' then
 | 
						|
           begin
 | 
						|
             b.varalignmin:=l;
 | 
						|
             if l>b.varalignmax then
 | 
						|
               b.varalignmax:=l;
 | 
						|
           end
 | 
						|
          else if tok='VARMAX' then
 | 
						|
           b.varalignmax:=l
 | 
						|
          else if tok='LOCALMIN' then
 | 
						|
           begin
 | 
						|
             b.localalignmin:=l;
 | 
						|
             if l>b.localalignmax then
 | 
						|
               b.localalignmax:=l;
 | 
						|
           end
 | 
						|
          else if tok='LOCALMAX' then
 | 
						|
           b.localalignmax:=l
 | 
						|
          else if tok='RECORDMIN' then
 | 
						|
           begin
 | 
						|
             b.recordalignmin:=l;
 | 
						|
             if l>b.recordalignmax then
 | 
						|
               b.recordalignmax:=l;
 | 
						|
           end
 | 
						|
          else if tok='RECORDMAX' then
 | 
						|
           b.recordalignmax:=l
 | 
						|
          else { Error }
 | 
						|
           UpdateAlignmentStr:=false;
 | 
						|
        until false;
 | 
						|
        Result:=Result and UpdateAlignment(a,b);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
 | 
						|
      var
 | 
						|
        tok   : string;
 | 
						|
        doset,
 | 
						|
        found : boolean;
 | 
						|
        opt   : toptimizerswitch;
 | 
						|
      begin
 | 
						|
        result:=true;
 | 
						|
        uppervar(s);
 | 
						|
        repeat
 | 
						|
          tok:=GetToken(s,',');
 | 
						|
          if tok='' then
 | 
						|
           break;
 | 
						|
          if Copy(tok,1,2)='NO' then
 | 
						|
            begin
 | 
						|
              delete(tok,1,2);
 | 
						|
              doset:=false;
 | 
						|
            end
 | 
						|
          else
 | 
						|
            doset:=true;
 | 
						|
          found:=false;
 | 
						|
          for opt:=low(toptimizerswitch) to high(toptimizerswitch) do
 | 
						|
            begin
 | 
						|
              if OptimizerSwitchStr[opt]=tok then
 | 
						|
                begin
 | 
						|
                  found:=true;
 | 
						|
                  break;
 | 
						|
                end;
 | 
						|
            end;
 | 
						|
          if found then
 | 
						|
            begin
 | 
						|
              if doset then
 | 
						|
                include(a,opt)
 | 
						|
              else
 | 
						|
                exclude(a,opt);
 | 
						|
            end
 | 
						|
          else
 | 
						|
            result:=false;
 | 
						|
        until false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
 | 
						|
      var
 | 
						|
        tok   : string;
 | 
						|
        doset,
 | 
						|
        found : boolean;
 | 
						|
        opt   : twpoptimizerswitch;
 | 
						|
      begin
 | 
						|
        result:=true;
 | 
						|
        uppervar(s);
 | 
						|
        repeat
 | 
						|
          tok:=GetToken(s,',');
 | 
						|
          if tok='' then
 | 
						|
           break;
 | 
						|
          if Copy(tok,1,2)='NO' then
 | 
						|
            begin
 | 
						|
              delete(tok,1,2);
 | 
						|
              doset:=false;
 | 
						|
            end
 | 
						|
          else
 | 
						|
            doset:=true;
 | 
						|
          found:=false;
 | 
						|
          if (tok = 'ALL') then
 | 
						|
            begin
 | 
						|
              for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
 | 
						|
                if doset then
 | 
						|
                  include(a,opt)
 | 
						|
                else
 | 
						|
                  exclude(a,opt);
 | 
						|
            end
 | 
						|
          else
 | 
						|
            begin
 | 
						|
              for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
 | 
						|
                begin
 | 
						|
                  if WPOptimizerSwitchStr[opt]=tok then
 | 
						|
                    begin
 | 
						|
                      found:=true;
 | 
						|
                      break;
 | 
						|
                    end;
 | 
						|
                end;
 | 
						|
              if found then
 | 
						|
                begin
 | 
						|
                  if doset then
 | 
						|
                    include(a,opt)
 | 
						|
                  else
 | 
						|
                    exclude(a,opt);
 | 
						|
                end
 | 
						|
              else
 | 
						|
                result:=false;
 | 
						|
            end;
 | 
						|
        until false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
 | 
						|
      var
 | 
						|
        tok   : string;
 | 
						|
        doset,
 | 
						|
        found : boolean;
 | 
						|
        opt   : tdebugswitch;
 | 
						|
      begin
 | 
						|
        result:=true;
 | 
						|
        uppervar(s);
 | 
						|
        repeat
 | 
						|
          tok:=GetToken(s,',');
 | 
						|
          if tok='' then
 | 
						|
           break;
 | 
						|
          if Copy(tok,1,2)='NO' then
 | 
						|
            begin
 | 
						|
              delete(tok,1,2);
 | 
						|
              doset:=false;
 | 
						|
            end
 | 
						|
          else
 | 
						|
            doset:=true;
 | 
						|
          found:=false;
 | 
						|
          for opt:=low(tdebugswitch) to high(tdebugswitch) do
 | 
						|
            begin
 | 
						|
              if DebugSwitchStr[opt]=tok then
 | 
						|
                begin
 | 
						|
                  found:=true;
 | 
						|
                  break;
 | 
						|
                end;
 | 
						|
            end;
 | 
						|
          if found then
 | 
						|
            begin
 | 
						|
              if doset then
 | 
						|
                include(a,opt)
 | 
						|
              else
 | 
						|
                exclude(a,opt);
 | 
						|
            end
 | 
						|
          else
 | 
						|
            result:=false;
 | 
						|
        until false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function IncludeFeature(const s : string) : boolean;
 | 
						|
      var
 | 
						|
        i : tfeature;
 | 
						|
      begin
 | 
						|
        result:=true;
 | 
						|
        for i:=low(tfeature) to high(tfeature) do
 | 
						|
          if s=featurestr[i] then
 | 
						|
            begin
 | 
						|
              include(features,i);
 | 
						|
              exit;
 | 
						|
            end;
 | 
						|
        result:=false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function SetMinFPConstPrec(const s: string; var a: tfloattype) : boolean;
 | 
						|
      var
 | 
						|
        value, error: longint;
 | 
						|
      begin
 | 
						|
        if (upper(s)='DEFAULT') then
 | 
						|
          begin
 | 
						|
            a:=s32real;
 | 
						|
            result:=true;
 | 
						|
            exit;
 | 
						|
          end;
 | 
						|
        result:=false;
 | 
						|
        val(s,value,error);
 | 
						|
        if (error<>0) then
 | 
						|
          exit;
 | 
						|
        case value of
 | 
						|
          32: a:=s32real;
 | 
						|
          64: a:=s64real;
 | 
						|
          { adding support for 80 bit here is tricky, since we can't really }
 | 
						|
          { check whether the target cpu+OS actually supports it            }
 | 
						|
          else
 | 
						|
            exit;
 | 
						|
        end;
 | 
						|
        result:=true;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function var_align(want_align: longint): shortint;
 | 
						|
      begin
 | 
						|
        var_align := used_align(want_align,current_settings.alignment.varalignmin,current_settings.alignment.varalignmax);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function var_align_size(siz: longint): shortint;
 | 
						|
      begin
 | 
						|
        siz := size_2_align(siz);
 | 
						|
        var_align_size := var_align(siz);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function const_align(want_align: longint): shortint;
 | 
						|
      begin
 | 
						|
        const_align := used_align(want_align,current_settings.alignment.constalignmin,current_settings.alignment.constalignmax);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function const_align_size(siz: longint): shortint;
 | 
						|
      begin
 | 
						|
        siz := size_2_align(siz);
 | 
						|
        const_align_size := const_align(siz);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{$ifdef ARM}
 | 
						|
    function is_double_hilo_swapped: boolean;{$ifdef USEINLINE}inline;{$endif}
 | 
						|
      begin
 | 
						|
        result := (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) and
 | 
						|
          not(cs_fp_emulation in current_settings.moduleswitches);
 | 
						|
{$ifdef FPC_DOUBLE_HILO_SWAPPED}
 | 
						|
        { inverse result if compiler was compiled with swapped hilo already }
 | 
						|
        result := not result;
 | 
						|
{$endif FPC_DOUBLE_HILO_SWAPPED}
 | 
						|
      end;
 | 
						|
{$endif ARM}
 | 
						|
 | 
						|
 | 
						|
    function floating_point_range_check_error : boolean;
 | 
						|
      begin
 | 
						|
        result:=cs_ieee_errors in current_settings.localswitches;
 | 
						|
      end;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                    Init
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
{$ifdef unix}
 | 
						|
  {$define need_path_search}
 | 
						|
{$endif unix}
 | 
						|
{$ifdef os2}
 | 
						|
  {$define need_path_search}
 | 
						|
{$endif os2}
 | 
						|
{$ifdef macos}
 | 
						|
  {$define need_path_search}
 | 
						|
{$endif macos}
 | 
						|
 | 
						|
   procedure get_exepath;
 | 
						|
     var
 | 
						|
       localExepath : TCmdStr;
 | 
						|
       exeName:TCmdStr;
 | 
						|
{$ifdef need_path_search}
 | 
						|
       hs1 : TPathStr;
 | 
						|
{$endif need_path_search}
 | 
						|
     begin
 | 
						|
       localexepath:=GetEnvironmentVariable('PPC_EXEC_PATH');
 | 
						|
       if localexepath='' then
 | 
						|
         begin
 | 
						|
           exeName := FixFileName(system.paramstr(0));
 | 
						|
           localexepath := ExtractFilePath(exeName);
 | 
						|
         end;
 | 
						|
{$ifdef need_path_search}
 | 
						|
       if localexepath='' then
 | 
						|
        begin
 | 
						|
          hs1 := ExtractFileName(exeName);
 | 
						|
          ChangeFileExt(hs1,source_info.exeext);
 | 
						|
{$ifdef macos}
 | 
						|
          FindFile(hs1,GetEnvironmentVariable('Commands'),false,localExepath);
 | 
						|
{$else macos}
 | 
						|
          FindFile(hs1,GetEnvironmentVariable('PATH'),false,localExepath);
 | 
						|
{$endif macos}
 | 
						|
          localExepath:=ExtractFilePath(localExepath);
 | 
						|
        end;
 | 
						|
{$endif need_path_search}
 | 
						|
       exepath:=FixPath(localExepath,false);
 | 
						|
     end;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
   procedure DoneGlobals;
 | 
						|
     begin
 | 
						|
       librarysearchpath.Free;
 | 
						|
       unitsearchpath.Free;
 | 
						|
       objectsearchpath.Free;
 | 
						|
       includesearchpath.Free;
 | 
						|
       frameworksearchpath.Free;
 | 
						|
       LinkLibraryAliases.Free;
 | 
						|
       LinkLibraryOrder.Free;
 | 
						|
     end;
 | 
						|
 | 
						|
   procedure InitGlobals;
 | 
						|
     begin
 | 
						|
        get_exepath;
 | 
						|
 | 
						|
        { reset globals }
 | 
						|
        do_build:=false;
 | 
						|
        do_release:=false;
 | 
						|
        do_make:=true;
 | 
						|
        compile_level:=0;
 | 
						|
        codegenerror:=false;
 | 
						|
        DLLsource:=false;
 | 
						|
        paratarget:=system_none;
 | 
						|
        paratargetasm:=as_none;
 | 
						|
        paratargetdbg:=dbg_none;
 | 
						|
 | 
						|
        { Output }
 | 
						|
        OutputFileName:='';
 | 
						|
        OutputPrefix:=Nil;
 | 
						|
        OutputSuffix:=Nil;
 | 
						|
 | 
						|
        OutputExeDir:='';
 | 
						|
        OutputUnitDir:='';
 | 
						|
 | 
						|
        { Utils directory }
 | 
						|
        utilsdirectory:='';
 | 
						|
        utilsprefix:='';
 | 
						|
        cshared:=false;
 | 
						|
        rlinkpath:='';
 | 
						|
        sysrootpath:='';
 | 
						|
 | 
						|
        { Search Paths }
 | 
						|
        librarysearchpath:=TSearchPathList.Create;
 | 
						|
        unitsearchpath:=TSearchPathList.Create;
 | 
						|
        includesearchpath:=TSearchPathList.Create;
 | 
						|
        objectsearchpath:=TSearchPathList.Create;
 | 
						|
        frameworksearchpath:=TSearchPathList.Create;
 | 
						|
 | 
						|
        { Def file }
 | 
						|
        usewindowapi:=false;
 | 
						|
        description:='Compiled by FPC '+version_string+' - '+target_cpu_string;
 | 
						|
        DescriptionSetExplicity:=false;
 | 
						|
        SetPEFlagsSetExplicity:=false;
 | 
						|
        ImageBaseSetExplicity:=false;
 | 
						|
        MinStackSizeSetExplicity:=false;
 | 
						|
        MaxStackSizeSetExplicity:=false;
 | 
						|
 | 
						|
        dllversion:='';
 | 
						|
        dllmajor:=1;
 | 
						|
        dllminor:=0;
 | 
						|
        dllrevision:=0;
 | 
						|
        nwscreenname := '';
 | 
						|
        nwthreadname := '';
 | 
						|
        nwcopyright  := '';
 | 
						|
        UseDeffileForExports:=false;
 | 
						|
        UseDeffileForExportsSetExplicitly:=false;
 | 
						|
        GenerateImportSection:=false;
 | 
						|
        RelocSection:=false;
 | 
						|
        RelocSectionSetExplicitly:=false;
 | 
						|
        LinkTypeSetExplicitly:=false;
 | 
						|
        { memory sizes, will be overridden by parameter or default for target
 | 
						|
          in options or init_parser }
 | 
						|
        stacksize:=0;
 | 
						|
        { not initialized yet }
 | 
						|
        jmp_buf_size:=-1;
 | 
						|
        apptype:=app_cui;
 | 
						|
 | 
						|
        { Init values }
 | 
						|
        init_settings:=default_settings;
 | 
						|
        if init_settings.optimizecputype=cpu_none then
 | 
						|
          init_settings.optimizecputype:=init_settings.cputype;
 | 
						|
 | 
						|
        LinkLibraryAliases :=TLinkStrMap.Create;
 | 
						|
        LinkLibraryOrder   :=TLinkStrMap.Create;
 | 
						|
 | 
						|
        { enable all features by default }
 | 
						|
        features:=[low(Tfeature)..high(Tfeature)];
 | 
						|
     end;
 | 
						|
 | 
						|
end.
 |