3 Copyright (c) 1998-2000 by Florian Klaempfl
5 This unit implements an extended file management and the first loading
6 and searching of the modules (ppufiles)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 ****************************************************************************
31 {$define SHORTASMPREFIX}
34 {$define SHORTASMPREFIX}
37 {$define SHORTASMPREFIX}
40 { Allthough OS/2 supports long filenames I play it safe and
41 use 8.3 filenames, because this allows the compiler to run
42 on a FAT partition. (DM) }
43 {$define SHORTASMPREFIX}
50 globtype
,cobjects
,globals
,ppu
51 {$IFDEF NEWST},objects
{$ENDIF};
56 InputFileBufSize
=32*1024;
60 InputFileBufSize
=1024;
65 trecompile_reason
= (rr_unknown
,rr_noppu
,rr_sourcenewer
,
66 rr_build
,rr_libolder
,rr_objolder
,rr_asmolder
,rr_crcchanged
);
68 tlongintarr
= array[0..1000000] of longint;
70 tlongintarr
= array[0..16000] of longint;
72 plongintarr
= ^tlongintarr
;
74 pinputfile
= ^tinputfile
;
76 path
,name
: pstring
; { path and filename }
77 next
: pinputfile
; { next file for reading }
80 endoffile
, { still bytes left to read }
81 closed
: boolean; { is the file closed }
83 buf
: pchar
; { buffer }
84 bufstart
, { buffer start position in the file }
85 bufsize
, { amount of bytes in the buffer }
86 maxbufsize
: longint; { size in memory for the buffer }
88 saveinputpointer
: pchar
; { save fields for scanner variables }
90 saveline_no
: longint;
92 linebuf
: plongintarr
; { line buffer to retrieve lines }
95 ref_count
: longint; { to handle the browser refs }
97 ref_next
: pinputfile
;
99 constructor init(const fn
:string);
101 procedure setpos(l
:longint);
102 procedure seekbuf(fpos
:longint);
104 function open
:boolean;
107 function tempopen
:boolean;
108 procedure setmacro(p
:pchar
;len
:longint);
109 procedure setline(line
,linepos
:longint);
110 function getlinestr(l
:longint):string;
111 {$ifdef FPC}protected{$else}public{$endif}
112 function fileopen(const filename
: string): boolean; virtual;
113 function fileseek(pos
: longint): boolean; virtual;
114 function fileread(var databuf
; maxsize
: longint): longint; virtual;
115 function fileeof
: boolean; virtual;
116 function fileclose
: boolean; virtual;
119 pdosinputfile
= ^tdosinputfile
;
120 tdosinputfile
= object(tinputfile
)
121 {$ifdef FPC}protected{$else}public{$endif}
122 function fileopen(const filename
: string): boolean; virtual;
123 function fileseek(pos
: longint): boolean; virtual;
124 function fileread(var databuf
; maxsize
: longint): longint; virtual;
125 function fileeof
: boolean; virtual;
126 function fileclose
: boolean; virtual;
128 f
: file; { current file handle }
131 pfilemanager
= ^tfilemanager
;
132 tfilemanager
= object
134 last_ref_index
: longint;
135 cacheindex
: longint;
136 cacheinputfile
: pinputfile
;
139 procedure register_file(f
: pinputfile
);
140 procedure inverse_register_indexes
;
141 function get_file(l
:longint) : pinputfile
;
142 function get_file_name(l
:longint):string;
143 function get_file_path(l
:longint):string;
147 Plinkitem
=^Tlinkitem
;
148 Tlinkitem
=object(Tobject
)
151 constructor init(const s
:string;m
:longint);
152 destructor done
;virtual;
155 plinkcontaineritem
=^tlinkcontaineritem
;
156 tlinkcontaineritem
=object(tcontaineritem
)
159 constructor init(const s
:string;m
:longint);
160 destructor done
;virtual;
163 plinkcontainer
=^tlinkcontainer
;
164 tlinkcontainer
=object(tcontainer
)
166 procedure insert(const s
: string;m
:longint);
167 function get(var m
:longint) : string;
168 function getusemask(mask
:longint) : string;
169 function find(const s
:string):boolean;
174 tunitmap
= array[0..maxunits
-1] of pointer;
175 punitmap
= ^tunitmap
;
182 tunitmap
= array[0..maxunits
-1] of pmodule
;
183 punitmap
= ^tunitmap
;
186 tmodule
= object(tlinkedlist_item
)
187 ppufile
: pppufile
; { the PPU file }
190 flags
: longint; { the PPU flags }
192 compiled
, { unit is already compiled }
193 do_reload
, { force reloading of the unit }
194 do_assemble
, { only assemble the object, don't recompile }
195 do_compile
, { need to compile the sources }
196 sources_avail
, { if all sources are reachable }
197 sources_checked
, { if there is already done a check for the sources }
199 in_compile
, { is it being compiled ?? }
200 in_second_compile
, { is this unit being compiled for the 2nd time? }
201 in_second_load
, { is this unit PPU loaded a 2nd time? }
202 in_implementation
, { processing the implementation part? }
203 in_global
: boolean; { allow global settings }
204 recompile_reason
: trecompile_reason
; { the reason why the unit should be recompiled }
206 islibrary
: boolean; { if it is a library (win32 dll) }
207 map
: punitmap
; { mapping of all used units }
208 unitcount
: word; { local unit counter }
209 unit_index
: word; { global counter for browser }
210 globalsymtable
, { pointer to the local/static symtable of this unit }
211 localsymtable
: pointer; { pointer to the psymtable of this unit }
212 scanner
: pointer; { scanner object used }
213 loaded_from
: pmodule
;
214 uses_imports
: boolean; { Set if the module imports from DLL's.}
215 imports
: plinkedlist
;
216 _exports
: plinkedlist
;
218 sourcefiles
: pfilemanager
;
219 resourcefiles
: tstringcontainer
;
225 linkotherofiles
, { objects,libs loaded from the source }
226 linkothersharedlibs
, { using $L or $LINKLIB or import lib (for linux) }
227 linkotherstaticlibs
: Tcollection
;
232 linkotherofiles
, { objects,libs loaded from the source }
233 linkothersharedlibs
, { using $L or $LINKLIB or import lib (for linux) }
234 linkotherstaticlibs
: tlinkcontainer
;
237 used_units
: tlinkedlist
;
238 dependent_units
: tlinkedlist
;
240 localunitsearchpath
, { local searchpaths }
241 localobjectsearchpath
,
242 localincludesearchpath
,
243 locallibrarysearchpath
: TSearchPathList
;
245 path
, { path where the module is find/created }
246 outputpath
, { path where the .s / .o / exe are created }
247 modulename
, { name of the module in uppercase }
248 objfilename
, { fullname of the objectfile }
249 asmfilename
, { fullname of the assemblerfile }
250 ppufilename
, { fullname of the ppufile }
251 staticlibfilename
, { fullname of the static libraryfile }
252 sharedlibfilename
, { fullname of the shared libraryfile }
253 exefilename
, { fullname of the exefile }
254 asmprefix
, { prefix for the smartlink asmfiles }
255 mainsource
: pstring
; { name of the main sourcefile }
256 {$ifdef Test_Double_checksum}
259 crc_array2
: pointer
;
261 {$endif def Test_Double_checksum}
262 constructor init
(const
s:string
;_is_unit:boolean);
263 destructor done
;virtual;
265 procedure setfilename
(const
fn:string
;allowoutput:boolean);
266 function
openppu:boolean
;
267 function search_unit
(const n
: string
;onlysource:boolean):boolean;
270 pused_unit
= ^tused_unit
;
271 tused_unit
= object(tlinkedlist_item
)
275 interface_checksum
: longint;
279 is_stab_written
: boolean;
281 constructor init(_u
: pmodule
;intface
:boolean);
282 constructor init_to_load(const n
:string;c
,intfc
:longint;intface
:boolean);
283 destructor done
;virtual;
286 pdependent_unit
= ^tdependent_unit
;
287 tdependent_unit
= object(tlinkedlist_item
)
289 constructor init(_u
: pmodule
);
293 main_module
: pmodule
; { Main module of the program }
294 current_module
: pmodule
; { Current module which is compiled or loaded }
295 compiled_module
: pmodule
; { Current module which is compiled }
296 current_ppu
: pppufile
; { Current ppufile which is read }
297 global_unit_count
: word;
298 usedunits
: tlinkedlist
; { Used units for this program }
299 loaded_units
: tlinkedlist
; { All loaded units }
300 SmartLinkOFiles
: TStringContainer
; { List of .o files which are generated,
301 used to delete them after linking }
303 function get_source_file(moduleindex
,fileindex
: word) : pinputfile
;
315 symtable
,scanner
{$IFDEF NEWST},symtablt
{$ENDIF};
317 {****************************************************************************
319 ****************************************************************************}
321 constructor tinputfile
.init(const fn
:string);
328 name
:=stringdup(n
+e
);
338 maxbufsize
:=InputFileBufSize
;
340 saveinputpointer
:=nil;
353 destructor tinputfile
.done
;
360 if assigned(linebuf
) then
361 freemem(linebuf
,maxlinebuf
shl 2);
365 procedure tinputfile
.setpos(l
:longint);
371 procedure tinputfile
.seekbuf(fpos
:longint);
381 procedure tinputfile
.readbuf
;
387 inc(bufstart
,bufsize
);
388 bufsize
:=fileread(buf
^,maxbufsize
-1);
394 function tinputfile
.open
:boolean;
399 if not fileopen(path
^+name
^) then
404 Getmem(buf
,MaxBufsize
);
411 procedure tinputfile
.close
;
415 if assigned(buf
) then
416 Freemem(buf
,maxbufsize
);
419 still needed for dispose in scanner PM }
428 if assigned(buf
) then
430 Freemem(buf
,maxbufsize
);
437 procedure tinputfile
.tempclose
;
444 Freemem(buf
,maxbufsize
);
450 function tinputfile
.tempopen
:boolean;
455 { seek buffer postion to bufstart }
458 move(buf
[bufstart
],buf
[0],bufsize
-bufstart
+1);
466 if not fileopen(path
^+name
^) then
470 Getmem(buf
,maxbufsize
);
479 procedure tinputfile
.setmacro(p
:pchar
;len
:longint);
481 { create new buffer }
495 procedure tinputfile
.setline(line
,linepos
:longint);
497 oldlinebuf
: plongintarr
;
501 while (line
>=maxlinebuf
) do
504 { create new linebuf and move old info }
505 getmem(linebuf
,(maxlinebuf
+linebufincrease
) shl 2);
506 if assigned(oldlinebuf
) then
508 move(oldlinebuf
^,linebuf
^,maxlinebuf
shl 2);
509 freemem(oldlinebuf
,maxlinebuf
shl 2);
511 fillchar(linebuf
^[maxlinebuf
],linebufincrease
shl 2,0);
512 inc(maxlinebuf
,linebufincrease
);
514 linebuf
^[line
]:=linepos
;
518 function tinputfile
.getlinestr(l
:longint):string;
529 { fpos is set negativ if the line was already written }
530 { but we still know the correct value }
536 if (fpos
<bufstart
) or (fpos
>bufstart
+bufsize
) then
541 { the begin is in the buf now simply read until #13,#10 }
543 p
:=@buf
[fpos
-bufstart
];
554 if c
in [#10,#13] then
562 setlength(getlinestr
,i
);
564 getlinestr
[0]:=chr(i
);
567 getlinestr
[0]:=chr(i
);
573 function tinputfile
.fileopen(const filename
: string): boolean;
580 function tinputfile
.fileseek(pos
: longint): boolean;
587 function tinputfile
.fileread(var databuf
; maxsize
: longint): longint;
594 function tinputfile
.fileeof
: boolean;
601 function tinputfile
.fileclose
: boolean;
608 {****************************************************************************
610 ****************************************************************************}
612 function tdosinputfile
.fileopen(const filename
: string): boolean;
623 fileopen
:=(ioresult
=0);
627 function tdosinputfile
.fileseek(pos
: longint): boolean;
632 fileseek
:=(ioresult
=0);
636 function tdosinputfile
.fileread(var databuf
; maxsize
: longint): longint;
637 var w
: {$ifdef TP}word{$else}longint{$endif};
639 blockread(f
,databuf
,maxsize
,w
);
644 function tdosinputfile
.fileeof
: boolean;
650 function tdosinputfile
.fileclose
: boolean;
655 fileclose
:=(ioresult
=0);
659 {****************************************************************************
661 ****************************************************************************}
663 constructor tfilemanager
.init
;
672 destructor tfilemanager
.done
;
677 while assigned(hp
) do
679 files
:=files
^.ref_next
;
687 procedure tfilemanager
.register_file(f
: pinputfile
);
689 { don't register macro's }
694 f
^.ref_index
:=last_ref_index
;
697 cacheindex
:=last_ref_index
;
701 writeln(stderr
,f
^.name
^,' index ',current_module
^.unit_index
*100000+f
^.ref_index
);
707 { this procedure is necessary after loading the
708 sources files from a PPU file PM }
709 procedure tfilemanager
.inverse_register_indexes
;
716 f
^.ref_index
:=last_ref_index
-f
^.ref_index
+1;
726 function tfilemanager
.get_file(l
:longint) : pinputfile
;
731 if (l
=cacheindex
) and assigned(cacheinputfile
) then
733 get_file
:=cacheinputfile
;
737 while assigned(ff
) and (ff
^.ref_index
<>l
) do
743 function tfilemanager
.get_file_name(l
:longint):string;
749 get_file_name
:=hp
^.name
^
755 function tfilemanager
.get_file_path(l
:longint):string;
761 get_file_path
:=hp
^.path
^
767 function get_source_file(moduleindex
,fileindex
: word) : pinputfile
;
772 hp
:=pmodule(loaded_units
.first
);
773 while assigned(hp
) and (hp
^.unit_index
<>moduleindex
) do
774 hp
:=pmodule(hp
^.next
);
775 get_source_file
:=nil;
776 if not assigned(hp
) then
778 f
:=pinputfile(hp
^.sourcefiles
^.files
);
781 if f
^.ref_index
=fileindex
then
786 f
:=pinputfile(f
^.ref_next
);
791 {****************************************************************************
793 ****************************************************************************}
796 constructor TLinkItem
.Init(const s
:string;m
:longint);
804 destructor TLinkItem
.Done
;
809 constructor TLinkContainerItem
.Init(const s
:string;m
:longint);
817 destructor TLinkContainerItem
.Done
;
824 {****************************************************************************
826 ****************************************************************************}
829 constructor TLinkContainer
.Init
;
835 procedure TLinkContainer
.insert(const s
: string;m
:longint);
837 newnode
: plinkcontaineritem
;
841 new(newnode
,init(s
,m
));
842 inherited insert(newnode
);
846 function TLinkContainer
.get(var m
:longint) : string;
848 p
: plinkcontaineritem
;
850 p
:=plinkcontaineritem(inherited get
);
863 function TLinkContainer
.getusemask(mask
:longint) : string;
865 p
: plinkcontaineritem
;
870 p
:=plinkcontaineritem(inherited get
);
876 getusemask
:=p
^.data
^;
877 found
:=(p
^.needlink
and mask
)<>0;
883 function TLinkContainer
.find(const s
:string):boolean;
885 newnode
: plinkcontaineritem
;
888 newnode
:=plinkcontaineritem(root
);
889 while assigned(newnode
) do
891 if newnode
^.data
^=s
then
896 newnode
:=plinkcontaineritem(newnode
^.next
);
903 {****************************************************************************
905 ****************************************************************************}
907 procedure tmodule
.setfilename(const fn
:string;allowoutput
:boolean);
913 stringdispose(objfilename
);
914 stringdispose(asmfilename
);
915 stringdispose
(ppufilename
);
916 stringdispose
(staticlibfilename
);
917 stringdispose
(sharedlibfilename
);
918 stringdispose
(exefilename
);
919 stringdispose
(outputpath
);
925 path:=stringdup
(FixPath
(p
,false
));
926 { obj,asm,ppu names }
930 if
(OutputUnitDir
<>'') then
933 if
(OutputExeDir
<>'') then
936 outputpath
:=stringdup(p
);
937 objfilename
:=stringdup(p
+n
+target_info
.objext
);
938 asmfilename
:=stringdup
(p
+n
+target_info.asmext
);
939 ppufilename:=stringdup
(p
+n
+target_info.unitext
);
940 { lib and exe could be loaded with a file specified with -o }
941 if AllowOutput
and (OutputFile
<>'') and (compile_level
=1) then
943 staticlibfilename:=stringdup
(p
+target_os.libprefix
+n
+target_os.staticlibext
);
944 if target_info.target
=target_i386_WIN32 then
945 sharedlibfilename:=stringdup
(p
+n
+target_os.sharedlibext
)
947 sharedlibfilename:=stringdup
(p
+target_os.libprefix
+n
+target_os.sharedlibext
);
948 { output dir of exe can be specified separatly }
949 if AllowOutput
and (OutputExeDir
<>'') then
953 exefilename:=stringdup
(p
+n
+target_info.exeext
);
957 function tmodule
.openppu
:boolean;
961 asmfiletime
: longint
;
964 Message1
(unit_t_ppu_loading
,ppufilename^
);
965 { Get ppufile time (also check if the file exists) }
966 ppufiletime:=getnamedfiletime
(ppufilename^
);
967 if ppufiletime
=-1 then
970 Message1
(unit_u_ppu_name
,ppufilename^
);
971 ppufile:=new
(pppufile
,init
(ppufilename^
));
972 ppufile^.
change_endian:=source_os.endian
<>target_os.endian
;
973 if
not ppufile^.open then
975 dispose
(ppufile
,done
);
977 Message
(unit_u_ppu_file_too_short
);
980 { check for a valid PPU file }
981 if not ppufile
^.CheckPPUId
then
983 dispose(ppufile
,done
);
985 Message(unit_u_ppu_invalid_header
);
988 { check for allowed PPU versions }
989 if not (ppufile
^.GetPPUVersion
= CurrentPPUVersion
) then
991 Message1(unit_u_ppu_invalid_version
,tostr(ppufile
^.GetPPUVersion
));
992 dispose(ppufile
,done
);
996 { check the target processor }
997 if ttargetcpu(ppufile
^.header
.cpu
)<>target_cpu
then
999 Message(unit_u_ppu_invalid_processor
);
1000 dispose(ppufile
,done
);
1005 if ttarget(ppufile
^.header
.target
)<>target_info
.target
then
1007 Message(unit_u_ppu_invalid_target
);
1008 dispose(ppufile
,done
);
1012 { Load values to be access easier }
1013 flags
:=ppufile
^.header
.flags
;
1014 crc
:=ppufile
^.header
.checksum
;
1015 interface_crc
:=ppufile
^.header
.interface_checksum
;
1017 Message1(unit_u_ppu_time
,filetimestring(ppufiletime
));
1018 Message1(unit_u_ppu_flags
,tostr(flags
));
1019 Message1(unit_u_ppu_crc
,tostr(ppufile
^.header
.checksum
));
1020 Message1(unit_u_ppu_crc
,tostr(ppufile
^.header
.interface_checksum
)+' (intfc)');
1021 { check the object and assembler file to see if we need only to
1022 assemble, only if it's not in a library }
1024 if (flags
and uf_in_library
)=0 then
1026 if (flags
and uf_smart_linked
)<>0 then
1028 objfiletime
:=getnamedfiletime(staticlibfilename
^);
1029 Message2(unit_u_check_time
,staticlibfilename
^,filetimestring(objfiletime
));
1030 if (ppufiletime
<0) or (objfiletime
<0) or (ppufiletime
>objfiletime
) then
1032 recompile_reason
:=rr_libolder
;
1033 Message(unit_u_recompile_staticlib_is_older
);
1035 dispose(ppufile
,done
);
1040 if (flags
and uf_static_linked
)<>0 then
1042 { the objectfile should be newer than the ppu file }
1043 objfiletime
:=getnamedfiletime(objfilename
^);
1044 Message2(unit_u_check_time
,objfilename
^,filetimestring(objfiletime
));
1045 if (ppufiletime
<0) or (objfiletime
<0) or (ppufiletime
>objfiletime
) then
1047 { check if assembler file is older than ppu file }
1048 asmfileTime
:=GetNamedFileTime
(asmfilename^
);
1049 Message2
(unit_u_check_time
,asmfilename^
,filetimestring
(asmfiletime
));
1050 if
(asmfiletime
<0) or (ppufiletime
>asmfiletime
) then
1052 Message
(unit_u_recompile_obj_and_asm_older
);
1053 recompile_reason:=rr_objolder
;
1055 dispose
(ppufile
,done
);
1061 Message
(unit_u_recompile_obj_older_than_asm
);
1062 if
not(cs_asm_extern
in aktglobalswitches
) then
1065 recompile_reason:=rr_asmolder
;
1066 dispose
(ppufile
,done
);
1078 function tmodule
.search_unit(const n
: string;onlysource
:boolean):boolean;
1083 Function UnitExists(const ext
:string):boolean;
1085 Message1(unit_t_unitsearch
,Singlepathstring
+filename
+ext
);
1086 UnitExists
:=FileExists(Singlepathstring
+FileName
+ext
);
1089 Function PPUSearchPath(const s
:string):boolean;
1094 singlepathstring
:=FixPath(s
,false);
1095 { Check for PPU file }
1096 Found
:=UnitExists(target_info
.unitext
);
1099 SetFileName(SinglePathString
+FileName
,false);
1102 PPUSearchPath
:=Found
;
1105 Function SourceSearchPath(const s
:string):boolean;
1111 singlepathstring
:=FixPath(s
,false);
1112 { Check for Sources }
1115 recompile_reason
:=rr_noppu
;
1116 {Check for .pp file}
1117 Found
:=UnitExists(target_os
.sourceext
);
1119 Ext
:=target_os
.sourceext
1123 Found
:=UnitExists(target_os
.pasext
);
1125 Ext
:=target_os
.pasext
;
1127 stringdispose(mainsource
);
1130 sources_avail
:=true;
1131 {Load Filenames when found}
1132 mainsource
:=StringDup(SinglePathString
+FileName
+Ext
);
1133 SetFileName(SinglePathString
+FileName
,false);
1136 sources_avail
:=false;
1137 SourceSearchPath
:=Found
;
1140 Function SearchPath(const s
:string):boolean;
1144 { First check for a ppu, then for the source }
1146 if not onlysource
then
1147 found
:=PPUSearchPath(s
);
1149 found
:=SourceSearchPath(s
);
1153 Function SearchPathList(list
:TSearchPathList
):boolean;
1155 hp
: PStringQueueItem
;
1160 while assigned(hp
) do
1162 found
:=SearchPath(hp
^.data
^);
1167 SearchPathList
:=found
;
1173 filename
:=FixFileName(n
);
1175 1. look for ppu in cwd
1176 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
1177 3. look for source in cwd
1178 4. local unit pathlist
1179 5. global unit pathlist }
1181 if not onlysource
then
1183 fnd
:=PPUSearchPath('.');
1184 if (not fnd
) and (current_module
^.outputpath
^<>'') then
1185 fnd
:=PPUSearchPath(current_module
^.outputpath
^);
1188 fnd
:=SourceSearchPath('.');
1190 fnd
:=SearchPathList(current_module
^.LocalUnitSearchPath
);
1192 fnd
:=SearchPathList(UnitSearchPath
);
1194 { try to find a file with the first 8 chars of the modulename, like
1196 if (not fnd
) and (length(filename
)>8) then
1198 filename
:=copy(filename
,1,8);
1199 fnd
:=SearchPath('.');
1201 fnd
:=SearchPathList(current_module
^.LocalUnitSearchPath
);
1203 fnd
:=SearchPathList(UnitSearchPath
);
1210 procedure tmodule
.reset
;
1212 pm
: pdependent_unit
;
1214 if assigned(scanner
) then
1215 pscannerfile(scanner
)^.invalid
:=true;
1216 if assigned(globalsymtable
) then
1218 dispose(punitsymtable(globalsymtable
),done
);
1219 globalsymtable
:=nil;
1221 if assigned(localsymtable
) then
1223 dispose(punitsymtable(localsymtable
),done
);
1226 if assigned(map
) then
1231 if assigned(ppufile
) then
1233 dispose(ppufile
,done
);
1244 { all units that depend on this one must be recompiled ! }
1245 pm
:=pdependent_unit(dependent_units
.first
);
1246 while assigned(pm
) do
1248 if pm
^.u
^.in_second_compile
then
1249 Comment(v_debug
,'No reload already in second compile: '+pm
^.u
^.modulename
^)
1252 pm
^.u
^.do_reload
:=true;
1253 Comment(v_debug
,'Reloading '+pm
^.u
^.modulename
^+' needed because '+modulename
^+' is reloaded');
1255 pm
:=pdependent_unit(pm
^.next
);
1257 dependent_units
.done
;
1258 dependent_units
.init
;
1261 linkunitofiles
.done
;
1262 linkunitofiles
.init
{$IFDEF NEWST}(8,4){$ENDIF};
1263 linkunitstaticlibs
.done
;
1264 linkunitstaticlibs
.init
{$IFDEF NEWST}(8,4){$ENDIF};
1265 linkunitsharedlibs
.done
;
1266 linkunitsharedlibs
.init
{$IFDEF NEWST}(8,4){$ENDIF};
1267 linkotherofiles
.done
;
1268 linkotherofiles
.init
{$IFDEF NEWST}(8,4){$ENDIF};
1269 linkotherstaticlibs
.done
;
1270 linkotherstaticlibs
.init
{$IFDEF NEWST}(8,4){$ENDIF};
1271 linkothersharedlibs
.done
;
1272 linkothersharedlibs
.init
{$IFDEF NEWST}(8,4){$ENDIF};
1273 uses_imports
:=false;
1276 { sources_avail:=true;
1277 should not be changed PM }
1279 in_implementation
:=false;
1282 should not be changed PFV }
1287 recompile_reason
:=rr_unknown
;
1291 constructor tmodule
.init(const s
:string;_is_unit
:boolean);
1298 { Programs have the name program to don't conflict with dup id's }
1300 {$ifdef UNITALIASES}
1301 modulename
:=stringdup(GetUnitAlias(Upper(n
)))
1303 modulename
:=stringdup(Upper(n
))
1306 modulename
:=stringdup('PROGRAM');
1307 mainsource
:=stringdup(s
);
1311 staticlibfilename:=nil
;
1312 sharedlibfilename:=nil
;
1314 { Dos has the famous 8.3 limit :( }
1315 {$ifdef SHORTASMPREFIX}
1316 asmprefix:=stringdup
(FixFileName
('as'));
1318 asmprefix:=stringdup
(FixFileName
(n
));
1322 setfilename
(p
+n
,true
);
1323 localunitsearchpath.init
;
1324 localobjectsearchpath.init
;
1325 localincludesearchpath.init
;
1326 locallibrarysearchpath.init
;
1328 dependent_units.init
;
1329 new
(sourcefiles
,init
);
1331 linkunitofiles.init
{$IFDEF NEWST}(8,4){$ENDIF};
1332 linkunitstaticlibs.init
{$IFDEF NEWST}(8,4){$ENDIF};
1333 linkunitsharedlibs.init
{$IFDEF NEWST}(8,4){$ENDIF};
1334 linkotherofiles.init
{$IFDEF NEWST}(8,4){$ENDIF};
1335 linkotherstaticlibs.init
{$IFDEF NEWST}(8,4){$ENDIF};
1336 linkothersharedlibs.init
{$IFDEF NEWST}(8,4){$ENDIF};
1340 globalsymtable:=nil
;
1348 inc(global_unit_count
);
1349 unit_index:=global_unit_count
;
1352 sources_avail:=true
;
1353 sources_checked:=false
;
1355 recompile_reason:=rr_unknown
;
1356 in_second_load:=false
;
1358 in_second_compile:=false
;
1359 in_implementation:=false
;
1363 uses_imports:=false
;
1364 imports:=new
(plinkedlist
,init
);
1365 _exports:=new
(plinkedlist
,init
);
1366 { search the PPU file if it is an unit }
1369 search_unit
(modulename^
,false
);
1370 { it the sources_available is changed then we know that
1371 the sources aren't available }
1372 if
not sources_avail then
1373 sources_checked:=true
;
1378 destructor tmodule
.done
;
1384 if assigned(map
) then
1386 if assigned(ppufile
) then
1387 dispose(ppufile
,done
);
1389 if assigned(imports
) then
1390 dispose(imports
,done
);
1392 if assigned(_exports
) then
1393 dispose(_exports
,done
);
1395 if assigned(scanner
) then
1396 pscannerfile(scanner
)^.invalid
:=true;
1397 if assigned(sourcefiles
) then
1398 dispose(sourcefiles
,done
);
1401 dependent_units
.done
;
1403 linkunitofiles
.done
;
1404 linkunitstaticlibs
.done
;
1405 linkunitsharedlibs
.done
;
1406 linkotherofiles
.done
;
1407 linkotherstaticlibs
.done
;
1408 linkothersharedlibs
.done
;
1409 stringdispose(objfilename
);
1410 stringdispose(asmfilename
);
1411 stringdispose
(ppufilename
);
1412 stringdispose
(staticlibfilename
);
1413 stringdispose
(sharedlibfilename
);
1414 stringdispose
(exefilename
);
1415 stringdispose
(outputpath
);
1416 stringdispose
(path
);
1417 stringdispose
(modulename
);
1418 stringdispose
(mainsource
);
1419 stringdispose
(asmprefix
);
1420 localunitsearchpath.done
;
1421 localobjectsearchpath.done
;
1422 localincludesearchpath.done
;
1423 locallibrarysearchpath.done
;
1427 if assigned
(globalsymtable
) then
1428 dispose
(punitsymtable
(globalsymtable
),done
);
1429 globalsymtable:=nil
;
1430 if assigned
(localsymtable
) then
1431 dispose
(punitsymtable
(localsymtable
),done
);
1440 {****************************************************************************
1442 ****************************************************************************}
1444 constructor tused_unit
.init(_u
: pmodule
;intface
:boolean);
1447 in_interface
:=intface
;
1449 is_stab_written
:=false;
1451 name
:=stringdup(_u
^.modulename
^);
1453 interface_checksum
:=_u
^.interface_crc
;
1458 constructor tused_unit
.init_to_load(const n
:string;c
,intfc
:longint;intface
:boolean);
1461 in_interface
:=intface
;
1463 is_stab_written
:=false;
1467 interface_checksum
:=intfc
;
1472 destructor tused_unit
.done
;
1474 stringdispose(name
);
1479 {****************************************************************************
1481 ****************************************************************************}
1483 constructor tdependent_unit
.init(_u
: pmodule
);
1491 Revision 1.1 2002/02/19 08:22:20 sasu
1494 Revision 1.1.2.3 2000/09/26 08:48:09 pierre
1495 * close ppu files if recompiling
1497 Revision 1.1.2.2 2000/08/13 08:59:18 peter
1498 * fixed fileseek() typo
1500 Revision 1.1.2.1 2000/08/12 15:29:52 peter
1501 * patch from Gabor for IDE to support memory stream reading
1503 Revision 1.1 2000/07/13 06:29:50 michael
1506 Revision 1.119 2000/07/03 21:08:54 pierre
1509 Revision 1.118 2000/06/15 18:10:11 peter
1510 * first look for ppu in cwd and outputpath and after that for source
1512 * fixpath() for not linux makes path now lowercase so comparing paths
1513 with different cases (sometimes a drive letter could be
1514 uppercased) gives the expected results
1515 * sources_checked flag if there was already a full search for sources
1516 which aren't found, so another scan isn't done when checking for the
1517 sources only when recompile is needed
1519 Revision 1.117 2000/02/28 17:23:56 daniel
1520 * Current work of symtable integration committed. The symtable can be
1521 activated by defining 'newst', but doesn't compile yet. Changes in type
1522 checking and oop are completed. What is left is to write a new
1523 symtablestack and adapt the parser to use it.
1525 Revision 1.116 2000/02/24 18:41:38 peter
1526 * removed warnings/notes
1528 Revision 1.115 2000/02/10 16:00:23 peter
1529 * dont' check for ppl files as they aren't used atm.
1531 Revision 1.114 2000/02/09 13:22:52 peter
1534 Revision 1.113 2000/01/11 09:52:06 peter
1535 * fixed placing of .sl directories
1536 * use -b again for base-file selection
1537 * fixed group writing for linux with smartlinking
1539 Revision 1.112 2000/01/07 01:14:27 peter
1540 * updated copyright to 2000
1542 Revision 1.111 1999/12/08 01:01:11 peter
1543 * fixed circular unit reference checking. loaded_from was reset after
1544 reseting a unit, so no loaded_from info was available anymore.
1546 Revision 1.110 1999/11/16 23:39:04 peter
1547 * use outputexedir for link.res location
1549 Revision 1.109 1999/11/12 11:03:50 peter
1550 * searchpaths changed to stringqueue object
1552 Revision 1.108 1999/11/06 14:34:20 peter
1553 * truncated log to 20 revs
1555 Revision 1.107 1999/11/04 23:13:25 peter
1556 * moved unit alias support into ifdef
1558 Revision 1.106 1999/11/04 10:54:02 peter
1559 + -Ua<oldname>=<newname> unit alias support
1561 Revision 1.105 1999/10/28 13:14:00 pierre
1562 * allow doubles in TLinkContainer needed for double libraries
1564 Revision 1.104 1999/09/27 23:40:12 peter
1565 * fixed macro within macro endless-loop
1567 Revision 1.103 1999/09/16 08:00:50 pierre
1568 + compiled_module to avoid wrong file info when load PPU files
1570 Revision 1.102 1999/08/31 15:51:10 pierre
1571 * in_second_compile cleaned up, in_compile and in_second_load added
1573 Revision 1.101 1999/08/27 10:43:20 pierre
1574 + interface CRC check with ifdef Test_double_checksum added
1576 Revision 1.100 1999/08/24 13:14:01 peter
1577 * MEMDEBUG to see the sizes of asmlist,asmsymbols,symtables