pmodules.pas 39 KB

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