pmodules.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl
  4. Handles the parsing and loading of the modules (ppufiles)
  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 pmodules;
  19. {define TEST_IMPL does not work well }
  20. interface
  21. uses
  22. files;
  23. procedure addlinkerfiles(hp:pmodule);
  24. procedure loadsystemunit;
  25. procedure proc_unit;
  26. procedure proc_program(islibrary : boolean);
  27. implementation
  28. uses
  29. cobjects,verbose,systems,globals,
  30. symtable,aasm,hcodegen,
  31. link,assemble,import
  32. {$ifdef NEWPPU}
  33. ,ppu
  34. {$endif NEWPPU}
  35. {$ifdef i386}
  36. ,i386
  37. {$endif}
  38. {$ifdef m68k}
  39. ,m68k
  40. {$endif}
  41. ,scanner,pbase,psystem,pdecl,psub,parser;
  42. procedure addlinkerfiles(hp:pmodule);
  43. begin
  44. with hp^ do
  45. begin
  46. while not linkofiles.empty do
  47. Linker.AddObject(linkofiles.Get);
  48. while not linksharedlibs.empty do
  49. Linker.AddSharedLibrary(linksharedlibs.Get);
  50. while not linkstaticlibs.empty do
  51. Linker.AddStaticLibrary(linkstaticlibs.Get);
  52. end;
  53. end;
  54. procedure insertsegment;
  55. procedure fixseg(p:paasmoutput;sec:tsection);
  56. begin
  57. p^.insert(new(pai_section,init(sec)));
  58. if (cs_smartlink in aktswitches) then
  59. p^.insert(new(pai_cut,init));
  60. p^.concat(new(pai_section,init(sec_none)));
  61. end;
  62. begin
  63. {Insert Ident of the compiler}
  64. if (not (cs_smartlink in aktswitches))
  65. {$ifndef EXTDEBUG}
  66. and (not current_module^.is_unit)
  67. {$endif}
  68. then
  69. begin
  70. datasegment^.insert(new(pai_align,init(4)));
  71. datasegment^.insert(new(pai_string,init('FPC '+version_string+' for '+target_string+' - '+target_info.short_name)));
  72. end;
  73. { Insert start and end of sections }
  74. fixseg(codesegment,sec_code);
  75. fixseg(datasegment,sec_data);
  76. fixseg(bsssegment,sec_bss);
  77. fixseg(consts,sec_data);
  78. end;
  79. procedure insertheap;
  80. begin
  81. if (cs_smartlink in aktswitches) then
  82. begin
  83. bsssegment^.concat(new(pai_cut,init));
  84. datasegment^.concat(new(pai_cut,init));
  85. end;
  86. { On the Macintosh Classic M68k Architecture
  87. The Heap variable is simply a POINTER to the
  88. real HEAP. The HEAP must be set up by the RTL
  89. and must store the pointer in this value.
  90. On OS/2 the heap is also intialized by the RTL. We do
  91. not output a pointer }
  92. case target_info.target of
  93. {$ifdef i386}
  94. target_OS2 : ;
  95. {$endif i386}
  96. {$ifdef m68k}
  97. target_Mac68K : bsssegment^.concat(new(pai_datablock,init_global('HEAP',4)));
  98. {$endif m68k}
  99. else
  100. bsssegment^.concat(new(pai_datablock,init_global('HEAP',heapsize)));
  101. end;
  102. datasegment^.concat(new(pai_symbol,init_global('HEAPSIZE')));
  103. datasegment^.concat(new(pai_const,init_32bit(heapsize)));
  104. end;
  105. procedure inserttargetspecific;
  106. begin
  107. {$ifdef i386}
  108. case target_info.target of
  109. target_GO32V2 : begin
  110. { stacksize can be specified }
  111. datasegment^.concat(new(pai_symbol,init_global('__stklen')));
  112. datasegment^.concat(new(pai_const,init_32bit(stacksize)));
  113. end;
  114. target_WIN32 : begin
  115. { Generate an external entry to be sure that _mainCRTStarup will be
  116. linked, can't use concat_external because those aren't written for
  117. asw (PFV) }
  118. datasegment^.concat(new(pai_const,init_symbol('_mainCRTStartup')));
  119. end;
  120. end;
  121. {$endif i386}
  122. end;
  123. {$ifdef NEWPPU}
  124. function loadunit(const s : string;compile_system:boolean) : pmodule;forward;
  125. procedure load_usedunits(compile_system:boolean);
  126. var
  127. pu : pused_unit;
  128. loaded_unit : pmodule;
  129. nextmapentry : longint;
  130. begin
  131. { init the map }
  132. new(current_module^.map);
  133. nextmapentry:=1;
  134. { load the used units from interface }
  135. pu:=pused_unit(current_module^.used_units.first);
  136. while assigned(pu) do
  137. begin
  138. if (not pu^.loaded) and (pu^.in_interface) then
  139. begin
  140. loaded_unit:=loadunit(pu^.name^,false);
  141. if current_module^.compiled then
  142. exit;
  143. { register unit in used units }
  144. pu^.u:=loaded_unit;
  145. pu^.loaded:=true;
  146. { need to recompile the current unit ? }
  147. if loaded_unit^.crc<>pu^.checksum then
  148. begin
  149. current_module^.do_compile:=true;
  150. exit;
  151. end;
  152. { setup the map entry for deref }
  153. current_module^.map^[nextmapentry]:=loaded_unit^.symtable;
  154. inc(nextmapentry);
  155. if nextmapentry>maxunits then
  156. Message(unit_f_too_much_units);
  157. end;
  158. pu:=pused_unit(pu^.next);
  159. end;
  160. { ok, now load the unit }
  161. current_module^.symtable:=new(punitsymtable,loadasunit);
  162. { if this is the system unit insert the intern symbols }
  163. if compile_system then
  164. begin
  165. make_ref:=false;
  166. insertinternsyms(psymtable(current_module^.symtable));
  167. make_ref:=true;
  168. end;
  169. { now only read the implementation part }
  170. current_module^.in_implementation:=true;
  171. { load the used units from implementation }
  172. pu:=pused_unit(current_module^.used_units.first);
  173. while assigned(pu) do
  174. begin
  175. if (not pu^.loaded) and (not pu^.in_interface) then
  176. begin
  177. loaded_unit:=loadunit(pu^.name^,false);
  178. if current_module^.compiled then
  179. exit;
  180. { register unit in used units }
  181. pu^.u:=loaded_unit;
  182. pu^.loaded:=true;
  183. {$ifdef TEST_IMPL}
  184. { need to recompile the current unit ? }
  185. if loaded_unit^.crc<>pu^.checksum then
  186. begin
  187. current_module^.do_compile:=true;
  188. exit;
  189. end;
  190. { setup the map entry for deref }
  191. current_module^.map^[nextmapentry]:=loaded_unit^.symtable;
  192. inc(nextmapentry);
  193. if nextmapentry>maxunits then
  194. Message(unit_f_too_much_units);
  195. {$endif TEST_IMPL}
  196. end;
  197. pu:=pused_unit(pu^.next);
  198. end;
  199. { remove the map, it's not needed anymore }
  200. dispose(current_module^.map);
  201. current_module^.map:=nil;
  202. end;
  203. function loadunit(const s : string;compile_system:boolean) : pmodule;
  204. var
  205. st : punitsymtable;
  206. old_current_ppu : pppufile;
  207. old_current_module,hp : pmodule;
  208. procedure loadppufile;
  209. begin
  210. { load interface section }
  211. if not current_module^.do_compile then
  212. load_interface;
  213. { only load units when we don't recompile }
  214. if not current_module^.do_compile then
  215. load_usedunits(compile_system);
  216. { recompile if set }
  217. if current_module^.do_compile then
  218. begin
  219. { we needn't the ppufile }
  220. if assigned(current_module^.ppufile) then
  221. begin
  222. dispose(current_module^.ppufile,done);
  223. current_module^.ppufile:=nil;
  224. end;
  225. { recompile the unit or give a fatal error if sources not available }
  226. if not(current_module^.sources_avail) then
  227. Message1(unit_f_cant_compile_unit,current_module^.modulename^)
  228. else
  229. begin
  230. if assigned(old_current_module^.current_inputfile) then
  231. old_current_module^.current_inputfile^.tempclose;
  232. compile(current_module^.mainsource^,compile_system);
  233. if (not old_current_module^.compiled) and assigned(old_current_module^.current_inputfile) then
  234. old_current_module^.current_inputfile^.tempreopen;
  235. end;
  236. end
  237. else
  238. begin
  239. { only reassemble ? }
  240. if (current_module^.do_assemble) then
  241. OnlyAsm(current_module^.asmfilename^);
  242. { add the files for the linker }
  243. addlinkerfiles(current_module);
  244. end;
  245. end;
  246. begin
  247. old_current_module:=current_module;
  248. old_current_ppu:=current_ppu;
  249. { be sure not to mix lines from different files }
  250. { update_line; }
  251. { unit not found }
  252. st:=nil;
  253. { search all loaded units }
  254. hp:=pmodule(loaded_units.first);
  255. while assigned(hp) do
  256. begin
  257. if hp^.modulename^=s then
  258. begin
  259. { the unit is already registered }
  260. { and this means that the unit }
  261. { is already compiled }
  262. { else there is a cyclic unit use }
  263. if assigned(hp^.symtable) then
  264. st:=punitsymtable(hp^.symtable)
  265. else
  266. begin
  267. { recompile the unit ? }
  268. if (not current_module^.in_implementation) and (hp^.in_implementation) then
  269. Message(unit_f_circular_unit_reference);
  270. end;
  271. break;
  272. end;
  273. { the next unit }
  274. hp:=pmodule(hp^.next);
  275. end;
  276. { the unit is not in the symtable stack }
  277. if (not assigned(st)) then
  278. begin
  279. { if the unit is loaded remove it first }
  280. if assigned(hp) then
  281. begin
  282. { remove the old unit }
  283. loaded_units.remove(hp);
  284. dispose(hp,done);
  285. end;
  286. { generates a new unit info record }
  287. current_module:=new(pmodule,init(s,true));
  288. current_ppu:=current_module^.ppufile;
  289. { now we can register the unit }
  290. loaded_units.insert(current_module);
  291. { now realy load the ppu }
  292. loadppufile;
  293. { set compiled flag }
  294. current_module^.compiled:=true;
  295. { register the unit _once_ }
  296. usedunits.concat(new(pused_unit,init(current_module,true)));
  297. { load return pointer }
  298. hp:=current_module;
  299. end;
  300. { set the old module }
  301. current_ppu:=old_current_ppu;
  302. current_module:=old_current_module;
  303. loadunit:=hp;
  304. end;
  305. {$else NEWPPU}
  306. {*****************************************************************************
  307. Old PPU
  308. *****************************************************************************}
  309. function loadunit(const s : string;compile_system, in_uses : boolean) : pmodule;forward;
  310. procedure load_ppu(oldhp,hp : pmodule;compile_system : boolean);
  311. var
  312. loaded_unit : pmodule;
  313. b : byte;
  314. checksum,
  315. count,
  316. nextmapentry : longint;
  317. hs : string;
  318. begin
  319. { init the map }
  320. new(hp^.map);
  321. nextmapentry:=1;
  322. { load the used units from interface }
  323. hp^.ppufile^.read_data(b,1,count);
  324. while (b=ibloadunit) do
  325. begin
  326. { read unit name }
  327. hp^.ppufile^.read_data(hs[0],1,count);
  328. hp^.ppufile^.read_data(hs[1],byte(hs[0]),count);
  329. hp^.ppufile^.read_data(checksum,4,count);
  330. loaded_unit:=loadunit(hs,false,false);
  331. if hp^.compiled then
  332. exit;
  333. { if the crc of a used unit is the same as }
  334. { written to the PPU file, we needn't to }
  335. { recompile the current unit }
  336. if (loaded_unit^.crc<>checksum) then
  337. begin
  338. { we have to compile the current unit }
  339. { remove stuff which isn't needed }
  340. { forget the map }
  341. dispose(hp^.map);
  342. hp^.map:=nil;
  343. hp^.ppufile^.close;
  344. dispose(hp^.ppufile,done);
  345. hp^.ppufile:=nil;
  346. if not(hp^.sources_avail) then
  347. Message1(unit_f_cant_compile_unit,hp^.modulename^)
  348. else
  349. begin
  350. if assigned(oldhp^.current_inputfile) then
  351. oldhp^.current_inputfile^.tempclose;
  352. compile(hp^.mainsource^,compile_system);
  353. if (not oldhp^.compiled) and assigned(oldhp^.current_inputfile) then
  354. oldhp^.current_inputfile^.tempreopen;
  355. end;
  356. exit;
  357. end;
  358. { setup the map entry for deref }
  359. hp^.map^[nextmapentry]:=loaded_unit^.symtable;
  360. inc(nextmapentry);
  361. if nextmapentry>maxunits then
  362. Message(unit_f_too_much_units);
  363. { read until ibend }
  364. hp^.ppufile^.read_data(b,1,count);
  365. end;
  366. { ok, now load the unit }
  367. hp^.symtable:=new(punitsymtable,load(hp^.modulename^));
  368. { if this is the system unit insert the intern }
  369. { symbols }
  370. make_ref:=false;
  371. if compile_system then
  372. insertinternsyms(psymtable(hp^.symtable));
  373. make_ref:=true;
  374. { now only read the implementation part }
  375. hp^.in_implementation:=true;
  376. { load the used units from implementation }
  377. hp^.ppufile^.read_data(b,1,count);
  378. while (b<>ibend) and (b=ibloadunit) do
  379. begin
  380. { read unit name }
  381. hp^.ppufile^.read_data(hs[0],1,count);
  382. hp^.ppufile^.read_data(hs[1],byte(hs[0]),count);
  383. hp^.ppufile^.read_data(checksum,4,count);
  384. loaded_unit:=loadunit(hs,false,false);
  385. if hp^.compiled then exit;
  386. { if the crc of a used unit is the same as }
  387. { written to the PPU file, we needn't to }
  388. { recompile the current unit }
  389. { but for the implementation part }
  390. { the written crc is false, because }
  391. { not defined when writing the ppufile !! }
  392. {$ifdef TEST_IMPL}
  393. if (checksum<>0) and (loaded_unit^.crc<>checksum) then
  394. begin
  395. { we have to compile the current unit }
  396. { remove stuff which isn't needed }
  397. { forget the map }
  398. dispose(hp^.map);
  399. hp^.map:=nil;
  400. hp^.ppufile^.close;
  401. dispose(hp^.ppufile,done);
  402. hp^.ppufile:=nil;
  403. if not(hp^.sources_avail) then
  404. Message1(unit_f_cant_compile_unit,hp^.modulename^)
  405. else
  406. begin
  407. oldhp^.current_inputfile^.tempclose;
  408. compile(hp^.mainsource^,compile_system);
  409. oldhp^.current_inputfile^.tempclose;
  410. end;
  411. exit;
  412. end;
  413. {$endif TEST_IMPL}
  414. { read until ibend }
  415. hp^.ppufile^.read_data(b,1,count);
  416. end;
  417. hp^.ppufile^.close;
  418. dispose(hp^.map);
  419. hp^.map:=nil;
  420. end;
  421. function loadunit(const s : string;compile_system, in_uses : boolean) : pmodule;
  422. var
  423. st : punitsymtable;
  424. old_current_module,hp,nextmodule : pmodule;
  425. pu : pused_unit;
  426. hs : pstring;
  427. begin
  428. old_current_module:=current_module;
  429. { be sure not to mix lines from different files }
  430. { update_line; }
  431. { unit not found }
  432. st:=nil;
  433. { search all loaded units }
  434. hp:=pmodule(loaded_units.first);
  435. while assigned(hp) do
  436. begin
  437. if hp^.modulename^=s then
  438. begin
  439. { the unit is already registered }
  440. { and this means that the unit }
  441. { is already compiled }
  442. { else there is a cyclic unit use }
  443. if assigned(hp^.symtable) then
  444. st:=punitsymtable(hp^.symtable)
  445. else
  446. begin
  447. { recompile the unit ? }
  448. if (not current_module^.in_implementation) and (hp^.in_implementation) then
  449. Message(unit_f_circular_unit_reference);
  450. end;
  451. break;
  452. end;
  453. { the next unit }
  454. hp:=pmodule(hp^.next);
  455. end;
  456. { no error and the unit isn't loaded }
  457. if not(assigned(hp)) and (st=nil) then
  458. begin
  459. { generates a new unit info record }
  460. hp:=new(pmodule,init(s,true));
  461. { now we can register the unit }
  462. loaded_units.insert(hp);
  463. current_module:=hp;
  464. { force build ? }
  465. if (hp^.do_compile) or (hp^.sources_avail and do_build) then
  466. begin
  467. { we needn't the ppufile }
  468. if assigned(hp^.ppufile) then
  469. begin
  470. dispose(hp^.ppufile,done);
  471. hp^.ppufile:=nil;
  472. end;
  473. if not(hp^.sources_avail) then
  474. Message1(unit_f_cant_compile_unit,hp^.modulename^)
  475. else
  476. begin
  477. if assigned(old_current_module^.current_inputfile) then
  478. old_current_module^.current_inputfile^.tempclose;
  479. compile(hp^.mainsource^,compile_system);
  480. if (not old_current_module^.compiled) and assigned(old_current_module^.current_inputfile) then
  481. old_current_module^.current_inputfile^.tempreopen;
  482. end;
  483. end
  484. else
  485. begin
  486. { only reassemble ? }
  487. if (hp^.do_assemble) then
  488. OnlyAsm(hp^.asmfilename^);
  489. { we should know there the PPU file else it's an error and
  490. we can't load the unit }
  491. if hp^.ppufile^.name^<>'' then
  492. load_ppu(old_current_module,hp,compile_system);
  493. { add the files for the linker }
  494. addlinkerfiles(hp);
  495. end;
  496. { register the unit _once_ }
  497. usedunits.concat(new(pused_unit,init(hp,0)));
  498. { the unit is written, so we can set the symtable type }
  499. { to unitsymtable, else we get some dupid errors }
  500. { this is not the right place because of the }
  501. { ready label }
  502. { psymtable(hp^.symtable)^.symtabletype:=unitsymtable; }
  503. { placed at this end of proc_unit }
  504. psymtable(hp^.symtable)^.unitid:=0;
  505. { reset the unitnumbers for the other units }
  506. pu:=pused_unit(old_current_module^.used_units.first);
  507. while assigned(pu) do
  508. begin
  509. psymtable(pu^.u^.symtable)^.unitid:=pu^.unitid;
  510. pu:=pused_unit(pu^.next);
  511. end;
  512. end
  513. else
  514. if assigned(hp) and (st=nil) then
  515. begin
  516. { we have to compile the unit again, but it is already inserted !!}
  517. { we may have problem with the lost symtable !! }
  518. current_module:=hp;
  519. { we must preserve the unit chain }
  520. nextmodule:=pmodule(hp^.next);
  521. { we have to cleanup a little }
  522. hp^.special_done;
  523. new(hs);
  524. hs^:=hp^.mainsource^;
  525. hp^.init(hs^,true);
  526. dispose(hs);
  527. { we must preserve the unit chain }
  528. hp^.next:=nextmodule;
  529. if assigned(hp^.ppufile) then
  530. load_ppu(old_current_module,hp,compile_system)
  531. else
  532. begin
  533. {$ifdef UseBrowser}
  534. { here we need to remove the names ! }
  535. hp^.sourcefiles.done;
  536. hp^.sourcefiles.init;
  537. {$endif UseBrowser}
  538. if assigned(old_current_module^.current_inputfile) then
  539. old_current_module^.current_inputfile^.tempclose;
  540. Message1(parser_d_compiling_second_time,hp^.mainsource^);
  541. compile(hp^.mainsource^,compile_system);
  542. if (not old_current_module^.compiled) and assigned(old_current_module^.current_inputfile) then
  543. old_current_module^.current_inputfile^.tempreopen;
  544. end;
  545. current_module^.compiled:=true;
  546. end;
  547. { set the old module }
  548. current_module:=old_current_module;
  549. { the current module uses the unit hp }
  550. current_module^.used_units.concat(new(pused_unit,init(hp,0)));
  551. pused_unit(current_module^.used_units.last)^.in_uses:=in_uses;
  552. if in_uses and not current_module^.in_implementation then
  553. pused_unit(current_module^.used_units.last)^.in_interface:=true;
  554. loadunit:=hp;
  555. end;
  556. {$endif NEWPPU}
  557. procedure loadsystemunit;
  558. var
  559. hp : pmodule;
  560. begin
  561. { if the current file isn't a system unit the the system unit
  562. will be loaded }
  563. if not(cs_compilesystem in aktswitches) then
  564. begin
  565. {$ifdef NEWPPU}
  566. hp:=loadunit(upper(target_info.system_unit),true);
  567. systemunit:=hp^.symtable;
  568. { add to the used units }
  569. current_module^.used_units.concat(new(pused_unit,init(hp,true)));
  570. {$else NEWPPU}
  571. hp:=loadunit(upper(target_info.system_unit),true,true);
  572. systemunit:=hp^.symtable;
  573. { add to the used units }
  574. current_module^.used_units.concat(new(pused_unit,init(hp,0)));
  575. {$endif NEWPPU}
  576. { read default constant definitions }
  577. make_ref:=false;
  578. readconstdefs;
  579. { we could try to overload caret by default }
  580. symtablestack:=systemunit;
  581. { if POWER is defined in the RTL then use it for starstar overloading }
  582. getsym('POWER',false);
  583. if assigned(srsym) and (srsym^.typ=procsym) and
  584. (overloaded_operators[STARSTAR]=nil) then
  585. overloaded_operators[STARSTAR]:=pprocsym(srsym);
  586. make_ref:=true;
  587. end
  588. else
  589. begin
  590. createconstdefs;
  591. systemunit:=nil;
  592. end;
  593. end;
  594. procedure loadunits;
  595. var
  596. s : stringid;
  597. hp : pused_unit;
  598. hp2 : pmodule;
  599. hp3 : psymtable;
  600. oldprocsym:Pprocsym;
  601. begin
  602. oldprocsym:=aktprocsym;
  603. consume(_USES);
  604. {$ifdef DEBUG}
  605. test_symtablestack;
  606. {$endif DEBUG}
  607. repeat
  608. s:=pattern;
  609. consume(ID);
  610. {$ifdef NEWPPU}
  611. hp2:=loadunit(s,false);
  612. { the current module uses the unit hp2 }
  613. current_module^.used_units.concat(new(pused_unit,init(hp2,not current_module^.in_implementation)));
  614. pused_unit(current_module^.used_units.last)^.in_uses:=true;
  615. {$else NEWPPU}
  616. hp2:=loadunit(s,false,true);
  617. {$endif NEWPPU}
  618. if current_module^.compiled then
  619. exit;
  620. refsymtable^.insert(new(punitsym,init(s,hp2^.symtable)));
  621. if token=COMMA then
  622. begin
  623. pattern:='';
  624. consume(COMMA);
  625. end
  626. else
  627. break;
  628. until false;
  629. consume(SEMICOLON);
  630. { set the symtable to systemunit so it gets reorderd correctly }
  631. symtablestack:=systemunit;
  632. { now insert the units in the symtablestack }
  633. hp:=pused_unit(current_module^.used_units.first);
  634. while assigned(hp) do
  635. begin
  636. {$IfDef GDB}
  637. if (cs_debuginfo in aktswitches) and
  638. not hp^.is_stab_written then
  639. begin
  640. punitsymtable(hp^.u^.symtable)^.concattypestabto(debuglist);
  641. hp^.is_stab_written:=true;
  642. hp^.unitid:=psymtable(hp^.u^.symtable)^.unitid;
  643. end;
  644. {$EndIf GDB}
  645. if hp^.in_uses then
  646. begin
  647. hp3:=symtablestack;
  648. while assigned(hp3) do
  649. begin
  650. { insert units only once ! }
  651. if hp^.u^.symtable=hp3 then
  652. break;
  653. hp3:=hp3^.next;
  654. { unit isn't inserted }
  655. if hp3=nil then
  656. begin
  657. psymtable(hp^.u^.symtable)^.next:=symtablestack;
  658. symtablestack:=psymtable(hp^.u^.symtable);
  659. {$ifdef CHAINPROCSYMS}
  660. symtablestack^.chainprocsyms;
  661. {$endif CHAINPROCSYMS}
  662. {$ifdef DEBUG}
  663. test_symtablestack;
  664. {$endif DEBUG}
  665. end;
  666. end;
  667. end;
  668. hp:=pused_unit(hp^.next);
  669. end;
  670. aktprocsym:=oldprocsym;
  671. end;
  672. procedure parse_implementation_uses(symt:Psymtable);
  673. var
  674. old_module_in_implementation : boolean;
  675. begin
  676. if token=_USES then
  677. begin
  678. old_module_in_implementation:=module_in_implementation;
  679. module_in_implementation:=true;
  680. current_module^.in_implementation:=true;
  681. symt^.symtabletype:=unitsymtable;
  682. loadunits;
  683. symt^.symtabletype:=globalsymtable;
  684. {$ifdef DEBUG}
  685. test_symtablestack;
  686. {$endif DEBUG}
  687. module_in_implementation:=old_module_in_implementation;
  688. end;
  689. end;
  690. procedure proc_unit;
  691. var
  692. { unitname : stringid; }
  693. names:Tstringcontainer;
  694. p : psymtable;
  695. unitst : punitsymtable;
  696. pu : pused_unit;
  697. s1,s2 : ^string; {Saves stack space}
  698. begin
  699. consume(_UNIT);
  700. if token=ID then
  701. begin
  702. { create filenames and unit name }
  703. current_module^.SetFileName(current_module^.current_inputfile^.path^,current_module^.current_inputfile^.name^);
  704. stringdispose(current_module^.modulename);
  705. current_module^.modulename:=stringdup(upper(pattern));
  706. { check for system unit }
  707. new(s1);
  708. new(s2);
  709. s1^:=upper(target_info.system_unit);
  710. s2^:=upper(current_module^.current_inputfile^.name^);
  711. if (cs_compilesystem in aktswitches) then
  712. begin
  713. if (cs_check_unit_name in aktswitches) and
  714. ((length(current_module^.modulename^)>8) or
  715. (current_module^.modulename^<>s1^) or
  716. (current_module^.modulename^<>s2^)) then
  717. Message1(unit_e_illegal_unit_name,s1^);
  718. end
  719. else
  720. if (current_module^.modulename^=s1^) then
  721. Message(unit_w_switch_us_missed);
  722. dispose(s2);
  723. dispose(s1);
  724. { Add Object File }
  725. if (cs_smartlink in aktswitches) then
  726. current_module^.linkstaticlibs.insert(current_module^.libfilename^)
  727. else
  728. current_module^.linkofiles.insert(current_module^.objfilename^);
  729. end;
  730. consume(ID);
  731. consume(SEMICOLON);
  732. consume(_INTERFACE);
  733. { this should be placed after uses !!}
  734. {$ifndef UseNiceNames}
  735. procprefix:='_'+current_module^.modulename^+'$$';
  736. {$else UseNiceNames}
  737. procprefix:='_'+tostr(length(current_module^.unitname^))+lowercase(current_module^.unitname^)+'_';
  738. {$endif UseNiceNames}
  739. parse_only:=true;
  740. { generate now the global symboltable }
  741. p:=new(punitsymtable,init(globalsymtable,current_module^.modulename^));
  742. refsymtable:=p;
  743. unitst:=punitsymtable(p);
  744. { the unit name must be usable as a unit specifier }
  745. { inside the unit itself (PM) }
  746. { this also forbids to have another symbol }
  747. { with the same name as the unit }
  748. refsymtable^.insert(new(punitsym,init(current_module^.modulename^,unitst)));
  749. { set the symbol table for the current unit }
  750. { this must be set later for interdependency }
  751. { current_module^.symtable:=psymtable(p); }
  752. { a unit compiled at command line must be inside the loaded_unit list }
  753. if (compile_level=1) then
  754. begin
  755. loaded_units.insert(current_module);
  756. if cs_unit_to_lib in initswitches then
  757. begin
  758. current_module^.flags:=current_module^.flags or uf_in_library;
  759. if cs_shared_lib in initswitches then
  760. current_module^.flags:=current_module^.flags or uf_shared_library;
  761. end;
  762. end;
  763. { insert qualifier for the system unit (allows system.writeln) }
  764. if not(cs_compilesystem in aktswitches) then
  765. begin
  766. { insert the system unit }
  767. { it is allways the first }
  768. systemunit^.next:=nil;
  769. symtablestack:=systemunit;
  770. refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  771. if token=_USES then
  772. begin
  773. unitst^.symtabletype:=unitsymtable;
  774. loadunits;
  775. { has it been compiled at a higher level ?}
  776. if current_module^.compiled then
  777. exit;
  778. unitst^.symtabletype:=globalsymtable;
  779. end;
  780. { ... but insert the symbol table later }
  781. p^.next:=symtablestack;
  782. symtablestack:=p;
  783. end
  784. else
  785. { while compiling a system unit, some types are directly inserted }
  786. begin
  787. p^.next:=symtablestack;
  788. symtablestack:=p;
  789. insert_intern_types(p);
  790. end;
  791. { displaced for inter-dependency considerations }
  792. current_module^.symtable:=psymtable(p);
  793. constsymtable:=symtablestack;
  794. { ... parse the declarations }
  795. read_interface_declarations;
  796. consume(_IMPLEMENTATION);
  797. parse_only:=false;
  798. {$ifdef GDB}
  799. { add all used definitions even for implementation}
  800. if (cs_debuginfo in aktswitches) then
  801. begin
  802. { all types }
  803. punitsymtable(refsymtable)^.concattypestabto(debuglist);
  804. { and all local symbols}
  805. refsymtable^.concatstabto(debuglist);
  806. end;
  807. {$endif GDB}
  808. { generates static symbol table }
  809. p:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
  810. {Generate a procsym.}
  811. make_ref:=false;
  812. aktprocsym:=new(Pprocsym,init(current_module^.modulename^+'_init'));
  813. aktprocsym^.definition:=new(Pprocdef,init);
  814. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or pounitinit;
  815. aktprocsym^.definition^.setmangledname(current_module^.modulename^+'_init');
  816. make_ref:=true;
  817. {The generated procsym has a local symtable. Discard it and turn
  818. it into the static one.}
  819. dispose(aktprocsym^.definition^.localst,done);
  820. aktprocsym^.definition^.localst:=p;
  821. { remove the globalsymtable from the symtable stack }
  822. { to reinsert it after loading the implementation units }
  823. symtablestack:=unitst^.next;
  824. { number the definitions, so a deref from other units works }
  825. refsymtable^.number_defs;
  826. { Read the implementation units }
  827. parse_implementation_uses(unitst);
  828. numberunits;
  829. { now we can change refsymtable }
  830. refsymtable:=p;
  831. { but reinsert the global symtable as lasts }
  832. unitst^.next:=symtablestack;
  833. symtablestack:=unitst;
  834. {$ifdef DEBUG}
  835. test_symtablestack;
  836. {$endif DEBUG}
  837. constsymtable:=symtablestack;
  838. {$ifdef Splitheap}
  839. if testsplit then
  840. begin
  841. Split_Heap;
  842. allow_special:=true;
  843. Switch_to_temp_heap;
  844. end;
  845. { it will report all crossings }
  846. allow_special:=false;
  847. {$endif Splitheap}
  848. { set some informations }
  849. procinfo.retdef:=voiddef;
  850. procinfo._class:=nil;
  851. procinfo.call_offset:=8;
  852. { for temporary values }
  853. procinfo.framepointer:=frame_pointer;
  854. { clear flags }
  855. procinfo.flags:=0;
  856. { Create a new procedure }
  857. codegen_newprocedure;
  858. { Compile the unit }
  859. names.init;
  860. names.insert(current_module^.modulename^+'_init');
  861. names.insert('INIT$$'+current_module^.modulename^);
  862. compile_proc_body(names,true,false);
  863. names.done;
  864. { Shutdown the codegen for this procedure }
  865. codegen_doneprocedure;
  866. consume(POINT);
  867. { size of the static data }
  868. datasize:=symtablestack^.datasize;
  869. { unsed static symbols ? }
  870. symtablestack^.allsymbolsused;
  871. {$ifdef GDB}
  872. { add all used definitions even for implementation}
  873. if (cs_debuginfo in aktswitches) then
  874. begin
  875. { all types }
  876. punitsymtable(symtablestack)^.concattypestabto(debuglist);
  877. { and all local symbols}
  878. symtablestack^.concatstabto(debuglist);
  879. end;
  880. {$endif GDB}
  881. current_module^.in_implementation:=false;
  882. { deletes all symtables generated in the implementation part }
  883. while symtablestack^.symtabletype<>globalsymtable do
  884. dellexlevel;
  885. { tests, if all forwards are resolved }
  886. symtablestack^.check_forwards;
  887. symtablestack^.symtabletype:=unitsymtable;
  888. punitsymtable(symtablestack)^.is_stab_written:=false;
  889. {Write out the unit if the compile was succesfull.}
  890. if status.errorcount=0 then
  891. writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack));
  892. pu:=pused_unit(usedunits.first);
  893. while assigned(pu) do
  894. begin
  895. punitsymtable(pu^.u^.symtable)^.is_stab_written:=false;
  896. pu:=pused_unit(pu^.next);
  897. end;
  898. inc(datasize,symtablestack^.datasize);
  899. { generate imports }
  900. if current_module^.uses_imports then
  901. importlib^.generatelib;
  902. { finish asmlist by adding segment starts }
  903. insertsegment;
  904. end;
  905. procedure proc_program(islibrary : boolean);
  906. var
  907. st : psymtable;
  908. names : Tstringcontainer;
  909. begin
  910. { Trying to compile the system unit... }
  911. { if no unit defined... then issue a }
  912. { fatal error (avoids pointer problems)}
  913. { when referencing the non-existant }
  914. { system unit. }
  915. { System Unit should be compiled using proc_unit !! (PFV) }
  916. { if (cs_compilesystem in aktswitches) then
  917. Begin
  918. if token<>_UNIT then
  919. Message1(scan_f_syn_expected,'UNIT');
  920. consume(_UNIT);
  921. end;}
  922. parse_only:=false;
  923. if islibrary then
  924. begin
  925. consume(_LIBRARY);
  926. stringdispose(current_module^.modulename);
  927. current_module^.modulename:=stringdup(pattern);
  928. consume(ID);
  929. consume(SEMICOLON);
  930. end
  931. else
  932. { is there an program head ? }
  933. if token=_PROGRAM then
  934. begin
  935. consume(_PROGRAM);
  936. stringdispose(current_module^.modulename);
  937. current_module^.modulename:=stringdup(pattern);
  938. consume(ID);
  939. if token=LKLAMMER then
  940. begin
  941. consume(LKLAMMER);
  942. idlist;
  943. consume(RKLAMMER);
  944. end;
  945. consume(SEMICOLON);
  946. end;
  947. { insert after the unit symbol tables the static symbol table }
  948. { of the program }
  949. st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
  950. {Generate a procsym.}
  951. make_ref:=false;
  952. aktprocsym:=new(Pprocsym,init('main'));
  953. aktprocsym^.definition:=new(Pprocdef,init);
  954. aktprocsym^.definition^.options:=aktprocsym^.definition^.options or poproginit;
  955. aktprocsym^.definition^.setmangledname(target_os.Cprefix+'main');
  956. make_ref:=true;
  957. {The localst is a local symtable. Change it into the static
  958. symtable.}
  959. dispose(aktprocsym^.definition^.localst,done);
  960. aktprocsym^.definition^.localst:=st;
  961. refsymtable:=st;
  962. { necessary for browser }
  963. loaded_units.insert(current_module);
  964. {Insert the symbols of the system unit into the stack of symbol
  965. tables.}
  966. symtablestack:=systemunit;
  967. systemunit^.next:=nil;
  968. refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  969. {Load the units used by the program we compile.}
  970. if token=_USES then
  971. loadunits;
  972. {Insert the name of the main program into the symbol table.}
  973. if current_module^.modulename^<>'' then
  974. st^.insert(new(pprogramsym,init(current_module^.modulename^)));
  975. { ...is also constsymtable, this is the symtable where }
  976. { the elements of enumeration types are inserted }
  977. constsymtable:=st;
  978. { set some informations about the main program }
  979. with procinfo do
  980. begin
  981. retdef:=voiddef;
  982. _class:=nil;
  983. call_offset:=8;
  984. framepointer:=frame_pointer;
  985. flags:=0;
  986. end;
  987. procprefix:='';
  988. in_except_block:=false;
  989. codegen_newprocedure;
  990. {The program intialization needs an alias, so it can be called
  991. from the bootstrap code.}
  992. names.init;
  993. names.insert('program_init');
  994. names.insert('PASCALMAIN');
  995. names.insert(target_os.cprefix+'main');
  996. compile_proc_body(names,true,false);
  997. names.done;
  998. codegen_doneprocedure;
  999. consume(POINT);
  1000. if (cs_smartlink in aktswitches) then
  1001. current_module^.linkstaticlibs.insert(current_module^.libfilename^)
  1002. else
  1003. current_module^.linkofiles.insert(current_module^.objfilename^);
  1004. { insert heap }
  1005. insertheap;
  1006. { generate imports }
  1007. if current_module^.uses_imports then
  1008. importlib^.generatelib;
  1009. inserttargetspecific;
  1010. datasize:=symtablestack^.datasize;
  1011. { finish asmlist by adding segment starts }
  1012. insertsegment;
  1013. end;
  1014. end.
  1015. {
  1016. $Log$
  1017. Revision 1.30 1998-06-17 14:10:16 peter
  1018. * small os2 fixes
  1019. * fixed interdependent units with newppu (remake3 under linux works now)
  1020. Revision 1.29 1998/06/16 08:56:25 peter
  1021. + targetcpu
  1022. * cleaner pmodules for newppu
  1023. Revision 1.28 1998/06/13 00:10:10 peter
  1024. * working browser and newppu
  1025. * some small fixes against crashes which occured in bp7 (but not in
  1026. fpc?!)
  1027. Revision 1.27 1998/06/11 13:58:08 peter
  1028. * small fix to let newppu compile
  1029. Revision 1.26 1998/06/09 16:01:47 pierre
  1030. + added procedure directive parsing for procvars
  1031. (accepted are popstack cdecl and pascal)
  1032. + added C vars with the following syntax
  1033. var C calias 'true_c_name';(can be followed by external)
  1034. reason is that you must add the Cprefix
  1035. which is target dependent
  1036. Revision 1.25 1998/06/08 22:59:49 peter
  1037. * smartlinking works for win32
  1038. * some defines to exclude some compiler parts
  1039. Revision 1.24 1998/06/08 13:13:44 pierre
  1040. + temporary variables now in temp_gen.pas unit
  1041. because it is processor independent
  1042. * mppc68k.bat modified to undefine i386 and support_mmx
  1043. (which are defaults for i386)
  1044. Revision 1.23 1998/06/05 17:47:29 peter
  1045. * some better uses clauses
  1046. Revision 1.22 1998/06/05 14:37:34 pierre
  1047. * fixes for inline for operators
  1048. * inline procedure more correctly restricted
  1049. Revision 1.21 1998/06/04 23:51:53 peter
  1050. * m68k compiles
  1051. + .def file creation moved to gendef.pas so it could also be used
  1052. for win32
  1053. Revision 1.20 1998/06/04 09:55:42 pierre
  1054. * demangled name of procsym reworked to become independant of the mangling scheme
  1055. Revision 1.19 1998/06/03 23:40:38 peter
  1056. + unlimited file support, release tempclose
  1057. Revision 1.18 1998/06/03 22:49:00 peter
  1058. + wordbool,longbool
  1059. * rename bis,von -> high,low
  1060. * moved some systemunit loading/creating to psystem.pas
  1061. Revision 1.17 1998/05/28 14:40:25 peter
  1062. * fixes for newppu, remake3 works now with it
  1063. Revision 1.16 1998/05/27 19:45:06 peter
  1064. * symtable.pas splitted into includefiles
  1065. * symtable adapted for $ifdef NEWPPU
  1066. Revision 1.15 1998/05/23 01:21:22 peter
  1067. + aktasmmode, aktoptprocessor, aktoutputformat
  1068. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  1069. + $LIBNAME to set the library name where the unit will be put in
  1070. * splitted cgi386 a bit (codeseg to large for bp7)
  1071. * nasm, tasm works again. nasm moved to ag386nsm.pas
  1072. Revision 1.14 1998/05/20 09:42:35 pierre
  1073. + UseTokenInfo now default
  1074. * unit in interface uses and implementation uses gives error now
  1075. * only one error for unknown symbol (uses lastsymknown boolean)
  1076. the problem came from the label code !
  1077. + first inlined procedures and function work
  1078. (warning there might be allowed cases were the result is still wrong !!)
  1079. * UseBrower updated gives a global list of all position of all used symbols
  1080. with switch -gb
  1081. Revision 1.13 1998/05/12 10:47:00 peter
  1082. * moved printstatus to verb_def
  1083. + V_Normal which is between V_Error and V_Warning and doesn't have a
  1084. prefix like error: warning: and is included in V_Default
  1085. * fixed some messages
  1086. * first time parameter scan is only for -v and -T
  1087. - removed old style messages
  1088. Revision 1.12 1998/05/11 13:07:56 peter
  1089. + $ifdef NEWPPU for the new ppuformat
  1090. + $define GDB not longer required
  1091. * removed all warnings and stripped some log comments
  1092. * no findfirst/findnext anymore to remove smartlink *.o files
  1093. Revision 1.11 1998/05/06 18:36:53 peter
  1094. * tai_section extended with code,data,bss sections and enumerated type
  1095. * ident 'compiled by FPC' moved to pmodules
  1096. * small fix for smartlink
  1097. Revision 1.10 1998/05/04 17:54:28 peter
  1098. + smartlinking works (only case jumptable left todo)
  1099. * redesign of systems.pas to support assemblers and linkers
  1100. + Unitname is now also in the PPU-file, increased version to 14
  1101. Revision 1.9 1998/05/01 16:38:45 florian
  1102. * handling of private and protected fixed
  1103. + change_keywords_to_tp implemented to remove
  1104. keywords which aren't supported by tp
  1105. * break and continue are now symbols of the system unit
  1106. + widestring, longstring and ansistring type released
  1107. Revision 1.8 1998/04/30 15:59:41 pierre
  1108. * GDB works again better :
  1109. correct type info in one pass
  1110. + UseTokenInfo for better source position
  1111. * fixed one remaining bug in scanner for line counts
  1112. * several little fixes
  1113. Revision 1.7 1998/04/29 10:33:59 pierre
  1114. + added some code for ansistring (not complete nor working yet)
  1115. * corrected operator overloading
  1116. * corrected nasm output
  1117. + started inline procedures
  1118. + added starstarn : use ** for exponentiation (^ gave problems)
  1119. + started UseTokenInfo cond to get accurate positions
  1120. Revision 1.6 1998/04/27 23:10:28 peter
  1121. + new scanner
  1122. * $makelib -> if smartlink
  1123. * small filename fixes pmodule.setfilename
  1124. * moved import from files.pas -> import.pas
  1125. Revision 1.5 1998/04/14 23:27:03 florian
  1126. + exclude/include with constant second parameter added
  1127. Revision 1.4 1998/04/10 14:41:43 peter
  1128. * removed some Hints
  1129. * small speed optimization for AsmLn
  1130. Revision 1.3 1998/04/03 09:51:00 daniel
  1131. * Fixed heap allocation for OS/2.
  1132. }