fppu.pas 82 KB

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