fppu.pas 51 KB

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