fppu.pas 51 KB

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