pmodules.pas 61 KB

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