fppu.pas 64 KB

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