fmodule.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  20. {$ifdef go32v1}
  21. {$define shortasmprefix}
  22. {$endif}
  23. {$ifdef go32v2}
  24. {$define shortasmprefix}
  25. {$endif}
  26. {$ifdef OS2}
  27. { Allthough OS/2 supports long filenames I play it safe and
  28. use 8.3 filenames, because this allows the compiler to run
  29. on a FAT partition. (DM) }
  30. {$define shortasmprefix}
  31. {$endif}
  32. interface
  33. uses
  34. cutils,cclasses,
  35. globals,finput,
  36. symbase;
  37. const
  38. maxunits = 1024;
  39. type
  40. trecompile_reason = (rr_unknown,
  41. rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
  42. );
  43. TExternalsItem=class(TLinkedListItem)
  44. public
  45. found : longbool;
  46. data : pstring;
  47. constructor Create(const s:string);
  48. Destructor Destroy;override;
  49. end;
  50. tlinkcontaineritem=class(tlinkedlistitem)
  51. public
  52. data : pstring;
  53. needlink : cardinal;
  54. constructor Create(const s:string;m:cardinal);
  55. destructor Destroy;override;
  56. end;
  57. tlinkcontainer=class(tlinkedlist)
  58. procedure add(const s : string;m:cardinal);
  59. function get(var m:cardinal) : string;
  60. function getusemask(mask:cardinal) : string;
  61. function find(const s:string):boolean;
  62. end;
  63. {$ifndef NEWMAP}
  64. tunitmap = array[0..maxunits-1] of pointer;
  65. punitmap = ^tunitmap;
  66. {$else NEWMAP}
  67. tunitmap = array[0..maxunits-1] of tmodule;
  68. punitmap = ^tunitmap;
  69. {$endif NEWMAP}
  70. tmodule = class(tmodulebase)
  71. compiled, { unit is already compiled }
  72. do_reload, { force reloading of the unit }
  73. do_compile, { need to compile the sources }
  74. sources_avail, { if all sources are reachable }
  75. sources_checked, { if there is already done a check for the sources }
  76. is_unit,
  77. in_compile, { is it being compiled ?? }
  78. in_second_compile, { is this unit being compiled for the 2nd time? }
  79. in_second_load, { is this unit PPU loaded a 2nd time? }
  80. in_implementation, { processing the implementation part? }
  81. in_global : boolean; { allow global settings }
  82. recompile_reason : trecompile_reason; { the reason why the unit should be recompiled }
  83. crc,
  84. interface_crc : cardinal;
  85. flags : cardinal; { the PPU flags }
  86. islibrary : boolean; { if it is a library (win32 dll) }
  87. map : punitmap; { mapping of all used units }
  88. unitcount : longint; { local unit counter }
  89. globalsymtable, { pointer to the global symtable of this unit }
  90. localsymtable : tsymtable;{ pointer to the local symtable of this unit }
  91. scanner : pointer; { scanner object used }
  92. loaded_from : tmodule;
  93. uses_imports : boolean; { Set if the module imports from DLL's.}
  94. imports : tlinkedlist;
  95. _exports : tlinkedlist;
  96. externals : tlinkedlist; {Only for DLL scanners by using Unix-style $LINKLIB }
  97. resourcefiles : tstringlist;
  98. linkunitofiles,
  99. linkunitstaticlibs,
  100. linkunitsharedlibs,
  101. linkotherofiles, { objects,libs loaded from the source }
  102. linkothersharedlibs, { using $L or $LINKLIB or import lib (for linux) }
  103. linkotherstaticlibs : tlinkcontainer;
  104. used_units : tlinkedlist;
  105. dependent_units : tlinkedlist;
  106. localunitsearchpath, { local searchpaths }
  107. localobjectsearchpath,
  108. localincludesearchpath,
  109. locallibrarysearchpath : TSearchPathList;
  110. asmprefix : pstring; { prefix for the smartlink asmfiles }
  111. constructor create(const s:string;_is_unit:boolean);
  112. destructor destroy;override;
  113. procedure reset;virtual;
  114. procedure numberunits;
  115. procedure setfilename(const fn:string;allowoutput:boolean);
  116. end;
  117. tused_unit = class(tlinkedlistitem)
  118. unitid : longint;
  119. name : pstring;
  120. checksum,
  121. interface_checksum : cardinal;
  122. loaded : boolean;
  123. in_uses,
  124. in_interface,
  125. is_stab_written : boolean;
  126. u : tmodule;
  127. constructor create(_u : tmodule;intface:boolean);
  128. constructor create_to_load(const n:string;c,intfc:cardinal;intface:boolean);
  129. destructor destroy;override;
  130. end;
  131. tdependent_unit = class(tlinkedlistitem)
  132. u : tmodule;
  133. constructor create(_u : tmodule);
  134. end;
  135. var
  136. main_module : tmodule; { Main module of the program }
  137. current_module : tmodule; { Current module which is compiled or loaded }
  138. compiled_module : tmodule; { Current module which is compiled }
  139. usedunits : tlinkedlist; { Used units for this program }
  140. loaded_units : tlinkedlist; { All loaded units }
  141. SmartLinkOFiles : TStringList; { List of .o files which are generated,
  142. used to delete them after linking }
  143. function get_source_file(moduleindex,fileindex : longint) : tinputfile;
  144. implementation
  145. uses
  146. {$ifdef delphi}
  147. dmisc,
  148. {$else}
  149. dos,
  150. {$endif}
  151. globtype,verbose,systems,
  152. scanner;
  153. {*****************************************************************************
  154. Global Functions
  155. *****************************************************************************}
  156. function get_source_file(moduleindex,fileindex : longint) : tinputfile;
  157. var
  158. hp : tmodule;
  159. begin
  160. hp:=tmodule(loaded_units.first);
  161. while assigned(hp) and (hp.unit_index<>moduleindex) do
  162. hp:=tmodule(hp.next);
  163. if assigned(hp) then
  164. get_source_file:=hp.sourcefiles.get_file(fileindex)
  165. else
  166. get_source_file:=nil;
  167. end;
  168. {****************************************************************************
  169. TLinkContainerItem
  170. ****************************************************************************}
  171. constructor TLinkContainerItem.Create(const s:string;m:cardinal);
  172. begin
  173. inherited Create;
  174. data:=stringdup(s);
  175. needlink:=m;
  176. end;
  177. destructor TLinkContainerItem.Destroy;
  178. begin
  179. stringdispose(data);
  180. end;
  181. {****************************************************************************
  182. TLinkContainer
  183. ****************************************************************************}
  184. procedure TLinkContainer.add(const s : string;m:cardinal);
  185. begin
  186. inherited concat(TLinkContainerItem.Create(s,m));
  187. end;
  188. function TLinkContainer.get(var m:cardinal) : string;
  189. var
  190. p : tlinkcontaineritem;
  191. begin
  192. p:=tlinkcontaineritem(inherited getfirst);
  193. if p=nil then
  194. begin
  195. get:='';
  196. m:=0;
  197. end
  198. else
  199. begin
  200. get:=p.data^;
  201. m:=p.needlink;
  202. p.free;
  203. end;
  204. end;
  205. function TLinkContainer.getusemask(mask:cardinal) : string;
  206. var
  207. p : tlinkcontaineritem;
  208. found : boolean;
  209. begin
  210. found:=false;
  211. repeat
  212. p:=tlinkcontaineritem(inherited getfirst);
  213. if p=nil then
  214. begin
  215. getusemask:='';
  216. exit;
  217. end;
  218. getusemask:=p.data^;
  219. found:=(p.needlink and mask)<>0;
  220. p.free;
  221. until found;
  222. end;
  223. function TLinkContainer.find(const s:string):boolean;
  224. var
  225. newnode : tlinkcontaineritem;
  226. begin
  227. find:=false;
  228. newnode:=tlinkcontaineritem(First);
  229. while assigned(newnode) do
  230. begin
  231. if newnode.data^=s then
  232. begin
  233. find:=true;
  234. exit;
  235. end;
  236. newnode:=tlinkcontaineritem(newnode.next);
  237. end;
  238. end;
  239. {****************************************************************************
  240. TExternalsItem
  241. ****************************************************************************}
  242. constructor tExternalsItem.Create(const s:string);
  243. begin
  244. inherited Create;
  245. found:=false;
  246. data:=stringdup(s);
  247. end;
  248. destructor tExternalsItem.Destroy;
  249. begin
  250. stringdispose(data);
  251. inherited;
  252. end;
  253. {****************************************************************************
  254. TUSED_UNIT
  255. ****************************************************************************}
  256. constructor tused_unit.create(_u : tmodule;intface:boolean);
  257. begin
  258. u:=_u;
  259. in_interface:=intface;
  260. in_uses:=false;
  261. is_stab_written:=false;
  262. loaded:=true;
  263. name:=stringdup(_u.modulename^);
  264. checksum:=_u.crc;
  265. interface_checksum:=_u.interface_crc;
  266. unitid:=0;
  267. end;
  268. constructor tused_unit.create_to_load(const n:string;c,intfc:cardinal;intface:boolean);
  269. begin
  270. u:=nil;
  271. in_interface:=intface;
  272. in_uses:=false;
  273. is_stab_written:=false;
  274. loaded:=false;
  275. name:=stringdup(n);
  276. checksum:=c;
  277. interface_checksum:=intfc;
  278. unitid:=0;
  279. end;
  280. destructor tused_unit.destroy;
  281. begin
  282. stringdispose(name);
  283. inherited destroy;
  284. end;
  285. {****************************************************************************
  286. TDENPENDENT_UNIT
  287. ****************************************************************************}
  288. constructor tdependent_unit.create(_u : tmodule);
  289. begin
  290. u:=_u;
  291. end;
  292. {****************************************************************************
  293. TMODULE
  294. ****************************************************************************}
  295. constructor tmodule.create(const s:string;_is_unit:boolean);
  296. var
  297. p : dirstr;
  298. n : namestr;
  299. e : extstr;
  300. begin
  301. FSplit(s,p,n,e);
  302. { Programs have the name 'Program' to don't conflict with dup id's }
  303. if _is_unit then
  304. inherited create(n)
  305. else
  306. inherited create('Program');
  307. mainsource:=stringdup(s);
  308. { Dos has the famous 8.3 limit :( }
  309. {$ifdef shortasmprefix}
  310. asmprefix:=stringdup(FixFileName('as'));
  311. {$else}
  312. asmprefix:=stringdup(FixFileName(n));
  313. {$endif}
  314. setfilename(p+n,true);
  315. localunitsearchpath:=TSearchPathList.Create;
  316. localobjectsearchpath:=TSearchPathList.Create;
  317. localincludesearchpath:=TSearchPathList.Create;
  318. locallibrarysearchpath:=TSearchPathList.Create;
  319. used_units:=TLinkedList.Create;
  320. dependent_units:=TLinkedList.Create;
  321. resourcefiles:=TStringList.Create;
  322. linkunitofiles:=TLinkContainer.Create;
  323. linkunitstaticlibs:=TLinkContainer.Create;
  324. linkunitsharedlibs:=TLinkContainer.Create;
  325. linkotherofiles:=TLinkContainer.Create;
  326. linkotherstaticlibs:=TLinkContainer.Create;
  327. linkothersharedlibs:=TLinkContainer.Create;
  328. crc:=0;
  329. interface_crc:=0;
  330. flags:=0;
  331. scanner:=nil;
  332. map:=nil;
  333. globalsymtable:=nil;
  334. localsymtable:=nil;
  335. loaded_from:=nil;
  336. do_reload:=false;
  337. unitcount:=1;
  338. do_compile:=false;
  339. sources_avail:=true;
  340. sources_checked:=false;
  341. compiled:=false;
  342. recompile_reason:=rr_unknown;
  343. in_second_load:=false;
  344. in_compile:=false;
  345. in_second_compile:=false;
  346. in_implementation:=false;
  347. in_global:=true;
  348. is_unit:=_is_unit;
  349. islibrary:=false;
  350. uses_imports:=false;
  351. imports:=TLinkedList.Create;
  352. _exports:=TLinkedList.Create;
  353. externals:=TLinkedList.Create;
  354. end;
  355. destructor tmodule.Destroy;
  356. {$ifdef MEMDEBUG}
  357. var
  358. d : tmemdebug;
  359. {$endif}
  360. begin
  361. if assigned(map) then
  362. dispose(map);
  363. if assigned(imports) then
  364. imports.free;
  365. imports:=nil;
  366. if assigned(_exports) then
  367. _exports.free;
  368. _exports:=nil;
  369. if assigned(externals) then
  370. externals.free;
  371. externals:=nil;
  372. if assigned(scanner) then
  373. tscannerfile(scanner).invalid:=true;
  374. used_units.free;
  375. dependent_units.free;
  376. resourcefiles.Free;
  377. linkunitofiles.Free;
  378. linkunitstaticlibs.Free;
  379. linkunitsharedlibs.Free;
  380. linkotherofiles.Free;
  381. linkotherstaticlibs.Free;
  382. linkothersharedlibs.Free;
  383. stringdispose(objfilename);
  384. stringdispose(asmfilename);
  385. stringdispose(ppufilename);
  386. stringdispose(staticlibfilename);
  387. stringdispose(sharedlibfilename);
  388. stringdispose(exefilename);
  389. stringdispose(outputpath);
  390. stringdispose(path);
  391. stringdispose(modulename);
  392. stringdispose(realmodulename);
  393. stringdispose(mainsource);
  394. stringdispose(asmprefix);
  395. localunitsearchpath.Free;
  396. localobjectsearchpath.free;
  397. localincludesearchpath.free;
  398. locallibrarysearchpath.free;
  399. {$ifdef MEMDEBUG}
  400. d.init('symtable');
  401. {$endif}
  402. if assigned(globalsymtable) then
  403. globalsymtable.free;
  404. globalsymtable:=nil;
  405. if assigned(localsymtable) then
  406. localsymtable.free;
  407. localsymtable:=nil;
  408. {$ifdef MEMDEBUG}
  409. d.free;
  410. {$endif}
  411. inherited Destroy;
  412. end;
  413. procedure tmodule.reset;
  414. var
  415. pm : tdependent_unit;
  416. begin
  417. if assigned(scanner) then
  418. tscannerfile(scanner).invalid:=true;
  419. if assigned(globalsymtable) then
  420. begin
  421. globalsymtable.free;
  422. globalsymtable:=nil;
  423. end;
  424. if assigned(localsymtable) then
  425. begin
  426. localsymtable.free;
  427. localsymtable:=nil;
  428. end;
  429. if assigned(map) then
  430. begin
  431. dispose(map);
  432. map:=nil;
  433. end;
  434. sourcefiles.free;
  435. sourcefiles:=tinputfilemanager.create;
  436. imports.free;
  437. imports:=tlinkedlist.create;
  438. _exports.free;
  439. _exports:=tlinkedlist.create;
  440. externals.free;
  441. externals:=tlinkedlist.create;
  442. used_units.free;
  443. used_units:=TLinkedList.Create;
  444. { all units that depend on this one must be recompiled ! }
  445. pm:=tdependent_unit(dependent_units.first);
  446. while assigned(pm) do
  447. begin
  448. if pm.u.in_second_compile then
  449. Comment(v_debug,'No reload already in second compile: '+pm.u.modulename^)
  450. else
  451. begin
  452. pm.u.do_reload:=true;
  453. Comment(v_debug,'Reloading '+pm.u.modulename^+' needed because '+modulename^+' is reloaded');
  454. end;
  455. pm:=tdependent_unit(pm.next);
  456. end;
  457. dependent_units.free;
  458. dependent_units:=TLinkedList.Create;
  459. resourcefiles.Free;
  460. resourcefiles:=TStringList.Create;
  461. linkunitofiles.Free;
  462. linkunitofiles:=TLinkContainer.Create;
  463. linkunitstaticlibs.Free;
  464. linkunitstaticlibs:=TLinkContainer.Create;
  465. linkunitsharedlibs.Free;
  466. linkunitsharedlibs:=TLinkContainer.Create;
  467. linkotherofiles.Free;
  468. linkotherofiles:=TLinkContainer.Create;
  469. linkotherstaticlibs.Free;
  470. linkotherstaticlibs:=TLinkContainer.Create;
  471. linkothersharedlibs.Free;
  472. linkothersharedlibs:=TLinkContainer.Create;
  473. uses_imports:=false;
  474. do_compile:=false;
  475. { sources_avail:=true;
  476. should not be changed PM }
  477. compiled:=false;
  478. in_implementation:=false;
  479. in_global:=true;
  480. crc:=0;
  481. interface_crc:=0;
  482. flags:=0;
  483. {loaded_from:=nil;
  484. should not be changed PFV }
  485. unitcount:=1;
  486. recompile_reason:=rr_unknown;
  487. end;
  488. procedure tmodule.setfilename(const fn:string;allowoutput:boolean);
  489. var
  490. p : dirstr;
  491. n : NameStr;
  492. e : ExtStr;
  493. begin
  494. stringdispose(objfilename);
  495. stringdispose(asmfilename);
  496. stringdispose(ppufilename);
  497. stringdispose(staticlibfilename);
  498. stringdispose(sharedlibfilename);
  499. stringdispose(exefilename);
  500. stringdispose(outputpath);
  501. stringdispose(path);
  502. { Create names }
  503. fsplit(fn,p,n,e);
  504. n:=FixFileName(n);
  505. { set path }
  506. path:=stringdup(FixPath(p,false));
  507. { obj,asm,ppu names }
  508. p:=path^;
  509. if AllowOutput then
  510. begin
  511. if (OutputUnitDir<>'') then
  512. p:=OutputUnitDir
  513. else
  514. if (OutputExeDir<>'') then
  515. p:=OutputExeDir;
  516. end;
  517. outputpath:=stringdup(p);
  518. objfilename:=stringdup(p+n+target_info.objext);
  519. asmfilename:=stringdup(p+n+target_info.asmext);
  520. ppufilename:=stringdup(p+n+target_info.unitext);
  521. { lib and exe could be loaded with a file specified with -o }
  522. if AllowOutput and (OutputFile<>'') and (compile_level=1) then
  523. n:=OutputFile;
  524. staticlibfilename:=stringdup(p+target_info.libprefix+n+target_info.staticlibext);
  525. if target_info.target=target_i386_WIN32 then
  526. sharedlibfilename:=stringdup(p+n+target_info.sharedlibext)
  527. else
  528. sharedlibfilename:=stringdup(p+target_info.libprefix+n+target_info.sharedlibext);
  529. { output dir of exe can be specified separatly }
  530. if AllowOutput and (OutputExeDir<>'') then
  531. p:=OutputExeDir
  532. else
  533. p:=path^;
  534. exefilename:=stringdup(p+n+target_info.exeext);
  535. end;
  536. procedure tmodule.numberunits;
  537. var
  538. counter : longint;
  539. hp : tused_unit;
  540. hp1 : tmodule;
  541. begin
  542. { Reset all numbers to -1 }
  543. hp1:=tmodule(loaded_units.first);
  544. while assigned(hp1) do
  545. begin
  546. if assigned(hp1.globalsymtable) then
  547. hp1.globalsymtable.unitid:=$ffff;
  548. hp1:=tmodule(hp1.next);
  549. end;
  550. { Our own symtable gets unitid 0, for a program there is
  551. no globalsymtable }
  552. if assigned(globalsymtable) then
  553. globalsymtable.unitid:=0;
  554. { number units }
  555. counter:=1;
  556. hp:=tused_unit(used_units.first);
  557. while assigned(hp) do
  558. begin
  559. tsymtable(hp.u.globalsymtable).unitid:=counter;
  560. inc(counter);
  561. hp:=tused_unit(hp.next);
  562. end;
  563. end;
  564. end.
  565. {
  566. $Log$
  567. Revision 1.15 2001-05-09 14:11:10 jonas
  568. * range check error fixes from Peter
  569. Revision 1.14 2001/05/06 14:49:16 peter
  570. * ppu object to class rewrite
  571. * move ppu read and write stuff to fppu
  572. Revision 1.13 2001/04/18 22:01:53 peter
  573. * registration of targets and assemblers
  574. Revision 1.12 2001/04/13 18:08:37 peter
  575. * scanner object to class
  576. Revision 1.11 2001/04/13 01:22:07 peter
  577. * symtable change to classes
  578. * range check generation and errors fixed, make cycle DEBUG=1 works
  579. * memory leaks fixed
  580. Revision 1.10 2001/04/02 21:20:29 peter
  581. * resulttype rewrite
  582. Revision 1.9 2001/03/13 18:45:06 peter
  583. * fixed some memory leaks
  584. Revision 1.8 2001/03/06 18:28:02 peter
  585. * patch from Pavel with a new and much faster DLL Scanner for
  586. automatic importing so $linklib works for DLLs. Thanks Pavel!
  587. Revision 1.7 2001/02/20 21:41:15 peter
  588. * new fixfilename, findfile for unix. Look first for lowercase, then
  589. NormalCase and last for UPPERCASE names.
  590. Revision 1.6 2000/12/25 00:07:25 peter
  591. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  592. tlinkedlist objects)
  593. Revision 1.5 2000/11/07 20:48:33 peter
  594. * removed ref_count from pinputfile it's not used
  595. Revision 1.4 2000/10/31 22:02:46 peter
  596. * symtable splitted, no real code changes
  597. Revision 1.3 2000/10/15 07:47:51 peter
  598. * unit names and procedure names are stored mixed case
  599. Revision 1.2 2000/09/24 15:06:16 peter
  600. * use defines.inc
  601. Revision 1.1 2000/08/27 16:11:50 peter
  602. * moved some util functions from globals,cobjects to cutils
  603. * splitted files into finput,fmodule
  604. }