pmodules.pas 39 KB

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