{ $Id$ Copyright (C) 1998-2000 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. **************************************************************************** } {$ifdef tp} {$E+,N+} {$endif} unit globals; interface uses {$ifdef win32} windows, {$endif} {$ifdef linux} linux, {$endif} {$ifdef Delphi} sysutils, dmisc, {$else} strings,dos, {$endif} {$ifdef TP} objects, {$endif} globtype,version,tokens,systems,cobjects; const {$ifdef linux} DirSep = '/'; {$else} {$ifdef amiga} DirSep = '/'; {$else} DirSep = '\'; {$endif} {$endif} {$ifdef Splitheap} testsplit : boolean = false; {$endif Splitheap} delphimodeswitches : tmodeswitches= [m_delphi,m_tp,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]; fpcmodeswitches : tmodeswitches= [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward, m_cvar_support,m_initfinal,m_add_pointer]; objfpcmodeswitches : tmodeswitches= [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_add_pointer]; tpmodeswitches : tmodeswitches= [m_tp7,m_tp,m_all,m_tp_procvar]; gpcmodeswitches : tmodeswitches= [m_gpc,m_all]; type TSearchPathList = object(TStringQueue) procedure AddPath(s:string;addfirst:boolean); procedure AddList(list:TSearchPathList;addfirst:boolean); function FindFile(const f : string;var b : boolean) : string; end; var { specified inputfile } inputdir : dirstr; inputfile : namestr; inputextension : extstr; { specified outputfile with -o parameter } outputfile : namestr; { specified with -FE or -FU } outputexedir : dirstr; outputunitdir : dirstr; { things specified with parameters } paralinkoptions, paradynamiclinker : string; parapreprocess : boolean; { directory where the utils can be found (options -FD) } utilsdirectory : dirstr; { some flags for global compiler switches } do_build, do_make : boolean; not_unit_proc : boolean; { path for searching units, different paths can be seperated by ; } exepath : dirstr; { Path to ppc } librarysearchpath, unitsearchpath, objectsearchpath, includesearchpath : TSearchPathList; { deffile } usewindowapi : boolean; description : string; dllversion : string; dllmajor,dllminor : word; { current position } token, { current token being parsed } idtoken : ttoken; { holds the token if the pattern is a known word } tokenpos, { last postion of the read token } aktfilepos : tfileposinfo; { current position } { type of currently parsed block } { isn't full implemented (FK) } block_type : tblock_type; in_args : boolean; { arguments must be checked especially } parsing_para_level : longint; { parameter level, used to convert proc calls to proc loads in firstcalln } { Must_be_valid : boolean; should the variable already have a value obsolete replace by set_varstate function } compile_level : word; make_ref : boolean; resolving_forward : boolean; { used to add forward reference as second ref } use_esp_stackframe : boolean; { to test for call with ESP as stack frame } inlining_procedure : boolean; { are we inlining a procedure } {$ifdef TP} use_big : boolean; {$endif} { commandline values } initdefines : tlinkedlist; initglobalswitches : tglobalswitches; initmoduleswitches : tmoduleswitches; initlocalswitches : tlocalswitches; initmodeswitches : tmodeswitches; {$IFDEF testvarsets} Initsetalloc, {0=fixed, 1 =var} {$ENDIF} initpackenum : longint; initpackrecords : tpackrecords; initoutputformat : tasm; initoptprocessor, initspecificoptprocessor : tprocessors; initasmmode : tasmmode; { current state values } aktglobalswitches : tglobalswitches; aktmoduleswitches : tmoduleswitches; aktlocalswitches : tlocalswitches; nextaktlocalswitches : tlocalswitches; localswitcheschanged : boolean; aktmodeswitches : tmodeswitches; {$IFDEF testvarsets} aktsetalloc, {$ENDIF} aktpackenum : longint; aktmaxfpuregisters: longint; aktpackrecords : tpackrecords; aktoutputformat : tasm; aktoptprocessor, aktspecificoptprocessor : tprocessors; aktasmmode : tasmmode; { Memory sizes } heapsize, maxheapsize, stacksize : longint; {$Ifdef EXTDEBUG} total_of_firstpass, firstpass_several : longint; {$ifdef FPC} EntryMemUsed : longint; {$endif FPC} { parameter switches } debugstop, only_one_pass : boolean; {$EndIf EXTDEBUG} { windows application type } apptype : tapptype; const RelocSection : boolean = true; RelocSectionSetExplicitly : boolean = false; LinkTypeSetExplicitly : boolean = false; DLLsource : boolean = false; DLLImageBase : pstring = nil; UseDeffileForExport : boolean = true; ForceDeffileForExport : 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 = false; { should we allow non static members ? } allow_only_static : boolean = false; Inside_asm_statement : boolean = false; { for error info in pp.pas } const parser_current_file : string = ''; {$ifdef debug} { if the pointer don't point to the heap then write an error } function assigned(p : pointer) : boolean; {$endif} function min(a,b : longint) : longint; function max(a,b : longint) : longint; function align(i,a:longint):longint; function align_from_size(datasize:longint;length:longint):longint; procedure Replace(var s:string;s1:string;const s2:string); procedure ReplaceCase(var s:string;const s1,s2:string); function upper(const s : string) : string; function lower(const s : string) : string; function trimspace(const s:string):string; {$ifdef FPC} function tostru(i:cardinal) : string; {$else} function tostru(i:longint) : string; {$endif} procedure uppervar(var s : string); function hexstr(val : longint;cnt : byte) : string; function tostr(i : longint) : string; function tostr_with_plus(i : longint) : string; procedure valint(S : string;var V : longint;var code : integer); function is_number(const s : string) : boolean; function ispowerof2(value : longint;var power : longint) : boolean; { enable ansistring comparison } function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint; function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar; function bstoslash(const s : string) : string; procedure abstract; function getdatestr:string; function gettimestr:string; function filetimestring( t : longint) : string; procedure DefaultReplacements(var s:string); function GetCurrentDir:string; function path_absolute(const s : string) : boolean; Function PathExists ( F : String) : Boolean; Function FileExists ( Const F : String) : Boolean; Function RemoveFile(const f:string):boolean; Function RemoveDir(d:string):boolean; Function GetFileTime ( Var F : File) : Longint; Function GetNamedFileTime ( Const F : String) : Longint; Function SplitPath(const s:string):string; Function SplitFileName(const s:string):string; Function SplitName(const s:string):string; Function SplitExtension(Const HStr:String):String; Function AddExtension(Const HStr,ext:String):String; Function ForceExtension(Const HStr,ext:String):String; Function FixPath(s:string;allowdot:boolean):string; function FixFileName(const s:string):string; procedure SplitBinCmd(const s:string;var bstr,cstr:string); procedure SynchronizeFileTime(const fn1,fn2:string); function FindFile(const f : string;path : string;var b : boolean) : string; function FindExe(bin:string;var found:boolean):string; function GetShortName(const n:string):string; Procedure Shell(const command:string); function GetEnvPChar(const envname:string):pchar; procedure FreeEnvPChar(p:pchar); procedure InitGlobals; procedure DoneGlobals; implementation uses comphook; procedure abstract; begin do_internalerror(255); end; function ngraphsearchvalue(const s1,s2 : string) : double; const n = 3; var equals,i,j : longint; hs : string; begin equals:=0; { is the string long enough ? } if min(length(s1),length(s2))-n+1<1 then begin ngraphsearchvalue:=0.0; exit; end; for i:=1 to length(s1)-n+1 do begin hs:=copy(s1,i,n); for j:=1 to length(s2)-n+1 do if hs=copy(s2,j,n) then inc(equals); end; {$ifdef fpc} ngraphsearchvalue:=equals/double(max(length(s1),length(s2))-n+1); {$else} ngraphsearchvalue:=equals/(max(length(s1),length(s2))-n+1); {$endif} end; function bstoslash(const s : string) : string; { return string s with all \ changed into / } var i : longint; begin for i:=1to length(s) do if s[i]='\' then bstoslash[i]:='/' else bstoslash[i]:=s[i]; {$ifndef TP} {$ifopt H+} setlength(bstoslash,length(s)); {$else} bstoslash[0]:=s[0]; {$endif} {$else} bstoslash[0]:=s[0]; {$endif} end; {$ifdef debug} function assigned(p : pointer) : boolean; {$ifndef FPC} {$ifndef DPMI} type ptrrec = record ofs,seg : word; end; var lp : longint; {$endif DPMI} {$endif FPC} begin {$ifdef FPC} { Assigned is used for procvar and stack stored temp records !! PM } (* if (p<>nil) {and ((pheapptr))} then do_internalerror(230); *) {$else} {$ifdef DPMI} assigned:=(p<>nil); exit; {$else DPMI} if p=nil then lp:=0 else lp:=longint(ptrrec(p).seg)*16+longint(ptrrec(p).ofs); if (lp<>0) and ((lplongint(seg(heapptr^))*16+longint(ofs(heapptr^)))) then do_internalerror(230); {$endif DPMI} {$endif FPC} assigned:=(p<>nil); end; {$endif} function min(a,b : longint) : longint; { return the minimal of a and b } begin if a>b then min:=b else min:=a; end; function max(a,b : longint) : longint; { return the maximum of a and b } begin if a2 then data_align:=4 else if length>1 then data_align:=2 else data_align:=1; {$ENDIF} {$IFDEF M68K} data_align:=2; {$ENDIF} align_from_size:=(datasize+data_align-1) and not(data_align-1); end; function align(i,a:longint):longint; { return value aligned boundary } begin align:=(i+a-1) and not(a-1); end; procedure Replace(var s:string;s1:string;const s2:string); var last, i : longint; begin s1:=upper(s1); last:=0; repeat i:=pos(s1,upper(s)); if i=last then i:=0; if (i>0) then begin Delete(s,i,length(s1)); Insert(s2,s,i); last:=i; end; until (i=0); end; procedure ReplaceCase(var s:string;const s1,s2:string); var last, i : longint; begin last:=0; repeat i:=pos(s1,s); if i=last then i:=0; if (i>0) then begin Delete(s,i,length(s1)); Insert(s2,s,i); last:=i; end; until (i=0); end; function upper(const s : string) : string; { return uppercased string of s } var i : longint; begin for i:=1 to length(s) do if s[i] in ['a'..'z'] then upper[i]:=char(byte(s[i])-32) else upper[i]:=s[i]; upper[0]:=s[0]; end; function lower(const s : string) : string; { return lowercased string of s } var i : longint; begin for i:=1 to length(s) do if s[i] in ['A'..'Z'] then lower[i]:=char(byte(s[i])+32) else lower[i]:=s[i]; lower[0]:=s[0]; end; procedure uppervar(var s : string); { uppercase string s } var i : longint; begin for i:=1 to length(s) do if s[i] in ['a'..'z'] then s[i]:=char(byte(s[i])-32); end; function hexstr(val : longint;cnt : byte) : string; const HexTbl : array[0..15] of char='0123456789ABCDEF'; var i : longint; begin hexstr[0]:=char(cnt); for i:=cnt downto 1 do begin hexstr[i]:=hextbl[val and $f]; val:=val shr 4; end; end; {$ifdef FPC} function tostru(i:cardinal):string; { return string of value i, but for cardinals } var hs : string; begin str(i,hs); tostru:=hs; end; {$else FPC} function tostru(i:longint):string; begin tostru:=tostr(i); end; {$endif FPC} function trimspace(const s:string):string; { return s with all leading and ending spaces and tabs removed } var i,j : longint; begin i:=length(s); while (i>0) and (s[i] in [#9,' ']) do dec(i); j:=1; while (j=0 } var hs : string; begin str(i,hs); if i>=0 then tostr_with_plus:='+'+hs else tostr_with_plus:=hs; end; procedure valint(S : string;var V : longint;var code : integer); { val() with support for octal, which is not supported under tp7 } {$ifndef FPC} var vs : longint; c : byte; begin if s[1]='%' then begin vs:=0; longint(v):=0; for c:=2 to length(s) do begin if s[c]='0' then vs:=vs shl 1 else if s[c]='1' then vs:=vs shl 1+1 else begin code:=c; exit; end; end; code:=0; longint(v):=vs; end else system.val(S,V,code); end; {$else not FPC} begin system.val(S,V,code); end; {$endif not FPC} function is_number(const s : string) : boolean; { is string a correct number ? } var w : integer; l : longint; begin valint(s,l,w); is_number:=(w=0); end; function ispowerof2(value : longint;var power : longint) : boolean; { return if value is a power of 2. And if correct return the power } var hl : longint; i : longint; begin hl:=1; ispowerof2:=true; for i:=0 to 31 do begin if hl=value then begin power:=i; exit; end; hl:=hl shl 1; end; ispowerof2:=false; end; { enable ansistring comparison } { 0 means equal } { 1 means p1 > p2 } { -1 means p1 < p2 } function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint; var i,j : longint; begin compareansistrings:=0; j:=min(length1,length2); i:=0; while (ip2[i] then begin compareansistrings:=1; exit; end else if p1[i]length2 then compareansistrings:=1 else if length10) and (s[1]='/') then path_absolute:=true; {$else linux} {$ifdef amiga} if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or (Pos(':',s) = length(s)) then path_absolute:=true; {$else} if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or ((length(s)>2) and (s[2]=':') and ((s[3]='\') or (s[3]='/'))) then path_absolute:=true; {$endif amiga} {$endif linux} end; {$ifndef FPC} Procedure FindClose(var Info : SearchRec); Begin End; {$endif not FPC} Function FileExists ( Const F : String) : Boolean; {$ifndef delphi} Var Info : SearchRec; {$endif} begin {$ifdef delphi} FileExists:=sysutils.FileExists(f); {$else} findfirst(F,readonly+archive+hidden,info); FileExists:=(doserror=0); findclose(Info); {$endif delphi} end; Function PathExists ( F : String) : Boolean; Var Info : SearchRec; begin if F[Length(f)] in ['/','\'] then Delete(f,length(f),1); findfirst(F,readonly+archive+hidden+directory,info); PathExists:=(doserror=0) and ((info.attr and directory)=directory); findclose(Info); end; Function RemoveFile(const f:string):boolean; var g : file; begin assign(g,f); {$I-} erase(g); {$I+} RemoveFile:=(ioresult=0); end; Function RemoveDir(d:string):boolean; begin if d[length(d)]=DirSep then Delete(d,length(d),1); {$I-} rmdir(d); {$I+} RemoveDir:=(ioresult=0); end; Function SplitPath(const s:string):string; var i : longint; begin i:=Length(s); while (i>0) and not(s[i] in ['/','\']) do dec(i); SplitPath:=Copy(s,1,i); end; Function SplitFileName(const s:string):string; var p : dirstr; n : namestr; e : extstr; begin FSplit(s,p,n,e); SplitFileName:=n+e; end; Function SplitName(const s:string):string; var i,j : longint; begin i:=Length(s); j:=Length(s); while (i>0) and not(s[i] in ['/','\']) do dec(i); while (j>0) and (s[j]<>'.') do dec(j); if j<=i then j:=255; SplitName:=Copy(s,i+1,j-(i+1)); end; Function SplitExtension(Const HStr:String):String; var j : longint; begin j:=length(Hstr); while (j>0) and (Hstr[j]<>'.') do begin if hstr[j]=DirSep then j:=0 else dec(j); end; if j=0 then j:=254; SplitExtension:=Copy(Hstr,j,255); end; Function AddExtension(Const HStr,ext:String):String; begin if (Ext<>'') and (SplitExtension(HStr)='') then AddExtension:=Hstr+Ext else AddExtension:=Hstr; end; Function ForceExtension(Const HStr,ext:String):String; var j : longint; begin j:=length(Hstr); while (j>0) and (Hstr[j]<>'.') do dec(j); if j=0 then j:=255; ForceExtension:=Copy(Hstr,1,j-1)+Ext; end; Function FixPath(s:string;allowdot:boolean):string; var i : longint; begin { Fix separator } for i:=1 to length(s) do if s[i] in ['/','\'] then s[i]:=DirSep; { Fix ending / } if (length(s)>0) and (s[length(s)]<>DirSep) and (s[length(s)]<>':') then s:=s+DirSep; { Remove ./ } if (not allowdot) and (s='.'+DirSep) then s:=''; { return } {$ifdef linux} FixPath:=s; {$else} FixPath:=Lower(s); {$endif} end; function FixFileName(const s:string):string; var i : longint; {$ifdef Linux} NoPath : boolean; {$endif Linux} begin {$ifdef Linux} NoPath:=true; {$endif Linux} for i:=length(s) downto 1 do begin case s[i] of {$ifdef Linux} '/','\' : begin FixFileName[i]:='/'; NoPath:=false; {Skip lowercasing path: 'X11'<>'x11' } end; 'A'..'Z' : if NoPath then FixFileName[i]:=char(byte(s[i])+32) else FixFileName[i]:=s[i]; {$else} '/' : FixFileName[i]:='\'; 'A'..'Z' : FixFileName[i]:=char(byte(s[i])+32); {$endif} else FixFileName[i]:=s[i]; end; end; {$ifndef TP} {$ifopt H+} SetLength(FixFileName,length(s)); {$else} FixFileName[0]:=s[0]; {$endif} {$else} FixFileName[0]:=s[0]; {$endif} end; procedure SplitBinCmd(const s:string;var bstr,cstr:string); var i : longint; begin i:=pos(' ',s); if i>0 then begin bstr:=Copy(s,1,i-1); cstr:=Copy(s,i+1,length(s)-i); end else begin bstr:=''; cstr:=''; end; end; procedure TSearchPathList.AddPath(s:string;addfirst:boolean); var j : longint; hs,hsd, CurrentDir, CurrPath : string; dir : searchrec; {$IFDEF NEWST} hp : PStringItem; {$ELSE} hp : PStringQueueItem; {$ENDIF} procedure addcurrpath; begin if addfirst then begin Delete(currPath); Insert(currPath); end else begin { Check if already in path, then we don't add it } hp:=Find(currPath); if not assigned(hp) then Concat(currPath); end; end; begin if s='' then exit; { Support default macro's } DefaultReplacements(s); { get current dir } CurrentDir:=GetCurrentDir; repeat { get currpath } if addfirst then begin j:=length(s); while (j>0) and (s[j]<>';') do dec(j); CurrPath:=FixPath(Copy(s,j+1,length(s)-j),false); if j=0 then s:='' else System.Delete(s,j,length(s)-j+1); end else begin j:=Pos(';',s); if j=0 then j:=255; CurrPath:=FixPath(Copy(s,1,j-1),false); System.Delete(s,1,j); end; { fix pathname } if CurrPath='' then CurrPath:='.'+DirSep else begin CurrPath:=FixPath(FExpand(CurrPath),false); if (CurrentDir<>'') and (Copy(CurrPath,1,length(CurrentDir))=CurrentDir) then CurrPath:='.'+DirSep+Copy(CurrPath,length(CurrentDir)+1,255); end; { wildcard adding ? } if pos('*',currpath)>0 then begin if currpath[length(currpath)]=dirsep then hs:=Copy(currpath,1,length(CurrPath)-1) else hs:=currpath; hsd:=SplitPath(hs); findfirst(hs,directory,dir); while doserror=0 do begin if (dir.name<>'.') and (dir.name<>'..') and ((dir.attr and directory)<>0) then begin currpath:=hsd+dir.name+dirsep; hp:=Find(currPath); if not assigned(hp) then AddCurrPath; end; findnext(dir); end; FindClose(dir); end else begin if PathExists(currpath) then addcurrpath; end; until (s=''); end; procedure TSearchPathList.AddList(list:TSearchPathList;addfirst:boolean); var s : string; hl : TSearchPathList; {$IFDEF NEWST} hp,hp2 : PStringItem; {$ELSE} hp,hp2 : PStringQueueItem; {$ENDIF} begin if list.empty then exit; { create temp and reverse the list } if addfirst then begin hl.Init; hp:=list.first; while assigned(hp) do begin hl.insert(hp^.data^); hp:=hp^.next; end; while not hl.empty do begin s:=hl.Get; Delete(s); Insert(s); end; hl.done; end else begin hp:=list.first; while assigned(hp) do begin hp2:=Find(hp^.data^); { Check if already in path, then we don't add it } if not assigned(hp2) then Concat(hp^.data^); hp:=hp^.next; end; end; end; function TSearchPathList.FindFile(const f : string;var b : boolean) : string; Var {$IFDEF NEWST} p : PStringItem; {$ELSE} p : PStringQueueItem; {$ENDIF} begin FindFile:=''; b:=false; p:=first; while assigned(p) do begin If FileExists(p^.data^+f) then begin FindFile:=p^.data^; b:=true; exit; end; p:=p^.next; end; end; Function GetFileTime ( Var F : File) : Longint; Var {$ifdef linux} Info : Stat; {$endif} L : longint; begin {$ifdef linux} FStat (F,Info); L:=Info.Mtime; {$else} GetFTime(f,l); {$endif} GetFileTime:=L; end; Function GetNamedFileTime (Const F : String) : Longint; var L : Longint; {$ifndef linux} info : SearchRec; {$else} info : stat; {$endif} begin l:=-1; {$ifdef linux} if FStat (F,Info) then L:=info.mtime; {$else} {$ifdef delphi} dmisc.FindFirst (F,archive+readonly+hidden,info); {$else delphi} FindFirst (F,archive+readonly+hidden,info); {$endif delphi} if DosError=0 then l:=info.time; {$ifdef Linux} FindClose(info); {$endif} {$ifdef Win32} FindClose(info); {$endif} {$endif} GetNamedFileTime:=l; end; {Touch Assembler and object time to ppu time is there is a ppufilename} procedure SynchronizeFileTime(const fn1,fn2:string); var f : file; l : longint; begin Assign(f,fn1); {$I-} reset(f,1); {$I+} if ioresult=0 then begin getftime(f,l); { just to be sure in case there are rounding errors } setftime(f,l); close(f); assign(f,fn2); {$I-} reset(f,1); {$I+} if ioresult=0 then begin setftime(f,l); close(f); end; end; end; function FindFile(const f : string;path : string;var b : boolean) : string; Var singlepathstring : string; i : longint; begin {$ifdef linux} for i:=1 to length(path) do if path[i]=':' then path[i]:=';'; {$endif} b:=false; FindFile:=''; repeat i:=pos(';',path); if i=0 then i:=256; singlepathstring:=FixPath(copy(path,1,i-1),false); delete(path,1,i); If FileExists (singlepathstring+f) then begin FindFile:=singlepathstring; b:=true; exit; end; until path=''; end; function FindExe(bin:string;var found:boolean):string; begin bin:=FixFileName(bin)+source_os.exeext; {$ifdef delphi} FindExe:=FindFile(bin,'.;'+exepath+';'+dmisc.getenv('PATH'),found)+bin; {$else delphi} FindExe:=FindFile(bin,'.;'+exepath+';'+dos.getenv('PATH'),found)+bin; {$endif delphi} end; function GetShortName(const n:string):string; {$ifdef win32} var hs,hs2 : string; i : longint; {$endif} {$ifdef go32v2} var hs : string; {$endif} begin GetShortName:=n; {$ifdef win32} hs:=n+#0; i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2)); if (i>0) and (i<=high(hs2)) then begin hs2[0]:=chr(strlen(@hs2[1])); GetShortName:=hs2; end; {$endif} {$ifdef go32v2} hs:=n; if Dos.GetShortName(hs) then GetShortName:=hs; {$endif} 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 linux} GetEnvPchar:=Linux.Getenv(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 GETENVOK} {$undef GETENVOK} {$else} GetEnvPchar:=StrPNew(Dos.Getenv(envname)); {$endif} end; procedure FreeEnvPChar(p:pchar); begin {$ifndef linux} StrDispose(p); {$endif} end; Procedure Shell(const command:string); { This is already defined in the linux.ppu for linux, need for the * expansion under linux } {$ifdef linux} begin Linux.Shell(command); end; {$else} var comspec : string; begin comspec:=getenv('COMSPEC'); Exec(comspec,' /C '+command); end; {$endif} {**************************************************************************** Init ****************************************************************************} procedure get_exepath; var hs1 : namestr; hs2 : extstr; begin {$ifdef delphi} exepath:=dmisc.getenv('PPC_EXEC_PATH'); {$else delphi} exepath:=dos.getenv('PPC_EXEC_PATH'); {$endif delphi} if exepath='' then fsplit(FixFileName(paramstr(0)),exepath,hs1,hs2); {$ifndef VER0_99_15} {$ifdef linux} if exepath='' then fsearch(hs1,dos.getenv('PATH')); {$endif} {$endif} exepath:=FixPath(exepath,false); end; procedure DoneGlobals; begin initdefines.done; if assigned(DLLImageBase) then StringDispose(DLLImageBase); RelocSection:=true; RelocSectionSetExplicitly:=false; DLLsource:=false; UseDeffileForExport:=true; librarysearchpath.Done; unitsearchpath.Done; objectsearchpath.Done; includesearchpath.Done; end; procedure InitGlobals; begin { set global switches } do_build:=false; do_make:=true; {$ifdef tp} use_big:=false; {$endif tp} compile_level:=0; { Output } OutputFile:=''; OutputExeDir:=''; OutputUnitDir:=''; { Utils directory } utilsdirectory:=''; { Search Paths } librarysearchpath.Init; unitsearchpath.Init; includesearchpath.Init; objectsearchpath.Init; { Def file } usewindowapi:=false; description:='Compiled by FPC '+version_string+' - '+target_cpu_string; dllversion:=''; { Init values } initmodeswitches:=fpcmodeswitches; initlocalswitches:=[cs_check_io]; initmoduleswitches:=[cs_extsyntax,cs_browser]; initglobalswitches:=[cs_check_unit_name,cs_link_static]; {$ifdef i386} initoptprocessor:=Class386; initspecificoptprocessor:=Class386; initpackenum:=4; {$IFDEF testvarsets} initsetalloc:=0; {$ENDIF} initpackrecords:=packrecord_2; initoutputformat:=target_asm.id; initasmmode:=asmmode_i386_att; {$else not i386} {$ifdef m68k} initoptprocessor:=MC68000; include(initmoduleswitches,cs_fp_emulation); initpackenum:=4; {$IFDEF testvarsets} initsetalloc:=0; {$ENDIF} initpackrecords:=packrecord_2; initoutputformat:=as_m68k_as; initasmmode:=asmmode_m68k_mot; {$endif m68k} {$endif i386} initdefines.init; { memory sizes, will be overriden by parameter or default for target in options or init_parser } stacksize:=0; heapsize:=0; maxheapsize:=0; { compile state } in_args:=false; { must_be_valid:=true; obsolete PM } not_unit_proc:=true; apptype:=at_cui; end; begin get_exepath; {$ifdef EXTDEBUG} {$ifdef FPC} EntryMemUsed:=system.HeapSize-MemAvail; {$endif FPC} {$endif} end. { $Log$ Revision 1.67 2000-06-19 19:57:19 pierre * smart link is default on win32 Revision 1.66 2000/06/18 18:05:54 peter * no binary value reading with % if not fpc mode * extended illegal char message with the char itself (Delphi like) Revision 1.65 2000/06/15 18:10:11 peter * first look for ppu in cwd and outputpath and after that for source in cwd * fixpath() for not linux makes path now lowercase so comparing paths with different cases (sometimes a drive letter could be uppercased) gives the expected results * sources_checked flag if there was already a full search for sources which aren't found, so another scan isn't done when checking for the sources only when recompile is needed Revision 1.64 2000/06/11 07:00:21 peter * fixed pchar->string conversion for delphi mode Revision 1.63 2000/05/12 08:58:51 pierre * adapted to Delphi 3 Revision 1.62 2000/05/12 05:55:04 pierre * * get it to compile with Delphi by Kovacs Attila Zoltan Revision 1.61 2000/05/11 09:37:25 pierre * do not use upcase for strings, reported by Kovacs Attila Zoltan Revision 1.60 2000/05/04 20:46:17 peter * ansistrings are now default on for delphi mode, as most ppl expect this Revision 1.59 2000/05/03 14:36:57 pierre * fix for tests/test/testrang.pp bug Revision 1.58 2000/04/14 12:27:57 pierre * setfiletime to both files in synchronize Revision 1.57 2000/03/23 15:35:47 peter * $VERSION is now version_string + $FULLVERSION is now full_version_string Revision 1.56 2000/03/20 16:04:05 pierre * probably a fix for bug 615 Revision 1.55 2000/03/08 15:39:45 daniel + Added align_from_size function as suggested by Peter. Revision 1.54 2000/02/28 17:23:57 daniel * Current work of symtable integration committed. The symtable can be activated by defining 'newst', but doesn't compile yet. Changes in type checking and oop are completed. What is left is to write a new symtablestack and adapt the parser to use it. Revision 1.53 2000/02/14 20:58:44 marco * Basic structures for new sethandling implemented. Revision 1.52 2000/02/10 11:45:48 peter * addpath fixed with list of paths when inserting at the beginning * if exepath=currentdir then it's not inserted in path list * searchpaths in ppc386.cfg are now added at the beginning of the list instead of at the end. (commandline is not changed) * check paths before inserting in list Revision 1.51 2000/02/09 13:22:53 peter * log truncated Revision 1.50 2000/01/26 14:31:03 marco * $VERSION is now also substituted in -F paths (that have subst active) Revision 1.49 2000/01/23 21:29:14 florian * CMOV support in optimizer (in define USECMOV) + start of support of exceptions in constructors Revision 1.48 2000/01/23 16:36:37 peter * better auto RTL dir detection Revision 1.47 2000/01/20 00:23:03 pierre * fix for GetShortName, now checks results from Win32 Revision 1.46 2000/01/07 01:14:27 peter * updated copyright to 2000 Revision 1.45 2000/01/07 00:08:09 peter * tp7 fix Revision 1.44 2000/01/06 15:48:59 peter * wildcard support for directory adding, this allows the use of units/* in ppc386.cfg Revision 1.43 2000/01/04 15:15:50 florian + added compiler switch $maxfpuregisters + fixed a small problem in secondvecn Revision 1.42 1999/12/22 01:01:48 peter - removed freelabel() * added undefined label detection in internal assembler, this prevents a lot of ld crashes and wrong .o files * .o files aren't written anymore if errors have occured * inlining of assembler labels is now correct Revision 1.41 1999/12/20 23:23:28 pierre + $description $version Revision 1.40 1999/12/20 21:42:34 pierre + dllversion global variable * FPC_USE_CPREFIX code removed, not necessary anymore as we use .edata direct writing by default now. Revision 1.39 1999/12/08 10:40:00 pierre + allow use of unit var in exports of DLL for win32 by using direct export writing by default instead of use of DEFFILE that does not allow assembler labels that do not start with an underscore. Use -WD to force use of Deffile for Win32 DLL Revision 1.38 1999/12/06 18:21:03 peter * support !ENVVAR for long commandlines * win32/go32v2 write short pathnames to link.res so c:\Program Files\ is finally supported as installdir. Revision 1.37 1999/12/02 17:34:34 peter * preprocessor support. But it fails on the caret in type blocks Revision 1.36 1999/11/18 15:34:45 pierre * Notes/Hints for local syms changed to Set_varstate function Revision 1.35 1999/11/17 17:04:59 pierre * Notes/hints changes Revision 1.34 1999/11/15 17:42:41 pierre * -g disables reloc section for win32 Revision 1.33 1999/11/12 11:03:50 peter * searchpaths changed to stringqueue object Revision 1.32 1999/11/09 23:34:46 pierre + resolving_forward boolean used for references Revision 1.31 1999/11/09 13:00:38 peter * define FPC_DELPHI,FPC_OBJFPC,FPC_TP,FPC_GPC * initial support for ansistring default with modes }