fppu.pas 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the first loading and searching of the modules
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit fppu;
  19. {$i fpcdefs.inc}
  20. { close ppufiles on system that are
  21. short on file handles like DOS system PM }
  22. {$ifdef GO32V2}
  23. {$define SHORT_ON_FILE_HANDLES}
  24. {$endif GO32V2}
  25. interface
  26. uses
  27. cutils,cclasses,
  28. globtype,globals,finput,fmodule,
  29. symbase,symppu,ppu;
  30. type
  31. tppumodule = class(tmodule)
  32. ppufile : tcompilerppufile; { the PPU file }
  33. sourcefn : pstring; { Source specified with "uses .. in '..'" }
  34. {$ifdef Test_Double_checksum}
  35. crc_array : pointer;
  36. crc_size : longint;
  37. crc_array2 : pointer;
  38. crc_size2 : longint;
  39. {$endif def Test_Double_checksum}
  40. constructor create(LoadedFrom:TModule;const s:string;const fn:string;_is_unit:boolean);
  41. destructor destroy;override;
  42. procedure reset;override;
  43. function openppu:boolean;
  44. procedure getppucrc;
  45. procedure writeppu;
  46. procedure loadppu;
  47. function needrecompile:boolean;
  48. private
  49. function search_unit(onlysource,shortname:boolean):boolean;
  50. procedure load_interface;
  51. procedure load_implementation;
  52. procedure load_symtable_refs;
  53. procedure load_usedunits;
  54. procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
  55. procedure writeusedmacros;
  56. procedure writesourcefiles;
  57. procedure writeusedunit;
  58. procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  59. procedure putasmsymbol_in_idx(s:tnamedindexitem;arg:pointer);
  60. procedure writeasmsymbols;
  61. procedure readusedmacros;
  62. procedure readsourcefiles;
  63. procedure readloadunit;
  64. procedure readlinkcontainer(var p:tlinkcontainer);
  65. procedure readasmsymbols;
  66. end;
  67. function registerunit(callermodule:tmodule;const s : stringid;const fn:string) : tppumodule;
  68. implementation
  69. uses
  70. verbose,systems,version,
  71. symtable,
  72. scanner,
  73. aasmbase,
  74. parser;
  75. {****************************************************************************
  76. TPPUMODULE
  77. ****************************************************************************}
  78. constructor tppumodule.create(LoadedFrom:TModule;const s:string;const fn:string;_is_unit:boolean);
  79. begin
  80. inherited create(LoadedFrom,s,_is_unit);
  81. ppufile:=nil;
  82. sourcefn:=stringdup(fn);
  83. end;
  84. destructor tppumodule.Destroy;
  85. begin
  86. if assigned(ppufile) then
  87. ppufile.free;
  88. ppufile:=nil;
  89. stringdispose(sourcefn);
  90. inherited Destroy;
  91. end;
  92. procedure tppumodule.reset;
  93. begin
  94. if assigned(ppufile) then
  95. begin
  96. ppufile.free;
  97. ppufile:=nil;
  98. end;
  99. inherited reset;
  100. end;
  101. function tppumodule.openppu:boolean;
  102. var
  103. ppufiletime : longint;
  104. begin
  105. openppu:=false;
  106. Message1(unit_t_ppu_loading,ppufilename^);
  107. { Get ppufile time (also check if the file exists) }
  108. ppufiletime:=getnamedfiletime(ppufilename^);
  109. if ppufiletime=-1 then
  110. exit;
  111. { Open the ppufile }
  112. Message1(unit_u_ppu_name,ppufilename^);
  113. ppufile:=tcompilerppufile.create(ppufilename^);
  114. if not ppufile.openfile then
  115. begin
  116. ppufile.free;
  117. ppufile:=nil;
  118. Message(unit_u_ppu_file_too_short);
  119. exit;
  120. end;
  121. { check for a valid PPU file }
  122. if not ppufile.CheckPPUId then
  123. begin
  124. ppufile.free;
  125. ppufile:=nil;
  126. Message(unit_u_ppu_invalid_header);
  127. exit;
  128. end;
  129. { check for allowed PPU versions }
  130. if not (ppufile.GetPPUVersion = CurrentPPUVersion) then
  131. begin
  132. Message1(unit_u_ppu_invalid_version,tostr(ppufile.GetPPUVersion));
  133. ppufile.free;
  134. ppufile:=nil;
  135. exit;
  136. end;
  137. { check the target processor }
  138. if tsystemcpu(ppufile.header.cpu)<>target_cpu then
  139. begin
  140. ppufile.free;
  141. ppufile:=nil;
  142. Message(unit_u_ppu_invalid_processor);
  143. exit;
  144. end;
  145. { check target }
  146. if tsystem(ppufile.header.target)<>target_info.system then
  147. begin
  148. ppufile.free;
  149. ppufile:=nil;
  150. Message(unit_u_ppu_invalid_target);
  151. exit;
  152. end;
  153. {$ifdef cpufpemu}
  154. { check if floating point emulation is on?}
  155. if ((ppufile.header.flags and uf_fpu_emulation)<>0) and
  156. (cs_fp_emulation in aktmoduleswitches) then
  157. begin
  158. ppufile.free;
  159. ppufile:=nil;
  160. Message(unit_u_ppu_invalid_fpumode);
  161. exit;
  162. end;
  163. {$endif cpufpemu}
  164. { Load values to be access easier }
  165. flags:=ppufile.header.flags;
  166. crc:=ppufile.header.checksum;
  167. interface_crc:=ppufile.header.interface_checksum;
  168. { Show Debug info }
  169. Message1(unit_u_ppu_time,filetimestring(ppufiletime));
  170. Message1(unit_u_ppu_flags,tostr(flags));
  171. Message1(unit_u_ppu_crc,hexstr(ppufile.header.checksum,8));
  172. Message1(unit_u_ppu_crc,hexstr(ppufile.header.interface_checksum,8)+' (intfc)');
  173. do_compile:=false;
  174. openppu:=true;
  175. end;
  176. function tppumodule.search_unit(onlysource,shortname:boolean):boolean;
  177. var
  178. singlepathstring,
  179. filename : string;
  180. Function UnitExists(const ext:string;var foundfile:string):boolean;
  181. begin
  182. Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
  183. UnitExists:=FindFile(FileName+ext,Singlepathstring,foundfile);
  184. end;
  185. Function PPUSearchPath(const s:string):boolean;
  186. var
  187. found : boolean;
  188. hs : string;
  189. begin
  190. Found:=false;
  191. singlepathstring:=FixPath(s,false);
  192. { Check for PPU file }
  193. Found:=UnitExists(target_info.unitext,hs);
  194. if Found then
  195. Begin
  196. SetFileName(hs,false);
  197. Found:=OpenPPU;
  198. End;
  199. PPUSearchPath:=Found;
  200. end;
  201. Function SourceSearchPath(const s:string):boolean;
  202. var
  203. found : boolean;
  204. hs : string;
  205. begin
  206. Found:=false;
  207. singlepathstring:=FixPath(s,false);
  208. { Check for Sources }
  209. ppufile:=nil;
  210. do_compile:=true;
  211. recompile_reason:=rr_noppu;
  212. {Check for .pp file}
  213. Found:=UnitExists(target_info.sourceext,hs);
  214. if not Found then
  215. begin
  216. { Check for .pas }
  217. Found:=UnitExists(target_info.pasext,hs);
  218. end;
  219. stringdispose(mainsource);
  220. if Found then
  221. begin
  222. sources_avail:=true;
  223. { Load Filenames when found }
  224. mainsource:=StringDup(hs);
  225. SetFileName(hs,false);
  226. end
  227. else
  228. sources_avail:=false;
  229. SourceSearchPath:=Found;
  230. end;
  231. Function SearchPath(const s:string):boolean;
  232. var
  233. found : boolean;
  234. begin
  235. { First check for a ppu, then for the source }
  236. found:=false;
  237. if not onlysource then
  238. found:=PPUSearchPath(s);
  239. if not found then
  240. found:=SourceSearchPath(s);
  241. SearchPath:=found;
  242. end;
  243. Function SearchPathList(list:TSearchPathList):boolean;
  244. var
  245. hp : TStringListItem;
  246. found : boolean;
  247. begin
  248. found:=false;
  249. hp:=TStringListItem(list.First);
  250. while assigned(hp) do
  251. begin
  252. found:=SearchPath(hp.Str);
  253. if found then
  254. break;
  255. hp:=TStringListItem(hp.next);
  256. end;
  257. SearchPathList:=found;
  258. end;
  259. var
  260. fnd : boolean;
  261. hs : string;
  262. begin
  263. if shortname then
  264. filename:=FixFileName(Copy(realmodulename^,1,8))
  265. else
  266. filename:=FixFileName(realmodulename^);
  267. { try to find unit
  268. 1. look for ppu in cwd
  269. 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
  270. 3. look for the specified source file (from the uses line)
  271. 4. look for source in cwd
  272. 5. local unit pathlist
  273. 6. global unit pathlist }
  274. fnd:=false;
  275. if not onlysource then
  276. begin
  277. fnd:=PPUSearchPath('.');
  278. if (not fnd) and (outputpath^<>'') then
  279. fnd:=PPUSearchPath(outputpath^);
  280. end;
  281. if (not fnd) and (sourcefn^<>'') then
  282. begin
  283. { the full filename is specified so we can't use here the
  284. searchpath (PFV) }
  285. Message1(unit_t_unitsearch,AddExtension(sourcefn^,target_info.sourceext));
  286. fnd:=FindFile(AddExtension(sourcefn^,target_info.sourceext),'',hs);
  287. if not fnd then
  288. begin
  289. Message1(unit_t_unitsearch,AddExtension(sourcefn^,target_info.pasext));
  290. fnd:=FindFile(AddExtension(sourcefn^,target_info.pasext),'',hs);
  291. end;
  292. if fnd then
  293. begin
  294. sources_avail:=true;
  295. do_compile:=true;
  296. recompile_reason:=rr_noppu;
  297. stringdispose(mainsource);
  298. mainsource:=StringDup(hs);
  299. SetFileName(hs,false);
  300. end;
  301. end;
  302. if not fnd then
  303. fnd:=SourceSearchPath('.');
  304. if (not fnd) and Assigned(Loaded_From) then
  305. fnd:=SearchPathList(Loaded_From.LocalUnitSearchPath);
  306. if not fnd then
  307. fnd:=SearchPathList(UnitSearchPath);
  308. { try to find a file with the first 8 chars of the modulename, like
  309. dos }
  310. if (not fnd) and (length(filename)>8) then
  311. begin
  312. filename:=copy(filename,1,8);
  313. fnd:=SearchPath('.');
  314. if (not fnd) then
  315. fnd:=SearchPathList(LocalUnitSearchPath);
  316. if not fnd then
  317. fnd:=SearchPathList(UnitSearchPath);
  318. end;
  319. search_unit:=fnd;
  320. end;
  321. {**********************************
  322. PPU Reading/Writing Helpers
  323. ***********************************}
  324. procedure tppumodule.writeusedmacro(p:TNamedIndexItem;arg:pointer);
  325. begin
  326. if tmacro(p).is_used or tmacro(p).defined_at_startup then
  327. begin
  328. ppufile.putstring(p.name);
  329. ppufile.putbyte(byte(tmacro(p).defined_at_startup));
  330. ppufile.putbyte(byte(tmacro(p).is_used));
  331. end;
  332. end;
  333. procedure tppumodule.writeusedmacros;
  334. begin
  335. ppufile.do_crc:=false;
  336. tscannerfile(scanner).macros.foreach({$ifdef FPCPROCVAR}@{$endif}writeusedmacro,nil);
  337. ppufile.writeentry(ibusedmacros);
  338. ppufile.do_crc:=true;
  339. end;
  340. procedure tppumodule.writesourcefiles;
  341. var
  342. hp : tinputfile;
  343. i,j : longint;
  344. begin
  345. { second write the used source files }
  346. ppufile.do_crc:=false;
  347. hp:=sourcefiles.files;
  348. { write source files directly in good order }
  349. j:=0;
  350. while assigned(hp) do
  351. begin
  352. inc(j);
  353. hp:=hp.ref_next;
  354. end;
  355. while j>0 do
  356. begin
  357. hp:=sourcefiles.files;
  358. for i:=1 to j-1 do
  359. hp:=hp.ref_next;
  360. ppufile.putstring(hp.name^);
  361. ppufile.putlongint(hp.getfiletime);
  362. dec(j);
  363. end;
  364. ppufile.writeentry(ibsourcefiles);
  365. ppufile.do_crc:=true;
  366. end;
  367. procedure tppumodule.writeusedunit;
  368. var
  369. hp : tused_unit;
  370. begin
  371. { renumber the units for derefence writing }
  372. numberunits;
  373. { write a reference for each used unit }
  374. hp:=tused_unit(used_units.first);
  375. while assigned(hp) do
  376. begin
  377. { implementation units should not change
  378. the CRC PM }
  379. ppufile.do_crc:=hp.in_interface;
  380. ppufile.putstring(hp.u.realmodulename^);
  381. { the checksum should not affect the crc of this unit ! (PFV) }
  382. ppufile.do_crc:=false;
  383. ppufile.putlongint(longint(hp.checksum));
  384. ppufile.putlongint(longint(hp.interface_checksum));
  385. ppufile.putbyte(byte(hp.in_interface));
  386. ppufile.do_crc:=true;
  387. hp:=tused_unit(hp.next);
  388. end;
  389. ppufile.do_interface_crc:=true;
  390. ppufile.writeentry(ibloadunit);
  391. end;
  392. procedure tppumodule.writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  393. var
  394. hcontainer : tlinkcontainer;
  395. s : string;
  396. mask : cardinal;
  397. begin
  398. hcontainer:=TLinkContainer.Create;
  399. while not p.empty do
  400. begin
  401. s:=p.get(mask);
  402. if strippath then
  403. ppufile.putstring(SplitFileName(s))
  404. else
  405. ppufile.putstring(s);
  406. ppufile.putlongint(mask);
  407. hcontainer.add(s,mask);
  408. end;
  409. ppufile.writeentry(id);
  410. p.Free;
  411. p:=hcontainer;
  412. end;
  413. procedure tppumodule.putasmsymbol_in_idx(s:tnamedindexitem;arg:pointer);
  414. begin
  415. if tasmsymbol(s).ppuidx<>-1 then
  416. librarydata.asmsymbolidx^[tasmsymbol(s).ppuidx-1]:=tasmsymbol(s);
  417. end;
  418. procedure tppumodule.writeasmsymbols;
  419. var
  420. s : tasmsymbol;
  421. i : longint;
  422. asmsymtype : byte;
  423. begin
  424. { get an ordered list of all symbols to put in the ppu }
  425. getmem(librarydata.asmsymbolidx,librarydata.asmsymbolppuidx*sizeof(pointer));
  426. fillchar(librarydata.asmsymbolidx^,librarydata.asmsymbolppuidx*sizeof(pointer),0);
  427. librarydata.symbolsearch.foreach({$ifdef FPCPROCVAR}@{$endif}putasmsymbol_in_idx,nil);
  428. { write the number of symbols }
  429. ppufile.putlongint(librarydata.asmsymbolppuidx);
  430. { write the symbols from the indexed list to the ppu }
  431. for i:=1 to librarydata.asmsymbolppuidx do
  432. begin
  433. s:=librarydata.asmsymbolidx^[i-1];
  434. if not assigned(s) then
  435. internalerror(200208071);
  436. asmsymtype:=1;
  437. if s.Classtype=tasmlabel then
  438. begin
  439. if tasmlabel(s).is_addr then
  440. asmsymtype:=4
  441. else if tasmlabel(s).typ=AT_DATA then
  442. asmsymtype:=3
  443. else
  444. asmsymtype:=2;
  445. end;
  446. ppufile.putbyte(asmsymtype);
  447. case asmsymtype of
  448. 1 :
  449. ppufile.putstring(s.name);
  450. 2 :
  451. ppufile.putlongint(tasmlabel(s).labelnr);
  452. end;
  453. ppufile.putbyte(byte(s.defbind));
  454. ppufile.putbyte(byte(s.typ));
  455. end;
  456. ppufile.writeentry(ibasmsymbols);
  457. end;
  458. procedure tppumodule.readusedmacros;
  459. var
  460. hs : string;
  461. mac : tmacro;
  462. was_defined_at_startup,
  463. was_used : boolean;
  464. begin
  465. { only possible when we've a scanner of the current file }
  466. if not assigned(current_scanner) then
  467. exit;
  468. while not ppufile.endofentry do
  469. begin
  470. hs:=ppufile.getstring;
  471. was_defined_at_startup:=boolean(ppufile.getbyte);
  472. was_used:=boolean(ppufile.getbyte);
  473. mac:=tmacro(tscannerfile(current_scanner).macros.search(hs));
  474. if assigned(mac) then
  475. begin
  476. {$ifndef EXTDEBUG}
  477. { if we don't have the sources why tell }
  478. if sources_avail then
  479. {$endif ndef EXTDEBUG}
  480. if (not was_defined_at_startup) and
  481. was_used and
  482. mac.defined_at_startup then
  483. Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
  484. end
  485. else { not assigned }
  486. if was_defined_at_startup and
  487. was_used then
  488. Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
  489. end;
  490. end;
  491. procedure tppumodule.readsourcefiles;
  492. var
  493. temp,hs : string;
  494. temp_dir : string;
  495. main_dir : string;
  496. incfile_found,
  497. main_found,
  498. is_main : boolean;
  499. orgfiletime,
  500. source_time : longint;
  501. hp : tinputfile;
  502. begin
  503. sources_avail:=true;
  504. is_main:=true;
  505. main_dir:='';
  506. while not ppufile.endofentry do
  507. begin
  508. hs:=ppufile.getstring;
  509. orgfiletime:=ppufile.getlongint;
  510. temp_dir:='';
  511. if (flags and uf_in_library)<>0 then
  512. begin
  513. sources_avail:=false;
  514. temp:=' library';
  515. end
  516. else if pos('Macro ',hs)=1 then
  517. begin
  518. { we don't want to find this file }
  519. { but there is a problem with file indexing !! }
  520. temp:='';
  521. end
  522. else
  523. begin
  524. { check the date of the source files }
  525. Source_Time:=GetNamedFileTime(path^+hs);
  526. incfile_found:=false;
  527. main_found:=false;
  528. if Source_Time<>-1 then
  529. hs:=path^+hs
  530. else
  531. if not(is_main) then
  532. begin
  533. Source_Time:=GetNamedFileTime(main_dir+hs);
  534. if Source_Time<>-1 then
  535. hs:=main_dir+hs;
  536. end;
  537. if (Source_Time=-1) then
  538. begin
  539. if is_main then
  540. main_found:=unitsearchpath.FindFile(hs,temp_dir)
  541. else
  542. incfile_found:=includesearchpath.FindFile(hs,temp_dir);
  543. if incfile_found or main_found then
  544. begin
  545. Source_Time:=GetNamedFileTime(temp_dir);
  546. if Source_Time<>-1 then
  547. hs:=temp_dir;
  548. end;
  549. end;
  550. if Source_Time=-1 then
  551. begin
  552. sources_avail:=false;
  553. temp:=' not found';
  554. end
  555. else
  556. begin
  557. if main_found then
  558. main_dir:=temp_dir;
  559. { time newer? But only allow if the file is not searched
  560. in the include path (PFV), else you've problems with
  561. units which use the same includefile names }
  562. if incfile_found then
  563. temp:=' found'
  564. else
  565. begin
  566. temp:=' time '+filetimestring(source_time);
  567. if (orgfiletime<>-1) and
  568. (source_time<>orgfiletime) then
  569. begin
  570. if ((flags and uf_release)=0) then
  571. begin
  572. do_compile:=true;
  573. recompile_reason:=rr_sourcenewer;
  574. end
  575. else
  576. Message2(unit_h_source_modified,hs,ppufilename^);
  577. temp:=temp+' *';
  578. end;
  579. end;
  580. end;
  581. hp:=tinputfile.create(hs);
  582. { the indexing is wrong here PM }
  583. sourcefiles.register_file(hp);
  584. end;
  585. if is_main then
  586. begin
  587. stringdispose(mainsource);
  588. mainsource:=stringdup(hs);
  589. end;
  590. Message1(unit_u_ppu_source,hs+temp);
  591. is_main:=false;
  592. end;
  593. { check if we want to rebuild every unit, only if the sources are
  594. available }
  595. if do_build and sources_avail and
  596. ((flags and uf_release)=0) then
  597. begin
  598. do_compile:=true;
  599. recompile_reason:=rr_build;
  600. end;
  601. end;
  602. procedure tppumodule.readloadunit;
  603. var
  604. hs : string;
  605. pu : tused_unit;
  606. hp : tppumodule;
  607. intfchecksum,
  608. checksum : cardinal;
  609. begin
  610. while not ppufile.endofentry do
  611. begin
  612. hs:=ppufile.getstring;
  613. checksum:=cardinal(ppufile.getlongint);
  614. intfchecksum:=cardinal(ppufile.getlongint);
  615. in_interface:=(ppufile.getbyte<>0);
  616. { set the state of this unit before registering, this is
  617. needed for a correct circular dependency check }
  618. hp:=registerunit(self,hs,'');
  619. pu:=addusedunit(hp,false);
  620. pu.checksum:=checksum;
  621. pu.interface_checksum:=intfchecksum;
  622. end;
  623. in_interface:=false;
  624. end;
  625. procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
  626. var
  627. s : string;
  628. m : longint;
  629. begin
  630. while not ppufile.endofentry do
  631. begin
  632. s:=ppufile.getstring;
  633. m:=ppufile.getlongint;
  634. p.add(s,m);
  635. end;
  636. end;
  637. procedure tppumodule.readasmsymbols;
  638. var
  639. labelnr,
  640. i : longint;
  641. name : string;
  642. bind : TAsmSymBind;
  643. typ : TAsmSymType;
  644. asmsymtype : byte;
  645. begin
  646. librarydata.asmsymbolppuidx:=ppufile.getlongint;
  647. if librarydata.asmsymbolppuidx>0 then
  648. begin
  649. getmem(librarydata.asmsymbolidx,librarydata.asmsymbolppuidx*sizeof(pointer));
  650. fillchar(librarydata.asmsymbolidx^,librarydata.asmsymbolppuidx*sizeof(pointer),0);
  651. for i:=1 to librarydata.asmsymbolppuidx do
  652. begin
  653. asmsymtype:=ppufile.getbyte;
  654. case asmsymtype of
  655. 1 :
  656. name:=ppufile.getstring;
  657. 2..4 :
  658. labelnr:=ppufile.getlongint;
  659. else
  660. internalerror(200208192);
  661. end;
  662. bind:=tasmsymbind(ppufile.getbyte);
  663. typ:=tasmsymtype(ppufile.getbyte);
  664. case asmsymtype of
  665. 1 :
  666. librarydata.asmsymbolidx^[i-1]:=librarydata.newasmsymboltype(name,bind,typ);
  667. 2 :
  668. librarydata.asmsymbolidx^[i-1]:=librarydata.newasmlabel(labelnr,false,false);
  669. 3 :
  670. librarydata.asmsymbolidx^[i-1]:=librarydata.newasmlabel(labelnr,true,false);
  671. 4 :
  672. librarydata.asmsymbolidx^[i-1]:=librarydata.newasmlabel(labelnr,false,true);
  673. end;
  674. end;
  675. end;
  676. end;
  677. procedure tppumodule.load_interface;
  678. var
  679. b : byte;
  680. newmodulename : string;
  681. begin
  682. { read interface part }
  683. repeat
  684. b:=ppufile.readentry;
  685. case b of
  686. ibmodulename :
  687. begin
  688. newmodulename:=ppufile.getstring;
  689. if (cs_check_unit_name in aktglobalswitches) and
  690. (upper(newmodulename)<>modulename^) then
  691. Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
  692. stringdispose(modulename);
  693. stringdispose(realmodulename);
  694. modulename:=stringdup(upper(newmodulename));
  695. realmodulename:=stringdup(newmodulename);
  696. end;
  697. ibsourcefiles :
  698. readsourcefiles;
  699. ibusedmacros :
  700. readusedmacros;
  701. ibloadunit :
  702. readloadunit;
  703. iblinkunitofiles :
  704. readlinkcontainer(LinkUnitOFiles);
  705. iblinkunitstaticlibs :
  706. readlinkcontainer(LinkUnitStaticLibs);
  707. iblinkunitsharedlibs :
  708. readlinkcontainer(LinkUnitSharedLibs);
  709. iblinkotherofiles :
  710. readlinkcontainer(LinkotherOFiles);
  711. iblinkotherstaticlibs :
  712. readlinkcontainer(LinkotherStaticLibs);
  713. iblinkothersharedlibs :
  714. readlinkcontainer(LinkotherSharedLibs);
  715. ibendinterface :
  716. break;
  717. else
  718. Message1(unit_f_ppu_invalid_entry,tostr(b));
  719. end;
  720. until false;
  721. end;
  722. procedure tppumodule.load_implementation;
  723. var
  724. b : byte;
  725. oldobjectlibrary : tasmlibrarydata;
  726. begin
  727. { read implementation part }
  728. repeat
  729. b:=ppufile.readentry;
  730. case b of
  731. ibasmsymbols :
  732. readasmsymbols;
  733. ibendimplementation :
  734. break;
  735. else
  736. Message1(unit_f_ppu_invalid_entry,tostr(b));
  737. end;
  738. until false;
  739. { we can now derefence all pointers to the implementation parts }
  740. oldobjectlibrary:=objectlibrary;
  741. objectlibrary:=librarydata;
  742. tstoredsymtable(globalsymtable).derefimpl;
  743. if assigned(localsymtable) then
  744. tstoredsymtable(localsymtable).derefimpl;
  745. objectlibrary:=oldobjectlibrary;
  746. end;
  747. procedure tppumodule.load_symtable_refs;
  748. var
  749. b : byte;
  750. unitindex : word;
  751. begin
  752. { load local symtable first }
  753. if ((flags and uf_local_browser)<>0) then
  754. begin
  755. localsymtable:=tstaticsymtable.create(modulename^);
  756. tstaticsymtable(localsymtable).ppuload(ppufile);
  757. end;
  758. { load browser }
  759. if (flags and uf_has_browser)<>0 then
  760. begin
  761. tstoredsymtable(globalsymtable).load_references(ppufile,true);
  762. unitindex:=1;
  763. while assigned(map^[unitindex]) do
  764. begin
  765. { each unit wrote one browser entry }
  766. tstoredsymtable(globalsymtable).load_references(ppufile,false);
  767. inc(unitindex);
  768. end;
  769. b:=ppufile.readentry;
  770. if b<>ibendbrowser then
  771. Message1(unit_f_ppu_invalid_entry,tostr(b));
  772. end;
  773. if ((flags and uf_local_browser)<>0) then
  774. tstaticsymtable(localsymtable).load_references(ppufile,true);
  775. end;
  776. procedure tppumodule.writeppu;
  777. var
  778. pu : tused_unit;
  779. begin
  780. Message1(unit_u_ppu_write,realmodulename^);
  781. { create unit flags }
  782. {$ifdef GDB}
  783. if cs_gdb_dbx in aktglobalswitches then
  784. flags:=flags or uf_has_dbx;
  785. {$endif GDB}
  786. if cs_browser in aktmoduleswitches then
  787. flags:=flags or uf_has_browser;
  788. if cs_local_browser in aktmoduleswitches then
  789. flags:=flags or uf_local_browser;
  790. if do_release then
  791. flags:=flags or uf_release;
  792. {$ifdef cpufpemu}
  793. if (cs_fp_emulation in aktmoduleswitches) then
  794. flags:=flags or uf_fpu_emulation;
  795. {$endif cpufpemu}
  796. {$ifdef Test_Double_checksum_write}
  797. Assign(CRCFile,s+'.IMP');
  798. Rewrite(CRCFile);
  799. {$endif def Test_Double_checksum_write}
  800. { create new ppufile }
  801. ppufile:=tcompilerppufile.create(ppufilename^);
  802. if not ppufile.createfile then
  803. Message(unit_f_ppu_cannot_write);
  804. { first the unitname }
  805. ppufile.putstring(realmodulename^);
  806. ppufile.writeentry(ibmodulename);
  807. writesourcefiles;
  808. writeusedmacros;
  809. writeusedunit;
  810. { write the objectfiles and libraries that come for this unit,
  811. preserve the containers becuase they are still needed to load
  812. the link.res. All doesn't depend on the crc! It doesn't matter
  813. if a unit is in a .o or .a file }
  814. ppufile.do_crc:=false;
  815. writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
  816. writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
  817. writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
  818. writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
  819. writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
  820. writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
  821. ppufile.do_crc:=true;
  822. ppufile.writeentry(ibendinterface);
  823. { write the symtable entries }
  824. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  825. { everything after this doesn't affect the crc }
  826. ppufile.do_crc:=false;
  827. { write asmsymbols }
  828. writeasmsymbols;
  829. { end of implementation }
  830. ppufile.writeentry(ibendimplementation);
  831. { write static symtable
  832. needed for local debugging of unit functions }
  833. if ((flags and uf_local_browser)<>0) and
  834. assigned(localsymtable) then
  835. tstoredsymtable(localsymtable).ppuwrite(ppufile);
  836. { write all browser section }
  837. if (flags and uf_has_browser)<>0 then
  838. begin
  839. tstoredsymtable(globalsymtable).write_references(ppufile,true);
  840. pu:=tused_unit(used_units.first);
  841. while assigned(pu) do
  842. begin
  843. tstoredsymtable(pu.u.globalsymtable).write_references(ppufile,false);
  844. pu:=tused_unit(pu.next);
  845. end;
  846. ppufile.writeentry(ibendbrowser);
  847. end;
  848. if ((flags and uf_local_browser)<>0) and
  849. assigned(localsymtable) then
  850. tstaticsymtable(localsymtable).write_references(ppufile,true);
  851. { the last entry ibend is written automaticly }
  852. { flush to be sure }
  853. ppufile.flush;
  854. { create and write header }
  855. ppufile.header.size:=ppufile.size;
  856. ppufile.header.checksum:=ppufile.crc;
  857. ppufile.header.interface_checksum:=ppufile.interface_crc;
  858. ppufile.header.compiler:=wordversion;
  859. ppufile.header.cpu:=word(target_cpu);
  860. ppufile.header.target:=word(target_info.system);
  861. ppufile.header.flags:=flags;
  862. ppufile.writeheader;
  863. { save crc in current module also }
  864. crc:=ppufile.crc;
  865. interface_crc:=ppufile.interface_crc;
  866. {$ifdef Test_Double_checksum_write}
  867. close(CRCFile);
  868. {$endif Test_Double_checksum_write}
  869. ppufile.closefile;
  870. ppufile.free;
  871. ppufile:=nil;
  872. end;
  873. procedure tppumodule.getppucrc;
  874. begin
  875. {$ifdef Test_Double_checksum_write}
  876. Assign(CRCFile,s+'.INT')
  877. Rewrite(CRCFile);
  878. {$endif def Test_Double_checksum_write}
  879. { create new ppufile }
  880. ppufile:=tcompilerppufile.create(ppufilename^);
  881. ppufile.crc_only:=true;
  882. if not ppufile.createfile then
  883. Message(unit_f_ppu_cannot_write);
  884. { first the unitname }
  885. ppufile.putstring(realmodulename^);
  886. ppufile.writeentry(ibmodulename);
  887. { the interface units affect the crc }
  888. writeusedunit;
  889. ppufile.writeentry(ibendinterface);
  890. { write the symtable entries }
  891. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  892. { save crc }
  893. crc:=ppufile.crc;
  894. interface_crc:=ppufile.interface_crc;
  895. { end of implementation, to generate a correct ppufile
  896. for ppudump when using INTFPPU define }
  897. ppufile.writeentry(ibendimplementation);
  898. {$ifdef Test_Double_checksum}
  899. crc_array:=ppufile.crc_test;
  900. ppufile.crc_test:=nil;
  901. crc_size:=ppufile.crc_index2;
  902. crc_array2:=ppufile.crc_test2;
  903. ppufile.crc_test2:=nil;
  904. crc_size2:=ppufile.crc_index2;
  905. {$endif Test_Double_checksum}
  906. {$ifdef Test_Double_checksum_write}
  907. close(CRCFile);
  908. {$endif Test_Double_checksum_write}
  909. { create and write header, this will only be used
  910. for debugging purposes }
  911. ppufile.header.size:=ppufile.size;
  912. ppufile.header.checksum:=ppufile.crc;
  913. ppufile.header.interface_checksum:=ppufile.interface_crc;
  914. ppufile.header.compiler:=wordversion;
  915. ppufile.header.cpu:=word(target_cpu);
  916. ppufile.header.target:=word(target_info.system);
  917. ppufile.header.flags:=flags;
  918. ppufile.writeheader;
  919. ppufile.closefile;
  920. ppufile.free;
  921. ppufile:=nil;
  922. end;
  923. procedure tppumodule.load_usedunits;
  924. var
  925. pu : tused_unit;
  926. load_refs : boolean;
  927. nextmapentry : longint;
  928. begin
  929. if current_module<>self then
  930. internalerror(200212284);
  931. load_refs:=true;
  932. { Add current unit to the map }
  933. map^[0]:=self;
  934. nextmapentry:=1;
  935. { load the used units from interface }
  936. in_interface:=true;
  937. pu:=tused_unit(used_units.first);
  938. while assigned(pu) do
  939. begin
  940. if pu.in_interface then
  941. begin
  942. tppumodule(pu.u).loadppu;
  943. { if this unit is compiled we can stop }
  944. if state=ms_compiled then
  945. exit;
  946. { add this unit to the dependencies }
  947. pu.u.adddependency(self);
  948. { need to recompile the current unit, check the interface
  949. crc. And when not compiled with -Ur then check the complete
  950. crc }
  951. if (pu.u.interface_crc<>pu.interface_checksum) or
  952. (
  953. ((ppufile.header.flags and uf_release)=0) and
  954. (pu.u.crc<>pu.checksum)
  955. ) then
  956. begin
  957. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^);
  958. recompile_reason:=rr_crcchanged;
  959. do_compile:=true;
  960. exit;
  961. end;
  962. { setup the map entry for deref }
  963. map^[nextmapentry]:=pu.u;
  964. inc(nextmapentry);
  965. if nextmapentry>maxunits then
  966. Message(unit_f_too_much_units);
  967. end;
  968. pu:=tused_unit(pu.next);
  969. end;
  970. { ok, now load the interface of this unit }
  971. if current_module<>self then
  972. internalerror(200208187);
  973. globalsymtable:=tglobalsymtable.create(modulename^);
  974. tstoredsymtable(globalsymtable).ppuload(ppufile);
  975. interface_compiled:=true;
  976. { now only read the implementation uses }
  977. in_interface:=false;
  978. pu:=tused_unit(used_units.first);
  979. while assigned(pu) do
  980. begin
  981. if (not pu.in_interface) then
  982. begin
  983. tppumodule(pu.u).loadppu;
  984. { if this unit is compiled we can stop }
  985. if state=ms_compiled then
  986. exit;
  987. { add this unit to the dependencies }
  988. pu.u.adddependency(self);
  989. { need to recompile the current unit ? }
  990. if (pu.u.interface_crc<>pu.interface_checksum) then
  991. begin
  992. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^+' {impl}');
  993. recompile_reason:=rr_crcchanged;
  994. do_compile:=true;
  995. exit;
  996. end;
  997. { setup the map entry for deref }
  998. map^[nextmapentry]:=pu.u;
  999. inc(nextmapentry);
  1000. if nextmapentry>maxunits then
  1001. Message(unit_f_too_much_units);
  1002. end;
  1003. pu:=tused_unit(pu.next);
  1004. end;
  1005. { read the implementation/objectdata part }
  1006. load_implementation;
  1007. { load browser info if stored }
  1008. if ((flags and uf_has_browser)<>0) and load_refs then
  1009. begin
  1010. if current_module<>self then
  1011. internalerror(200208188);
  1012. load_symtable_refs;
  1013. end;
  1014. end;
  1015. function tppumodule.needrecompile:boolean;
  1016. var
  1017. pu : tused_unit;
  1018. begin
  1019. result:=false;
  1020. pu:=tused_unit(used_units.first);
  1021. while assigned(pu) do
  1022. begin
  1023. { need to recompile the current unit, check the interface
  1024. crc. And when not compiled with -Ur then check the complete
  1025. crc }
  1026. if (pu.u.interface_crc<>pu.interface_checksum) or
  1027. (
  1028. (pu.in_interface) and
  1029. (pu.u.crc<>pu.checksum)
  1030. ) then
  1031. begin
  1032. result:=true;
  1033. exit;
  1034. end;
  1035. pu:=tused_unit(pu.next);
  1036. end;
  1037. end;
  1038. procedure tppumodule.loadppu;
  1039. const
  1040. ImplIntf : array[boolean] of string[15]=('implementation','interface');
  1041. var
  1042. do_load,
  1043. second_time : boolean;
  1044. hp,
  1045. old_current_module : tmodule;
  1046. begin
  1047. old_current_module:=current_module;
  1048. Message3(unit_u_load_unit,old_current_module.modulename^,
  1049. ImplIntf[old_current_module.in_interface],
  1050. modulename^);
  1051. if modulename^='NCGUTIL' then
  1052. do_load:=do_load;
  1053. { check if the globalsymtable is already available, but
  1054. we must reload when the do_reload flag is set }
  1055. if (not do_reload) and
  1056. assigned(globalsymtable) then
  1057. exit;
  1058. { reset }
  1059. do_load:=true;
  1060. second_time:=false;
  1061. current_module:=self;
  1062. SetCompileModule(current_module);
  1063. Fillchar(aktfilepos,0,sizeof(aktfilepos));
  1064. { A force reload }
  1065. if do_reload then
  1066. begin
  1067. Message(unit_u_forced_reload);
  1068. do_reload:=false;
  1069. { When the unit is already loaded or being loaded
  1070. we can maybe skip a complete reload/recompile }
  1071. if assigned(globalsymtable) and
  1072. (not needrecompile) then
  1073. begin
  1074. { When we don't have any data stored yet there
  1075. is nothing to resolve }
  1076. if interface_compiled then
  1077. begin
  1078. Message1(unit_u_reresolving_unit,modulename^);
  1079. aktglobalsymtable:=tstoredsymtable(globalsymtable);
  1080. tstoredsymtable(globalsymtable).deref;
  1081. tstoredsymtable(globalsymtable).derefimpl;
  1082. if assigned(localsymtable) then
  1083. begin
  1084. aktstaticsymtable:=tstoredsymtable(localsymtable);
  1085. tstoredsymtable(localsymtable).deref;
  1086. tstoredsymtable(localsymtable).derefimpl;
  1087. end;
  1088. end
  1089. else
  1090. Message1(unit_u_skipping_reresolving_unit,modulename^);
  1091. do_load:=false;
  1092. end;
  1093. end;
  1094. if do_load then
  1095. begin
  1096. { we are loading a new module, save the state of the scanner
  1097. and reset scanner+module }
  1098. if assigned(current_scanner) then
  1099. current_scanner.tempcloseinputfile;
  1100. current_scanner:=nil;
  1101. { loading the unit for a second time? }
  1102. if state=ms_registered then
  1103. state:=ms_load
  1104. else
  1105. begin
  1106. { try to load the unit a second time first }
  1107. Message1(unit_u_second_load_unit,modulename^);
  1108. Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
  1109. { Flag modules to reload }
  1110. flagdependent(old_current_module);
  1111. { Reset the module }
  1112. reset;
  1113. if state=ms_compile then
  1114. begin
  1115. Message1(unit_u_second_compile_unit,modulename^);
  1116. state:=ms_second_compile;
  1117. do_compile:=true;
  1118. end
  1119. else
  1120. state:=ms_second_load;
  1121. second_time:=true;
  1122. end;
  1123. { close old_current_ppu on system that are
  1124. short on file handles like DOS PM }
  1125. {$ifdef SHORT_ON_FILE_HANDLES}
  1126. if old_current_module.is_unit and
  1127. assigned(tppumodule(old_current_module).ppufile) then
  1128. tppumodule(old_current_module).ppufile.tempclose;
  1129. {$endif SHORT_ON_FILE_HANDLES}
  1130. { try to opening ppu, skip this when we already
  1131. know that we need to compile the unit }
  1132. if not do_compile then
  1133. begin
  1134. Message1(unit_u_loading_unit,modulename^);
  1135. search_unit(false,false);
  1136. if not do_compile then
  1137. begin
  1138. load_interface;
  1139. if not do_compile then
  1140. begin
  1141. load_usedunits;
  1142. if not do_compile then
  1143. Message1(unit_u_finished_loading_unit,modulename^);
  1144. end;
  1145. end;
  1146. { PPU is not needed anymore }
  1147. if assigned(ppufile) then
  1148. begin
  1149. ppufile.closefile;
  1150. ppufile.free;
  1151. ppufile:=nil;
  1152. end;
  1153. end;
  1154. { Do we need to recompile the unit }
  1155. if do_compile then
  1156. begin
  1157. { recompile the unit or give a fatal error if sources not available }
  1158. if not(sources_avail) then
  1159. begin
  1160. if (not search_unit(true,false)) and
  1161. (length(modulename^)>8) then
  1162. search_unit(true,true);
  1163. if not(sources_avail) then
  1164. begin
  1165. if recompile_reason=rr_noppu then
  1166. Message1(unit_f_cant_find_ppu,modulename^)
  1167. else
  1168. Message1(unit_f_cant_compile_unit,modulename^);
  1169. end;
  1170. end;
  1171. { Flag modules to reload }
  1172. flagdependent(old_current_module);
  1173. { Reset the module }
  1174. reset;
  1175. { compile this module }
  1176. if not(state in [ms_compile,ms_second_compile]) then
  1177. state:=ms_compile;
  1178. compile(mainsource^);
  1179. end;
  1180. { set compiled flag }
  1181. if current_module<>self then
  1182. internalerror(200212282);
  1183. state:=ms_compiled;
  1184. if in_interface then
  1185. internalerror(200212283);
  1186. { for a second_time recompile reload all dependent units,
  1187. for a first time compile register the unit _once_ }
  1188. if second_time then
  1189. begin
  1190. { now reload all dependent units }
  1191. hp:=tmodule(loaded_units.first);
  1192. while assigned(hp) do
  1193. begin
  1194. if hp.do_reload then
  1195. tppumodule(hp).loadppu;
  1196. hp:=tmodule(hp.next);
  1197. end;
  1198. end
  1199. else
  1200. usedunits.concat(tused_unit.create(self,true,false));
  1201. { reopen the old module }
  1202. {$ifdef SHORT_ON_FILE_HANDLES}
  1203. if old_current_module.is_unit and
  1204. assigned(tppumodule(old_current_module).ppufile) then
  1205. tppumodule(old_current_module).ppufile.tempopen;
  1206. {$endif SHORT_ON_FILE_HANDLES}
  1207. { reload old scanner }
  1208. current_scanner:=tscannerfile(old_current_module.scanner);
  1209. if assigned(current_scanner) then
  1210. begin
  1211. current_scanner.tempopeninputfile;
  1212. current_scanner.gettokenpos
  1213. end
  1214. else
  1215. fillchar(aktfilepos,sizeof(aktfilepos),0);
  1216. end;
  1217. { we are back, restore current_module }
  1218. current_module:=old_current_module;
  1219. SetCompileModule(current_module);
  1220. end;
  1221. {*****************************************************************************
  1222. RegisterUnit
  1223. *****************************************************************************}
  1224. function registerunit(callermodule:tmodule;const s : stringid;const fn:string) : tppumodule;
  1225. var
  1226. ups : stringid;
  1227. hp : tppumodule;
  1228. hp2,
  1229. shortnamehp : tmodule;
  1230. begin
  1231. { Info }
  1232. ups:=upper(s);
  1233. { search all loaded units }
  1234. shortnamehp:=nil;
  1235. hp:=tppumodule(loaded_units.first);
  1236. while assigned(hp) do
  1237. begin
  1238. if hp.modulename^=ups then
  1239. begin
  1240. { only check for units. The main program is also
  1241. as a unit in the loaded_units list. We simply need
  1242. to ignore this entry (PFV) }
  1243. if hp.is_unit then
  1244. begin
  1245. { both units in interface ? }
  1246. if callermodule.in_interface and
  1247. hp.in_interface then
  1248. begin
  1249. { check for a cycle }
  1250. hp2:=callermodule.loaded_from;
  1251. while assigned(hp2) and (hp2<>hp) do
  1252. begin
  1253. if hp2.in_interface then
  1254. hp2:=hp2.loaded_from
  1255. else
  1256. hp2:=nil;
  1257. end;
  1258. if assigned(hp2) then
  1259. Message2(unit_f_circular_unit_reference,callermodule.modulename^,hp.modulename^);
  1260. end;
  1261. break;
  1262. end;
  1263. end
  1264. else
  1265. if copy(hp.modulename^,1,8)=ups then
  1266. shortnamehp:=hp;
  1267. { the next unit }
  1268. hp:=tppumodule(hp.next);
  1269. end;
  1270. if assigned(shortnamehp) and not assigned(hp) then
  1271. Message2(unit_w_unit_name_error,s,shortnamehp.modulename^);
  1272. { the unit is not in the loaded units,
  1273. we create an entry and register the unit }
  1274. if not assigned(hp) then
  1275. begin
  1276. Message1(unit_u_registering_new_unit,Upper(s));
  1277. hp:=tppumodule.create(callermodule,s,fn,true);
  1278. hp.loaded_from:=callermodule;
  1279. loaded_units.insert(hp);
  1280. end;
  1281. { return }
  1282. registerunit:=hp;
  1283. end;
  1284. end.
  1285. {
  1286. $Log$
  1287. Revision 1.37 2003-06-08 11:40:14 peter
  1288. * moved message to msg file
  1289. Revision 1.36 2003/06/07 20:26:32 peter
  1290. * re-resolving added instead of reloading from ppu
  1291. * tderef object added to store deref info for resolving
  1292. Revision 1.35 2003/05/25 10:27:12 peter
  1293. * moved Comment calls to messge file
  1294. Revision 1.34 2003/05/23 17:04:37 peter
  1295. * write interface crc to .ppu.intf when enabled
  1296. * when a unit is compiled with -Ur check only interface crc
  1297. Revision 1.33 2003/04/27 11:21:32 peter
  1298. * aktprocdef renamed to current_procdef
  1299. * procinfo renamed to current_procinfo
  1300. * procinfo will now be stored in current_module so it can be
  1301. cleaned up properly
  1302. * gen_main_procsym changed to create_main_proc and release_main_proc
  1303. to also generate a tprocinfo structure
  1304. * fixed unit implicit initfinal
  1305. Revision 1.32 2003/04/27 07:29:50 peter
  1306. * current_procdef cleanup, current_procdef is now always nil when parsing
  1307. a new procdef declaration
  1308. * aktprocsym removed
  1309. * lexlevel removed, use symtable.symtablelevel instead
  1310. * implicit init/final code uses the normal genentry/genexit
  1311. * funcret state checking updated for new funcret handling
  1312. Revision 1.31 2003/04/26 00:30:52 peter
  1313. * reset aktfilepos when setting new module for compile
  1314. Revision 1.30 2003/03/27 17:44:13 peter
  1315. * fixed small mem leaks
  1316. Revision 1.29 2002/12/29 14:57:50 peter
  1317. * unit loading changed to first register units and load them
  1318. afterwards. This is needed to support uses xxx in yyy correctly
  1319. * unit dependency check fixed
  1320. Revision 1.28 2002/12/06 16:56:57 peter
  1321. * only compile cs_fp_emulation support when cpufpuemu is defined
  1322. * define cpufpuemu for m68k only
  1323. Revision 1.27 2002/11/20 12:36:24 mazen
  1324. * $UNITPATH directive is now working
  1325. Revision 1.26 2002/11/15 01:58:46 peter
  1326. * merged changes from 1.0.7 up to 04-11
  1327. - -V option for generating bug report tracing
  1328. - more tracing for option parsing
  1329. - errors for cdecl and high()
  1330. - win32 import stabs
  1331. - win32 records<=8 are returned in eax:edx (turned off by default)
  1332. - heaptrc update
  1333. - more info for temp management in .s file with EXTDEBUG
  1334. Revision 1.25 2002/10/20 14:49:31 peter
  1335. * store original source time in ppu so it can be compared instead of
  1336. comparing with the ppu time
  1337. Revision 1.24 2002/10/04 20:13:10 peter
  1338. * set in_second_load flag before resetting the module, this is
  1339. required to skip some checkings
  1340. Revision 1.23 2002/08/19 19:36:42 peter
  1341. * More fixes for cross unit inlining, all tnodes are now implemented
  1342. * Moved pocall_internconst to po_internconst because it is not a
  1343. calling type at all and it conflicted when inlining of these small
  1344. functions was requested
  1345. Revision 1.22 2002/08/18 19:58:28 peter
  1346. * more current_scanner fixes
  1347. Revision 1.21 2002/08/15 15:09:41 carl
  1348. + fpu emulation helpers (ppu checking also)
  1349. Revision 1.20 2002/08/12 16:46:04 peter
  1350. * tscannerfile is now destroyed in tmodule.reset and current_scanner
  1351. is updated accordingly. This removes all the loading and saving of
  1352. the old scanner and the invalid flag marking
  1353. Revision 1.19 2002/08/11 14:28:19 peter
  1354. * TScannerFile.SetInvalid added that will also reset inputfile
  1355. Revision 1.18 2002/08/11 13:24:11 peter
  1356. * saving of asmsymbols in ppu supported
  1357. * asmsymbollist global is removed and moved into a new class
  1358. tasmlibrarydata that will hold the info of a .a file which
  1359. corresponds with a single module. Added librarydata to tmodule
  1360. to keep the library info stored for the module. In the future the
  1361. objectfiles will also be stored to the tasmlibrarydata class
  1362. * all getlabel/newasmsymbol and friends are moved to the new class
  1363. Revision 1.17 2002/07/26 21:15:37 florian
  1364. * rewrote the system handling
  1365. Revision 1.16 2002/05/16 19:46:36 carl
  1366. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1367. + try to fix temp allocation (still in ifdef)
  1368. + generic constructor calls
  1369. + start of tassembler / tmodulebase class cleanup
  1370. Revision 1.15 2002/05/14 19:34:41 peter
  1371. * removed old logs and updated copyright year
  1372. Revision 1.14 2002/05/12 16:53:05 peter
  1373. * moved entry and exitcode to ncgutil and cgobj
  1374. * foreach gets extra argument for passing local data to the
  1375. iterator function
  1376. * -CR checks also class typecasts at runtime by changing them
  1377. into as
  1378. * fixed compiler to cycle with the -CR option
  1379. * fixed stabs with elf writer, finally the global variables can
  1380. be watched
  1381. * removed a lot of routines from cga unit and replaced them by
  1382. calls to cgobj
  1383. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1384. u32bit then the other is typecasted also to u32bit without giving
  1385. a rangecheck warning/error.
  1386. * fixed pascal calling method with reversing also the high tree in
  1387. the parast, detected by tcalcst3 test
  1388. Revision 1.13 2002/04/04 19:05:56 peter
  1389. * removed unused units
  1390. * use tlocation.size in cg.a_*loc*() routines
  1391. Revision 1.12 2002/03/28 20:46:44 carl
  1392. - remove go32v1 support
  1393. Revision 1.11 2002/01/19 14:20:13 peter
  1394. * check for -Un when loading ppu with wrong name
  1395. }