fmodule.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the first loading and searching of the modules
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit fmodule;
  19. {$i fpcdefs.inc}
  20. {$ifdef go32v2}
  21. {$define shortasmprefix}
  22. {$endif}
  23. {$ifdef OS2}
  24. { Allthough OS/2 supports long filenames I play it safe and
  25. use 8.3 filenames, because this allows the compiler to run
  26. on a FAT partition. (DM) }
  27. {$define shortasmprefix}
  28. {$endif}
  29. interface
  30. uses
  31. cutils,cclasses,
  32. globals,finput,
  33. symbase;
  34. const
  35. maxunits = 1024;
  36. type
  37. trecompile_reason = (rr_unknown,
  38. rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
  39. );
  40. TExternalsItem=class(TLinkedListItem)
  41. public
  42. found : longbool;
  43. data : pstring;
  44. constructor Create(const s:string);
  45. Destructor Destroy;override;
  46. end;
  47. tlinkcontaineritem=class(tlinkedlistitem)
  48. public
  49. data : pstring;
  50. needlink : cardinal;
  51. constructor Create(const s:string;m:cardinal);
  52. destructor Destroy;override;
  53. end;
  54. tlinkcontainer=class(tlinkedlist)
  55. procedure add(const s : string;m:cardinal);
  56. function get(var m:cardinal) : string;
  57. function getusemask(mask:cardinal) : string;
  58. function find(const s:string):boolean;
  59. end;
  60. {$ifndef NEWMAP}
  61. tunitmap = array[0..maxunits-1] of pointer;
  62. punitmap = ^tunitmap;
  63. {$else NEWMAP}
  64. tunitmap = array[0..maxunits-1] of tmodule;
  65. punitmap = ^tunitmap;
  66. {$endif NEWMAP}
  67. tmodule = class(tmodulebase)
  68. compiled, { unit is already compiled }
  69. do_reload, { force reloading of the unit }
  70. do_compile, { need to compile the sources }
  71. sources_avail, { if all sources are reachable }
  72. sources_checked, { if there is already done a check for the sources }
  73. is_unit,
  74. in_second_compile, { is this unit being compiled for the 2nd time? }
  75. in_second_load, { is this unit PPU loaded a 2nd time? }
  76. in_implementation, { processing the implementation part? }
  77. in_global : boolean; { allow global settings }
  78. recompile_reason : trecompile_reason; { the reason why the unit should be recompiled }
  79. crc,
  80. interface_crc : cardinal;
  81. flags : cardinal; { the PPU flags }
  82. islibrary : boolean; { if it is a library (win32 dll) }
  83. map : punitmap; { mapping of all used units }
  84. unitcount : longint; { local unit counter }
  85. globalsymtable, { pointer to the global symtable of this unit }
  86. localsymtable : tsymtable;{ pointer to the local symtable of this unit }
  87. scanner : pointer; { scanner object used }
  88. loaded_from : tmodule;
  89. uses_imports : boolean; { Set if the module imports from DLL's.}
  90. imports : tlinkedlist;
  91. _exports : tlinkedlist;
  92. externals : tlinkedlist; {Only for DLL scanners by using Unix-style $LINKLIB }
  93. resourcefiles : tstringlist;
  94. linkunitofiles,
  95. linkunitstaticlibs,
  96. linkunitsharedlibs,
  97. linkotherofiles, { objects,libs loaded from the source }
  98. linkothersharedlibs, { using $L or $LINKLIB or import lib (for linux) }
  99. linkotherstaticlibs : tlinkcontainer;
  100. used_units : tlinkedlist;
  101. dependent_units : tlinkedlist;
  102. localunitsearchpath, { local searchpaths }
  103. localobjectsearchpath,
  104. localincludesearchpath,
  105. locallibrarysearchpath : TSearchPathList;
  106. asmprefix : pstring; { prefix for the smartlink asmfiles }
  107. constructor create(const s:string;_is_unit:boolean);
  108. destructor destroy;override;
  109. procedure reset;virtual;
  110. procedure numberunits;
  111. end;
  112. tused_unit = class(tlinkedlistitem)
  113. unitid : longint;
  114. name : pstring;
  115. realname : pstring;
  116. checksum,
  117. interface_checksum : cardinal;
  118. loaded : boolean;
  119. in_uses,
  120. in_interface,
  121. is_stab_written : boolean;
  122. u : tmodule;
  123. constructor create(_u : tmodule;intface:boolean);
  124. constructor create_to_load(const n:string;c,intfc:cardinal;intface:boolean);
  125. destructor destroy;override;
  126. end;
  127. tdependent_unit = class(tlinkedlistitem)
  128. u : tmodule;
  129. constructor create(_u : tmodule);
  130. end;
  131. var
  132. main_module : tmodule; { Main module of the program }
  133. current_module : tmodule; { Current module which is compiled or loaded }
  134. compiled_module : tmodule; { Current module which is compiled }
  135. usedunits : tlinkedlist; { Used units for this program }
  136. loaded_units : tlinkedlist; { All loaded units }
  137. SmartLinkOFiles : TStringList; { List of .o files which are generated,
  138. used to delete them after linking }
  139. function get_source_file(moduleindex,fileindex : longint) : tinputfile;
  140. implementation
  141. uses
  142. {$ifdef delphi}
  143. dmisc,
  144. {$else}
  145. dos,
  146. {$endif}
  147. verbose,systems,
  148. scanner;
  149. {*****************************************************************************
  150. Global Functions
  151. *****************************************************************************}
  152. function get_source_file(moduleindex,fileindex : longint) : tinputfile;
  153. var
  154. hp : tmodule;
  155. begin
  156. hp:=tmodule(loaded_units.first);
  157. while assigned(hp) and (hp.unit_index<>moduleindex) do
  158. hp:=tmodule(hp.next);
  159. if assigned(hp) then
  160. get_source_file:=hp.sourcefiles.get_file(fileindex)
  161. else
  162. get_source_file:=nil;
  163. end;
  164. {****************************************************************************
  165. TLinkContainerItem
  166. ****************************************************************************}
  167. constructor TLinkContainerItem.Create(const s:string;m:cardinal);
  168. begin
  169. inherited Create;
  170. data:=stringdup(s);
  171. needlink:=m;
  172. end;
  173. destructor TLinkContainerItem.Destroy;
  174. begin
  175. stringdispose(data);
  176. end;
  177. {****************************************************************************
  178. TLinkContainer
  179. ****************************************************************************}
  180. procedure TLinkContainer.add(const s : string;m:cardinal);
  181. begin
  182. inherited concat(TLinkContainerItem.Create(s,m));
  183. end;
  184. function TLinkContainer.get(var m:cardinal) : string;
  185. var
  186. p : tlinkcontaineritem;
  187. begin
  188. p:=tlinkcontaineritem(inherited getfirst);
  189. if p=nil then
  190. begin
  191. get:='';
  192. m:=0;
  193. end
  194. else
  195. begin
  196. get:=p.data^;
  197. m:=p.needlink;
  198. p.free;
  199. end;
  200. end;
  201. function TLinkContainer.getusemask(mask:cardinal) : string;
  202. var
  203. p : tlinkcontaineritem;
  204. found : boolean;
  205. begin
  206. found:=false;
  207. repeat
  208. p:=tlinkcontaineritem(inherited getfirst);
  209. if p=nil then
  210. begin
  211. getusemask:='';
  212. exit;
  213. end;
  214. getusemask:=p.data^;
  215. found:=(p.needlink and mask)<>0;
  216. p.free;
  217. until found;
  218. end;
  219. function TLinkContainer.find(const s:string):boolean;
  220. var
  221. newnode : tlinkcontaineritem;
  222. begin
  223. find:=false;
  224. newnode:=tlinkcontaineritem(First);
  225. while assigned(newnode) do
  226. begin
  227. if newnode.data^=s then
  228. begin
  229. find:=true;
  230. exit;
  231. end;
  232. newnode:=tlinkcontaineritem(newnode.next);
  233. end;
  234. end;
  235. {****************************************************************************
  236. TExternalsItem
  237. ****************************************************************************}
  238. constructor tExternalsItem.Create(const s:string);
  239. begin
  240. inherited Create;
  241. found:=false;
  242. data:=stringdup(s);
  243. end;
  244. destructor tExternalsItem.Destroy;
  245. begin
  246. stringdispose(data);
  247. inherited;
  248. end;
  249. {****************************************************************************
  250. TUSED_UNIT
  251. ****************************************************************************}
  252. constructor tused_unit.create(_u : tmodule;intface:boolean);
  253. begin
  254. u:=_u;
  255. in_interface:=intface;
  256. in_uses:=false;
  257. is_stab_written:=false;
  258. loaded:=true;
  259. name:=stringdup(_u.modulename^);
  260. realname:=stringdup(_u.realmodulename^);
  261. checksum:=_u.crc;
  262. interface_checksum:=_u.interface_crc;
  263. unitid:=0;
  264. end;
  265. constructor tused_unit.create_to_load(const n:string;c,intfc:cardinal;intface:boolean);
  266. begin
  267. u:=nil;
  268. in_interface:=intface;
  269. in_uses:=false;
  270. is_stab_written:=false;
  271. loaded:=false;
  272. name:=stringdup(upper(n));
  273. realname:=stringdup(n);
  274. checksum:=c;
  275. interface_checksum:=intfc;
  276. unitid:=0;
  277. end;
  278. destructor tused_unit.destroy;
  279. begin
  280. stringdispose(realname);
  281. stringdispose(name);
  282. inherited destroy;
  283. end;
  284. {****************************************************************************
  285. TDENPENDENT_UNIT
  286. ****************************************************************************}
  287. constructor tdependent_unit.create(_u : tmodule);
  288. begin
  289. u:=_u;
  290. end;
  291. {****************************************************************************
  292. TMODULE
  293. ****************************************************************************}
  294. constructor tmodule.create(const s:string;_is_unit:boolean);
  295. var
  296. p : dirstr;
  297. n : namestr;
  298. e : extstr;
  299. begin
  300. FSplit(s,p,n,e);
  301. { Programs have the name 'Program' to don't conflict with dup id's }
  302. if _is_unit then
  303. inherited create(n)
  304. else
  305. inherited create('Program');
  306. mainsource:=stringdup(s);
  307. { Dos has the famous 8.3 limit :( }
  308. {$ifdef shortasmprefix}
  309. asmprefix:=stringdup(FixFileName('as'));
  310. {$else}
  311. asmprefix:=stringdup(FixFileName(n));
  312. {$endif}
  313. setfilename(p+n,true);
  314. localunitsearchpath:=TSearchPathList.Create;
  315. localobjectsearchpath:=TSearchPathList.Create;
  316. localincludesearchpath:=TSearchPathList.Create;
  317. locallibrarysearchpath:=TSearchPathList.Create;
  318. used_units:=TLinkedList.Create;
  319. dependent_units:=TLinkedList.Create;
  320. resourcefiles:=TStringList.Create;
  321. linkunitofiles:=TLinkContainer.Create;
  322. linkunitstaticlibs:=TLinkContainer.Create;
  323. linkunitsharedlibs:=TLinkContainer.Create;
  324. linkotherofiles:=TLinkContainer.Create;
  325. linkotherstaticlibs:=TLinkContainer.Create;
  326. linkothersharedlibs:=TLinkContainer.Create;
  327. crc:=0;
  328. interface_crc:=0;
  329. flags:=0;
  330. scanner:=nil;
  331. map:=nil;
  332. globalsymtable:=nil;
  333. localsymtable:=nil;
  334. loaded_from:=nil;
  335. do_reload:=false;
  336. unitcount:=1;
  337. do_compile:=false;
  338. sources_avail:=true;
  339. sources_checked:=false;
  340. compiled:=false;
  341. recompile_reason:=rr_unknown;
  342. in_second_load:=false;
  343. in_second_compile:=false;
  344. in_implementation:=false;
  345. in_global:=true;
  346. is_unit:=_is_unit;
  347. islibrary:=false;
  348. uses_imports:=false;
  349. imports:=TLinkedList.Create;
  350. _exports:=TLinkedList.Create;
  351. externals:=TLinkedList.Create;
  352. end;
  353. destructor tmodule.Destroy;
  354. {$ifdef MEMDEBUG}
  355. var
  356. d : tmemdebug;
  357. {$endif}
  358. begin
  359. if assigned(map) then
  360. dispose(map);
  361. if assigned(imports) then
  362. imports.free;
  363. imports:=nil;
  364. if assigned(_exports) then
  365. _exports.free;
  366. _exports:=nil;
  367. if assigned(externals) then
  368. externals.free;
  369. externals:=nil;
  370. if assigned(scanner) then
  371. tscannerfile(scanner).invalid:=true;
  372. used_units.free;
  373. dependent_units.free;
  374. resourcefiles.Free;
  375. linkunitofiles.Free;
  376. linkunitstaticlibs.Free;
  377. linkunitsharedlibs.Free;
  378. linkotherofiles.Free;
  379. linkotherstaticlibs.Free;
  380. linkothersharedlibs.Free;
  381. stringdispose(objfilename);
  382. stringdispose(newfilename);
  383. stringdispose(ppufilename);
  384. stringdispose(staticlibfilename);
  385. stringdispose(sharedlibfilename);
  386. stringdispose(exefilename);
  387. stringdispose(outputpath);
  388. stringdispose(path);
  389. stringdispose(modulename);
  390. stringdispose(realmodulename);
  391. stringdispose(mainsource);
  392. stringdispose(asmprefix);
  393. localunitsearchpath.Free;
  394. localobjectsearchpath.free;
  395. localincludesearchpath.free;
  396. locallibrarysearchpath.free;
  397. {$ifdef MEMDEBUG}
  398. d:=tmemdebug.create('symtable');
  399. {$endif}
  400. if assigned(globalsymtable) then
  401. globalsymtable.free;
  402. globalsymtable:=nil;
  403. if assigned(localsymtable) then
  404. localsymtable.free;
  405. localsymtable:=nil;
  406. {$ifdef MEMDEBUG}
  407. d.free;
  408. {$endif}
  409. inherited Destroy;
  410. end;
  411. procedure tmodule.reset;
  412. var
  413. pm : tdependent_unit;
  414. begin
  415. if assigned(scanner) then
  416. tscannerfile(scanner).invalid:=true;
  417. if assigned(globalsymtable) then
  418. begin
  419. globalsymtable.free;
  420. globalsymtable:=nil;
  421. end;
  422. if assigned(localsymtable) then
  423. begin
  424. localsymtable.free;
  425. localsymtable:=nil;
  426. end;
  427. if assigned(map) then
  428. begin
  429. dispose(map);
  430. map:=nil;
  431. end;
  432. sourcefiles.free;
  433. sourcefiles:=tinputfilemanager.create;
  434. imports.free;
  435. imports:=tlinkedlist.create;
  436. _exports.free;
  437. _exports:=tlinkedlist.create;
  438. externals.free;
  439. externals:=tlinkedlist.create;
  440. used_units.free;
  441. used_units:=TLinkedList.Create;
  442. { all units that depend on this one must be recompiled ! }
  443. pm:=tdependent_unit(dependent_units.first);
  444. while assigned(pm) do
  445. begin
  446. if pm.u.in_second_compile then
  447. Comment(v_debug,'No reload already in second compile: '+pm.u.modulename^)
  448. else
  449. begin
  450. pm.u.do_reload:=true;
  451. Comment(v_debug,'Reloading '+pm.u.modulename^+' needed because '+modulename^+' is reloaded');
  452. end;
  453. pm:=tdependent_unit(pm.next);
  454. end;
  455. dependent_units.free;
  456. dependent_units:=TLinkedList.Create;
  457. resourcefiles.Free;
  458. resourcefiles:=TStringList.Create;
  459. linkunitofiles.Free;
  460. linkunitofiles:=TLinkContainer.Create;
  461. linkunitstaticlibs.Free;
  462. linkunitstaticlibs:=TLinkContainer.Create;
  463. linkunitsharedlibs.Free;
  464. linkunitsharedlibs:=TLinkContainer.Create;
  465. linkotherofiles.Free;
  466. linkotherofiles:=TLinkContainer.Create;
  467. linkotherstaticlibs.Free;
  468. linkotherstaticlibs:=TLinkContainer.Create;
  469. linkothersharedlibs.Free;
  470. linkothersharedlibs:=TLinkContainer.Create;
  471. uses_imports:=false;
  472. do_compile:=false;
  473. { sources_avail:=true;
  474. should not be changed PM }
  475. compiled:=false;
  476. in_implementation:=false;
  477. in_global:=true;
  478. crc:=0;
  479. interface_crc:=0;
  480. flags:=0;
  481. {loaded_from:=nil;
  482. should not be changed PFV }
  483. unitcount:=1;
  484. recompile_reason:=rr_unknown;
  485. end;
  486. procedure tmodule.numberunits;
  487. var
  488. counter : longint;
  489. hp : tused_unit;
  490. hp1 : tmodule;
  491. begin
  492. { Reset all numbers to -1 }
  493. hp1:=tmodule(loaded_units.first);
  494. while assigned(hp1) do
  495. begin
  496. if assigned(hp1.globalsymtable) then
  497. hp1.globalsymtable.unitid:=$ffff;
  498. hp1:=tmodule(hp1.next);
  499. end;
  500. { Our own symtable gets unitid 0, for a program there is
  501. no globalsymtable }
  502. if assigned(globalsymtable) then
  503. globalsymtable.unitid:=0;
  504. { number units }
  505. counter:=1;
  506. hp:=tused_unit(used_units.first);
  507. while assigned(hp) do
  508. begin
  509. tsymtable(hp.u.globalsymtable).unitid:=counter;
  510. inc(counter);
  511. hp:=tused_unit(hp.next);
  512. end;
  513. end;
  514. end.
  515. {
  516. $Log$
  517. Revision 1.23 2002-05-16 19:46:36 carl
  518. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  519. + try to fix temp allocation (still in ifdef)
  520. + generic constructor calls
  521. + start of tassembler / tmodulebase class cleanup
  522. Revision 1.22 2002/05/14 19:34:41 peter
  523. * removed old logs and updated copyright year
  524. Revision 1.21 2002/04/04 19:05:55 peter
  525. * removed unused units
  526. * use tlocation.size in cg.a_*loc*() routines
  527. Revision 1.20 2002/03/28 20:46:59 carl
  528. - remove go32v1 support
  529. }