pmodules.pas 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. { close old_current_ppu on system that are
  20. short on file handles like DOS system PM }
  21. {$ifdef GO32V1}
  22. {$define SHORT_ON_FILE_HANDLES}
  23. {$endif GO32V1}
  24. {$ifdef GO32V2}
  25. {$define SHORT_ON_FILE_HANDLES}
  26. {$endif GO32V2}
  27. {$define New_GDB}
  28. interface
  29. procedure proc_unit;
  30. procedure proc_program(islibrary : boolean);
  31. implementation
  32. uses
  33. globtype,version,systems,tokens,
  34. cobjects,comphook,compiler,
  35. globals,verbose,files,
  36. symconst,symtable,aasm,
  37. {$ifdef newcg}
  38. cgbase,
  39. {$else newcg}
  40. hcodegen,
  41. {$endif newcg}
  42. link,assemble,import,export,gendef,ppu,comprsrc,
  43. cresstr,cpubase,cpuasm,
  44. {$ifdef GDB}
  45. gdb,
  46. {$endif GDB}
  47. scanner,pbase,psystem,pdecl,psub,parser;
  48. procedure create_objectfile;
  49. begin
  50. { create the .s file and assemble it }
  51. GenerateAsm(false);
  52. { Also create a smartlinked version ? }
  53. if (cs_create_smart in aktmoduleswitches) then
  54. begin
  55. { regenerate the importssection for win32 }
  56. if assigned(importssection) and
  57. (target_info.target=target_i386_win32) then
  58. begin
  59. importssection^.clear;
  60. importlib^.generatesmartlib;
  61. end;
  62. GenerateAsm(true);
  63. if target_asm.needar then
  64. Linker^.MakeStaticLibrary;
  65. end;
  66. { resource files }
  67. CompileResourceFiles;
  68. end;
  69. procedure insertobjectfile;
  70. { Insert the used object file for this unit in the used list for this unit }
  71. begin
  72. current_module^.linkunitofiles.insert(current_module^.objfilename^,link_static);
  73. current_module^.flags:=current_module^.flags or uf_static_linked;
  74. if (cs_create_smart in aktmoduleswitches) then
  75. begin
  76. current_module^.linkunitstaticlibs.insert(current_module^.staticlibfilename^,link_smart);
  77. current_module^.flags:=current_module^.flags or uf_smart_linked;
  78. end;
  79. end;
  80. procedure insertsegment;
  81. procedure fixseg(p:paasmoutput;sec:tsection);
  82. begin
  83. p^.insert(new(pai_section,init(sec)));
  84. if (cs_create_smart in aktmoduleswitches) then
  85. p^.insert(new(pai_cut,init));
  86. p^.concat(new(pai_section,init(sec_none)));
  87. end;
  88. begin
  89. { Insert Ident of the compiler }
  90. if (not (cs_create_smart in aktmoduleswitches))
  91. {$ifndef EXTDEBUG}
  92. and (not current_module^.is_unit)
  93. {$endif}
  94. then
  95. begin
  96. datasegment^.insert(new(pai_align,init(4)));
  97. datasegment^.insert(new(pai_string,init('FPC '+full_version_string+
  98. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.short_name)));
  99. end;
  100. { finish codesegment }
  101. codesegment^.concat(new(pai_align,init(16)));
  102. { Insert start and end of sections }
  103. fixseg(codesegment,sec_code);
  104. fixseg(datasegment,sec_data);
  105. fixseg(bsssegment,sec_bss);
  106. { we should use .rdata section for these two no ? }
  107. { .rdata is a read only data section (PM) }
  108. fixseg(rttilist,sec_data);
  109. fixseg(consts,sec_data);
  110. if assigned(resourcestringlist) then
  111. fixseg(resourcestringlist,sec_data);
  112. {$ifdef GDB}
  113. if assigned(debuglist) then
  114. begin
  115. debuglist^.insert(new(pai_symbol,initname('gcc2_compiled',0)));
  116. fixseg(debuglist,sec_code);
  117. end;
  118. {$endif GDB}
  119. end;
  120. Procedure InsertResourceTablesTable;
  121. var
  122. hp : pused_unit;
  123. ResourceStringTables : taasmoutput;
  124. count : longint;
  125. begin
  126. ResourceStringTables.init;
  127. count:=0;
  128. hp:=pused_unit(usedunits.first);
  129. while assigned(hp) do
  130. begin
  131. If (hp^.u^.flags and uf_has_resources)=uf_has_resources then
  132. begin
  133. ResourceStringTables.concat(new(pai_const_symbol,initname(hp^.u^.modulename^+'_RESOURCESTRINGLIST')));
  134. inc(count);
  135. end;
  136. hp:=Pused_unit(hp^.next);
  137. end;
  138. { Add program resources, if any }
  139. If ResourceStringList<>Nil then
  140. begin
  141. ResourceStringTables.concat(new(pai_const_symbol,initname(Current_Module^.modulename^+'_RESOURCESTRINGLIST')));
  142. Inc(Count);
  143. end;
  144. { TableCount }
  145. With ResourceStringTables do
  146. begin
  147. insert(new(pai_const,init_32bit(count)));
  148. insert(new(pai_symbol,initname_global('FPC_RESOURCESTRINGTABLES',0)));
  149. concat(new(pai_symbol_end,initname('FPC_RESOURCESTRINGTABLES')));
  150. end;
  151. { insert in data segment }
  152. if (cs_create_smart in aktmoduleswitches) then
  153. datasegment^.concat(new(pai_cut,init));
  154. datasegment^.concatlist(@ResourceStringTables);
  155. ResourceStringTables.done;
  156. end;
  157. procedure InsertInitFinalTable;
  158. var
  159. hp : pused_unit;
  160. unitinits : taasmoutput;
  161. count : longint;
  162. begin
  163. unitinits.init;
  164. count:=0;
  165. hp:=pused_unit(usedunits.first);
  166. while assigned(hp) do
  167. begin
  168. { call the unit init code and make it external }
  169. if (hp^.u^.flags and (uf_init or uf_finalize))<>0 then
  170. begin
  171. if (hp^.u^.flags and uf_init)<>0 then
  172. begin
  173. unitinits.concat(new(pai_const_symbol,initname('INIT$$'+hp^.u^.modulename^)));
  174. end
  175. else
  176. unitinits.concat(new(pai_const,init_32bit(0)));
  177. if (hp^.u^.flags and uf_finalize)<>0 then
  178. begin
  179. unitinits.concat(new(pai_const_symbol,initname('FINALIZE$$'+hp^.u^.modulename^)));
  180. end
  181. else
  182. unitinits.concat(new(pai_const,init_32bit(0)));
  183. inc(count);
  184. end;
  185. hp:=Pused_unit(hp^.next);
  186. end;
  187. if current_module^.islibrary then
  188. if (current_module^.flags and uf_finalize)<>0 then
  189. begin
  190. { INIT code is done by PASCALMAIN calling }
  191. unitinits.concat(new(pai_const,init_32bit(0)));
  192. unitinits.concat(new(pai_const_symbol,initname('FINALIZE$$'+current_module^.modulename^)));
  193. inc(count);
  194. end;
  195. { TableCount,InitCount }
  196. unitinits.insert(new(pai_const,init_32bit(0)));
  197. unitinits.insert(new(pai_const,init_32bit(count)));
  198. unitinits.insert(new(pai_symbol,initname_global('INITFINAL',0)));
  199. unitinits.concat(new(pai_symbol_end,initname('INITFINAL')));
  200. { insert in data segment }
  201. if (cs_create_smart in aktmoduleswitches) then
  202. datasegment^.concat(new(pai_cut,init));
  203. datasegment^.concatlist(@unitinits);
  204. unitinits.done;
  205. end;
  206. procedure insertheap;
  207. begin
  208. if (cs_create_smart in aktmoduleswitches) then
  209. begin
  210. bsssegment^.concat(new(pai_cut,init));
  211. datasegment^.concat(new(pai_cut,init));
  212. end;
  213. { On the Macintosh Classic M68k Architecture
  214. The Heap variable is simply a POINTER to the
  215. real HEAP. The HEAP must be set up by the RTL
  216. and must store the pointer in this value.
  217. On OS/2 the heap is also intialized by the RTL. We do
  218. not output a pointer }
  219. case target_info.target of
  220. {$ifdef i386}
  221. target_i386_OS2:
  222. ;
  223. {$endif i386}
  224. {$ifdef alpha}
  225. target_alpha_linux:
  226. ;
  227. {$endif alpha}
  228. {$ifdef powerpc}
  229. target_powerpc_linux:
  230. ;
  231. {$endif powerpc}
  232. {$ifdef m68k}
  233. target_m68k_Mac:
  234. bsssegment^.concat(new(pai_datablock,init_global('HEAP',4)));
  235. target_m68k_PalmOS:
  236. ;
  237. {$endif m68k}
  238. else
  239. bsssegment^.concat(new(pai_datablock,init_global('HEAP',heapsize)));
  240. end;
  241. {$ifdef m68k}
  242. if target_info.target<>target_m68k_PalmOS then
  243. begin
  244. datasegment^.concat(new(pai_symbol,initname_global('HEAP_SIZE',0)));
  245. datasegment^.concat(new(pai_const,init_32bit(heapsize)));
  246. end;
  247. {$else m68k}
  248. datasegment^.concat(new(pai_symbol,initname_global('HEAPSIZE',4)));
  249. datasegment^.concat(new(pai_const,init_32bit(heapsize)));
  250. {$endif m68k}
  251. end;
  252. procedure inserttargetspecific;
  253. begin
  254. case target_info.target of
  255. {$ifdef alpha}
  256. target_alpha_linux:
  257. ;
  258. {$endif alpha}
  259. {$ifdef powerpc}
  260. target_powerpc_linux:
  261. ;
  262. {$endif powerpc}
  263. {$ifdef i386}
  264. target_i386_GO32V2 :
  265. begin
  266. { stacksize can be specified }
  267. datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
  268. datasegment^.concat(new(pai_const,init_32bit(stacksize)));
  269. end;
  270. {$endif i386}
  271. {$ifdef m68k}
  272. target_m68k_Atari :
  273. begin
  274. { stacksize can be specified }
  275. datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
  276. datasegment^.concat(new(pai_const,init_32bit(stacksize)));
  277. end;
  278. {$endif m68k}
  279. end;
  280. end;
  281. function loadunit(const s : string;compile_system:boolean) : pmodule;forward;
  282. procedure load_usedunits(compile_system:boolean);
  283. var
  284. pu : pused_unit;
  285. loaded_unit : pmodule;
  286. load_refs : boolean;
  287. nextmapentry : longint;
  288. begin
  289. load_refs:=true;
  290. { init the map }
  291. new(current_module^.map);
  292. fillchar(current_module^.map^,sizeof(tunitmap),#0);
  293. {$ifdef NEWMAP}
  294. current_module^.map^[0]:=current_module;
  295. {$endif NEWMAP}
  296. nextmapentry:=1;
  297. { load the used units from interface }
  298. current_module^.in_implementation:=false;
  299. pu:=pused_unit(current_module^.used_units.first);
  300. while assigned(pu) do
  301. begin
  302. if (not pu^.loaded) and (pu^.in_interface) then
  303. begin
  304. loaded_unit:=loadunit(pu^.name^,false);
  305. if current_module^.compiled then
  306. exit;
  307. { register unit in used units }
  308. pu^.u:=loaded_unit;
  309. pu^.loaded:=true;
  310. { doubles are not important for that list PM }
  311. pu^.u^.dependent_units.concat(new(pdependent_unit,init(current_module)));
  312. { need to recompile the current unit ? }
  313. if loaded_unit^.crc<>pu^.checksum then
  314. begin
  315. Message2(unit_u_recompile_crc_change,current_module^.modulename^,pu^.name^);
  316. current_module^.recompile_reason:=rr_crcchanged;
  317. current_module^.do_compile:=true;
  318. dispose(current_module^.map);
  319. current_module^.map:=nil;
  320. exit;
  321. end;
  322. { setup the map entry for deref }
  323. {$ifndef NEWMAP}
  324. current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
  325. {$else NEWMAP}
  326. current_module^.map^[nextmapentry]:=loaded_unit;
  327. {$endif NEWMAP}
  328. inc(nextmapentry);
  329. if nextmapentry>maxunits then
  330. Message(unit_f_too_much_units);
  331. end;
  332. pu:=pused_unit(pu^.next);
  333. end;
  334. { ok, now load the unit }
  335. current_module^.globalsymtable:=new(punitsymtable,loadasunit);
  336. { now only read the implementation part }
  337. current_module^.in_implementation:=true;
  338. { load the used units from implementation }
  339. pu:=pused_unit(current_module^.used_units.first);
  340. while assigned(pu) do
  341. begin
  342. if (not pu^.loaded) and (not pu^.in_interface) then
  343. begin
  344. loaded_unit:=loadunit(pu^.name^,false);
  345. if current_module^.compiled then
  346. exit;
  347. { register unit in used units }
  348. pu^.u:=loaded_unit;
  349. pu^.loaded:=true;
  350. { need to recompile the current unit ? }
  351. if (loaded_unit^.interface_crc<>pu^.interface_checksum) {and
  352. not(current_module^.in_second_compile) } then
  353. begin
  354. Message2(unit_u_recompile_crc_change,current_module^.modulename^,pu^.name^+' {impl}');
  355. current_module^.recompile_reason:=rr_crcchanged;
  356. current_module^.do_compile:=true;
  357. dispose(current_module^.map);
  358. current_module^.map:=nil;
  359. exit;
  360. end;
  361. { setup the map entry for deref }
  362. {$ifndef NEWMAP}
  363. current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
  364. {$else NEWMAP}
  365. current_module^.map^[nextmapentry]:=loaded_unit;
  366. {$endif NEWMAP}
  367. inc(nextmapentry);
  368. if nextmapentry>maxunits then
  369. Message(unit_f_too_much_units);
  370. end;
  371. pu:=pused_unit(pu^.next);
  372. end;
  373. { load browser info if stored }
  374. if ((current_module^.flags and uf_has_browser)<>0) and load_refs then
  375. punitsymtable(current_module^.globalsymtable)^.load_symtable_refs;
  376. { remove the map, it's not needed anymore }
  377. dispose(current_module^.map);
  378. current_module^.map:=nil;
  379. end;
  380. function loadunit(const s : string;compile_system:boolean) : pmodule;
  381. const
  382. ImplIntf : array[boolean] of string[15]=('interface','implementation');
  383. var
  384. st : punitsymtable;
  385. second_time : boolean;
  386. old_current_ppu : pppufile;
  387. old_current_module,hp,hp2 : pmodule;
  388. name : string;{ necessary because current_module^.mainsource^ is reset in compile !! }
  389. scanner : pscannerfile;
  390. procedure loadppufile;
  391. begin
  392. { load interface section }
  393. if not current_module^.do_compile then
  394. load_interface;
  395. { only load units when we don't recompile }
  396. if not current_module^.do_compile then
  397. load_usedunits(compile_system);
  398. { recompile if set }
  399. if current_module^.do_compile then
  400. begin
  401. { we don't need the ppufile anymore }
  402. if assigned(current_module^.ppufile) then
  403. begin
  404. dispose(current_module^.ppufile,done);
  405. current_module^.ppufile:=nil;
  406. current_ppu:=nil;
  407. end;
  408. { recompile the unit or give a fatal error if sources not available }
  409. if not(current_module^.sources_avail) then
  410. if (not current_module^.search_unit(current_module^.modulename^,true))
  411. and (length(current_module^.modulename^)>8) then
  412. current_module^.search_unit(copy(current_module^.modulename^,1,8),true);
  413. if not(current_module^.sources_avail) then
  414. begin
  415. if current_module^.recompile_reason=rr_noppu then
  416. Message1(unit_f_cant_find_ppu,current_module^.modulename^)
  417. else
  418. Message1(unit_f_cant_compile_unit,current_module^.modulename^);
  419. end
  420. else
  421. begin
  422. if current_module^.in_compile then
  423. begin
  424. current_module^.in_second_compile:=true;
  425. Message1(parser_d_compiling_second_time,current_module^.modulename^);
  426. end;
  427. current_scanner^.tempcloseinputfile;
  428. name:=current_module^.mainsource^;
  429. if assigned(scanner) then
  430. scanner^.invalid:=true;
  431. compile(name,compile_system);
  432. current_module^.in_second_compile:=false;
  433. if (not current_scanner^.invalid) then
  434. current_scanner^.tempopeninputfile;
  435. end;
  436. end
  437. else
  438. begin
  439. { only reassemble ? }
  440. if (current_module^.do_assemble) then
  441. OnlyAsm;
  442. end;
  443. if assigned(current_module^.ppufile) then
  444. begin
  445. dispose(current_module^.ppufile,done);
  446. current_module^.ppufile:=nil;
  447. current_ppu:=nil;
  448. end;
  449. end;
  450. var
  451. dummy : pmodule;
  452. begin
  453. old_current_module:=current_module;
  454. old_current_ppu:=current_ppu;
  455. { Info }
  456. Message3(unit_u_load_unit,current_module^.modulename^,ImplIntf[current_module^.in_implementation],s);
  457. { unit not found }
  458. st:=nil;
  459. dummy:=nil;
  460. { search all loaded units }
  461. hp:=pmodule(loaded_units.first);
  462. while assigned(hp) do
  463. begin
  464. if hp^.modulename^=s then
  465. begin
  466. { forced to reload ? }
  467. if hp^.do_reload then
  468. begin
  469. hp^.do_reload:=false;
  470. break;
  471. end;
  472. { the unit is already registered }
  473. { and this means that the unit }
  474. { is already compiled }
  475. { else there is a cyclic unit use }
  476. if assigned(hp^.globalsymtable) then
  477. st:=punitsymtable(hp^.globalsymtable)
  478. else
  479. begin
  480. { both units in interface ? }
  481. if (not current_module^.in_implementation) and (not hp^.in_implementation) then
  482. begin
  483. { check for a cycle }
  484. hp2:=current_module^.loaded_from;
  485. while assigned(hp2) and (hp2<>hp) do
  486. begin
  487. if hp2^.in_implementation then
  488. hp2:=nil
  489. else
  490. hp2:=hp2^.loaded_from;
  491. end;
  492. if assigned(hp2) then
  493. Message2(unit_f_circular_unit_reference,current_module^.modulename^,hp^.modulename^);
  494. end;
  495. end;
  496. break;
  497. end
  498. else if copy(hp^.modulename^,1,8)=s then
  499. dummy:=hp;
  500. { the next unit }
  501. hp:=pmodule(hp^.next);
  502. end;
  503. if assigned(dummy) and not assigned(hp) then
  504. Message2(unit_w_unit_name_error,s,dummy^.modulename^);
  505. { the unit is not in the symtable stack }
  506. if (not assigned(st)) then
  507. begin
  508. if assigned(hp) then
  509. begin
  510. { remove the old unit }
  511. loaded_units.remove(hp);
  512. scanner:=hp^.scanner;
  513. hp^.reset;
  514. hp^.scanner:=scanner;
  515. { try to reopen ppu }
  516. hp^.search_unit(s,false);
  517. { try to load the unit a second time first }
  518. current_module:=hp;
  519. current_module^.in_second_load:=true;
  520. Message1(unit_u_second_load_unit,current_module^.modulename^);
  521. second_time:=true;
  522. end
  523. else
  524. { generates a new unit info record }
  525. begin
  526. current_module:=new(pmodule,init(s,true));
  527. scanner:=nil;
  528. second_time:=false;
  529. end;
  530. current_ppu:=current_module^.ppufile;
  531. { close old_current_ppu on system that are
  532. short on file handles like DOS PM }
  533. {$ifdef SHORT_ON_FILE_HANDLES}
  534. if assigned(old_current_ppu) then
  535. old_current_ppu^.tempclose;
  536. {$endif SHORT_ON_FILE_HANDLES}
  537. { now we can register the unit }
  538. current_module^.loaded_from:=old_current_module;
  539. loaded_units.insert(current_module);
  540. { now realy load the ppu }
  541. loadppufile;
  542. { set compiled flag }
  543. current_module^.compiled:=true;
  544. { load return pointer }
  545. hp:=current_module;
  546. { for a second_time recompile reload all dependent units,
  547. for a first time compile register the unit _once_ }
  548. if second_time then
  549. begin
  550. { now reload all dependent units }
  551. hp2:=pmodule(loaded_units.first);
  552. while assigned(hp2) do
  553. begin
  554. if hp2^.do_reload then
  555. dummy:=loadunit(hp2^.modulename^,false);
  556. hp2:=pmodule(hp2^.next);
  557. end;
  558. end
  559. else
  560. usedunits.concat(new(pused_unit,init(current_module,true)));
  561. end;
  562. { set the old module }
  563. {$ifdef SHORT_ON_FILE_HANDLES}
  564. if assigned(old_current_ppu) then
  565. old_current_ppu^.tempopen;
  566. {$endif SHORT_ON_FILE_HANDLES}
  567. current_ppu:=old_current_ppu;
  568. current_module:=old_current_module;
  569. loadunit:=hp;
  570. end;
  571. procedure loaddefaultunits;
  572. var
  573. hp : pmodule;
  574. begin
  575. { are we compiling the system unit? }
  576. if (cs_compilesystem in aktmoduleswitches) then
  577. begin
  578. { create system defines }
  579. createconstdefs;
  580. { we don't need to reset anything, it's already done in parser.pas }
  581. exit;
  582. end;
  583. { insert the system unit, it is allways the first }
  584. hp:=loadunit(upper(target_info.system_unit),true);
  585. systemunit:=hp^.globalsymtable;
  586. { it's always the first unit }
  587. systemunit^.next:=nil;
  588. symtablestack:=systemunit;
  589. { add to the used units }
  590. current_module^.used_units.concat(new(pused_unit,init(hp,true)));
  591. refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  592. { read default constant definitions }
  593. make_ref:=false;
  594. readconstdefs;
  595. { if POWER is defined in the RTL then use it for starstar overloading }
  596. getsym('POWER',false);
  597. make_ref:=true;
  598. if assigned(srsym) and (srsym^.typ=procsym) and (overloaded_operators[_STARSTAR]=nil) then
  599. overloaded_operators[_STARSTAR]:=pprocsym(srsym);
  600. { Objpas unit? }
  601. if m_objpas in aktmodeswitches then
  602. begin
  603. hp:=loadunit('OBJPAS',false);
  604. psymtable(hp^.globalsymtable)^.next:=symtablestack;
  605. symtablestack:=hp^.globalsymtable;
  606. { add to the used units }
  607. current_module^.used_units.concat(new(pused_unit,init(hp,true)));
  608. refsymtable^.insert(new(punitsym,init('OBJPAS',hp^.globalsymtable)));
  609. end;
  610. { Profile unit? Needed for go32v2 only }
  611. if (cs_profile in aktmoduleswitches) and (target_info.target=target_i386_go32v2) then
  612. begin
  613. hp:=loadunit('PROFILE',false);
  614. psymtable(hp^.globalsymtable)^.next:=symtablestack;
  615. symtablestack:=hp^.globalsymtable;
  616. { add to the used units }
  617. current_module^.used_units.concat(new(pused_unit,init(hp,true)));
  618. refsymtable^.insert(new(punitsym,init('PROFILE',hp^.globalsymtable)));
  619. end;
  620. { Heaptrc unit? (not needed for units), this is here to be sure that it is really
  621. loaded as first unit }
  622. if (cs_gdb_heaptrc in aktglobalswitches) and not(current_module^.is_unit)then
  623. begin
  624. hp:=loadunit('HEAPTRC',false);
  625. psymtable(hp^.globalsymtable)^.next:=symtablestack;
  626. symtablestack:=hp^.globalsymtable;
  627. { add to the used units }
  628. current_module^.used_units.concat(new(pused_unit,init(hp,true)));
  629. refsymtable^.insert(new(punitsym,init('HEAPTRC',hp^.globalsymtable)));
  630. end;
  631. { save default symtablestack }
  632. defaultsymtablestack:=symtablestack;
  633. end;
  634. procedure loadunits;
  635. var
  636. s : stringid;
  637. pu,
  638. hp : pused_unit;
  639. hp2 : pmodule;
  640. hp3 : psymtable;
  641. oldprocsym:Pprocsym;
  642. begin
  643. oldprocsym:=aktprocsym;
  644. consume(_USES);
  645. {$ifdef DEBUG}
  646. test_symtablestack;
  647. {$endif DEBUG}
  648. repeat
  649. s:=pattern;
  650. consume(_ID);
  651. { Give a warning if objpas is loaded }
  652. if s='OBJPAS' then
  653. Message(parser_w_no_objpas_use_mode);
  654. { check if the unit is already used }
  655. pu:=pused_unit(current_module^.used_units.first);
  656. while assigned(pu) do
  657. begin
  658. if (pu^.name^=s) then
  659. break;
  660. pu:=pused_unit(pu^.next);
  661. end;
  662. { avoid uses of itself }
  663. if not assigned(pu) and (s<>current_module^.modulename^) then
  664. begin
  665. { load the unit }
  666. hp2:=loadunit(s,false);
  667. { the current module uses the unit hp2 }
  668. current_module^.used_units.concat(new(pused_unit,init(hp2,not current_module^.in_implementation)));
  669. pused_unit(current_module^.used_units.last)^.in_uses:=true;
  670. if current_module^.compiled then
  671. exit;
  672. refsymtable^.insert(new(punitsym,init(s,hp2^.globalsymtable)));
  673. end
  674. else
  675. Message1(sym_e_duplicate_id,s);
  676. if token=_COMMA then
  677. begin
  678. pattern:='';
  679. consume(_COMMA);
  680. end
  681. else
  682. break;
  683. until false;
  684. consume(_SEMICOLON);
  685. { set the symtable to systemunit so it gets reorderd correctly }
  686. symtablestack:=defaultsymtablestack;
  687. { now insert the units in the symtablestack }
  688. hp:=pused_unit(current_module^.used_units.first);
  689. while assigned(hp) do
  690. begin
  691. {$IfDef GDB}
  692. if (cs_debuginfo in aktmoduleswitches) and
  693. (cs_gdb_dbx in aktglobalswitches) and
  694. not hp^.is_stab_written then
  695. begin
  696. punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
  697. hp^.is_stab_written:=true;
  698. hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
  699. end;
  700. {$EndIf GDB}
  701. if hp^.in_uses then
  702. begin
  703. hp3:=symtablestack;
  704. while assigned(hp3) do
  705. begin
  706. { insert units only once ! }
  707. if hp^.u^.globalsymtable=hp3 then
  708. break;
  709. hp3:=hp3^.next;
  710. { unit isn't inserted }
  711. if hp3=nil then
  712. begin
  713. psymtable(hp^.u^.globalsymtable)^.next:=symtablestack;
  714. symtablestack:=psymtable(hp^.u^.globalsymtable);
  715. {$ifdef CHAINPROCSYMS}
  716. symtablestack^.chainprocsyms;
  717. {$endif CHAINPROCSYMS}
  718. {$ifdef DEBUG}
  719. test_symtablestack;
  720. {$endif DEBUG}
  721. end;
  722. end;
  723. end;
  724. hp:=pused_unit(hp^.next);
  725. end;
  726. aktprocsym:=oldprocsym;
  727. end;
  728. procedure write_gdb_info;
  729. {$IfDef GDB}
  730. var
  731. hp : pused_unit;
  732. begin
  733. if not (cs_debuginfo in aktmoduleswitches) then
  734. exit;
  735. if (cs_gdb_dbx in aktglobalswitches) then
  736. begin
  737. debuglist^.concat(new(pai_asm_comment,init(strpnew('EINCL of global '+
  738. punitsymtable(current_module^.globalsymtable)^.name^+' has index '+
  739. tostr(punitsymtable(current_module^.globalsymtable)^.unitid)))));
  740. debuglist^.concat(new(pai_stabs,init(strpnew('"'+
  741. punitsymtable(current_module^.globalsymtable)^.name^+'",'+
  742. tostr(N_EINCL)+',0,0,0'))));
  743. punitsymtable(current_module^.globalsymtable)^.dbx_count_ok:=true;
  744. dbx_counter:=punitsymtable(current_module^.globalsymtable)^.prev_dbx_counter;
  745. do_count_dbx:=false;
  746. end;
  747. { now insert the units in the symtablestack }
  748. hp:=pused_unit(current_module^.used_units.first);
  749. while assigned(hp) do
  750. begin
  751. if (cs_debuginfo in aktmoduleswitches) and
  752. not hp^.is_stab_written then
  753. begin
  754. punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
  755. hp^.is_stab_written:=true;
  756. hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
  757. end;
  758. hp:=pused_unit(hp^.next);
  759. end;
  760. if current_module^.in_implementation then
  761. begin
  762. if assigned(current_module^.localsymtable) then
  763. begin
  764. { all types }
  765. punitsymtable(current_module^.localsymtable)^.concattypestabto(debuglist);
  766. { and all local symbols}
  767. punitsymtable(current_module^.localsymtable)^.concatstabto(debuglist);
  768. end;
  769. end
  770. else
  771. begin
  772. if assigned(current_module^.globalsymtable) then
  773. begin
  774. { all types }
  775. punitsymtable(current_module^.globalsymtable)^.concattypestabto(debuglist);
  776. { and all local symbols}
  777. punitsymtable(current_module^.globalsymtable)^.concatstabto(debuglist);
  778. end;
  779. end;
  780. end;
  781. {$Else GDB}
  782. begin
  783. end;
  784. {$EndIf GDB}
  785. procedure parse_implementation_uses(symt:Psymtable);
  786. begin
  787. if token=_USES then
  788. begin
  789. symt^.symtabletype:=unitsymtable;
  790. loadunits;
  791. symt^.symtabletype:=globalsymtable;
  792. {$ifdef DEBUG}
  793. test_symtablestack;
  794. {$endif DEBUG}
  795. end;
  796. end;
  797. procedure setupglobalswitches;
  798. procedure def_symbol(const s:string);
  799. var
  800. mac : pmacrosym;
  801. begin
  802. mac:=new(pmacrosym,init(s));
  803. mac^.defined:=true;
  804. Message1(parser_m_macro_defined,mac^.name);
  805. macros^.insert(mac);
  806. end;
  807. begin
  808. { can't have local browser when no global browser }
  809. if (cs_local_browser in aktmoduleswitches) and
  810. not(cs_browser in aktmoduleswitches) then
  811. aktmoduleswitches:=aktmoduleswitches-[cs_local_browser];
  812. { define a symbol in delphi,objfpc,tp,gpc mode }
  813. if (m_delphi in aktmodeswitches) then
  814. def_symbol('FPC_DELPHI')
  815. else
  816. if (m_tp in aktmodeswitches) then
  817. def_symbol('FPC_TP')
  818. else
  819. if (m_objfpc in aktmodeswitches) then
  820. def_symbol('FPC_OBJFPC')
  821. else
  822. if (m_gpc in aktmodeswitches) then
  823. def_symbol('FPC_GPC');
  824. { turn ansistrings on by default ? }
  825. if (m_default_ansistring in aktmodeswitches) then
  826. aktlocalswitches:=aktlocalswitches+[cs_ansistrings];
  827. end;
  828. procedure gen_main_procsym(const name:string;options:tproctypeoption;st:psymtable);
  829. var
  830. stt : psymtable;
  831. begin
  832. {Generate a procsym for main}
  833. make_ref:=false;
  834. aktprocsym:=new(Pprocsym,init(name));
  835. { main are allways used }
  836. inc(aktprocsym^.refs);
  837. {Try to insert in in static symtable ! }
  838. stt:=symtablestack;
  839. symtablestack:=st;
  840. aktprocsym^.definition:=new(Pprocdef,init);
  841. symtablestack:=stt;
  842. aktprocsym^.definition^.proctypeoption:=options;
  843. aktprocsym^.definition^.setmangledname(target_os.cprefix+name);
  844. aktprocsym^.definition^.forwarddef:=false;
  845. make_ref:=true;
  846. { The localst is a local symtable. Change it into the static
  847. symtable }
  848. dispose(aktprocsym^.definition^.localst,done);
  849. aktprocsym^.definition^.localst:=st;
  850. { and insert the procsym in symtable }
  851. st^.insert(aktprocsym);
  852. { set some informations about the main program }
  853. with procinfo^ do
  854. begin
  855. returntype.setdef(voiddef);
  856. _class:=nil;
  857. call_offset:=8;
  858. framepointer:=frame_pointer;
  859. flags:=0;
  860. end;
  861. end;
  862. procedure proc_unit;
  863. function is_assembler_generated:boolean;
  864. begin
  865. is_assembler_generated:=(Errorcount=0) and
  866. not(
  867. codesegment^.empty and
  868. datasegment^.empty and
  869. bsssegment^.empty and
  870. ((importssection=nil) or importssection^.empty) and
  871. ((resourcesection=nil) or resourcesection^.empty) and
  872. ((resourcestringlist=nil) or resourcestringlist^.empty)
  873. );
  874. end;
  875. var
  876. {$ifdef fixLeaksOnError}
  877. names : Pstringcontainer;
  878. {$else fixLeaksOnError}
  879. names : Tstringcontainer;
  880. {$endif fixLeaksOnError}
  881. st : psymtable;
  882. unitst : punitsymtable;
  883. {$ifdef GDB}
  884. pu : pused_unit;
  885. {$endif GDB}
  886. {$ifndef Dont_use_double_checksum}
  887. store_crc,store_interface_crc : longint;
  888. {$endif}
  889. s1,s2 : ^string; {Saves stack space}
  890. begin
  891. consume(_UNIT);
  892. if Compile_Level=1 then
  893. IsExe:=false;
  894. if token=_ID then
  895. begin
  896. { create filenames and unit name }
  897. current_module^.SetFileName(current_scanner^.inputfile^.path^+current_scanner^.inputfile^.name^,true);
  898. stringdispose(current_module^.modulename);
  899. current_module^.modulename:=stringdup(upper(pattern));
  900. { check for system unit }
  901. new(s1);
  902. new(s2);
  903. s1^:=upper(target_info.system_unit);
  904. s2^:=upper(SplitName(current_scanner^.inputfile^.name^));
  905. if (cs_compilesystem in aktmoduleswitches) then
  906. begin
  907. if ((length(current_module^.modulename^)>8) or
  908. (current_module^.modulename^<>s1^) or
  909. (current_module^.modulename^<>s2^)) then
  910. Message1(unit_e_illegal_unit_name,current_module^.modulename^);
  911. end
  912. else
  913. begin
  914. if (cs_check_unit_name in aktglobalswitches) and
  915. not((current_module^.modulename^=s2^) or
  916. ((length(current_module^.modulename^)>8) and
  917. (copy(current_module^.modulename^,1,8)=s2^))) then
  918. Message1(unit_e_illegal_unit_name,current_module^.modulename^);
  919. if (current_module^.modulename^=s1^) then
  920. Message(unit_w_switch_us_missed);
  921. end;
  922. dispose(s2);
  923. dispose(s1);
  924. end;
  925. consume(_ID);
  926. consume(_SEMICOLON);
  927. consume(_INTERFACE);
  928. { global switches are read, so further changes aren't allowed }
  929. current_module^.in_global:=false;
  930. { handle the global switches }
  931. setupglobalswitches;
  932. Message1(unit_u_start_parse_interface,current_module^.modulename^);
  933. { update status }
  934. status.currentmodule:=current_module^.modulename^;
  935. { maybe turn off m_objpas if we are compiling objpas }
  936. if (current_module^.modulename^='OBJPAS') then
  937. aktmodeswitches:=aktmodeswitches-[m_objpas];
  938. { this should be placed after uses !!}
  939. {$ifndef UseNiceNames}
  940. procprefix:='_'+current_module^.modulename^+'$$';
  941. {$else UseNiceNames}
  942. procprefix:='_'+tostr(length(current_module^.modulename^))+lowercase(current_module^.modulename^)+'_';
  943. {$endif UseNiceNames}
  944. parse_only:=true;
  945. { generate now the global symboltable }
  946. st:=new(punitsymtable,init(globalsymtable,current_module^.modulename^));
  947. refsymtable:=st;
  948. unitst:=punitsymtable(st);
  949. { define first as local to overcome dependency conflicts }
  950. current_module^.localsymtable:=st;
  951. { the unit name must be usable as a unit specifier }
  952. { inside the unit itself (PM) }
  953. { this also forbids to have another symbol }
  954. { with the same name as the unit }
  955. refsymtable^.insert(new(punitsym,init(current_module^.modulename^,unitst)));
  956. { a unit compiled at command line must be inside the loaded_unit list }
  957. if (compile_level=1) then
  958. loaded_units.insert(current_module);
  959. { load default units, like the system unit }
  960. loaddefaultunits;
  961. { reset }
  962. make_ref:=true;
  963. lexlevel:=0;
  964. { insert qualifier for the system unit (allows system.writeln) }
  965. if not(cs_compilesystem in aktmoduleswitches) then
  966. begin
  967. if token=_USES then
  968. begin
  969. unitst^.symtabletype:=unitsymtable;
  970. loadunits;
  971. { has it been compiled at a higher level ?}
  972. if current_module^.compiled then
  973. begin
  974. { this unit symtable is obsolete }
  975. { dispose(unitst,done);
  976. disposed as localsymtable !! }
  977. exit;
  978. end;
  979. unitst^.symtabletype:=globalsymtable;
  980. end;
  981. { ... but insert the symbol table later }
  982. st^.next:=symtablestack;
  983. symtablestack:=st;
  984. end
  985. else
  986. { while compiling a system unit, some types are directly inserted }
  987. begin
  988. st^.next:=symtablestack;
  989. symtablestack:=st;
  990. insert_intern_types(st);
  991. end;
  992. { now we know the place to insert the constants }
  993. constsymtable:=symtablestack;
  994. { move the global symtab from the temporary local to global }
  995. current_module^.globalsymtable:=current_module^.localsymtable;
  996. current_module^.localsymtable:=nil;
  997. reset_global_defs;
  998. { number all units, so we know if a unit is used by this unit or
  999. needs to be added implicitly }
  1000. numberunits;
  1001. { ... parse the declarations }
  1002. Message1(parser_u_parsing_interface,current_module^.modulename^);
  1003. read_interface_declarations;
  1004. { leave when we got an error }
  1005. if (Errorcount>0) and not status.skip_error then
  1006. begin
  1007. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1008. status.skip_error:=true;
  1009. exit;
  1010. end;
  1011. {$ifdef New_GDB}
  1012. write_gdb_info;
  1013. {$endIf Def New_GDB}
  1014. {$ifndef Dont_use_double_checksum}
  1015. if not(cs_compilesystem in aktmoduleswitches) then
  1016. if (Errorcount=0) then
  1017. writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack),true);
  1018. {$endif Test_Double_checksum}
  1019. { Parse the implementation section }
  1020. consume(_IMPLEMENTATION);
  1021. current_module^.in_implementation:=true;
  1022. Message1(unit_u_start_parse_implementation,current_module^.modulename^);
  1023. parse_only:=false;
  1024. { generates static symbol table }
  1025. st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
  1026. current_module^.localsymtable:=st;
  1027. { remove the globalsymtable from the symtable stack }
  1028. { to reinsert it after loading the implementation units }
  1029. symtablestack:=unitst^.next;
  1030. { we don't want implementation units symbols in unitsymtable !! PM }
  1031. refsymtable:=st;
  1032. { Read the implementation units }
  1033. parse_implementation_uses(unitst);
  1034. if current_module^.compiled then
  1035. begin
  1036. exit;
  1037. end;
  1038. { reset ranges/stabs in exported definitions }
  1039. reset_global_defs;
  1040. { All units are read, now give them a number }
  1041. numberunits;
  1042. { now we can change refsymtable }
  1043. refsymtable:=st;
  1044. { but reinsert the global symtable as lasts }
  1045. unitst^.next:=symtablestack;
  1046. symtablestack:=unitst;
  1047. {$ifdef DEBUG}
  1048. test_symtablestack;
  1049. {$endif DEBUG}
  1050. constsymtable:=symtablestack;
  1051. {$ifdef Splitheap}
  1052. if testsplit then
  1053. begin
  1054. Split_Heap;
  1055. allow_special:=true;
  1056. Switch_to_temp_heap;
  1057. end;
  1058. { it will report all crossings }
  1059. allow_special:=false;
  1060. {$endif Splitheap}
  1061. Message1(parser_u_parsing_implementation,current_module^.modulename^);
  1062. { Compile the unit }
  1063. codegen_newprocedure;
  1064. gen_main_procsym(current_module^.modulename^+'_init',potype_unitinit,st);
  1065. {$ifdef fixLeaksOnError}
  1066. new(names,init);
  1067. strContStack.push(names);
  1068. names^.insert('INIT$$'+current_module^.modulename^);
  1069. names^.insert(target_os.cprefix+current_module^.modulename^+'_init');
  1070. compile_proc_body(names^,true,false);
  1071. if names <> PstringContainer(strContStack.pop) then
  1072. writeln('Problem with strContStack in pmodules (1)');
  1073. dispose(names,done);
  1074. {$else fixLeaksOnError}
  1075. names.init;
  1076. names.insert('INIT$$'+current_module^.modulename^);
  1077. names.insert(target_os.cprefix+current_module^.modulename^+'_init');
  1078. compile_proc_body(names,true,false);
  1079. names.done;
  1080. {$endif fixLeaksOnError}
  1081. codegen_doneprocedure;
  1082. { avoid self recursive destructor call !! PM }
  1083. aktprocsym^.definition^.localst:=nil;
  1084. { finalize? }
  1085. if token=_FINALIZATION then
  1086. begin
  1087. { set module options }
  1088. current_module^.flags:=current_module^.flags or uf_finalize;
  1089. { Compile the finalize }
  1090. codegen_newprocedure;
  1091. gen_main_procsym(current_module^.modulename^+'_finalize',potype_unitfinalize,st);
  1092. {$ifdef fixLeaksOnError}
  1093. new(names,init);
  1094. strContStack.push(names);
  1095. names^.insert('FINALIZE$$'+current_module^.modulename^);
  1096. names^.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
  1097. compile_proc_body(names^,true,false);
  1098. if names <> PstringContainer(strContStack.pop) then
  1099. writeln('Problem with strContStack in pmodules (2)');
  1100. dispose(names,done);
  1101. {$else fixLeaksOnError}
  1102. names.init;
  1103. names.insert('FINALIZE$$'+current_module^.modulename^);
  1104. names.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
  1105. compile_proc_body(names,true,false);
  1106. names.done;
  1107. {$endif fixLeaksOnError}
  1108. codegen_doneprocedure;
  1109. end;
  1110. { the last char should always be a point }
  1111. consume(_POINT);
  1112. If ResourceStringList<>Nil then
  1113. begin
  1114. insertresourcestrings;
  1115. current_module^.flags:=current_module^.flags or uf_has_resources;
  1116. WriteResourceFile(Current_module^.ModuleName^);
  1117. end;
  1118. { avoid self recursive destructor call !! PM }
  1119. aktprocsym^.definition^.localst:=nil;
  1120. { absence does not matter here !! }
  1121. aktprocsym^.definition^.forwarddef:=false;
  1122. { test static symtable }
  1123. if (Errorcount=0) then
  1124. begin
  1125. st^.allsymbolsused;
  1126. st^.allprivatesused;
  1127. end;
  1128. { size of the static data }
  1129. datasize:=st^.datasize;
  1130. {$ifdef GDB}
  1131. { add all used definitions even for implementation}
  1132. if (cs_debuginfo in aktmoduleswitches) then
  1133. begin
  1134. {$IfnDef New_GDB}
  1135. if assigned(current_module^.globalsymtable) then
  1136. begin
  1137. { all types }
  1138. punitsymtable(current_module^.globalsymtable)^.concattypestabto(debuglist);
  1139. { and all local symbols}
  1140. punitsymtable(current_module^.globalsymtable)^.concatstabto(debuglist);
  1141. end;
  1142. { all local types }
  1143. punitsymtable(st)^.concattypestabto(debuglist);
  1144. { and all local symbols}
  1145. st^.concatstabto(debuglist);
  1146. {$else New_GDB}
  1147. write_gdb_info;
  1148. {$endIf Def New_GDB}
  1149. end;
  1150. {$endif GDB}
  1151. reset_global_defs;
  1152. { tests, if all (interface) forwards are resolved }
  1153. if (Errorcount=0) then
  1154. begin
  1155. symtablestack^.check_forwards;
  1156. symtablestack^.allprivatesused;
  1157. end;
  1158. { now we have a correct unit, change the symtable type }
  1159. current_module^.in_implementation:=false;
  1160. symtablestack^.symtabletype:=unitsymtable;
  1161. {$ifdef GDB}
  1162. punitsymtable(symtablestack)^.is_stab_written:=false;
  1163. {$endif GDB}
  1164. { leave when we got an error }
  1165. if (Errorcount>0) and not status.skip_error then
  1166. begin
  1167. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1168. status.skip_error:=true;
  1169. exit;
  1170. end;
  1171. { generate imports }
  1172. if current_module^.uses_imports then
  1173. importlib^.generatelib;
  1174. { insert own objectfile, or say that it's in a library
  1175. (no check for an .o when loading) }
  1176. if is_assembler_generated then
  1177. insertobjectfile
  1178. else
  1179. current_module^.flags:=current_module^.flags or uf_no_link;
  1180. if cs_local_browser in aktmoduleswitches then
  1181. current_module^.localsymtable:=refsymtable;
  1182. { Write out the ppufile }
  1183. {$ifndef Dont_use_double_checksum}
  1184. store_interface_crc:=current_module^.interface_crc;
  1185. store_crc:=current_module^.crc;
  1186. {$endif Test_Double_checksum}
  1187. if (Errorcount=0) then
  1188. writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack),false);
  1189. {$ifndef Dont_use_double_checksum}
  1190. if not(cs_compilesystem in aktmoduleswitches) then
  1191. if store_interface_crc<>current_module^.interface_crc then
  1192. Do_comment(V_Warning,current_module^.ppufilename^+' Interface CRC changed '+
  1193. tostr(store_crc)+'<>'+tostr(current_module^.interface_crc));
  1194. {$ifdef EXTDEBUG}
  1195. if not(cs_compilesystem in aktmoduleswitches) then
  1196. if (store_crc<>current_module^.crc) and simplify_ppu then
  1197. Do_comment(V_Warning,current_module^.ppufilename^+' implementation CRC changed '+
  1198. tostr(store_crc)+'<>'+tostr(current_module^.interface_crc));
  1199. {$endif EXTDEBUG}
  1200. {$endif ndef Dont_use_Double_checksum}
  1201. { must be done only after local symtable ref stores !! }
  1202. closecurrentppu;
  1203. {$ifdef GDB}
  1204. pu:=pused_unit(usedunits.first);
  1205. while assigned(pu) do
  1206. begin
  1207. if assigned(pu^.u^.globalsymtable) then
  1208. punitsymtable(pu^.u^.globalsymtable)^.is_stab_written:=false;
  1209. pu:=pused_unit(pu^.next);
  1210. end;
  1211. {$endif GDB}
  1212. { remove static symtable (=refsymtable) here to save some mem }
  1213. if not (cs_local_browser in aktmoduleswitches) then
  1214. begin
  1215. dispose(st,done);
  1216. current_module^.localsymtable:=nil;
  1217. end;
  1218. if is_assembler_generated then
  1219. begin
  1220. { finish asmlist by adding segment starts }
  1221. insertsegment;
  1222. { assemble }
  1223. create_objectfile;
  1224. end;
  1225. { leave when we got an error }
  1226. if (Errorcount>0) and not status.skip_error then
  1227. begin
  1228. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1229. status.skip_error:=true;
  1230. exit;
  1231. end;
  1232. end;
  1233. procedure proc_program(islibrary : boolean);
  1234. var
  1235. st : psymtable;
  1236. hp : pmodule;
  1237. {$ifdef fixLeaksOnError}
  1238. names : Pstringcontainer;
  1239. {$else fixLeaksOnError}
  1240. names : Tstringcontainer;
  1241. {$endif fixLeaksOnError}
  1242. begin
  1243. DLLsource:=islibrary;
  1244. IsExe:=true;
  1245. parse_only:=false;
  1246. { relocation works only without stabs under win32 !! PM }
  1247. { internal assembler uses rva for stabs info
  1248. so it should work with relocated DLLs }
  1249. if RelocSection and
  1250. (target_info.target=target_i386_win32) and
  1251. (target_info.assem<>as_i386_pecoff) then
  1252. begin
  1253. aktglobalswitches:=aktglobalswitches+[cs_link_strip];
  1254. { Warning stabs info does not work with reloc section !! }
  1255. if cs_debuginfo in aktmoduleswitches then
  1256. begin
  1257. Message1(parser_w_parser_reloc_no_debug,current_module^.mainsource^);
  1258. Message(parser_w_parser_win32_debug_needs_WN);
  1259. aktmoduleswitches:=aktmoduleswitches-[cs_debuginfo];
  1260. end;
  1261. end;
  1262. if islibrary then
  1263. begin
  1264. consume(_LIBRARY);
  1265. stringdispose(current_module^.modulename);
  1266. current_module^.modulename:=stringdup(pattern);
  1267. current_module^.islibrary:=true;
  1268. exportlib^.preparelib(pattern);
  1269. consume(_ID);
  1270. consume(_SEMICOLON);
  1271. end
  1272. else
  1273. { is there an program head ? }
  1274. if token=_PROGRAM then
  1275. begin
  1276. consume(_PROGRAM);
  1277. stringdispose(current_module^.modulename);
  1278. current_module^.modulename:=stringdup(pattern);
  1279. if (target_info.target=target_i386_WIN32) then
  1280. exportlib^.preparelib(pattern);
  1281. consume(_ID);
  1282. if token=_LKLAMMER then
  1283. begin
  1284. consume(_LKLAMMER);
  1285. idlist;
  1286. consume(_RKLAMMER);
  1287. end;
  1288. consume(_SEMICOLON);
  1289. end
  1290. else if (target_info.target=target_i386_WIN32) then
  1291. exportlib^.preparelib(current_module^.modulename^);
  1292. { global switches are read, so further changes aren't allowed }
  1293. current_module^.in_global:=false;
  1294. { get correct output names }
  1295. current_module^.SetFileName(current_scanner^.inputfile^.path^+current_scanner^.inputfile^.name^,true);
  1296. { setup things using the global switches }
  1297. setupglobalswitches;
  1298. { set implementation flag }
  1299. current_module^.in_implementation:=true;
  1300. { insert after the unit symbol tables the static symbol table }
  1301. { of the program }
  1302. st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
  1303. current_module^.localsymtable:=st;
  1304. symtablestack:=st;
  1305. refsymtable:=st;
  1306. { necessary for browser }
  1307. loaded_units.insert(current_module);
  1308. { load standard units (system,objpas,profile unit) }
  1309. loaddefaultunits;
  1310. { reset }
  1311. lexlevel:=0;
  1312. {Load the units used by the program we compile.}
  1313. if token=_USES then
  1314. loadunits;
  1315. { reset ranges/stabs in exported definitions }
  1316. reset_global_defs;
  1317. { All units are read, now give them a number }
  1318. numberunits;
  1319. {Insert the name of the main program into the symbol table.}
  1320. if current_module^.modulename^<>'' then
  1321. {st^.insert(new(pprogramsym,init(current_module^.modulename^)));}
  1322. st^.insert(new(punitsym,init(current_module^.modulename^,punitsymtable(st))));
  1323. { ...is also constsymtable, this is the symtable where }
  1324. { the elements of enumeration types are inserted }
  1325. constsymtable:=st;
  1326. Message1(parser_u_parsing_implementation,current_module^.mainsource^);
  1327. { reset }
  1328. procprefix:='';
  1329. {The program intialization needs an alias, so it can be called
  1330. from the bootstrap code.}
  1331. codegen_newprocedure;
  1332. gen_main_procsym('main',potype_proginit,st);
  1333. {$ifdef fixLeaksOnError}
  1334. new(names,init);
  1335. strContStack.push(names);
  1336. names^.insert('program_init');
  1337. names^.insert('PASCALMAIN');
  1338. names^.insert(target_os.cprefix+'main');
  1339. {$ifdef m68k}
  1340. if target_info.target=target_m68k_PalmOS then
  1341. names^.insert('PilotMain');
  1342. {$endif m68k}
  1343. compile_proc_body(names^,true,false);
  1344. if names <> PstringContainer(strContStack.pop) then
  1345. writeln('Problem with strContStack in pmodules (1)');
  1346. dispose(names,done);
  1347. {$else fixLeaksOnError}
  1348. names.init;
  1349. names.insert('program_init');
  1350. names.insert('PASCALMAIN');
  1351. names.insert(target_os.cprefix+'main');
  1352. {$ifdef m68k}
  1353. if target_info.target=target_m68k_PalmOS then
  1354. names.insert('PilotMain');
  1355. {$endif m68k}
  1356. compile_proc_body(names,true,false);
  1357. names.done;
  1358. {$endif fixLeaksOnError}
  1359. { avoid self recursive destructor call !! PM }
  1360. aktprocsym^.definition^.localst:=nil;
  1361. { consider these symbols as global ones }
  1362. { for browser }
  1363. current_module^.globalsymtable:=current_module^.localsymtable;
  1364. current_module^.localsymtable:=nil;
  1365. If ResourceStringList<>Nil then
  1366. begin
  1367. insertresourcestrings;
  1368. WriteResourceFile(Current_module^.ModuleName^);
  1369. end;
  1370. codegen_doneprocedure;
  1371. { finalize? }
  1372. if token=_FINALIZATION then
  1373. begin
  1374. { set module options }
  1375. current_module^.flags:=current_module^.flags or uf_finalize;
  1376. { Compile the finalize }
  1377. codegen_newprocedure;
  1378. gen_main_procsym(current_module^.modulename^+'_finalize',potype_unitfinalize,st);
  1379. {$ifdef fixLeaksOnError}
  1380. new(names,init);
  1381. strContStack.push(names);
  1382. names^.insert('FINALIZE$$'+current_module^.modulename^);
  1383. names^.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
  1384. compile_proc_body(names^,true,false);
  1385. if names <> PstringContainer(strContStack.pop) then
  1386. writeln('Problem with strContStack in pmodules (1)');
  1387. dispose(names,done);
  1388. {$else fixLeaksOnError}
  1389. names.init;
  1390. names.insert('FINALIZE$$'+current_module^.modulename^);
  1391. names.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
  1392. compile_proc_body(names,true,false);
  1393. names.done;
  1394. {$endif fixLeaksOnError}
  1395. codegen_doneprocedure;
  1396. end;
  1397. { consume the last point }
  1398. consume(_POINT);
  1399. {$ifdef New_GDB}
  1400. write_gdb_info;
  1401. {$endIf Def New_GDB}
  1402. { leave when we got an error }
  1403. if (Errorcount>0) and not status.skip_error then
  1404. begin
  1405. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1406. status.skip_error:=true;
  1407. exit;
  1408. end;
  1409. { test static symtable }
  1410. if (Errorcount=0) then
  1411. begin
  1412. st^.allsymbolsused;
  1413. st^.allprivatesused;
  1414. end;
  1415. { generate imports }
  1416. if current_module^.uses_imports then
  1417. importlib^.generatelib;
  1418. if islibrary or
  1419. (target_info.target=target_i386_WIN32) then
  1420. exportlib^.generatelib;
  1421. { insert heap }
  1422. insertResourceTablesTable;
  1423. insertinitfinaltable;
  1424. insertheap;
  1425. inserttargetspecific;
  1426. datasize:=symtablestack^.datasize;
  1427. { finish asmlist by adding segment starts }
  1428. insertsegment;
  1429. { insert own objectfile }
  1430. insertobjectfile;
  1431. { assemble and link }
  1432. create_objectfile;
  1433. { leave when we got an error }
  1434. if (Errorcount>0) and not status.skip_error then
  1435. begin
  1436. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1437. status.skip_error:=true;
  1438. exit;
  1439. end;
  1440. { create the executable when we are at level 1 }
  1441. if (compile_level=1) then
  1442. begin
  1443. { insert all .o files from all loaded units }
  1444. hp:=pmodule(loaded_units.first);
  1445. while assigned(hp) do
  1446. begin
  1447. Linker^.AddModuleFiles(hp);
  1448. hp:=pmodule(hp^.next);
  1449. end;
  1450. { write .def file }
  1451. if (cs_link_deffile in aktglobalswitches) then
  1452. deffile.writefile;
  1453. { finally we can create a executable }
  1454. if (not current_module^.is_unit) then
  1455. begin
  1456. if DLLSource then
  1457. Linker^.MakeSharedLibrary
  1458. else
  1459. Linker^.MakeExecutable;
  1460. end;
  1461. end;
  1462. end;
  1463. end.
  1464. {
  1465. $Log$
  1466. Revision 1.181 2000-01-12 10:30:15 peter
  1467. * align codesegment at the end after main proc
  1468. Revision 1.180 2000/01/11 17:16:05 jonas
  1469. * removed a lot of memory leaks when an error is encountered (caused by
  1470. procinfo and pstringcontainers). There are still plenty left though :)
  1471. Revision 1.179 2000/01/11 09:52:07 peter
  1472. * fixed placing of .sl directories
  1473. * use -b again for base-file selection
  1474. * fixed group writing for linux with smartlinking
  1475. Revision 1.178 2000/01/07 01:14:29 peter
  1476. * updated copyright to 2000
  1477. Revision 1.177 1999/12/20 22:29:26 pierre
  1478. * relocation with debug info in rva (only with internal compiler)
  1479. Revision 1.176 1999/12/10 10:02:53 peter
  1480. * only check relocsection for win32
  1481. Revision 1.175 1999/11/30 10:40:44 peter
  1482. + ttype, tsymlist
  1483. Revision 1.174 1999/11/29 16:24:52 pierre
  1484. * bug in previous commit corrected
  1485. Revision 1.173 1999/11/29 15:18:27 pierre
  1486. + allow exports in win32 executables
  1487. Revision 1.172 1999/11/24 11:41:05 pierre
  1488. * defaultsymtablestack is now restored after parser.compile
  1489. Revision 1.171 1999/11/22 22:21:46 pierre
  1490. * Compute correct Exe Filenam
  1491. Revision 1.170 1999/11/22 00:23:09 pierre
  1492. * also complain about unused functions in program
  1493. Revision 1.169 1999/11/20 01:19:10 pierre
  1494. * DLL index used for win32 target with DEF file
  1495. + DLL initialization/finalization support
  1496. Revision 1.168 1999/11/18 23:35:40 pierre
  1497. * avoid double warnings
  1498. Revision 1.167 1999/11/18 15:34:47 pierre
  1499. * Notes/Hints for local syms changed to
  1500. Set_varstate function
  1501. Revision 1.166 1999/11/17 17:05:02 pierre
  1502. * Notes/hints changes
  1503. Revision 1.165 1999/11/15 15:03:47 pierre
  1504. * Pavel's changes for reloc section in executable
  1505. + warning that -g needs -WN under win32
  1506. Revision 1.164 1999/11/09 23:46:00 pierre
  1507. * power search for ** operator not in browser
  1508. * DBX support work, still does not work !
  1509. Revision 1.163 1999/11/09 13:00:37 peter
  1510. * define FPC_DELPHI,FPC_OBJFPC,FPC_TP,FPC_GPC
  1511. * initial support for ansistring default with modes
  1512. Revision 1.162 1999/11/06 14:34:22 peter
  1513. * truncated log to 20 revs
  1514. Revision 1.161 1999/11/02 15:06:57 peter
  1515. * import library fixes for win32
  1516. * alignment works again
  1517. Revision 1.160 1999/10/21 14:29:37 peter
  1518. * redesigned linker object
  1519. + library support for linux (only procedures can be exported)
  1520. Revision 1.159 1999/10/12 21:20:45 florian
  1521. * new codegenerator compiles again
  1522. Revision 1.158 1999/10/03 19:44:42 peter
  1523. * removed objpasunit reference, tvarrec is now searched in systemunit
  1524. where it already was located
  1525. Revision 1.157 1999/09/27 23:44:54 peter
  1526. * procinfo is now a pointer
  1527. * support for result setting in sub procedure
  1528. Revision 1.156 1999/09/20 16:39:00 peter
  1529. * cs_create_smart instead of cs_smartlink
  1530. * -CX is create smartlink
  1531. * -CD is create dynamic, but does nothing atm.
  1532. Revision 1.155 1999/09/16 23:05:54 florian
  1533. * m68k compiler is again compilable (only gas writer, no assembler reader)
  1534. Revision 1.154 1999/09/16 14:18:12 pierre
  1535. + warning if truncate unit name found
  1536. Revision 1.153 1999/09/13 22:56:17 peter
  1537. * fixed crashes under plain dos
  1538. Revision 1.152 1999/09/01 22:18:42 peter
  1539. * moved parsing interface/implementation to -vu
  1540. Revision 1.151 1999/08/31 15:51:10 pierre
  1541. * in_second_compile cleaned up, in_compile and in_second_load added
  1542. Revision 1.150 1999/08/30 16:21:40 pierre
  1543. * tempclosing of ppufiles under dos was wrong
  1544. Revision 1.149 1999/08/28 15:34:19 florian
  1545. * bug 519 fixed
  1546. Revision 1.148 1999/08/27 14:53:00 pierre
  1547. * double checksum problem solved
  1548. Revision 1.147 1999/08/27 10:57:56 pierre
  1549. + define SHORT_ON_FILE_HANDLES for DOS targets
  1550. causes tempclose of ppufiles
  1551. + double_checksum code released
  1552. (you can try with -dDONT_USE_DOUBLE_CHECKSUM to see the difference)
  1553. this allow second compilation of compiler without any
  1554. unit recompilation !!!!
  1555. Revision 1.146 1999/08/26 21:16:21 peter
  1556. * write date of the compiler into the executable
  1557. Revision 1.145 1999/08/26 20:24:44 michael
  1558. + Hopefuly last fixes for resourcestrings
  1559. Revision 1.144 1999/08/24 22:38:53 michael
  1560. * more resourcestring changes
  1561. Revision 1.143 1999/08/24 12:01:34 michael
  1562. + changes for resourcestrings
  1563. Revision 1.142 1999/08/16 15:35:27 pierre
  1564. * fix for DLL relocation problems
  1565. * external bss vars had wrong stabs for pecoff
  1566. + -WB11000000 to specify default image base, allows to
  1567. load several DLLs with debugging info included
  1568. (relocatable DLL are stripped because the relocation
  1569. of the .Stab section is misplaced by ldw)
  1570. }