fppu.pas 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the first loading and searching of the modules
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit fppu;
  18. {$i fpcdefs.inc}
  19. { $define DEBUG_UNIT_CRC_CHANGES}
  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. cmsgs,verbose,
  31. cutils,cclasses,cstreams,
  32. globtype,globals,finput,fmodule,
  33. symbase,ppu,symtype;
  34. type
  35. { tppumodule }
  36. tppumodule = class(tmodule)
  37. ppufile : tcompilerppufile; { the PPU file }
  38. sourcefn : TPathStr; { Source specified with "uses .. in '..'" }
  39. comments : TCmdStrList;
  40. nsprefix : TCmdStr; { Namespace prefix the unit was found with }
  41. {$ifdef Test_Double_checksum}
  42. crc_array : pointer;
  43. crc_size : longint;
  44. crc_array2 : pointer;
  45. crc_size2 : longint;
  46. {$endif def Test_Double_checksum}
  47. constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
  48. destructor destroy;override;
  49. procedure reset;override;
  50. function openppufile:boolean;
  51. function openppustream(strm:TCStream):boolean;
  52. procedure getppucrc;
  53. procedure writeppu;
  54. procedure loadppu;
  55. function needrecompile:boolean;
  56. procedure setdefgeneration;
  57. procedure reload_flagged_units;
  58. procedure end_of_parsing;override;
  59. private
  60. unitimportsymsderefs : tfplist;
  61. { Each time a unit's defs are (re)created, its defsgeneration is
  62. set to the value of a global counter, and the global counter is
  63. increased. We only reresolve its dependent units' defs in case
  64. they have been resolved only for an older generation, in order to
  65. avoid endless resolving loops in case of cyclic dependencies. }
  66. defsgeneration : longint;
  67. function openppu(ppufiletime:longint):boolean;
  68. function search_unit_files(onlysource:boolean):boolean;
  69. function search_unit(onlysource,shortname:boolean):boolean;
  70. function loadfrompackage:boolean;
  71. procedure load_interface;
  72. procedure load_implementation;
  73. procedure load_usedunits;
  74. procedure printcomments;
  75. procedure queuecomment(const s:TMsgStr;v,w:longint);
  76. procedure buildderefunitimportsyms;
  77. procedure derefunitimportsyms;
  78. procedure freederefunitimportsyms;
  79. procedure writesourcefiles;
  80. procedure writeusedunit(intf:boolean);
  81. procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  82. procedure writederefmap;
  83. procedure writederefdata;
  84. procedure writeImportSymbols;
  85. procedure writeResources;
  86. procedure writeOrderedSymbols;
  87. procedure writeunitimportsyms;
  88. procedure writeasmsyms(kind:tunitasmlisttype;list:tfphashobjectlist);
  89. procedure readsourcefiles;
  90. procedure readloadunit;
  91. procedure readlinkcontainer(var p:tlinkcontainer);
  92. procedure readderefmap;
  93. procedure readderefdata;
  94. procedure readImportSymbols;
  95. procedure readResources;
  96. procedure readOrderedSymbols;
  97. procedure readwpofile;
  98. procedure readunitimportsyms;
  99. procedure readasmsyms;
  100. {$IFDEF MACRO_DIFF_HINT}
  101. procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
  102. procedure writeusedmacros;
  103. procedure readusedmacros;
  104. {$ENDIF}
  105. end;
  106. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
  107. implementation
  108. uses
  109. SysUtils,
  110. cfileutl,
  111. systems,version,options,
  112. symtable, symsym,
  113. wpoinfo,
  114. scanner,
  115. aasmbase,ogbase,
  116. parser,
  117. comphook,
  118. entfile,fpkg,fpcp;
  119. var
  120. currentdefgeneration: longint;
  121. {****************************************************************************
  122. TPPUMODULE
  123. ****************************************************************************}
  124. constructor tppumodule.create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
  125. begin
  126. inherited create(LoadedFrom,amodulename,afilename,_is_unit);
  127. ppufile:=nil;
  128. sourcefn:=afilename;
  129. unitimportsymsderefs:=tfplist.create;
  130. end;
  131. destructor tppumodule.Destroy;
  132. begin
  133. if assigned(ppufile) then
  134. ppufile.free;
  135. ppufile:=nil;
  136. comments.free;
  137. comments:=nil;
  138. { all derefs allocated with new
  139. are dispose'd inside this method }
  140. freederefunitimportsyms;
  141. unitimportsymsderefs.free;
  142. unitimportsymsderefs:=nil;
  143. inherited Destroy;
  144. end;
  145. procedure tppumodule.reset;
  146. begin
  147. inc(currentdefgeneration);
  148. if assigned(ppufile) then
  149. begin
  150. ppufile.free;
  151. ppufile:=nil;
  152. end;
  153. freederefunitimportsyms;
  154. unitimportsymsderefs.free;
  155. unitimportsymsderefs:=tfplist.create;
  156. inherited reset;
  157. end;
  158. procedure tppumodule.queuecomment(const s:TMsgStr;v,w:longint);
  159. begin
  160. if comments = nil then
  161. comments := TCmdStrList.create;
  162. comments.insert(s);
  163. end;
  164. procedure tppumodule.printcomments;
  165. var
  166. comment: string;
  167. begin
  168. if comments = nil then
  169. exit;
  170. { comments are inserted in reverse order }
  171. repeat
  172. comment := comments.getlast;
  173. if length(comment) = 0 then
  174. exit;
  175. do_comment(v_normal, comment);
  176. until false;
  177. end;
  178. function tppumodule.openppufile:boolean;
  179. var
  180. ppufiletime : longint;
  181. begin
  182. openppufile:=false;
  183. Message1(unit_t_ppu_loading,ppufilename,@queuecomment);
  184. { Get ppufile time (also check if the file exists) }
  185. ppufiletime:=getnamedfiletime(ppufilename);
  186. if ppufiletime=-1 then
  187. exit;
  188. { Open the ppufile }
  189. Message1(unit_u_ppu_name,ppufilename);
  190. ppufile:=tcompilerppufile.create(ppufilename);
  191. if not ppufile.openfile then
  192. begin
  193. ppufile.free;
  194. ppufile:=nil;
  195. Message(unit_u_ppu_file_too_short);
  196. exit;
  197. end;
  198. result:=openppu(ppufiletime);
  199. end;
  200. function tppumodule.openppustream(strm:TCStream):boolean;
  201. begin
  202. result:=false;
  203. { Open the ppufile }
  204. Message1(unit_u_ppu_name,ppufilename);
  205. ppufile:=tcompilerppufile.create(ppufilename);
  206. if not ppufile.openstream(strm) then
  207. begin
  208. ppufile.free;
  209. ppufile:=nil;
  210. Message(unit_u_ppu_file_too_short);
  211. exit;
  212. end;
  213. result:=openppu(-1);
  214. end;
  215. function tppumodule.openppu(ppufiletime:longint):boolean;
  216. begin
  217. openppu:=false;
  218. { check for a valid PPU file }
  219. if not ppufile.CheckPPUId then
  220. begin
  221. ppufile.free;
  222. ppufile:=nil;
  223. Message(unit_u_ppu_invalid_header);
  224. exit;
  225. end;
  226. { check for allowed PPU versions }
  227. if not (ppufile.getversion = CurrentPPUVersion) then
  228. begin
  229. Message1(unit_u_ppu_invalid_version,tostr(ppufile.getversion),@queuecomment);
  230. ppufile.free;
  231. ppufile:=nil;
  232. exit;
  233. end;
  234. { check the target processor }
  235. if tsystemcpu(ppufile.header.common.cpu)<>target_cpu then
  236. begin
  237. ppufile.free;
  238. ppufile:=nil;
  239. Message(unit_u_ppu_invalid_processor,@queuecomment);
  240. exit;
  241. end;
  242. { check target }
  243. if tsystem(ppufile.header.common.target)<>target_info.system then
  244. begin
  245. ppufile.free;
  246. ppufile:=nil;
  247. Message(unit_u_ppu_invalid_target,@queuecomment);
  248. exit;
  249. end;
  250. {$ifdef i8086}
  251. { check i8086 memory model flags }
  252. if ((ppufile.header.common.flags and uf_i8086_far_code)<>0) xor
  253. (current_settings.x86memorymodel in [mm_medium,mm_large,mm_huge]) then
  254. begin
  255. ppufile.free;
  256. ppufile:=nil;
  257. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  258. exit;
  259. end;
  260. if ((ppufile.header.common.flags and uf_i8086_far_data)<>0) xor
  261. (current_settings.x86memorymodel in [mm_compact,mm_large]) then
  262. begin
  263. ppufile.free;
  264. ppufile:=nil;
  265. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  266. exit;
  267. end;
  268. if ((ppufile.header.common.flags and uf_i8086_huge_data)<>0) xor
  269. (current_settings.x86memorymodel=mm_huge) then
  270. begin
  271. ppufile.free;
  272. ppufile:=nil;
  273. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  274. exit;
  275. end;
  276. if ((ppufile.header.common.flags and uf_i8086_cs_equals_ds)<>0) xor
  277. (current_settings.x86memorymodel=mm_tiny) then
  278. begin
  279. ppufile.free;
  280. ppufile:=nil;
  281. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  282. exit;
  283. end;
  284. if ((ppufile.header.common.flags and uf_i8086_ss_equals_ds)<>0) xor
  285. (current_settings.x86memorymodel in [mm_tiny,mm_small,mm_medium]) then
  286. begin
  287. ppufile.free;
  288. ppufile:=nil;
  289. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  290. exit;
  291. end;
  292. {$endif i8086}
  293. {$ifdef cpufpemu}
  294. { check if floating point emulation is on?
  295. fpu emulation isn't unit levelwise because it affects calling convention }
  296. if ((ppufile.header.common.flags and uf_fpu_emulation)<>0) xor
  297. (cs_fp_emulation in current_settings.moduleswitches) then
  298. begin
  299. ppufile.free;
  300. ppufile:=nil;
  301. Message(unit_u_ppu_invalid_fpumode,@queuecomment);
  302. exit;
  303. end;
  304. {$endif cpufpemu}
  305. { Load values to be access easier }
  306. flags:=ppufile.header.common.flags;
  307. crc:=ppufile.header.checksum;
  308. interface_crc:=ppufile.header.interface_checksum;
  309. indirect_crc:=ppufile.header.indirect_checksum;
  310. change_endian:=ppufile.change_endian;
  311. { Show Debug info }
  312. if ppufiletime<>-1 then
  313. Message1(unit_u_ppu_time,filetimestring(ppufiletime))
  314. else
  315. Message1(unit_u_ppu_time,'unknown');
  316. Message1(unit_u_ppu_flags,tostr(flags));
  317. Message1(unit_u_ppu_crc,hexstr(ppufile.header.checksum,8));
  318. Message1(unit_u_ppu_crc,hexstr(ppufile.header.interface_checksum,8)+' (intfc)');
  319. Message1(unit_u_ppu_crc,hexstr(ppufile.header.indirect_checksum,8)+' (indc)');
  320. Comment(V_used,'Number of definitions: '+tostr(ppufile.header.deflistsize));
  321. Comment(V_used,'Number of symbols: '+tostr(ppufile.header.symlistsize));
  322. do_compile:=false;
  323. openppu:=true;
  324. end;
  325. function tppumodule.search_unit_files(onlysource:boolean):boolean;
  326. var
  327. found : boolean;
  328. begin
  329. found:=false;
  330. if search_unit(onlysource,false) then
  331. found:=true;
  332. if (not found) and
  333. (length(modulename^)>8) and
  334. search_unit(onlysource,true) then
  335. found:=true;
  336. search_unit_files:=found;
  337. end;
  338. function tppumodule.search_unit(onlysource,shortname:boolean):boolean;
  339. var
  340. singlepathstring,
  341. filename : TCmdStr;
  342. Function UnitExists(const ext:string;var foundfile:TCmdStr;const prefix:TCmdStr):boolean;
  343. var
  344. s : tcmdstr;
  345. begin
  346. if CheckVerbosity(V_Tried) then
  347. Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
  348. s:=FileName+ext;
  349. if prefix<>'' then
  350. s:=prefix+'.'+s;
  351. UnitExists:=FindFile(s,Singlepathstring,true,foundfile);
  352. end;
  353. Function PPUSearchPath(const s,prefix:TCmdStr):boolean;
  354. var
  355. found : boolean;
  356. hs,
  357. newname : TCmdStr;
  358. begin
  359. Found:=false;
  360. singlepathstring:=FixPath(s,false);
  361. { Check for PPU file }
  362. Found:=UnitExists(target_info.unitext,hs,prefix);
  363. if Found then
  364. Begin
  365. SetFileName(hs,false);
  366. if prefix<>'' then
  367. begin
  368. newname:=prefix+'.'+realmodulename^;
  369. stringdispose(realmodulename);
  370. realmodulename:=stringdup(newname);
  371. stringdispose(modulename);
  372. modulename:=stringdup(upper(newname));
  373. end;
  374. Found:=openppufile;
  375. End;
  376. PPUSearchPath:=Found;
  377. end;
  378. Function SourceSearchPath(const s,prefix:TCmdStr):boolean;
  379. var
  380. found : boolean;
  381. hs,
  382. newname : TCmdStr;
  383. begin
  384. Found:=false;
  385. singlepathstring:=FixPath(s,false);
  386. { Check for Sources }
  387. ppufile:=nil;
  388. do_compile:=true;
  389. recompile_reason:=rr_noppu;
  390. {Check for .pp file}
  391. Found:=UnitExists(sourceext,hs,prefix);
  392. if not Found then
  393. begin
  394. { Check for .pas }
  395. Found:=UnitExists(pasext,hs,prefix);
  396. end;
  397. if not Found and
  398. ((m_mac in current_settings.modeswitches) or
  399. (tf_p_ext_support in target_info.flags)) then
  400. begin
  401. { Check for .p, if mode is macpas}
  402. Found:=UnitExists(pext,hs,prefix);
  403. end;
  404. mainsource:='';
  405. if Found then
  406. begin
  407. sources_avail:=true;
  408. { Load Filenames when found }
  409. mainsource:=hs;
  410. SetFileName(hs,false);
  411. if prefix<>'' then
  412. begin
  413. newname:=prefix+'.'+realmodulename^;
  414. stringdispose(realmodulename);
  415. realmodulename:=stringdup(newname);
  416. stringdispose(modulename);
  417. modulename:=stringdup(upper(newname));
  418. end;
  419. end
  420. else
  421. sources_avail:=false;
  422. SourceSearchPath:=Found;
  423. end;
  424. Function SearchPath(const s,prefix:TCmdStr):boolean;
  425. var
  426. found : boolean;
  427. begin
  428. { First check for a ppu, then for the source }
  429. found:=false;
  430. if not onlysource then
  431. found:=PPUSearchPath(s,prefix);
  432. if not found then
  433. found:=SourceSearchPath(s,prefix);
  434. SearchPath:=found;
  435. end;
  436. Function SearchPathList(list:TSearchPathList;const prefix:TCmdStr):boolean;
  437. var
  438. hp : TCmdStrListItem;
  439. found : boolean;
  440. begin
  441. found:=false;
  442. hp:=TCmdStrListItem(list.First);
  443. while assigned(hp) do
  444. begin
  445. found:=SearchPath(hp.Str,prefix);
  446. if found then
  447. break;
  448. hp:=TCmdStrListItem(hp.next);
  449. end;
  450. SearchPathList:=found;
  451. end;
  452. function SearchPPUPaths(const prefix:TCmdStr):boolean;
  453. begin
  454. result:=PPUSearchPath('.',prefix);
  455. if (not result) and (outputpath<>'') then
  456. result:=PPUSearchPath(outputpath,prefix);
  457. if (not result) and Assigned(main_module) and (main_module.Path<>'') then
  458. result:=PPUSearchPath(main_module.Path,prefix);
  459. end;
  460. function SearchSourcePaths(const prefix:TCmdStr):boolean;
  461. begin
  462. result:=SourceSearchPath('.',prefix);
  463. if (not result) and Assigned(main_module) and (main_module.Path<>'') then
  464. result:=SourceSearchPath(main_module.Path,prefix);
  465. if (not result) and Assigned(loaded_from) then
  466. result:=SearchPathList(loaded_from.LocalUnitSearchPath,prefix);
  467. if not result then
  468. result:=SearchPathList(UnitSearchPath,prefix);
  469. end;
  470. var
  471. fnd : boolean;
  472. hs : TPathStr;
  473. nsitem : TCmdStrListItem;
  474. begin
  475. if shortname then
  476. filename:=FixFileName(Copy(realmodulename^,1,8))
  477. else
  478. filename:=FixFileName(realmodulename^);
  479. { try to find unit
  480. 1. look for ppu in cwd
  481. 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
  482. 3. look for ppu in maindir
  483. 4. look for the specified source file (from the uses line)
  484. 5. look for source in cwd
  485. 6. look for source in maindir
  486. 7. local unit pathlist
  487. 8. global unit pathlist
  488. 9. for each default namespace:
  489. repeat 1 - 3 and 5 - 8 with namespace as prefix }
  490. fnd:=false;
  491. if not onlysource then
  492. fnd:=SearchPPUPaths('');
  493. if (not fnd) and (sourcefn<>'') then
  494. begin
  495. { the full filename is specified so we can't use here the
  496. searchpath (PFV) }
  497. if CheckVerbosity(V_Tried) then
  498. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,sourceext));
  499. fnd:=FindFile(ChangeFileExt(sourcefn,sourceext),'',true,hs);
  500. if not fnd then
  501. begin
  502. if CheckVerbosity(V_Tried) then
  503. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,pasext));
  504. fnd:=FindFile(ChangeFileExt(sourcefn,pasext),'',true,hs);
  505. end;
  506. if not fnd and
  507. ((m_mac in current_settings.modeswitches) or
  508. (tf_p_ext_support in target_info.flags)) then
  509. begin
  510. if CheckVerbosity(V_Tried) then
  511. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,pext));
  512. fnd:=FindFile(ChangeFileExt(sourcefn,pext),'',true,hs);
  513. end;
  514. if fnd then
  515. begin
  516. sources_avail:=true;
  517. do_compile:=true;
  518. recompile_reason:=rr_noppu;
  519. mainsource:=hs;
  520. SetFileName(hs,false);
  521. end;
  522. end;
  523. if not fnd then
  524. begin
  525. fnd:=SearchSourcePaths('');
  526. if not fnd and (namespacelist.count>0) then
  527. begin
  528. nsitem:=TCmdStrListItem(namespacelist.first);
  529. while assigned(nsitem) do
  530. begin
  531. if not onlysource then
  532. begin
  533. fnd:=SearchPPUPaths(nsitem.str);
  534. if fnd then
  535. break;
  536. end;
  537. fnd:=SearchSourcePaths(nsitem.str);
  538. if fnd then
  539. break;
  540. nsitem:=TCmdStrListItem(nsitem.next);
  541. end;
  542. if assigned(nsitem) then
  543. nsprefix:=nsitem.str;
  544. end;
  545. end;
  546. search_unit:=fnd;
  547. end;
  548. function tppumodule.loadfrompackage: boolean;
  549. (*var
  550. singlepathstring,
  551. filename : TCmdStr;
  552. Function UnitExists(const ext:string;var foundfile:TCmdStr):boolean;
  553. begin
  554. if CheckVerbosity(V_Tried) then
  555. Message1(unit_t_unitsearch,Singlepathstring+filename);
  556. UnitExists:=FindFile(FileName,Singlepathstring,true,foundfile);
  557. end;
  558. Function PPUSearchPath(const s:TCmdStr):boolean;
  559. var
  560. found : boolean;
  561. hs : TCmdStr;
  562. begin
  563. Found:=false;
  564. singlepathstring:=FixPath(s,false);
  565. { Check for PPU file }
  566. Found:=UnitExists(target_info.unitext,hs);
  567. if Found then
  568. Begin
  569. SetFileName(hs,false);
  570. //Found:=OpenPPU;
  571. End;
  572. PPUSearchPath:=Found;
  573. end;
  574. Function SearchPathList(list:TSearchPathList):boolean;
  575. var
  576. hp : TCmdStrListItem;
  577. found : boolean;
  578. begin
  579. found:=false;
  580. hp:=TCmdStrListItem(list.First);
  581. while assigned(hp) do
  582. begin
  583. found:=PPUSearchPath(hp.Str);
  584. if found then
  585. break;
  586. hp:=TCmdStrListItem(hp.next);
  587. end;
  588. SearchPathList:=found;
  589. end;*)
  590. var
  591. pkg : ppackageentry;
  592. pkgunit : pcontainedunit;
  593. i,idx : longint;
  594. strm : TCStream;
  595. begin
  596. result:=false;
  597. for i:=0 to packagelist.count-1 do
  598. begin
  599. pkg:=ppackageentry(packagelist[i]);
  600. if not assigned(pkg^.package) then
  601. internalerror(2013053103);
  602. idx:=pkg^.package.containedmodules.FindIndexOf(modulename^);
  603. if idx>=0 then
  604. begin
  605. { the unit is part of this package }
  606. pkgunit:=pcontainedunit(pkg^.package.containedmodules[idx]);
  607. if not assigned(pkgunit^.module) then
  608. pkgunit^.module:=self;
  609. { ToDo: check whether we really don't need this anymore }
  610. {filename:=pkgunit^.ppufile;
  611. if not SearchPathList(unitsearchpath) then
  612. exit};
  613. strm:=tpcppackage(pkg^.package).getmodulestream(self);
  614. if not assigned(strm) then
  615. internalerror(2015103002);
  616. if not openppustream(strm) then
  617. exit;
  618. package:=pkg^.package;
  619. Message2(unit_u_loading_from_package,modulename^,pkg^.package.packagename^);
  620. { now load the unit and all used units }
  621. load_interface;
  622. setdefgeneration;
  623. load_usedunits;
  624. Message1(unit_u_finished_loading_unit,modulename^);
  625. result:=true;
  626. break;
  627. end;
  628. end;
  629. end;
  630. procedure tppumodule.buildderefunitimportsyms;
  631. var
  632. i : longint;
  633. deref : pderef;
  634. begin
  635. for i:=0 to unitimportsyms.count-1 do
  636. begin
  637. new(deref);
  638. deref^.build(unitimportsyms[i]);
  639. unitimportsymsderefs.add(deref);
  640. end;
  641. end;
  642. procedure tppumodule.derefunitimportsyms;
  643. var
  644. i : longint;
  645. sym : tsym;
  646. begin
  647. for i:=0 to unitimportsymsderefs.count-1 do
  648. begin
  649. sym:=tsym(pderef(unitimportsymsderefs[i])^.resolve);
  650. unitimportsyms.add(sym);
  651. end;
  652. end;
  653. procedure tppumodule.freederefunitimportsyms;
  654. var
  655. i : longint;
  656. deref : pderef;
  657. begin
  658. for i:=0 to unitimportsymsderefs.count-1 do
  659. begin
  660. deref:=pderef(unitimportsymsderefs[i]);
  661. system.dispose(deref);
  662. end;
  663. end;
  664. {**********************************
  665. PPU Reading/Writing Helpers
  666. ***********************************}
  667. {$IFDEF MACRO_DIFF_HINT}
  668. var
  669. is_initial: Boolean;
  670. procedure tppumodule.writeusedmacro(p:TNamedIndexItem;arg:pointer);
  671. begin
  672. if tmacro(p).is_used or is_initial then
  673. begin
  674. ppufile.putstring(p.name);
  675. ppufile.putboolean(is_initial);
  676. ppufile.putboolean(tmacro(p).is_used);
  677. end;
  678. end;
  679. procedure tppumodule.writeusedmacros;
  680. begin
  681. ppufile.do_crc:=false;
  682. is_initial:= true;
  683. initialmacrosymtable.foreach(@writeusedmacro,nil);
  684. is_initial:= false;
  685. if assigned(globalmacrosymtable) then
  686. globalmacrosymtable.foreach(@writeusedmacro,nil);
  687. localmacrosymtable.foreach(@writeusedmacro,nil);
  688. ppufile.writeentry(ibusedmacros);
  689. ppufile.do_crc:=true;
  690. end;
  691. {$ENDIF}
  692. procedure tppumodule.writesourcefiles;
  693. var
  694. hp : tinputfile;
  695. i,j : longint;
  696. begin
  697. { second write the used source files }
  698. ppufile.do_crc:=false;
  699. hp:=sourcefiles.files;
  700. { write source files directly in good order }
  701. j:=0;
  702. while assigned(hp) do
  703. begin
  704. inc(j);
  705. hp:=hp.ref_next;
  706. end;
  707. while j>0 do
  708. begin
  709. hp:=sourcefiles.files;
  710. for i:=1 to j-1 do
  711. hp:=hp.ref_next;
  712. ppufile.putstring(hp.inc_path+hp.name);
  713. ppufile.putlongint(hp.getfiletime);
  714. dec(j);
  715. end;
  716. ppufile.writeentry(ibsourcefiles);
  717. ppufile.do_crc:=true;
  718. end;
  719. procedure tppumodule.writeusedunit(intf:boolean);
  720. var
  721. hp : tused_unit;
  722. oldcrc : boolean;
  723. begin
  724. { write a reference for each used unit }
  725. hp:=tused_unit(used_units.first);
  726. while assigned(hp) do
  727. begin
  728. if hp.in_interface=intf then
  729. begin
  730. ppufile.putstring(hp.u.realmodulename^);
  731. { the checksum should not affect the crc of this unit ! (PFV) }
  732. oldcrc:=ppufile.do_crc;
  733. ppufile.do_crc:=false;
  734. ppufile.putlongint(longint(hp.checksum));
  735. ppufile.putlongint(longint(hp.interface_checksum));
  736. ppufile.putlongint(longint(hp.indirect_checksum));
  737. ppufile.do_crc:=oldcrc;
  738. { combine all indirect checksums from units used by this unit }
  739. if intf then
  740. ppufile.indirect_crc:=ppufile.indirect_crc xor hp.indirect_checksum;
  741. end;
  742. hp:=tused_unit(hp.next);
  743. end;
  744. ppufile.do_interface_crc:=true;
  745. ppufile.writeentry(ibloadunit);
  746. end;
  747. procedure tppumodule.writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  748. var
  749. hcontainer : tlinkcontainer;
  750. s : TPathStr;
  751. mask : cardinal;
  752. begin
  753. hcontainer:=TLinkContainer.Create;
  754. while not p.empty do
  755. begin
  756. s:=p.get(mask);
  757. if strippath then
  758. ppufile.putstring(ExtractFileName(s))
  759. else
  760. ppufile.putstring(s);
  761. ppufile.putlongint(mask);
  762. hcontainer.add(s,mask);
  763. end;
  764. ppufile.writeentry(id);
  765. p.Free;
  766. p:=hcontainer;
  767. end;
  768. procedure tppumodule.writederefmap;
  769. var
  770. i : longint;
  771. oldcrc : boolean;
  772. begin
  773. { This does not influence crc }
  774. oldcrc:=ppufile.do_crc;
  775. ppufile.do_crc:=false;
  776. { The unit map used for resolving }
  777. ppufile.putlongint(derefmapcnt);
  778. for i:=0 to derefmapcnt-1 do
  779. begin
  780. if not assigned(derefmap[i].u) then
  781. internalerror(2005011512);
  782. ppufile.putstring(derefmap[i].u.modulename^)
  783. end;
  784. ppufile.writeentry(ibderefmap);
  785. ppufile.do_crc:=oldcrc;
  786. end;
  787. procedure tppumodule.writederefdata;
  788. var
  789. oldcrc : boolean;
  790. len,hlen : longint;
  791. buf : array[0..1023] of byte;
  792. begin
  793. if longword(derefdataintflen)>derefdata.size then
  794. internalerror(200310223);
  795. derefdata.seek(0);
  796. { Write interface data }
  797. len:=derefdataintflen;
  798. while (len>0) do
  799. begin
  800. if len>1024 then
  801. hlen:=1024
  802. else
  803. hlen:=len;
  804. derefdata.read(buf,hlen);
  805. ppufile.putdata(buf,hlen);
  806. dec(len,hlen);
  807. end;
  808. { Write implementation data, this does not influence crc }
  809. oldcrc:=ppufile.do_crc;
  810. ppufile.do_crc:=false;
  811. len:=derefdata.size-derefdataintflen;
  812. while (len>0) do
  813. begin
  814. if len>1024 then
  815. hlen:=1024
  816. else
  817. hlen:=len;
  818. derefdata.read(buf,hlen);
  819. ppufile.putdata(buf,hlen);
  820. dec(len,hlen);
  821. end;
  822. if derefdata.pos<>derefdata.size then
  823. internalerror(200310224);
  824. ppufile.do_crc:=oldcrc;
  825. ppufile.writeentry(ibderefdata);
  826. end;
  827. procedure tppumodule.writeImportSymbols;
  828. var
  829. i,j : longint;
  830. ImportLibrary : TImportLibrary;
  831. ImportSymbol : TImportSymbol;
  832. begin
  833. for i:=0 to ImportLibraryList.Count-1 do
  834. begin
  835. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  836. ppufile.putstring(ImportLibrary.Name);
  837. ppufile.putlongint(ImportLibrary.ImportSymbolList.Count);
  838. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  839. begin
  840. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  841. ppufile.putstring(ImportSymbol.Name);
  842. ppufile.putstring(ImportSymbol.MangledName);
  843. ppufile.putlongint(ImportSymbol.OrdNr);
  844. ppufile.putbyte(byte(ImportSymbol.IsVar));
  845. end;
  846. end;
  847. ppufile.writeentry(ibImportSymbols);
  848. end;
  849. procedure tppumodule.writeResources;
  850. var
  851. res : TCmdStrListItem;
  852. begin
  853. res:=TCmdStrListItem(ResourceFiles.First);
  854. while res<>nil do
  855. begin
  856. ppufile.putstring(res.FPStr);
  857. res:=TCmdStrListItem(res.Next);
  858. end;
  859. ppufile.writeentry(ibresources);
  860. end;
  861. procedure tppumodule.writeOrderedSymbols;
  862. var
  863. res : TCmdStrListItem;
  864. begin
  865. res:=TCmdStrListItem(linkorderedsymbols.First);
  866. while res<>nil do
  867. begin
  868. ppufile.putstring(res.FPStr);
  869. res:=TCmdStrListItem(res.Next);
  870. end;
  871. ppufile.writeentry(iborderedsymbols);
  872. end;
  873. procedure tppumodule.writeunitimportsyms;
  874. var
  875. i : longint;
  876. begin
  877. ppufile.putlongint(unitimportsymsderefs.count);
  878. for i:=0 to unitimportsymsderefs.count-1 do
  879. ppufile.putderef(pderef(unitimportsymsderefs[i])^);
  880. ppufile.writeentry(ibunitimportsyms);
  881. end;
  882. procedure tppumodule.writeasmsyms(kind:tunitasmlisttype;list:tfphashobjectlist);
  883. var
  884. i : longint;
  885. sym : TAsmSymbol;
  886. begin
  887. ppufile.putbyte(ord(kind));
  888. ppufile.putlongint(list.count);
  889. for i:=0 to list.count-1 do
  890. begin
  891. sym:=TAsmSymbol(list[i]);
  892. ppufile.putstring(sym.Name);
  893. ppufile.putbyte(ord(sym.bind));
  894. ppufile.putbyte(ord(sym.typ));
  895. end;
  896. ppufile.writeentry(ibasmsymbols);
  897. end;
  898. {$IFDEF MACRO_DIFF_HINT}
  899. {
  900. Define MACRO_DIFF_HINT for the whole compiler (and ppudump)
  901. to turn this facility on. Also the hint messages defined
  902. below must be commented in in the msg/errore.msg file.
  903. There is some problems with this, thats why it is shut off:
  904. At the first compilation, consider a macro which is not initially
  905. defined, but it is used (e g the check that it is undefined is true).
  906. Since it do not exist, there is no macro object where the is_used
  907. flag can be set. Later on when the macro is defined, and the ppu
  908. is opened, the check cannot detect this.
  909. Also, in which macro object should this flag be set ? It cant be set
  910. for macros in the initialmacrosymboltable since this table is shared
  911. between different files.
  912. }
  913. procedure tppumodule.readusedmacros;
  914. var
  915. hs : string;
  916. mac : tmacro;
  917. was_initial,
  918. was_used : boolean;
  919. {Reads macros which was defined or used when the module was compiled.
  920. This is done when a ppu file is open, before it possibly is parsed.}
  921. begin
  922. while not ppufile.endofentry do
  923. begin
  924. hs:=ppufile.getstring;
  925. was_initial:=ppufile.getboolean;
  926. was_used:=ppufile.getboolean;
  927. mac:=tmacro(initialmacrosymtable.Find(hs));
  928. if assigned(mac) then
  929. begin
  930. {$ifndef EXTDEBUG}
  931. { if we don't have the sources why tell }
  932. if sources_avail then
  933. {$endif ndef EXTDEBUG}
  934. if (not was_initial) and was_used then
  935. Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
  936. end
  937. else { not assigned }
  938. if was_initial and
  939. was_used then
  940. Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
  941. end;
  942. end;
  943. {$ENDIF}
  944. procedure tppumodule.readsourcefiles;
  945. var
  946. temp,hs : string;
  947. inc_path : string;
  948. temp_dir : TCmdStr;
  949. main_dir : TCmdStr;
  950. found,
  951. is_main : boolean;
  952. orgfiletime,
  953. source_time : longint;
  954. hp : tinputfile;
  955. begin
  956. sources_avail:=(flags and uf_release) = 0;
  957. is_main:=true;
  958. main_dir:='';
  959. while not ppufile.endofentry do
  960. begin
  961. hs:=SetDirSeparators(ppufile.getstring);
  962. inc_path:=ExtractFilePath(hs);
  963. orgfiletime:=ppufile.getlongint;
  964. temp_dir:='';
  965. if sources_avail then
  966. begin
  967. if (flags and uf_in_library)<>0 then
  968. begin
  969. sources_avail:=false;
  970. temp:=' library';
  971. end
  972. else if pos('Macro ',hs)=1 then
  973. begin
  974. { we don't want to find this file }
  975. { but there is a problem with file indexing !! }
  976. temp:='';
  977. end
  978. else
  979. begin
  980. { check the date of the source files:
  981. 1 path of ppu
  982. 2 path of main source
  983. 3 current dir
  984. 4 include/unit path }
  985. Source_Time:=GetNamedFileTime(path+hs);
  986. found:=false;
  987. if Source_Time<>-1 then
  988. hs:=path+hs
  989. else
  990. if not(is_main) then
  991. begin
  992. Source_Time:=GetNamedFileTime(main_dir+hs);
  993. if Source_Time<>-1 then
  994. hs:=main_dir+hs;
  995. end;
  996. if Source_Time=-1 then
  997. Source_Time:=GetNamedFileTime(hs);
  998. if (Source_Time=-1) then
  999. begin
  1000. if is_main then
  1001. found:=unitsearchpath.FindFile(hs,true,temp_dir)
  1002. else
  1003. found:=includesearchpath.FindFile(hs,true,temp_dir);
  1004. if found then
  1005. begin
  1006. Source_Time:=GetNamedFileTime(temp_dir);
  1007. if Source_Time<>-1 then
  1008. hs:=temp_dir;
  1009. end;
  1010. end;
  1011. if Source_Time<>-1 then
  1012. begin
  1013. if is_main then
  1014. main_dir:=ExtractFilePath(hs);
  1015. temp:=' time '+filetimestring(source_time);
  1016. if (orgfiletime<>-1) and
  1017. (source_time<>orgfiletime) then
  1018. begin
  1019. do_compile:=true;
  1020. recompile_reason:=rr_sourcenewer;
  1021. Message2(unit_u_source_modified,hs,ppufilename,@queuecomment);
  1022. temp:=temp+' *';
  1023. end;
  1024. end
  1025. else
  1026. begin
  1027. sources_avail:=false;
  1028. temp:=' not found';
  1029. end;
  1030. hp:=tdosinputfile.create(hs);
  1031. hp.inc_path:=inc_path;
  1032. { the indexing is wrong here PM }
  1033. sourcefiles.register_file(hp);
  1034. end;
  1035. end
  1036. else
  1037. begin
  1038. { still register the source module for proper error messages
  1039. since source_avail for the module is still false, this should not hurt }
  1040. sourcefiles.register_file(tdosinputfile.create(hs));
  1041. temp:=' not available';
  1042. end;
  1043. if is_main then
  1044. begin
  1045. mainsource:=hs;
  1046. end;
  1047. Message1(unit_u_ppu_source,hs+temp,@queuecomment);
  1048. is_main:=false;
  1049. end;
  1050. { check if we want to rebuild every unit, only if the sources are
  1051. available }
  1052. if do_build and sources_avail then
  1053. begin
  1054. do_compile:=true;
  1055. recompile_reason:=rr_build;
  1056. end;
  1057. end;
  1058. procedure tppumodule.readloadunit;
  1059. var
  1060. hs : string;
  1061. pu : tused_unit;
  1062. hp : tppumodule;
  1063. indchecksum,
  1064. intfchecksum,
  1065. checksum : cardinal;
  1066. begin
  1067. while not ppufile.endofentry do
  1068. begin
  1069. hs:=ppufile.getstring;
  1070. checksum:=cardinal(ppufile.getlongint);
  1071. intfchecksum:=cardinal(ppufile.getlongint);
  1072. indchecksum:=cardinal(ppufile.getlongint);
  1073. { set the state of this unit before registering, this is
  1074. needed for a correct circular dependency check }
  1075. hp:=registerunit(self,hs,'');
  1076. pu:=addusedunit(hp,false,nil);
  1077. pu.checksum:=checksum;
  1078. pu.interface_checksum:=intfchecksum;
  1079. pu.indirect_checksum:=indchecksum;
  1080. end;
  1081. in_interface:=false;
  1082. end;
  1083. procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
  1084. var
  1085. s : string;
  1086. m : longint;
  1087. begin
  1088. while not ppufile.endofentry do
  1089. begin
  1090. s:=ppufile.getstring;
  1091. m:=ppufile.getlongint;
  1092. p.add(s,m);
  1093. end;
  1094. end;
  1095. procedure tppumodule.readderefmap;
  1096. var
  1097. i : longint;
  1098. begin
  1099. { Load unit map used for resolving }
  1100. derefmapsize:=ppufile.getlongint;
  1101. derefmapcnt:=derefmapsize;
  1102. getmem(derefmap,derefmapsize*sizeof(tderefmaprec));
  1103. fillchar(derefmap^,derefmapsize*sizeof(tderefmaprec),0);
  1104. for i:=0 to derefmapsize-1 do
  1105. derefmap[i].modulename:=ppufile.getpshortstring;
  1106. end;
  1107. procedure tppumodule.readderefdata;
  1108. var
  1109. len,hlen : longint;
  1110. buf : array[0..1023] of byte;
  1111. begin
  1112. len:=ppufile.entrysize;
  1113. while (len>0) do
  1114. begin
  1115. if len>1024 then
  1116. hlen:=1024
  1117. else
  1118. hlen:=len;
  1119. ppufile.getdata(buf,hlen);
  1120. derefdata.write(buf,hlen);
  1121. dec(len,hlen);
  1122. end;
  1123. end;
  1124. procedure tppumodule.readImportSymbols;
  1125. var
  1126. j,
  1127. extsymcnt : longint;
  1128. ImportLibrary : TImportLibrary;
  1129. extsymname : string;
  1130. extsymmangledname : string;
  1131. extsymordnr : longint;
  1132. extsymisvar : boolean;
  1133. begin
  1134. while not ppufile.endofentry do
  1135. begin
  1136. ImportLibrary:=TImportLibrary.Create(ImportLibraryList,ppufile.getstring);
  1137. extsymcnt:=ppufile.getlongint;
  1138. for j:=0 to extsymcnt-1 do
  1139. begin
  1140. extsymname:=ppufile.getstring;
  1141. extsymmangledname:=ppufile.getstring;
  1142. extsymordnr:=ppufile.getlongint;
  1143. extsymisvar:=(ppufile.getbyte<>0);
  1144. TImportSymbol.Create(ImportLibrary.ImportSymbolList,extsymname,
  1145. extsymmangledname,extsymordnr,extsymisvar);
  1146. end;
  1147. end;
  1148. end;
  1149. procedure tppumodule.readResources;
  1150. begin
  1151. while not ppufile.endofentry do
  1152. resourcefiles.Insert(ppufile.getstring);
  1153. end;
  1154. procedure tppumodule.readOrderedSymbols;
  1155. begin
  1156. while not ppufile.endofentry do
  1157. linkorderedsymbols.Concat(ppufile.getstring);
  1158. end;
  1159. procedure tppumodule.readwpofile;
  1160. var
  1161. orgwpofilename: string;
  1162. orgwpofiletime: longint;
  1163. begin
  1164. { check whether we are using the same wpo feedback input file as when
  1165. this unit was compiled (same file name and file date)
  1166. }
  1167. orgwpofilename:=ppufile.getstring;
  1168. orgwpofiletime:=ppufile.getlongint;
  1169. if (extractfilename(orgwpofilename)<>extractfilename(wpofeedbackinput)) or
  1170. (orgwpofiletime<>GetNamedFileTime(orgwpofilename)) then
  1171. { make sure we don't throw away a precompiled unit if the user simply
  1172. forgot to specify the right wpo feedback file
  1173. }
  1174. message3(unit_e_different_wpo_file,ppufilename,orgwpofilename,filetimestring(orgwpofiletime));
  1175. end;
  1176. procedure tppumodule.readunitimportsyms;
  1177. var
  1178. c,i : longint;
  1179. deref : pderef;
  1180. begin
  1181. c:=ppufile.getlongint;
  1182. for i:=0 to c-1 do
  1183. begin
  1184. new(deref);
  1185. ppufile.getderef(deref^);
  1186. unitimportsymsderefs.add(deref);
  1187. end;
  1188. end;
  1189. procedure tppumodule.readasmsyms;
  1190. var
  1191. c,i : longint;
  1192. name : TSymStr;
  1193. bind : TAsmsymbind;
  1194. typ : TAsmsymtype;
  1195. list : tfphashobjectlist;
  1196. begin
  1197. case tunitasmlisttype(ppufile.getbyte) of
  1198. ualt_public:
  1199. list:=publicasmsyms;
  1200. ualt_extern:
  1201. list:=externasmsyms;
  1202. else
  1203. internalerror(2016060301);
  1204. end;
  1205. c:=ppufile.getlongint;
  1206. for i:=0 to c-1 do
  1207. begin
  1208. name:=ppufile.getstring;
  1209. bind:=TAsmsymbind(ppufile.getbyte);
  1210. typ:=TAsmsymtype(ppufile.getbyte);
  1211. TAsmSymbol.Create(list,name,bind,typ);
  1212. end;
  1213. end;
  1214. procedure tppumodule.load_interface;
  1215. var
  1216. b : byte;
  1217. newmodulename : string;
  1218. begin
  1219. { read interface part }
  1220. repeat
  1221. b:=ppufile.readentry;
  1222. case b of
  1223. ibjvmnamespace :
  1224. begin
  1225. namespace:=ppufile.getpshortstring;
  1226. end;
  1227. ibmodulename :
  1228. begin
  1229. newmodulename:=ppufile.getstring;
  1230. if (cs_check_unit_name in current_settings.globalswitches) and
  1231. (upper(newmodulename)<>modulename^) then
  1232. Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
  1233. stringdispose(modulename);
  1234. stringdispose(realmodulename);
  1235. modulename:=stringdup(upper(newmodulename));
  1236. realmodulename:=stringdup(newmodulename);
  1237. end;
  1238. ibfeatures :
  1239. begin
  1240. ppufile.getsmallset(features);
  1241. end;
  1242. ibmoduleoptions:
  1243. begin
  1244. ppufile.getsmallset(moduleoptions);
  1245. if mo_has_deprecated_msg in moduleoptions then
  1246. begin
  1247. stringdispose(deprecatedmsg);
  1248. deprecatedmsg:=ppufile.getpshortstring;
  1249. end;
  1250. end;
  1251. ibsourcefiles :
  1252. readsourcefiles;
  1253. {$IFDEF MACRO_DIFF_HINT}
  1254. ibusedmacros :
  1255. readusedmacros;
  1256. {$ENDIF}
  1257. ibloadunit :
  1258. readloadunit;
  1259. iblinkunitofiles :
  1260. readlinkcontainer(LinkUnitOFiles);
  1261. iblinkunitstaticlibs :
  1262. readlinkcontainer(LinkUnitStaticLibs);
  1263. iblinkunitsharedlibs :
  1264. readlinkcontainer(LinkUnitSharedLibs);
  1265. iblinkotherofiles :
  1266. readlinkcontainer(LinkotherOFiles);
  1267. iblinkotherstaticlibs :
  1268. readlinkcontainer(LinkotherStaticLibs);
  1269. iblinkothersharedlibs :
  1270. readlinkcontainer(LinkotherSharedLibs);
  1271. iblinkotherframeworks :
  1272. readlinkcontainer(LinkOtherFrameworks);
  1273. ibmainname:
  1274. begin
  1275. mainname:=ppufile.getpshortstring;
  1276. if (mainaliasname<>defaultmainaliasname) then
  1277. Message1(scan_w_multiple_main_name_overrides,mainaliasname);
  1278. mainaliasname:=mainname^;
  1279. end;
  1280. ibImportSymbols :
  1281. readImportSymbols;
  1282. ibderefmap :
  1283. readderefmap;
  1284. ibderefdata :
  1285. readderefdata;
  1286. ibresources:
  1287. readResources;
  1288. iborderedsymbols:
  1289. readOrderedSymbols;
  1290. ibwpofile:
  1291. readwpofile;
  1292. ibendinterface :
  1293. break;
  1294. else
  1295. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1296. end;
  1297. { we can already stop when we know that we must recompile }
  1298. if do_compile then
  1299. exit;
  1300. until false;
  1301. end;
  1302. procedure tppumodule.load_implementation;
  1303. var
  1304. b : byte;
  1305. begin
  1306. { read implementation part }
  1307. repeat
  1308. b:=ppufile.readentry;
  1309. case b of
  1310. ibloadunit :
  1311. readloadunit;
  1312. ibasmsymbols :
  1313. readasmsyms;
  1314. ibunitimportsyms:
  1315. readunitimportsyms;
  1316. ibendimplementation :
  1317. break;
  1318. else
  1319. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1320. end;
  1321. until false;
  1322. end;
  1323. procedure tppumodule.writeppu;
  1324. begin
  1325. Message1(unit_u_ppu_write,realmodulename^);
  1326. { create unit flags }
  1327. if do_release then
  1328. flags:=flags or uf_release;
  1329. if assigned(localsymtable) then
  1330. flags:=flags or uf_local_symtable;
  1331. if (cs_checkpointer_called in current_settings.moduleswitches) then
  1332. flags:=flags or uf_checkpointer_called;
  1333. {$ifdef i8086}
  1334. if current_settings.x86memorymodel in [mm_medium,mm_large,mm_huge] then
  1335. flags:=flags or uf_i8086_far_code;
  1336. if current_settings.x86memorymodel in [mm_compact,mm_large] then
  1337. flags:=flags or uf_i8086_far_data;
  1338. if current_settings.x86memorymodel=mm_huge then
  1339. flags:=flags or uf_i8086_huge_data;
  1340. if current_settings.x86memorymodel=mm_tiny then
  1341. flags:=flags or uf_i8086_cs_equals_ds;
  1342. if current_settings.x86memorymodel in [mm_tiny,mm_small,mm_medium] then
  1343. flags:=flags or uf_i8086_ss_equals_ds;
  1344. {$endif i8086}
  1345. {$ifdef cpufpemu}
  1346. if (cs_fp_emulation in current_settings.moduleswitches) then
  1347. flags:=flags or uf_fpu_emulation;
  1348. {$endif cpufpemu}
  1349. {$ifdef Test_Double_checksum_write}
  1350. Assign(CRCFile,s+'.IMP');
  1351. Rewrite(CRCFile);
  1352. {$endif def Test_Double_checksum_write}
  1353. { create new ppufile }
  1354. ppufile:=tcompilerppufile.create(ppufilename);
  1355. if not ppufile.createfile then
  1356. Message(unit_f_ppu_cannot_write);
  1357. { first the (JVM) namespace }
  1358. if assigned(namespace) then
  1359. begin
  1360. ppufile.putstring(namespace^);
  1361. ppufile.writeentry(ibjvmnamespace);
  1362. end;
  1363. { the unitname }
  1364. ppufile.putstring(realmodulename^);
  1365. ppufile.writeentry(ibmodulename);
  1366. ppufile.putsmallset(moduleoptions);
  1367. if mo_has_deprecated_msg in moduleoptions then
  1368. ppufile.putstring(deprecatedmsg^);
  1369. ppufile.writeentry(ibmoduleoptions);
  1370. { write the alternate main procedure name if any }
  1371. if assigned(mainname) then
  1372. begin
  1373. ppufile.putstring(mainname^);
  1374. ppufile.writeentry(ibmainname);
  1375. end;
  1376. if cs_compilesystem in current_settings.moduleswitches then
  1377. begin
  1378. ppufile.putsmallset(features);
  1379. ppufile.writeentry(ibfeatures);
  1380. end;
  1381. writesourcefiles;
  1382. {$IFDEF MACRO_DIFF_HINT}
  1383. writeusedmacros;
  1384. {$ENDIF}
  1385. { write interface uses }
  1386. writeusedunit(true);
  1387. { write the objectfiles and libraries that come for this unit,
  1388. preserve the containers because they are still needed to load
  1389. the link.res.
  1390. All doesn't depend on the crc! It doesn't matter
  1391. if a unit is in a .o or .a file }
  1392. ppufile.do_crc:=false;
  1393. { write after source files, so that we know whether or not the compiler
  1394. will recompile the unit when checking whether the correct wpo file is
  1395. used (if it will recompile the unit anyway, it doesn't matter)
  1396. }
  1397. if (wpofeedbackinput<>'') then
  1398. begin
  1399. ppufile.putstring(wpofeedbackinput);
  1400. ppufile.putlongint(getnamedfiletime(wpofeedbackinput));
  1401. ppufile.writeentry(ibwpofile);
  1402. end;
  1403. writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
  1404. writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
  1405. writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
  1406. writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
  1407. writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
  1408. writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
  1409. writelinkcontainer(linkotherframeworks,iblinkotherframeworks,true);
  1410. writeImportSymbols;
  1411. writeResources;
  1412. writeOrderedSymbols;
  1413. ppufile.do_crc:=true;
  1414. { generate implementation deref data, the interface deref data is
  1415. already generated when calculating the interface crc }
  1416. if (cs_compilesystem in current_settings.moduleswitches) then
  1417. begin
  1418. tstoredsymtable(globalsymtable).buildderef;
  1419. derefdataintflen:=derefdata.size;
  1420. end
  1421. else
  1422. { the unit may have been re-resolved, in which case the current
  1423. position in derefdata is not necessarily at the end }
  1424. derefdata.seek(derefdata.size);
  1425. tstoredsymtable(globalsymtable).buildderefimpl;
  1426. tunitwpoinfo(wpoinfo).buildderef;
  1427. tunitwpoinfo(wpoinfo).buildderefimpl;
  1428. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1429. begin
  1430. tstoredsymtable(globalmacrosymtable).buildderef;
  1431. tstoredsymtable(globalmacrosymtable).buildderefimpl;
  1432. end;
  1433. if (flags and uf_local_symtable)<>0 then
  1434. tstoredsymtable(localsymtable).buildderef_registered;
  1435. buildderefunitimportsyms;
  1436. writederefmap;
  1437. writederefdata;
  1438. ppufile.writeentry(ibendinterface);
  1439. { write the symtable entries }
  1440. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1441. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1442. begin
  1443. ppufile.putbyte(byte(true));
  1444. ppufile.writeentry(ibexportedmacros);
  1445. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1446. end
  1447. else
  1448. begin
  1449. ppufile.putbyte(byte(false));
  1450. ppufile.writeentry(ibexportedmacros);
  1451. end;
  1452. { everything after this doesn't affect the crc }
  1453. ppufile.do_crc:=false;
  1454. { write implementation uses }
  1455. writeusedunit(false);
  1456. { write all public assembler symbols }
  1457. writeasmsyms(ualt_public,publicasmsyms);
  1458. { write all external assembler symbols }
  1459. writeasmsyms(ualt_extern,externasmsyms);
  1460. { write all symbols imported from another unit }
  1461. writeunitimportsyms;
  1462. { end of implementation }
  1463. ppufile.writeentry(ibendimplementation);
  1464. { write static symtable
  1465. needed for local debugging of unit functions }
  1466. if (flags and uf_local_symtable)<>0 then
  1467. tstoredsymtable(localsymtable).ppuwrite(ppufile);
  1468. { write whole program optimisation-related information }
  1469. tunitwpoinfo(wpoinfo).ppuwrite(ppufile);
  1470. { the last entry ibend is written automatically }
  1471. { flush to be sure }
  1472. ppufile.flush;
  1473. { create and write header }
  1474. ppufile.header.common.size:=ppufile.size;
  1475. ppufile.header.checksum:=ppufile.crc;
  1476. ppufile.header.interface_checksum:=ppufile.interface_crc;
  1477. ppufile.header.indirect_checksum:=ppufile.indirect_crc;
  1478. ppufile.header.common.compiler:=wordversion;
  1479. ppufile.header.common.cpu:=word(target_cpu);
  1480. ppufile.header.common.target:=word(target_info.system);
  1481. ppufile.header.common.flags:=flags;
  1482. ppufile.header.deflistsize:=current_module.deflist.count;
  1483. ppufile.header.symlistsize:=current_module.symlist.count;
  1484. ppufile.writeheader;
  1485. { save crc in current module also }
  1486. crc:=ppufile.crc;
  1487. interface_crc:=ppufile.interface_crc;
  1488. indirect_crc:=ppufile.indirect_crc;
  1489. {$ifdef Test_Double_checksum_write}
  1490. close(CRCFile);
  1491. {$endif Test_Double_checksum_write}
  1492. ppufile.closefile;
  1493. ppufile.free;
  1494. ppufile:=nil;
  1495. end;
  1496. procedure tppumodule.getppucrc;
  1497. begin
  1498. {$ifdef Test_Double_checksum_write}
  1499. Assign(CRCFile,s+'.INT')
  1500. Rewrite(CRCFile);
  1501. {$endif def Test_Double_checksum_write}
  1502. { create new ppufile }
  1503. ppufile:=tcompilerppufile.create(ppufilename);
  1504. ppufile.crc_only:=true;
  1505. if not ppufile.createfile then
  1506. Message(unit_f_ppu_cannot_write);
  1507. { first the (JVM) namespace }
  1508. if assigned(namespace) then
  1509. begin
  1510. ppufile.putstring(namespace^);
  1511. ppufile.writeentry(ibjvmnamespace);
  1512. end;
  1513. { the unitname }
  1514. ppufile.putstring(realmodulename^);
  1515. ppufile.writeentry(ibmodulename);
  1516. ppufile.putsmallset(moduleoptions);
  1517. if mo_has_deprecated_msg in moduleoptions then
  1518. ppufile.putstring(deprecatedmsg^);
  1519. ppufile.writeentry(ibmoduleoptions);
  1520. { the interface units affect the crc }
  1521. writeusedunit(true);
  1522. { deref data of interface that affect the crc }
  1523. derefdata.reset;
  1524. tstoredsymtable(globalsymtable).buildderef;
  1525. derefdataintflen:=derefdata.size;
  1526. writederefmap;
  1527. writederefdata;
  1528. ppufile.writeentry(ibendinterface);
  1529. { write the symtable entries }
  1530. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1531. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1532. begin
  1533. ppufile.putbyte(byte(true));
  1534. ppufile.writeentry(ibexportedmacros);
  1535. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1536. end
  1537. else
  1538. begin
  1539. ppufile.putbyte(byte(false));
  1540. ppufile.writeentry(ibexportedmacros);
  1541. end;
  1542. { save crc }
  1543. crc:=ppufile.crc;
  1544. interface_crc:=ppufile.interface_crc;
  1545. indirect_crc:=ppufile.indirect_crc;
  1546. { end of implementation, to generate a correct ppufile
  1547. for ppudump when using INTFPPU define }
  1548. ppufile.writeentry(ibendimplementation);
  1549. {$ifdef Test_Double_checksum}
  1550. crc_array:=ppufile.crc_test;
  1551. ppufile.crc_test:=nil;
  1552. crc_size:=ppufile.crc_index2;
  1553. crc_array2:=ppufile.crc_test2;
  1554. ppufile.crc_test2:=nil;
  1555. crc_size2:=ppufile.crc_index2;
  1556. {$endif Test_Double_checksum}
  1557. {$ifdef Test_Double_checksum_write}
  1558. close(CRCFile);
  1559. {$endif Test_Double_checksum_write}
  1560. { create and write header, this will only be used
  1561. for debugging purposes }
  1562. ppufile.header.common.size:=ppufile.size;
  1563. ppufile.header.checksum:=ppufile.crc;
  1564. ppufile.header.interface_checksum:=ppufile.interface_crc;
  1565. ppufile.header.indirect_checksum:=ppufile.indirect_crc;
  1566. ppufile.header.common.compiler:=wordversion;
  1567. ppufile.header.common.cpu:=word(target_cpu);
  1568. ppufile.header.common.target:=word(target_info.system);
  1569. ppufile.header.common.flags:=flags;
  1570. ppufile.writeheader;
  1571. ppufile.closefile;
  1572. ppufile.free;
  1573. ppufile:=nil;
  1574. end;
  1575. procedure tppumodule.load_usedunits;
  1576. var
  1577. pu : tused_unit;
  1578. begin
  1579. if current_module<>self then
  1580. internalerror(200212284);
  1581. { load the used units from interface }
  1582. in_interface:=true;
  1583. pu:=tused_unit(used_units.first);
  1584. while assigned(pu) do
  1585. begin
  1586. if pu.in_interface then
  1587. begin
  1588. tppumodule(pu.u).loadppu;
  1589. { if this unit is compiled we can stop }
  1590. if state=ms_compiled then
  1591. exit;
  1592. { add this unit to the dependencies }
  1593. pu.u.adddependency(self);
  1594. { need to recompile the current unit, check the interface
  1595. crc. And when not compiled with -Ur then check the complete
  1596. crc }
  1597. if (pu.u.interface_crc<>pu.interface_checksum) or
  1598. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1599. (
  1600. ((ppufile.header.common.flags and uf_release)=0) and
  1601. (pu.u.crc<>pu.checksum)
  1602. ) then
  1603. begin
  1604. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename,@queuecomment);
  1605. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1606. if (pu.u.interface_crc<>pu.interface_checksum) then
  1607. writeln(' intfcrc change: ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1608. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1609. writeln(' indcrc change: ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
  1610. else
  1611. writeln(' implcrc change: ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
  1612. {$endif DEBUG_UNIT_CRC_CHANGES}
  1613. recompile_reason:=rr_crcchanged;
  1614. do_compile:=true;
  1615. exit;
  1616. end;
  1617. end;
  1618. pu:=tused_unit(pu.next);
  1619. end;
  1620. { ok, now load the interface of this unit }
  1621. if current_module<>self then
  1622. internalerror(200208187);
  1623. deflist.count:=ppufile.header.deflistsize;
  1624. symlist.count:=ppufile.header.symlistsize;
  1625. globalsymtable:=tglobalsymtable.create(modulename^,moduleid);
  1626. tstoredsymtable(globalsymtable).ppuload(ppufile);
  1627. if ppufile.readentry<>ibexportedmacros then
  1628. Message(unit_f_ppu_read_error);
  1629. if boolean(ppufile.getbyte) then
  1630. begin
  1631. globalmacrosymtable:=tmacrosymtable.Create(true);
  1632. tstoredsymtable(globalmacrosymtable).ppuload(ppufile)
  1633. end;
  1634. interface_compiled:=true;
  1635. { read the implementation part, containing
  1636. the implementation uses and ObjData }
  1637. in_interface:=false;
  1638. load_implementation;
  1639. { now only read the implementation uses }
  1640. pu:=tused_unit(used_units.first);
  1641. while assigned(pu) do
  1642. begin
  1643. if (not pu.in_interface) then
  1644. begin
  1645. tppumodule(pu.u).loadppu;
  1646. { if this unit is compiled we can stop }
  1647. if state=ms_compiled then
  1648. exit;
  1649. { add this unit to the dependencies }
  1650. pu.u.adddependency(self);
  1651. { need to recompile the current unit ? }
  1652. if (pu.u.interface_crc<>pu.interface_checksum) or
  1653. (pu.u.indirect_crc<>pu.indirect_checksum) then
  1654. begin
  1655. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename+' {impl}',@queuecomment);
  1656. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1657. if (pu.u.interface_crc<>pu.interface_checksum) then
  1658. writeln(' intfcrc change (2): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1659. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1660. writeln(' indcrc change (2): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8));
  1661. {$endif DEBUG_UNIT_CRC_CHANGES}
  1662. recompile_reason:=rr_crcchanged;
  1663. do_compile:=true;
  1664. exit;
  1665. end;
  1666. end;
  1667. pu:=tused_unit(pu.next);
  1668. end;
  1669. { load implementation symtable }
  1670. if (flags and uf_local_symtable)<>0 then
  1671. begin
  1672. localsymtable:=tstaticsymtable.create(modulename^,moduleid);
  1673. tstaticsymtable(localsymtable).ppuload(ppufile);
  1674. end;
  1675. { we can now derefence all pointers to the implementation parts }
  1676. tstoredsymtable(globalsymtable).derefimpl(false);
  1677. { we've just loaded the localsymtable from the ppu file, so everything
  1678. in it was registered by definition (otherwise it wouldn't have been in
  1679. there) }
  1680. if assigned(localsymtable) then
  1681. tstoredsymtable(localsymtable).derefimpl(false);
  1682. derefunitimportsyms;
  1683. { read whole program optimisation-related information }
  1684. wpoinfo:=tunitwpoinfo.ppuload(ppufile);
  1685. tunitwpoinfo(wpoinfo).deref;
  1686. tunitwpoinfo(wpoinfo).derefimpl;
  1687. end;
  1688. function tppumodule.needrecompile:boolean;
  1689. var
  1690. pu : tused_unit;
  1691. begin
  1692. result:=false;
  1693. pu:=tused_unit(used_units.first);
  1694. while assigned(pu) do
  1695. begin
  1696. { need to recompile the current unit, check the interface
  1697. crc. And when not compiled with -Ur then check the complete
  1698. crc }
  1699. if (pu.u.interface_crc<>pu.interface_checksum) or
  1700. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1701. (
  1702. (pu.in_interface) and
  1703. (pu.u.crc<>pu.checksum)
  1704. ) then
  1705. begin
  1706. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1707. if (pu.u.interface_crc<>pu.interface_checksum) then
  1708. writeln(' intfcrc change (3): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1709. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1710. writeln(' indcrc change (3): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
  1711. else
  1712. writeln(' implcrc change (3): ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
  1713. {$endif DEBUG_UNIT_CRC_CHANGES}
  1714. result:=true;
  1715. exit;
  1716. end;
  1717. pu:=tused_unit(pu.next);
  1718. end;
  1719. end;
  1720. procedure tppumodule.setdefgeneration;
  1721. begin
  1722. defsgeneration:=currentdefgeneration;
  1723. inc(currentdefgeneration);
  1724. end;
  1725. procedure tppumodule.reload_flagged_units;
  1726. var
  1727. hp : tppumodule;
  1728. begin
  1729. { now reload all dependent units with outdated defs }
  1730. hp:=tppumodule(loaded_units.first);
  1731. while assigned(hp) do
  1732. begin
  1733. if hp.do_reload and
  1734. (hp.defsgeneration<defsgeneration) then
  1735. begin
  1736. hp.defsgeneration:=defsgeneration;
  1737. hp.loadppu
  1738. end
  1739. else
  1740. hp.do_reload:=false;
  1741. hp:=tppumodule(hp.next);
  1742. end;
  1743. end;
  1744. procedure tppumodule.end_of_parsing;
  1745. begin
  1746. { module is now compiled }
  1747. state:=ms_compiled;
  1748. { free ppu }
  1749. if assigned(ppufile) then
  1750. begin
  1751. ppufile.free;
  1752. ppufile:=nil;
  1753. end;
  1754. inherited end_of_parsing;
  1755. end;
  1756. procedure tppumodule.loadppu;
  1757. const
  1758. ImplIntf : array[boolean] of string[15]=('implementation','interface');
  1759. var
  1760. do_load,
  1761. second_time : boolean;
  1762. old_current_module : tmodule;
  1763. pu : tused_unit;
  1764. begin
  1765. old_current_module:=current_module;
  1766. Message3(unit_u_load_unit,old_current_module.modulename^,
  1767. ImplIntf[old_current_module.in_interface],
  1768. modulename^);
  1769. { Update loaded_from to detect cycles }
  1770. loaded_from:=old_current_module;
  1771. { check if the globalsymtable is already available, but
  1772. we must reload when the do_reload flag is set }
  1773. if (not do_reload) and
  1774. assigned(globalsymtable) then
  1775. exit;
  1776. { reset }
  1777. do_load:=true;
  1778. second_time:=false;
  1779. set_current_module(self);
  1780. { try to load it as a package unit first }
  1781. if (packagelist.count>0) and loadfrompackage then
  1782. begin
  1783. do_load:=false;
  1784. do_reload:=false;
  1785. state:=ms_compiled;
  1786. { PPU is not needed anymore }
  1787. if assigned(ppufile) then
  1788. begin
  1789. ppufile.closefile;
  1790. ppufile.free;
  1791. ppufile:=nil;
  1792. end;
  1793. { add the unit to the used units list of the program }
  1794. usedunits.concat(tused_unit.create(self,true,false,nil));
  1795. end;
  1796. { A force reload }
  1797. if do_reload then
  1798. begin
  1799. Message(unit_u_forced_reload);
  1800. do_reload:=false;
  1801. { When the unit is already loaded or being loaded
  1802. we can maybe skip a complete reload/recompile }
  1803. if assigned(globalsymtable) and
  1804. (not needrecompile) then
  1805. begin
  1806. { When we don't have any data stored yet there
  1807. is nothing to resolve }
  1808. if interface_compiled then
  1809. begin
  1810. Message1(unit_u_reresolving_unit,modulename^);
  1811. tstoredsymtable(globalsymtable).deref(false);
  1812. tstoredsymtable(globalsymtable).derefimpl(false);
  1813. if assigned(localsymtable) then
  1814. begin
  1815. { we have only builderef(impl)'d the registered symbols of
  1816. the localsymtable -> also only deref those again }
  1817. tstoredsymtable(localsymtable).deref(true);
  1818. tstoredsymtable(localsymtable).derefimpl(true);
  1819. end;
  1820. if assigned(wpoinfo) then
  1821. begin
  1822. tunitwpoinfo(wpoinfo).deref;
  1823. tunitwpoinfo(wpoinfo).derefimpl;
  1824. end;
  1825. { We have to flag the units that depend on this unit even
  1826. though it didn't change, because they might also
  1827. indirectly depend on the unit that did change (e.g.,
  1828. in case rgobj, rgx86 and rgcpu have been compiled
  1829. already, and then rgobj is recompiled for some reason
  1830. -> rgx86 is re-reresolved, but the vmtentries of trgcpu
  1831. must also be re-resolved, because they will also contain
  1832. pointers to procdefs in the old trgobj (in case of a
  1833. recompile, all old defs are freed) }
  1834. flagdependent(old_current_module);
  1835. reload_flagged_units;
  1836. end
  1837. else
  1838. Message1(unit_u_skipping_reresolving_unit,modulename^);
  1839. do_load:=false;
  1840. end;
  1841. end;
  1842. if do_load then
  1843. begin
  1844. { loading the unit for a second time? }
  1845. if state=ms_registered then
  1846. state:=ms_load
  1847. else
  1848. begin
  1849. { try to load the unit a second time first }
  1850. Message1(unit_u_second_load_unit,modulename^);
  1851. Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
  1852. { Flag modules to reload }
  1853. flagdependent(old_current_module);
  1854. { Reset the module }
  1855. reset;
  1856. if state in [ms_compile,ms_second_compile] then
  1857. begin
  1858. Message1(unit_u_second_compile_unit,modulename^);
  1859. state:=ms_second_compile;
  1860. do_compile:=true;
  1861. end
  1862. else
  1863. state:=ms_second_load;
  1864. second_time:=true;
  1865. end;
  1866. { close old_current_ppu on system that are
  1867. short on file handles like DOS PM }
  1868. {$ifdef SHORT_ON_FILE_HANDLES}
  1869. if old_current_module.is_unit and
  1870. assigned(tppumodule(old_current_module).ppufile) then
  1871. tppumodule(old_current_module).ppufile.tempclose;
  1872. {$endif SHORT_ON_FILE_HANDLES}
  1873. { try to opening ppu, skip this when we already
  1874. know that we need to compile the unit }
  1875. if not do_compile then
  1876. begin
  1877. Message1(unit_u_loading_unit,modulename^);
  1878. search_unit_files(false);
  1879. if not do_compile then
  1880. begin
  1881. load_interface;
  1882. setdefgeneration;
  1883. if not do_compile then
  1884. begin
  1885. load_usedunits;
  1886. if not do_compile then
  1887. Message1(unit_u_finished_loading_unit,modulename^);
  1888. end;
  1889. end;
  1890. { PPU is not needed anymore }
  1891. if assigned(ppufile) then
  1892. begin
  1893. ppufile.closefile;
  1894. ppufile.free;
  1895. ppufile:=nil;
  1896. end;
  1897. end;
  1898. { Do we need to recompile the unit }
  1899. if do_compile then
  1900. begin
  1901. { recompile the unit or give a fatal error if sources not available }
  1902. if not(sources_avail) then
  1903. begin
  1904. search_unit_files(true);
  1905. if not(sources_avail) then
  1906. begin
  1907. printcomments;
  1908. if recompile_reason=rr_noppu then
  1909. begin
  1910. pu:=tused_unit(loaded_from.used_units.first);
  1911. while assigned(pu) do
  1912. begin
  1913. if pu.u=self then
  1914. break;
  1915. pu:=tused_unit(pu.next);
  1916. end;
  1917. if assigned(pu) and assigned(pu.unitsym) then
  1918. MessagePos2(pu.unitsym.fileinfo,unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^)
  1919. else
  1920. Message2(unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^);
  1921. end
  1922. else
  1923. Message1(unit_f_cant_compile_unit,realmodulename^);
  1924. end;
  1925. end;
  1926. { we found the sources, we do not need the verbose messages anymore }
  1927. if comments <> nil then
  1928. begin
  1929. comments.free;
  1930. comments:=nil;
  1931. end;
  1932. { Flag modules to reload }
  1933. flagdependent(old_current_module);
  1934. { Reset the module }
  1935. reset;
  1936. { compile this module }
  1937. if not(state in [ms_compile,ms_second_compile]) then
  1938. state:=ms_compile;
  1939. compile(mainsource);
  1940. setdefgeneration;
  1941. end
  1942. else
  1943. state:=ms_compiled;
  1944. if current_module<>self then
  1945. internalerror(200212282);
  1946. if in_interface then
  1947. internalerror(200212283);
  1948. { for a second_time recompile reload all dependent units,
  1949. for a first time compile register the unit _once_ }
  1950. if second_time then
  1951. reload_flagged_units
  1952. else
  1953. usedunits.concat(tused_unit.create(self,true,false,nil));
  1954. { reopen the old module }
  1955. {$ifdef SHORT_ON_FILE_HANDLES}
  1956. if old_current_module.is_unit and
  1957. assigned(tppumodule(old_current_module).ppufile) then
  1958. tppumodule(old_current_module).ppufile.tempopen;
  1959. {$endif SHORT_ON_FILE_HANDLES}
  1960. end;
  1961. { we are back, restore current_module }
  1962. set_current_module(old_current_module);
  1963. end;
  1964. {*****************************************************************************
  1965. RegisterUnit
  1966. *****************************************************************************}
  1967. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
  1968. var
  1969. ups : TIDString;
  1970. hp : tppumodule;
  1971. hp2 : tmodule;
  1972. begin
  1973. { Info }
  1974. ups:=upper(s);
  1975. { search all loaded units }
  1976. hp:=tppumodule(loaded_units.first);
  1977. while assigned(hp) do
  1978. begin
  1979. if hp.modulename^=ups then
  1980. begin
  1981. { only check for units. The main program is also
  1982. as a unit in the loaded_units list. We simply need
  1983. to ignore this entry (PFV) }
  1984. if hp.is_unit then
  1985. begin
  1986. { both units in interface ? }
  1987. if callermodule.in_interface and
  1988. hp.in_interface then
  1989. begin
  1990. { check for a cycle }
  1991. hp2:=callermodule.loaded_from;
  1992. while assigned(hp2) and (hp2<>hp) do
  1993. begin
  1994. if hp2.in_interface then
  1995. hp2:=hp2.loaded_from
  1996. else
  1997. hp2:=nil;
  1998. end;
  1999. if assigned(hp2) then
  2000. Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
  2001. end;
  2002. break;
  2003. end;
  2004. end;
  2005. { the next unit }
  2006. hp:=tppumodule(hp.next);
  2007. end;
  2008. { the unit is not in the loaded units,
  2009. we create an entry and register the unit }
  2010. if not assigned(hp) then
  2011. begin
  2012. Message1(unit_u_registering_new_unit,Upper(s));
  2013. hp:=tppumodule.create(callermodule,s,fn,true);
  2014. hp.loaded_from:=callermodule;
  2015. addloadedunit(hp);
  2016. end;
  2017. { return }
  2018. registerunit:=hp;
  2019. end;
  2020. end.