pmodules.pas 39 KB

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