fppu.pas 52 KB

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